Duplicate queries

This commit is contained in:
Rory Powell 2021-12-07 12:26:00 +00:00
parent 5d4fb2e7c7
commit 52ea1fe1da
4 changed files with 126 additions and 1 deletions

View File

@ -11,6 +11,14 @@
await queries.delete(query)
notifications.success("Query deleted")
}
async function duplicateQuery() {
try {
await queries.duplicate(query, queries.save)
} 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

View File

@ -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})`
}

View File

@ -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)")
})
})
})

View File

@ -1,9 +1,17 @@
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,
@ -17,6 +25,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 +58,7 @@ export function createQueriesStore() {
} else {
queries.push(json)
}
sortQueries(queries)
return { list: queries, selected: json._id }
})
return json
@ -76,6 +86,20 @@ export function createQueriesStore() {
})
return response
},
duplicate: async (query, saveFn) => {
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)
)
saveFn(datasourceId, newQuery)
},
}
}