1
0
Fork 0
mirror of synced 2024-10-03 10:36:59 +13:00

Ensure grid schema structure is predictable and prevent copying IDs for query datasources

This commit is contained in:
Andrew Kingston 2023-10-04 09:25:35 +01:00
parent d03fdb6df9
commit c4a516ccb3
6 changed files with 61 additions and 48 deletions

View file

@ -22,6 +22,7 @@
columns, columns,
definition, definition,
datasource, datasource,
schema,
} = getContext("grid") } = getContext("grid")
const bannedDisplayColumnTypes = [ const bannedDisplayColumnTypes = [
@ -126,16 +127,16 @@
// Generate new name // Generate new name
let newName = `${column.name} copy` let newName = `${column.name} copy`
let attempts = 2 let attempts = 2
while ($definition.schema[newName]) { while ($schema[newName]) {
newName = `${column.name} copy ${attempts++}` newName = `${column.name} copy ${attempts++}`
} }
// Save schema with new column // Save schema with new column
const existingColumnDefinition = $definition.schema[column.name] const existingColumnDefinition = $schema[column.name]
await datasource.actions.saveDefinition({ await datasource.actions.saveDefinition({
...$definition, ...$definition,
schema: { schema: {
...$definition.schema, ...$schema,
[newName]: { [newName]: {
...existingColumnDefinition, ...existingColumnDefinition,
name: newName, name: newName,

View file

@ -75,7 +75,9 @@
</MenuItem> </MenuItem>
<MenuItem <MenuItem
icon="Copy" icon="Copy"
disabled={isNewRow || !$focusedRow?._id} disabled={isNewRow ||
!$focusedRow?._id ||
$focusedRow?._id?.startsWith("fake-")}
on:click={() => copyToClipboard($focusedRow?._id)} on:click={() => copyToClipboard($focusedRow?._id)}
on:click={menu.actions.close} on:click={menu.actions.close}
> >

View file

@ -69,7 +69,7 @@ export const deriveStores = context => {
} }
export const createActions = context => { export const createActions = context => {
const { columns, stickyColumn, datasource, definition } = context const { columns, stickyColumn, datasource, definition, schema } = context
// Updates the datasources primary display column // Updates the datasources primary display column
const changePrimaryDisplay = async column => { const changePrimaryDisplay = async column => {
@ -101,7 +101,7 @@ export const createActions = context => {
const $columns = get(columns) const $columns = get(columns)
const $definition = get(definition) const $definition = get(definition)
const $stickyColumn = get(stickyColumn) const $stickyColumn = get(stickyColumn)
const newSchema = cloneDeep($definition.schema) let newSchema = cloneDeep(get(schema)) || {}
// Build new updated datasource schema // Build new updated datasource schema
Object.keys(newSchema).forEach(column => { Object.keys(newSchema).forEach(column => {
@ -142,11 +142,11 @@ export const createActions = context => {
} }
export const initialise = context => { export const initialise = context => {
const { definition, columns, stickyColumn, schema } = context const { definition, columns, stickyColumn, enrichedSchema } = context
// Merge new schema fields with existing schema in order to preserve widths // Merge new schema fields with existing schema in order to preserve widths
schema.subscribe($schema => { enrichedSchema.subscribe($enrichedSchema => {
if (!$schema) { if (!$enrichedSchema) {
columns.set([]) columns.set([])
stickyColumn.set(null) stickyColumn.set(null)
return return
@ -155,13 +155,16 @@ export const initialise = context => {
// Find primary display // Find primary display
let primaryDisplay let primaryDisplay
if ($definition.primaryDisplay && $schema[$definition.primaryDisplay]) { if (
$definition.primaryDisplay &&
$enrichedSchema[$definition.primaryDisplay]
) {
primaryDisplay = $definition.primaryDisplay primaryDisplay = $definition.primaryDisplay
} }
// Get field list // Get field list
let fields = [] let fields = []
Object.keys($schema).forEach(field => { Object.keys($enrichedSchema).forEach(field => {
if (field !== primaryDisplay) { if (field !== primaryDisplay) {
fields.push(field) fields.push(field)
} }
@ -172,11 +175,11 @@ export const initialise = context => {
fields fields
.map(field => ({ .map(field => ({
name: field, name: field,
label: $schema[field].displayName || field, label: $enrichedSchema[field].displayName || field,
schema: $schema[field], schema: $enrichedSchema[field],
width: $schema[field].width || DefaultColumnWidth, width: $enrichedSchema[field].width || DefaultColumnWidth,
visible: $schema[field].visible ?? true, visible: $enrichedSchema[field].visible ?? true,
order: $schema[field].order, order: $enrichedSchema[field].order,
})) }))
.sort((a, b) => { .sort((a, b) => {
// Sort by order first // Sort by order first
@ -207,9 +210,9 @@ export const initialise = context => {
} }
stickyColumn.set({ stickyColumn.set({
name: primaryDisplay, name: primaryDisplay,
label: $schema[primaryDisplay].displayName || primaryDisplay, label: $enrichedSchema[primaryDisplay].displayName || primaryDisplay,
schema: $schema[primaryDisplay], schema: $enrichedSchema[primaryDisplay],
width: $schema[primaryDisplay].width || DefaultColumnWidth, width: $enrichedSchema[primaryDisplay].width || DefaultColumnWidth,
visible: true, visible: true,
order: 0, order: 0,
left: GutterWidth, left: GutterWidth,

View file

@ -12,27 +12,36 @@ export const createStores = () => {
export const deriveStores = context => { export const deriveStores = context => {
const { definition, schemaOverrides, columnWhitelist } = context const { definition, schemaOverrides, columnWhitelist } = context
const schema = derived( const schema = derived(definition, $definition => {
[definition, schemaOverrides, columnWhitelist], let schema = $definition?.schema
([$definition, $schemaOverrides, $columnWhitelist]) => { if (!schema) {
if (!$definition?.schema) { return null
}
// Ensure schema is configured as objects.
// Certain datasources like queries use primitives.
Object.keys(schema || {}).forEach(key => {
if (typeof schema[key] !== "object") {
schema[key] = { type: schema[key] }
}
})
return schema
})
const enrichedSchema = derived(
[schema, schemaOverrides, columnWhitelist],
([$schema, $schemaOverrides, $columnWhitelist]) => {
if (!$schema) {
return null return null
} }
let newSchema = { ...$definition?.schema } let enrichedSchema = { ...$schema }
// Ensure schema is configured as objects.
// Certain datasources like queries use primitives.
Object.keys(newSchema).forEach(key => {
if (typeof newSchema[key] !== "object") {
newSchema[key] = { type: newSchema[key] }
}
})
// Apply schema overrides // Apply schema overrides
Object.keys($schemaOverrides || {}).forEach(field => { Object.keys($schemaOverrides || {}).forEach(field => {
if (newSchema[field]) { if (enrichedSchema[field]) {
newSchema[field] = { enrichedSchema[field] = {
...newSchema[field], ...enrichedSchema[field],
...$schemaOverrides[field], ...$schemaOverrides[field],
} }
} }
@ -40,19 +49,20 @@ export const deriveStores = context => {
// Apply whitelist if specified // Apply whitelist if specified
if ($columnWhitelist?.length) { if ($columnWhitelist?.length) {
Object.keys(newSchema).forEach(key => { Object.keys(enrichedSchema).forEach(key => {
if (!$columnWhitelist.includes(key)) { if (!$columnWhitelist.includes(key)) {
delete newSchema[key] delete enrichedSchema[key]
} }
}) })
} }
return newSchema return enrichedSchema
} }
) )
return { return {
schema, schema,
enrichedSchema,
} }
} }

View file

@ -418,7 +418,7 @@ export const createActions = context => {
// Ensure we have a unique _id. // Ensure we have a unique _id.
// This means generating one for non DS+. // This means generating one for non DS+.
if (!newRow._id) { if (!newRow._id) {
newRow._id = Helpers.hashString(JSON.stringify(newRow)) newRow._id = `fake-${Helpers.hashString(JSON.stringify(newRow))}`
} }
if (!rowCacheMap[newRow._id]) { if (!rowCacheMap[newRow._id]) {

View file

@ -17,7 +17,7 @@ export const createStores = context => {
} }
export const initialise = context => { export const initialise = context => {
const { sort, initialSortColumn, initialSortOrder, definition } = context const { sort, initialSortColumn, initialSortOrder, schema } = context
// Reset sort when initial sort props change // Reset sort when initial sort props change
initialSortColumn.subscribe(newSortColumn => { initialSortColumn.subscribe(newSortColumn => {
@ -28,15 +28,12 @@ export const initialise = context => {
}) })
// Derive if the current sort column exists in the schema // Derive if the current sort column exists in the schema
const sortColumnExists = derived( const sortColumnExists = derived([sort, schema], ([$sort, $schema]) => {
[sort, definition], if (!$sort?.column || !$schema) {
([$sort, $definition]) => { return true
if (!$sort?.column || !$definition) {
return true
}
return $definition.schema?.[$sort.column] != null
} }
) return $schema[$sort.column] != null
})
// Clear sort state if our sort column does not exist // Clear sort state if our sort column does not exist
sortColumnExists.subscribe(exists => { sortColumnExists.subscribe(exists => {