enable renaming of records by using IDs

This commit is contained in:
Martin McKeaveney 2020-06-23 23:26:54 +01:00
parent 83da838fcd
commit e1b88e6620
17 changed files with 82 additions and 52 deletions

View File

@ -1,5 +1,6 @@
import { writable } from "svelte/store"
import { cloneDeep } from "lodash/fp"
import { uuid } from "builderStore/uuid"
import api from "../api"
export const getBackendUiStore = () => {
@ -61,14 +62,15 @@ export const getBackendUiStore = () => {
save: async ({ model }) => {
const updatedModel = cloneDeep(model)
// TODO: refactor
for (let key in updatedModel.schema) {
const field = updatedModel.schema[key]
if (field.name && field.name !== key) {
updatedModel.schema[field.name] = field
delete updatedModel.schema[key]
}
}
// // TODO: refactor
// for (let key in updatedModel.schema) {
// const field = updatedModel.schema[key]
// // TODO: use IDs
// if (field.name && field.name !== key) {
// updatedModel.schema[field.name] = field
// delete updatedModel.schema[key]
// }
// }
const SAVE_MODEL_URL = `/api/models`
const response = await api.post(SAVE_MODEL_URL, updatedModel)
@ -86,8 +88,6 @@ export const getBackendUiStore = () => {
state.models = state.models
}
// TODO: fetch models
store.actions.models.select(savedModel)
return state
})
@ -98,13 +98,13 @@ export const getBackendUiStore = () => {
state.draftModel.schema = {}
}
const id = uuid()
state.draftModel.schema = {
...state.draftModel.schema,
[field.name]: field,
[id]: field,
}
state.selectedField = field.name
state.selectedField = id
state.tabs.NAVIGATION_PANEL = "NAVIGATE"
return state

View File

@ -18,6 +18,7 @@
"_id",
"_rev",
$backendUiStore.selectedModel.name,
modelId
]
async function fetchRecords() {
@ -26,10 +27,6 @@
records = await response.json()
}
onMount(() => {
fetchRecords()
})
function linkRecord(id) {
if (linkedRecords.has(id)) {
linkedRecords.delete(id)
@ -39,6 +36,10 @@
linkedRecords = linkedRecords
}
onMount(() => {
fetchRecords()
})
</script>
<section>

View File

@ -15,6 +15,7 @@
"type",
"_id",
"_rev",
$backendUiStore.selectedModel._id,
$backendUiStore.selectedModel.name,
]

View File

@ -48,9 +48,6 @@
if ($backendUiStore.selectedView) {
api.fetchDataForView($backendUiStore.selectedView).then(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 = () => {
open(
CreateEditRecordModal,
@ -94,7 +97,7 @@
<tr>
<th>Edit</th>
{#each headers as header}
<th>{header}</th>
<th>{$backendUiStore.selectedModel.schema[header].name}</th>
{/each}
</tr>
</thead>
@ -129,9 +132,11 @@
</td>
{#each headers as header}
<td>
{#if Array.isArray(row[header])}
<LinkedRecord {header} ids={row[header]} />
{:else}{row[header] || 0}{/if}
{#if schema[header].type === "link"}
<LinkedRecord header={schema[header].name} ids={row[header]} />
{:else}
{row[header]}
{/if}
</td>
{/each}
</tr>

View File

@ -79,13 +79,13 @@
{#if meta.type === 'link'}
<LinkedRecordSelector
bind:linked={record[key]}
linkName={key}
linkName={meta.name}
modelId={meta.modelId} />
{:else}
<RecordFieldControl
type={determineInputType(meta)}
options={determineOptions(meta)}
label={key}
label={meta.name}
bind:value={record[key]} />
{/if}
</div>
@ -101,7 +101,7 @@
header {
margin-bottom: 40px;
display: grid;
grid-gap: 5px;
grid-gap: 20px;
grid-template-columns: 40px 1fr;
align-items: center;
}
@ -115,7 +115,6 @@
background: var(--secondary);
color: var(--ink);
font-size: 20px;
margin-right: 20px;
border-radius: 3px;
}

View File

@ -1,5 +1,6 @@
<script>
import { backendUiStore } from "builderStore"
import { uuid } from "builderStore/uuid"
import { fade } from "svelte/transition"
import { FIELDS, BLOCKS, MODELS } from "constants/backend"
import Block from "components/common/Block.svelte"
@ -11,9 +12,16 @@
function createModel(model) {
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({
model: {
...model,
...newModel,
...rest,
},
})

View File

@ -23,12 +23,12 @@
$: selectedTab = $backendUiStore.tabs.NAVIGATION_PANEL
function selectModel(model, fieldName) {
function selectModel(model, fieldId) {
backendUiStore.actions.models.select(model)
if (fieldName) {
if (fieldId) {
backendUiStore.update(state => {
state.selectedField = fieldName
state.selectedField = fieldId
return state
})
}
@ -38,6 +38,7 @@
backendUiStore.update(state => {
state.selectedModel = {}
state.draftModel = { schema: {} }
state.tabs.SETUP_PANEL = "SETUP"
return state
})
}
@ -63,13 +64,13 @@
on:click={() => selectModel(model)} />
{#if model._id === $backendUiStore.selectedModel._id}
<div in:slide>
{#each Object.keys(model.schema) as field}
{#each Object.keys(model.schema) as fieldId}
<ListItem
selected={model._id === $backendUiStore.selectedModel._id && field === $backendUiStore.selectedField}
selected={model._id === $backendUiStore.selectedModel._id && fieldId === $backendUiStore.selectedField}
indented
icon="ri-layout-column-fill"
title={field}
on:click={() => selectModel(model, field)} />
title={model.schema[fieldId].name}
on:click={() => selectModel(model, fieldId)} />
{/each}
</div>
{/if}

View File

@ -22,6 +22,18 @@
field.constraints &&
field.constraints.presence &&
!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>
<div class="info">
@ -66,10 +78,12 @@
{:else if field.type === 'link'}
<div class="field">
<label>Link</label>
<select class="budibase__input" bind:value={field.modelId}>
<select class="budibase__input" bind:value={field.modelId} on:change={attachModelIdToSchema}>
<option value={''} />
{#each $backendUiStore.models as model}
{#if model._id !== $backendUiStore.draftModel._id}
<option value={model._id}>{model.name}</option>
{/if}
{/each}
</select>
</div>

View File

@ -43,6 +43,8 @@
const response = await api.delete(DELETE_MODEL_URL)
backendUiStore.update(state => {
state.selectedView = null
state.selectedModel = {}
state.draftModel = {}
state.models = state.models.filter(({ _id }) => _id !== model._id)
notifier.danger(`${model.name} deleted successfully.`)
return state
@ -64,7 +66,7 @@
{#if selectedTab === 'SETUP'}
{#if $backendUiStore.selectedField}
<ModelFieldEditor />
{:else}
{:else if $backendUiStore.draftModel.schema}
<div class="titled-input">
<header>Name</header>
<input

View File

@ -45,7 +45,7 @@ exports.create = async function(ctx) {
}
const appId = newid()
// insert an appId -> clientId lookup
const masterDb = new CouchDB("clientAppLookup")
const masterDb = new CouchDB("client_app_lookup")
await masterDb.put({
_id: appId,
@ -132,7 +132,7 @@ const createEmptyAppPackage = async (ctx, app) => {
}
const lookupClientId = async appId => {
const masterDb = new CouchDB("clientAppLookup")
const masterDb = new CouchDB("client_app_lookup")
const { clientId } = await masterDb.get(appId)
return clientId
}

View File

@ -11,7 +11,7 @@ exports.authenticate = async ctx => {
if (!username) ctx.throw(400, "Username 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)

View File

@ -7,7 +7,7 @@ const {
} = require("../../utilities/budibaseDir")
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 db = new CouchDB(ClientDb.name(clientId))
const app = await db.get(ctx.params.appId)

View File

@ -8,7 +8,7 @@ exports.create = async function(ctx) {
const appShortId = appId.substring(0, 7)
const instanceId = `inst_${appShortId}_${newid()}`
const masterDb = new CouchDB("clientAppLookup")
const masterDb = new CouchDB("client_app_lookup")
const { clientId } = await masterDb.get(appId)
const db = new CouchDB(instanceId)

View File

@ -16,7 +16,7 @@ exports.find = async function(ctx) {
ctx.body = model
}
exports.create = async function(ctx) {
exports.save = async function(ctx) {
const db = new CouchDB(ctx.user.instanceId)
const modelToSave = {
type: "model",
@ -33,7 +33,7 @@ exports.create = async function(ctx) {
if (schema[key].type === "link") {
// create the link field in the other model
const linkedModel = await db.get(schema[key].modelId)
linkedModel.schema[modelToSave.name] = {
linkedModel.schema[modelToSave._id] = {
name: modelToSave.name,
type: "link",
modelId: modelToSave._id,

View File

@ -56,8 +56,8 @@ exports.save = async function(ctx) {
const doc = row.doc
return {
...doc,
[model.name]: doc[model.name]
? [...doc[model.name], record._id]
[model._id]: doc[model._id]
? [...doc[model._id], record._id]
: [record._id],
}
})

View File

@ -41,7 +41,7 @@ exports.create = async function(ctx) {
const response = await database.post(user)
const masterDb = new CouchDB("clientAppLookup")
const masterDb = new CouchDB("client_app_lookup")
const { clientId } = await masterDb.get(appId)
// the clientDB needs to store a map of users against the app

View File

@ -12,8 +12,7 @@ router
authorized(READ_MODEL, ctx => ctx.params.id),
modelController.find
)
.post("/api/models", authorized(BUILDER), modelController.create)
// .patch("/api/:instanceId/models", controller.update)
.post("/api/models", authorized(BUILDER), modelController.save)
.delete(
"/api/models/:modelId/:revId",
authorized(BUILDER),