enable renaming of records by using IDs
This commit is contained in:
parent
83da838fcd
commit
e1b88e6620
|
@ -1,5 +1,6 @@
|
||||||
import { writable } from "svelte/store"
|
import { writable } from "svelte/store"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
import { uuid } from "builderStore/uuid"
|
||||||
import api from "../api"
|
import api from "../api"
|
||||||
|
|
||||||
export const getBackendUiStore = () => {
|
export const getBackendUiStore = () => {
|
||||||
|
@ -61,14 +62,15 @@ export const getBackendUiStore = () => {
|
||||||
save: async ({ model }) => {
|
save: async ({ model }) => {
|
||||||
const updatedModel = cloneDeep(model)
|
const updatedModel = cloneDeep(model)
|
||||||
|
|
||||||
// TODO: refactor
|
// // TODO: refactor
|
||||||
for (let key in updatedModel.schema) {
|
// for (let key in updatedModel.schema) {
|
||||||
const field = updatedModel.schema[key]
|
// const field = updatedModel.schema[key]
|
||||||
if (field.name && field.name !== key) {
|
// // TODO: use IDs
|
||||||
updatedModel.schema[field.name] = field
|
// if (field.name && field.name !== key) {
|
||||||
delete updatedModel.schema[key]
|
// updatedModel.schema[field.name] = field
|
||||||
}
|
// delete updatedModel.schema[key]
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const SAVE_MODEL_URL = `/api/models`
|
const SAVE_MODEL_URL = `/api/models`
|
||||||
const response = await api.post(SAVE_MODEL_URL, updatedModel)
|
const response = await api.post(SAVE_MODEL_URL, updatedModel)
|
||||||
|
@ -86,8 +88,6 @@ export const getBackendUiStore = () => {
|
||||||
state.models = state.models
|
state.models = state.models
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fetch models
|
|
||||||
|
|
||||||
store.actions.models.select(savedModel)
|
store.actions.models.select(savedModel)
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
|
@ -98,13 +98,13 @@ export const getBackendUiStore = () => {
|
||||||
state.draftModel.schema = {}
|
state.draftModel.schema = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const id = uuid()
|
||||||
|
|
||||||
state.draftModel.schema = {
|
state.draftModel.schema = {
|
||||||
...state.draftModel.schema,
|
...state.draftModel.schema,
|
||||||
[field.name]: field,
|
[id]: field,
|
||||||
}
|
}
|
||||||
|
state.selectedField = id
|
||||||
state.selectedField = field.name
|
|
||||||
|
|
||||||
state.tabs.NAVIGATION_PANEL = "NAVIGATE"
|
state.tabs.NAVIGATION_PANEL = "NAVIGATE"
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"_id",
|
"_id",
|
||||||
"_rev",
|
"_rev",
|
||||||
$backendUiStore.selectedModel.name,
|
$backendUiStore.selectedModel.name,
|
||||||
|
modelId
|
||||||
]
|
]
|
||||||
|
|
||||||
async function fetchRecords() {
|
async function fetchRecords() {
|
||||||
|
@ -26,10 +27,6 @@
|
||||||
records = await response.json()
|
records = await response.json()
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
fetchRecords()
|
|
||||||
})
|
|
||||||
|
|
||||||
function linkRecord(id) {
|
function linkRecord(id) {
|
||||||
if (linkedRecords.has(id)) {
|
if (linkedRecords.has(id)) {
|
||||||
linkedRecords.delete(id)
|
linkedRecords.delete(id)
|
||||||
|
@ -39,6 +36,10 @@
|
||||||
|
|
||||||
linkedRecords = linkedRecords
|
linkedRecords = linkedRecords
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
fetchRecords()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"type",
|
"type",
|
||||||
"_id",
|
"_id",
|
||||||
"_rev",
|
"_rev",
|
||||||
|
$backendUiStore.selectedModel._id,
|
||||||
$backendUiStore.selectedModel.name,
|
$backendUiStore.selectedModel.name,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -48,9 +48,6 @@
|
||||||
if ($backendUiStore.selectedView) {
|
if ($backendUiStore.selectedView) {
|
||||||
api.fetchDataForView($backendUiStore.selectedView).then(records => {
|
api.fetchDataForView($backendUiStore.selectedView).then(records => {
|
||||||
data = records || []
|
data = records || []
|
||||||
headers = Object.keys($backendUiStore.selectedModel.schema).filter(
|
|
||||||
key => !INTERNAL_HEADERS.includes(key)
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,6 +59,12 @@
|
||||||
)
|
)
|
||||||
: []
|
: []
|
||||||
|
|
||||||
|
$: headers = Object.keys($backendUiStore.selectedModel.schema).filter(
|
||||||
|
id => !INTERNAL_HEADERS.includes(id)
|
||||||
|
)
|
||||||
|
|
||||||
|
$: schema = $backendUiStore.selectedModel.schema
|
||||||
|
|
||||||
const createNewRecord = () => {
|
const createNewRecord = () => {
|
||||||
open(
|
open(
|
||||||
CreateEditRecordModal,
|
CreateEditRecordModal,
|
||||||
|
@ -94,7 +97,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<th>Edit</th>
|
<th>Edit</th>
|
||||||
{#each headers as header}
|
{#each headers as header}
|
||||||
<th>{header}</th>
|
<th>{$backendUiStore.selectedModel.schema[header].name}</th>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
@ -129,9 +132,11 @@
|
||||||
</td>
|
</td>
|
||||||
{#each headers as header}
|
{#each headers as header}
|
||||||
<td>
|
<td>
|
||||||
{#if Array.isArray(row[header])}
|
{#if schema[header].type === "link"}
|
||||||
<LinkedRecord {header} ids={row[header]} />
|
<LinkedRecord header={schema[header].name} ids={row[header]} />
|
||||||
{:else}{row[header] || 0}{/if}
|
{:else}
|
||||||
|
{row[header]}
|
||||||
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{/each}
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -79,13 +79,13 @@
|
||||||
{#if meta.type === 'link'}
|
{#if meta.type === 'link'}
|
||||||
<LinkedRecordSelector
|
<LinkedRecordSelector
|
||||||
bind:linked={record[key]}
|
bind:linked={record[key]}
|
||||||
linkName={key}
|
linkName={meta.name}
|
||||||
modelId={meta.modelId} />
|
modelId={meta.modelId} />
|
||||||
{:else}
|
{:else}
|
||||||
<RecordFieldControl
|
<RecordFieldControl
|
||||||
type={determineInputType(meta)}
|
type={determineInputType(meta)}
|
||||||
options={determineOptions(meta)}
|
options={determineOptions(meta)}
|
||||||
label={key}
|
label={meta.name}
|
||||||
bind:value={record[key]} />
|
bind:value={record[key]} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,7 +101,7 @@
|
||||||
header {
|
header {
|
||||||
margin-bottom: 40px;
|
margin-bottom: 40px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 5px;
|
grid-gap: 20px;
|
||||||
grid-template-columns: 40px 1fr;
|
grid-template-columns: 40px 1fr;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,6 @@
|
||||||
background: var(--secondary);
|
background: var(--secondary);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-right: 20px;
|
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { backendUiStore } from "builderStore"
|
import { backendUiStore } from "builderStore"
|
||||||
|
import { uuid } from "builderStore/uuid"
|
||||||
import { fade } from "svelte/transition"
|
import { fade } from "svelte/transition"
|
||||||
import { FIELDS, BLOCKS, MODELS } from "constants/backend"
|
import { FIELDS, BLOCKS, MODELS } from "constants/backend"
|
||||||
import Block from "components/common/Block.svelte"
|
import Block from "components/common/Block.svelte"
|
||||||
|
@ -11,9 +12,16 @@
|
||||||
function createModel(model) {
|
function createModel(model) {
|
||||||
const { schema, ...rest } = $backendUiStore.selectedModel
|
const { schema, ...rest } = $backendUiStore.selectedModel
|
||||||
|
|
||||||
|
const newModel = { ...model, schema: {} }
|
||||||
|
|
||||||
|
// TODO: could be better
|
||||||
|
for (let key in model.schema) {
|
||||||
|
newModel.schema[uuid()] = model.schema[key]
|
||||||
|
}
|
||||||
|
|
||||||
backendUiStore.actions.models.save({
|
backendUiStore.actions.models.save({
|
||||||
model: {
|
model: {
|
||||||
...model,
|
...newModel,
|
||||||
...rest,
|
...rest,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -23,12 +23,12 @@
|
||||||
|
|
||||||
$: selectedTab = $backendUiStore.tabs.NAVIGATION_PANEL
|
$: selectedTab = $backendUiStore.tabs.NAVIGATION_PANEL
|
||||||
|
|
||||||
function selectModel(model, fieldName) {
|
function selectModel(model, fieldId) {
|
||||||
backendUiStore.actions.models.select(model)
|
backendUiStore.actions.models.select(model)
|
||||||
|
|
||||||
if (fieldName) {
|
if (fieldId) {
|
||||||
backendUiStore.update(state => {
|
backendUiStore.update(state => {
|
||||||
state.selectedField = fieldName
|
state.selectedField = fieldId
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
backendUiStore.update(state => {
|
backendUiStore.update(state => {
|
||||||
state.selectedModel = {}
|
state.selectedModel = {}
|
||||||
state.draftModel = { schema: {} }
|
state.draftModel = { schema: {} }
|
||||||
|
state.tabs.SETUP_PANEL = "SETUP"
|
||||||
return state
|
return state
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -63,13 +64,13 @@
|
||||||
on:click={() => selectModel(model)} />
|
on:click={() => selectModel(model)} />
|
||||||
{#if model._id === $backendUiStore.selectedModel._id}
|
{#if model._id === $backendUiStore.selectedModel._id}
|
||||||
<div in:slide>
|
<div in:slide>
|
||||||
{#each Object.keys(model.schema) as field}
|
{#each Object.keys(model.schema) as fieldId}
|
||||||
<ListItem
|
<ListItem
|
||||||
selected={model._id === $backendUiStore.selectedModel._id && field === $backendUiStore.selectedField}
|
selected={model._id === $backendUiStore.selectedModel._id && fieldId === $backendUiStore.selectedField}
|
||||||
indented
|
indented
|
||||||
icon="ri-layout-column-fill"
|
icon="ri-layout-column-fill"
|
||||||
title={field}
|
title={model.schema[fieldId].name}
|
||||||
on:click={() => selectModel(model, field)} />
|
on:click={() => selectModel(model, fieldId)} />
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -22,6 +22,18 @@
|
||||||
field.constraints &&
|
field.constraints &&
|
||||||
field.constraints.presence &&
|
field.constraints.presence &&
|
||||||
!constraints.presence.allowEmpty
|
!constraints.presence.allowEmpty
|
||||||
|
|
||||||
|
function attachModelIdToSchema(evt) {
|
||||||
|
const { draftModel } = $backendUiStore
|
||||||
|
if ($backendUiStore.selectedField !== evt.target.value) {
|
||||||
|
delete draftModel.schema[$backendUiStore.selectedField]
|
||||||
|
draftModel.schema[evt.target.value] = field
|
||||||
|
backendUiStore.update(state => {
|
||||||
|
state.selectedField = evt.target.value
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="info">
|
<div class="info">
|
||||||
|
@ -66,10 +78,12 @@
|
||||||
{:else if field.type === 'link'}
|
{:else if field.type === 'link'}
|
||||||
<div class="field">
|
<div class="field">
|
||||||
<label>Link</label>
|
<label>Link</label>
|
||||||
<select class="budibase__input" bind:value={field.modelId}>
|
<select class="budibase__input" bind:value={field.modelId} on:change={attachModelIdToSchema}>
|
||||||
<option value={''} />
|
<option value={''} />
|
||||||
{#each $backendUiStore.models as model}
|
{#each $backendUiStore.models as model}
|
||||||
<option value={model._id}>{model.name}</option>
|
{#if model._id !== $backendUiStore.draftModel._id}
|
||||||
|
<option value={model._id}>{model.name}</option>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
const response = await api.delete(DELETE_MODEL_URL)
|
const response = await api.delete(DELETE_MODEL_URL)
|
||||||
backendUiStore.update(state => {
|
backendUiStore.update(state => {
|
||||||
state.selectedView = null
|
state.selectedView = null
|
||||||
|
state.selectedModel = {}
|
||||||
|
state.draftModel = {}
|
||||||
state.models = state.models.filter(({ _id }) => _id !== model._id)
|
state.models = state.models.filter(({ _id }) => _id !== model._id)
|
||||||
notifier.danger(`${model.name} deleted successfully.`)
|
notifier.danger(`${model.name} deleted successfully.`)
|
||||||
return state
|
return state
|
||||||
|
@ -64,7 +66,7 @@
|
||||||
{#if selectedTab === 'SETUP'}
|
{#if selectedTab === 'SETUP'}
|
||||||
{#if $backendUiStore.selectedField}
|
{#if $backendUiStore.selectedField}
|
||||||
<ModelFieldEditor />
|
<ModelFieldEditor />
|
||||||
{:else}
|
{:else if $backendUiStore.draftModel.schema}
|
||||||
<div class="titled-input">
|
<div class="titled-input">
|
||||||
<header>Name</header>
|
<header>Name</header>
|
||||||
<input
|
<input
|
||||||
|
|
|
@ -45,7 +45,7 @@ exports.create = async function(ctx) {
|
||||||
}
|
}
|
||||||
const appId = newid()
|
const appId = newid()
|
||||||
// insert an appId -> clientId lookup
|
// insert an appId -> clientId lookup
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
|
|
||||||
await masterDb.put({
|
await masterDb.put({
|
||||||
_id: appId,
|
_id: appId,
|
||||||
|
@ -132,7 +132,7 @@ const createEmptyAppPackage = async (ctx, app) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const lookupClientId = async appId => {
|
const lookupClientId = async appId => {
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
const { clientId } = await masterDb.get(appId)
|
const { clientId } = await masterDb.get(appId)
|
||||||
return clientId
|
return clientId
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ exports.authenticate = async ctx => {
|
||||||
if (!username) ctx.throw(400, "Username Required.")
|
if (!username) ctx.throw(400, "Username Required.")
|
||||||
if (!password) ctx.throw(400, "Password Required")
|
if (!password) ctx.throw(400, "Password Required")
|
||||||
|
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
|
|
||||||
const { clientId } = await masterDb.get(ctx.user.appId)
|
const { clientId } = await masterDb.get(ctx.user.appId)
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ const {
|
||||||
} = require("../../utilities/budibaseDir")
|
} = require("../../utilities/budibaseDir")
|
||||||
|
|
||||||
exports.fetchAppComponentDefinitions = async function(ctx) {
|
exports.fetchAppComponentDefinitions = async function(ctx) {
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
const { clientId } = await masterDb.get(ctx.params.appId)
|
const { clientId } = await masterDb.get(ctx.params.appId)
|
||||||
const db = new CouchDB(ClientDb.name(clientId))
|
const db = new CouchDB(ClientDb.name(clientId))
|
||||||
const app = await db.get(ctx.params.appId)
|
const app = await db.get(ctx.params.appId)
|
||||||
|
|
|
@ -8,7 +8,7 @@ exports.create = async function(ctx) {
|
||||||
const appShortId = appId.substring(0, 7)
|
const appShortId = appId.substring(0, 7)
|
||||||
const instanceId = `inst_${appShortId}_${newid()}`
|
const instanceId = `inst_${appShortId}_${newid()}`
|
||||||
|
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
const { clientId } = await masterDb.get(appId)
|
const { clientId } = await masterDb.get(appId)
|
||||||
|
|
||||||
const db = new CouchDB(instanceId)
|
const db = new CouchDB(instanceId)
|
||||||
|
|
|
@ -16,7 +16,7 @@ exports.find = async function(ctx) {
|
||||||
ctx.body = model
|
ctx.body = model
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.create = async function(ctx) {
|
exports.save = async function(ctx) {
|
||||||
const db = new CouchDB(ctx.user.instanceId)
|
const db = new CouchDB(ctx.user.instanceId)
|
||||||
const modelToSave = {
|
const modelToSave = {
|
||||||
type: "model",
|
type: "model",
|
||||||
|
@ -33,7 +33,7 @@ exports.create = async function(ctx) {
|
||||||
if (schema[key].type === "link") {
|
if (schema[key].type === "link") {
|
||||||
// create the link field in the other model
|
// create the link field in the other model
|
||||||
const linkedModel = await db.get(schema[key].modelId)
|
const linkedModel = await db.get(schema[key].modelId)
|
||||||
linkedModel.schema[modelToSave.name] = {
|
linkedModel.schema[modelToSave._id] = {
|
||||||
name: modelToSave.name,
|
name: modelToSave.name,
|
||||||
type: "link",
|
type: "link",
|
||||||
modelId: modelToSave._id,
|
modelId: modelToSave._id,
|
||||||
|
|
|
@ -56,8 +56,8 @@ exports.save = async function(ctx) {
|
||||||
const doc = row.doc
|
const doc = row.doc
|
||||||
return {
|
return {
|
||||||
...doc,
|
...doc,
|
||||||
[model.name]: doc[model.name]
|
[model._id]: doc[model._id]
|
||||||
? [...doc[model.name], record._id]
|
? [...doc[model._id], record._id]
|
||||||
: [record._id],
|
: [record._id],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -41,7 +41,7 @@ exports.create = async function(ctx) {
|
||||||
|
|
||||||
const response = await database.post(user)
|
const response = await database.post(user)
|
||||||
|
|
||||||
const masterDb = new CouchDB("clientAppLookup")
|
const masterDb = new CouchDB("client_app_lookup")
|
||||||
const { clientId } = await masterDb.get(appId)
|
const { clientId } = await masterDb.get(appId)
|
||||||
|
|
||||||
// the clientDB needs to store a map of users against the app
|
// the clientDB needs to store a map of users against the app
|
||||||
|
|
|
@ -12,8 +12,7 @@ router
|
||||||
authorized(READ_MODEL, ctx => ctx.params.id),
|
authorized(READ_MODEL, ctx => ctx.params.id),
|
||||||
modelController.find
|
modelController.find
|
||||||
)
|
)
|
||||||
.post("/api/models", authorized(BUILDER), modelController.create)
|
.post("/api/models", authorized(BUILDER), modelController.save)
|
||||||
// .patch("/api/:instanceId/models", controller.update)
|
|
||||||
.delete(
|
.delete(
|
||||||
"/api/models/:modelId/:revId",
|
"/api/models/:modelId/:revId",
|
||||||
authorized(BUILDER),
|
authorized(BUILDER),
|
||||||
|
|
Loading…
Reference in New Issue