Merge pull request #3702 from Budibase/duplicate-query
Duplicate queries
This commit is contained in:
commit
83a28eb4bb
|
@ -11,6 +11,14 @@
|
|||
await queries.delete(query)
|
||||
notifications.success("Query deleted")
|
||||
}
|
||||
|
||||
async function duplicateQuery() {
|
||||
try {
|
||||
await queries.duplicate(query)
|
||||
} catch (e) {
|
||||
notifications.error(e.message)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<ActionMenu>
|
||||
|
@ -18,6 +26,7 @@
|
|||
<Icon size="S" hoverable name="MoreSmallList" />
|
||||
</div>
|
||||
<MenuItem icon="Delete" on:click={confirmDeleteDialog.show}>Delete</MenuItem>
|
||||
<MenuItem icon="Duplicate" on:click={duplicateQuery}>Duplicate</MenuItem>
|
||||
</ActionMenu>
|
||||
|
||||
<ConfirmDialog
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* Duplicates a name with respect to a collection of existing names
|
||||
* e.g.
|
||||
* name all names result
|
||||
* ------ ----------- --------
|
||||
* ("foo") ["foo"] "foo (1)"
|
||||
* ("foo") ["foo", "foo (1)"] "foo (2)"
|
||||
* ("foo (1)") ["foo", "foo (1)"] "foo (2)"
|
||||
* ("foo") ["foo", "foo (2)"] "foo (1)"
|
||||
*
|
||||
* Repl
|
||||
*/
|
||||
export const duplicateName = (name, allNames) => {
|
||||
const baseName = name.split(" (")[0]
|
||||
const isDuplicate = new RegExp(`${baseName}\\s\\((\\d+)\\)$`)
|
||||
|
||||
// get the sequence from matched names
|
||||
const sequence = []
|
||||
allNames.filter(n => {
|
||||
if (n === baseName) {
|
||||
return true
|
||||
}
|
||||
const match = n.match(isDuplicate)
|
||||
if (match) {
|
||||
sequence.push(parseInt(match[1]))
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
sequence.sort((a, b) => a - b)
|
||||
|
||||
// get the next number in the sequence
|
||||
let number
|
||||
if (sequence.length === 0) {
|
||||
number = 1
|
||||
} else {
|
||||
// get the next number in the sequence
|
||||
for (let i = 0; i < sequence.length; i++) {
|
||||
if (sequence[i] !== i + 1) {
|
||||
number = i + 1
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!number) {
|
||||
number = sequence.length + 1
|
||||
}
|
||||
}
|
||||
|
||||
return `${baseName} (${number})`
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
const { duplicateName } = require("../duplicate")
|
||||
|
||||
describe("duplicate", () => {
|
||||
|
||||
describe("duplicates a name ", () => {
|
||||
it("with a single existing", async () => {
|
||||
const names = ["foo"]
|
||||
const name = "foo"
|
||||
|
||||
const duplicate = duplicateName(name, names)
|
||||
|
||||
expect(duplicate).toBe("foo (1)")
|
||||
})
|
||||
|
||||
it("with multiple existing", async () => {
|
||||
const names = ["foo", "foo (1)", "foo (2)"]
|
||||
const name = "foo"
|
||||
|
||||
const duplicate = duplicateName(name, names)
|
||||
|
||||
expect(duplicate).toBe("foo (3)")
|
||||
})
|
||||
|
||||
it("with mixed multiple existing", async () => {
|
||||
const names = ["foo", "foo (1)", "foo (2)", "bar", "bar (1)", "bar (2)"]
|
||||
const name = "foo"
|
||||
|
||||
const duplicate = duplicateName(name, names)
|
||||
|
||||
expect(duplicate).toBe("foo (3)")
|
||||
})
|
||||
|
||||
it("with incomplete sequence", async () => {
|
||||
const names = ["foo", "foo (2)", "foo (3)"]
|
||||
const name = "foo"
|
||||
|
||||
const duplicate = duplicateName(name, names)
|
||||
|
||||
expect(duplicate).toBe("foo (1)")
|
||||
})
|
||||
})
|
||||
})
|
|
@ -1,14 +1,19 @@
|
|||
import { writable, get } from "svelte/store"
|
||||
import { datasources, integrations, tables, views } from "./"
|
||||
import api from "builderStore/api"
|
||||
import { duplicateName } from "../../helpers/duplicate"
|
||||
|
||||
const sortQueries = queryList => {
|
||||
queryList.sort((q1, q2) => {
|
||||
return q1.name.localeCompare(q2.name)
|
||||
})
|
||||
}
|
||||
|
||||
export function createQueriesStore() {
|
||||
const { subscribe, set, update } = writable({ list: [], selected: null })
|
||||
const store = writable({ list: [], selected: null })
|
||||
const { subscribe, set, update } = store
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
update,
|
||||
const actions = {
|
||||
init: async () => {
|
||||
const response = await api.get(`/api/queries`)
|
||||
const json = await response.json()
|
||||
|
@ -17,6 +22,7 @@ export function createQueriesStore() {
|
|||
fetch: async () => {
|
||||
const response = await api.get(`/api/queries`)
|
||||
const json = await response.json()
|
||||
sortQueries(json)
|
||||
update(state => ({ ...state, list: json }))
|
||||
return json
|
||||
},
|
||||
|
@ -49,6 +55,7 @@ export function createQueriesStore() {
|
|||
} else {
|
||||
queries.push(json)
|
||||
}
|
||||
sortQueries(queries)
|
||||
return { list: queries, selected: json._id }
|
||||
})
|
||||
return json
|
||||
|
@ -76,6 +83,27 @@ export function createQueriesStore() {
|
|||
})
|
||||
return response
|
||||
},
|
||||
duplicate: async query => {
|
||||
let list = get(store).list
|
||||
const newQuery = { ...query }
|
||||
const datasourceId = query.datasourceId
|
||||
|
||||
delete newQuery._id
|
||||
delete newQuery._rev
|
||||
newQuery.name = duplicateName(
|
||||
query.name,
|
||||
list.map(q => q.name)
|
||||
)
|
||||
|
||||
actions.save(datasourceId, newQuery)
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
set,
|
||||
update,
|
||||
...actions,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ jest.mock('builderStore/api');
|
|||
import { SOME_QUERY, SAVE_QUERY_RESPONSE } from './fixtures/queries'
|
||||
|
||||
import { createQueriesStore } from "../queries"
|
||||
import { datasources } from '../datasources'
|
||||
|
||||
describe("Queries Store", () => {
|
||||
let store = createQueriesStore()
|
||||
|
|
Loading…
Reference in New Issue