clientId fetching before app load, custom views, fixed schema
This commit is contained in:
parent
44bba145c7
commit
a645df082c
|
@ -59,6 +59,7 @@
|
|||
"@babel/preset-env": "^7.5.5",
|
||||
"@babel/runtime": "^7.5.5",
|
||||
"@rollup/plugin-alias": "^3.0.1",
|
||||
"@rollup/plugin-json": "^4.0.3",
|
||||
"@sveltech/routify": "1.5.0-beta.40",
|
||||
"babel-jest": "^24.8.0",
|
||||
"browser-sync": "^2.26.7",
|
||||
|
|
|
@ -16,7 +16,15 @@
|
|||
})
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
onMount(async () => {
|
||||
const res = await fetch(`/api/client/id`)
|
||||
const json = await res.json()
|
||||
|
||||
store.update(state => {
|
||||
state.clientId = json
|
||||
return state
|
||||
})
|
||||
|
||||
window.addEventListener("error", showErrorBanner)
|
||||
window.addEventListener("unhandledrejection", showErrorBanner)
|
||||
})
|
||||
|
@ -26,6 +34,8 @@
|
|||
|
||||
<AppNotification />
|
||||
|
||||
<Modal>
|
||||
<Router {routes} />
|
||||
</Modal>
|
||||
{#if $store.clientId}
|
||||
<Modal>
|
||||
<Router {routes} />
|
||||
</Modal>
|
||||
{/if}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const apiCall = method => (url, body) =>
|
||||
fetch(url, {
|
||||
const apiCall = method => async (url, body) => {
|
||||
const response = await fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
|
@ -7,6 +7,13 @@ const apiCall = method => (url, body) =>
|
|||
body: body && JSON.stringify(body),
|
||||
})
|
||||
|
||||
// if (response.status === 500) {
|
||||
// throw new Error("Server Error");
|
||||
// }
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
const post = apiCall("POST")
|
||||
const get = apiCall("GET")
|
||||
const patch = apiCall("PATCH")
|
||||
|
|
|
@ -8,12 +8,9 @@ import {
|
|||
|
||||
export const getBackendUiStore = () => {
|
||||
const INITIAL_BACKEND_UI_STATE = {
|
||||
selectedView: {
|
||||
records: [],
|
||||
name: "",
|
||||
},
|
||||
breadcrumbs: [],
|
||||
models: [],
|
||||
views: [],
|
||||
users: [],
|
||||
selectedDatabase: {},
|
||||
selectedModel: {},
|
||||
|
@ -24,12 +21,15 @@ export const getBackendUiStore = () => {
|
|||
store.actions = {
|
||||
database: {
|
||||
select: async db => {
|
||||
const response = await api.get(`/api/${db.id}/models`)
|
||||
const models = await response.json()
|
||||
const modelsResponse = await api.get(`/api/${db.id}/models`)
|
||||
const viewsResponse = await api.get(`/api/${db.id}/views`)
|
||||
const models = await modelsResponse.json()
|
||||
const views = await viewsResponse.json()
|
||||
store.update(state => {
|
||||
state.selectedDatabase = db
|
||||
state.breadcrumbs = [db.name]
|
||||
state.models = models
|
||||
state.views = views;
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
|
|
@ -43,8 +43,7 @@ export const getStore = () => {
|
|||
libraries: null,
|
||||
showSettings: false,
|
||||
useAnalytics: true,
|
||||
appId: "",
|
||||
clientId: "budibase"
|
||||
appId: ""
|
||||
}
|
||||
|
||||
const store = writable(initial)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
{#if hasErrors}
|
||||
<div uk-alert class="uk-alert-danger">
|
||||
{#each errors as error}
|
||||
<div>{error.field ? `${error.field}: ` : ''}{error.error}</div>
|
||||
<div>{error.dataPath} {error.message}</div>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -77,10 +77,6 @@
|
|||
currentPage * ITEMS_PER_PAGE + ITEMS_PER_PAGE
|
||||
)
|
||||
|
||||
// async function fetchRecordsForView(view, instance) {
|
||||
// return await api.fetchDataForView($backendUiStore.selectedView)
|
||||
// }
|
||||
|
||||
function drillIntoRecord(record) {
|
||||
backendUiStore.update(state => {
|
||||
state.breadcrumbs = [...state.breadcrumbs, record.type, record.id]
|
||||
|
@ -100,7 +96,7 @@
|
|||
<section>
|
||||
<div class="table-controls">
|
||||
<h2 class="title">
|
||||
{takeRight(2, $backendUiStore.breadcrumbs).join(' / ')}
|
||||
{$backendUiStore.selectedModel.name}
|
||||
</h2>
|
||||
</div>
|
||||
<table class="uk-table">
|
||||
|
|
|
@ -30,11 +30,11 @@ export async function loadRecord(key, { appname, instanceId }) {
|
|||
export async function saveRecord(record, instanceId) {
|
||||
const SAVE_RECORDS_URL = `/api/${instanceId}/records`
|
||||
const response = await api.post(SAVE_RECORDS_URL, record)
|
||||
|
||||
return await response.json()
|
||||
}
|
||||
|
||||
export async function fetchDataForView(viewName, instanceId) {
|
||||
// const FETCH_RECORDS_URL = `/_builder/instance/${appname}/${instanceId}/api/listRecords/${viewName}`
|
||||
const FETCH_RECORDS_URL = `/api/${instanceId}/${viewName}/records`
|
||||
|
||||
const response = await api.get(FETCH_RECORDS_URL)
|
||||
|
|
|
@ -89,7 +89,6 @@
|
|||
<div>{key}</div>
|
||||
</td>
|
||||
<td>{meta.type}</td>
|
||||
<!-- <td>{meta.typeOptions.values || ''}</td> -->
|
||||
<td>
|
||||
<i
|
||||
class="ri-delete-bin-6-line hoverable"
|
||||
|
|
|
@ -16,21 +16,18 @@
|
|||
getDefaultTypeOptions,
|
||||
} from "components/common/core"
|
||||
|
||||
const FIELD_TYPES = ["string", "number", "boolean"]
|
||||
|
||||
export let field = { type: "string" }
|
||||
export let schema
|
||||
export let goBack
|
||||
export let onFinished = () => {}
|
||||
|
||||
let errors = []
|
||||
let draftField = cloneDeep(field);
|
||||
let draftField = cloneDeep(field)
|
||||
|
||||
const save = () => {
|
||||
// errors = validate.field(allFields)(clonedField)
|
||||
// if (errors.length > 0) return
|
||||
// field.typeOptions = cloneDeep(clonedField.typeOptions)
|
||||
schema[field.name] = draftField;
|
||||
goBack();
|
||||
// onFinished({ ...field, ...clonedField })
|
||||
schema[field.name] = draftField
|
||||
goBack()
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -43,37 +40,23 @@
|
|||
<Dropdown
|
||||
label="Type"
|
||||
bind:selected={draftField.type}
|
||||
options={keys(allTypes)} />
|
||||
options={FIELD_TYPES} />
|
||||
|
||||
{#if field.type === 'string'}
|
||||
<NumberBox
|
||||
label="Max Length"
|
||||
bind:value={draftField.maxLength} />
|
||||
<ValuesList
|
||||
label="Categories"
|
||||
bind:values={draftField.values} />
|
||||
{:else if field.type === 'bool'}
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<Checkbox
|
||||
label="Allow Null"
|
||||
bind:checked={draftField.allowNulls} />
|
||||
<NumberBox label="Max Length" bind:value={draftField.maxLength} />
|
||||
<ValuesList label="Categories" bind:values={draftField.values} />
|
||||
{:else if field.type === 'boolean'}
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<Checkbox label="Allow Null" bind:checked={draftField.allowNulls} />
|
||||
{:else if field.format === 'datetime'}
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<DatePicker
|
||||
label="Min Value"
|
||||
bind:value={draftField.minValue} />
|
||||
<DatePicker
|
||||
label="Max Value"
|
||||
bind:value={draftField.maxValue} />
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<DatePicker label="Min Value" bind:value={draftField.minValue} />
|
||||
<DatePicker label="Max Value" bind:value={draftField.maxValue} />
|
||||
{:else if field.type === 'number'}
|
||||
<NumberBox
|
||||
label="Min Value"
|
||||
bind:value={draftField.minimum} />
|
||||
<NumberBox
|
||||
label="Max Value"
|
||||
bind:value={draftField.maximum} />
|
||||
<NumberBox label="Min Value" bind:value={draftField.minimum} />
|
||||
<NumberBox label="Max Value" bind:value={draftField.maximum} />
|
||||
{:else if draftField.type.startsWith('array')}
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<!-- TODO: revisit and fix with JSON schema -->
|
||||
<NumberBox
|
||||
label="Min Length"
|
||||
bind:value={draftField.typeOptions.minLength} />
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
import * as api from "../api"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
|
||||
const CLASS_NAME_MAP = {
|
||||
boolean: "uk-checkbox"
|
||||
}
|
||||
|
||||
export let record = {}
|
||||
export let onClosed
|
||||
|
||||
|
@ -57,16 +61,15 @@
|
|||
|
||||
backendUiStore.update(state => {
|
||||
state.selectedView = state.selectedView
|
||||
return state
|
||||
onClosed();
|
||||
return state
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="actions">
|
||||
<h4 class="budibase__title--4">Create / Edit Record</h4>
|
||||
<!-- <ErrorsBox {errors} /> -->
|
||||
{JSON.stringify(errors)}
|
||||
<ErrorsBox {errors} />
|
||||
<form on:submit|preventDefault class="uk-form-stacked">
|
||||
{#if !record}
|
||||
<div class="uk-margin">
|
||||
|
@ -81,7 +84,7 @@
|
|||
{#each modelSchema as [key, meta]}
|
||||
<div class="uk-margin">
|
||||
<RecordFieldControl
|
||||
{errors}
|
||||
className={CLASS_NAME_MAP[meta.type]}
|
||||
type={determineInputType(meta)}
|
||||
label={key}
|
||||
bind:value={record[key]} />
|
||||
|
|
|
@ -3,50 +3,39 @@
|
|||
import CodeArea from "components/common/CodeArea.svelte"
|
||||
import Button from "components/common/Button.svelte"
|
||||
import Dropdown from "components/common/Dropdown.svelte"
|
||||
import { store } from "builderStore"
|
||||
import { store, backendUiStore } from "builderStore"
|
||||
import { filter, some, map, compose } from "lodash/fp"
|
||||
import {
|
||||
hierarchy as hierarchyFunctions,
|
||||
common,
|
||||
} from "../../../../../../core/src/"
|
||||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
import ActionButton from "components/common/ActionButton.svelte"
|
||||
import api from "builderStore/api"
|
||||
|
||||
const SNIPPET_EDITORS = {
|
||||
MAP: "Map",
|
||||
FILTER: "Filter",
|
||||
SHARD: "Shard Name",
|
||||
REDUCE: "Reduce",
|
||||
}
|
||||
|
||||
let view
|
||||
let indexableModels = []
|
||||
const COUCHDB_FUNCTION = `function(doc) {
|
||||
|
||||
}`
|
||||
|
||||
export let onClosed
|
||||
export let view = {}
|
||||
|
||||
let currentSnippetEditor = SNIPPET_EDITORS.MAP
|
||||
|
||||
const indexableModelsFromIndex = compose(
|
||||
map(node => ({
|
||||
node,
|
||||
isallowed:
|
||||
view.allowedModelNodeIds &&
|
||||
view.allowedModelNodeIds.some(id => node.nodeId === id),
|
||||
})),
|
||||
filter(hierarchyFunctions.isModel),
|
||||
filter(hierarchyFunctions.isDecendant($store.currentNode.parent())),
|
||||
hierarchyFunctions.getFlattenedHierarchy
|
||||
)
|
||||
$: instanceId = $backendUiStore.selectedDatabase.id
|
||||
|
||||
store.subscribe($store => {
|
||||
view = $store.currentNode
|
||||
indexableModels = indexableModelsFromIndex($store.hierarchy)
|
||||
})
|
||||
function deleteView() {}
|
||||
|
||||
const toggleAllowedModel = model => {
|
||||
if (model.isallowed) {
|
||||
view.allowedModelNodeIds = view.allowedModelNodeIds.filter(
|
||||
id => id !== model.node.nodeId
|
||||
)
|
||||
} else {
|
||||
view.allowedModelNodeIds.push(model.node.nodeId)
|
||||
}
|
||||
async function saveView() {
|
||||
const SAVE_VIEW_URL = `/api/${instanceId}/views`
|
||||
const response = await api.post(SAVE_VIEW_URL, view)
|
||||
backendUiStore.update(state => {
|
||||
state.views = [...state.views, response.view]
|
||||
return state
|
||||
})
|
||||
onClosed();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -63,26 +52,6 @@
|
|||
<div class="uk-width-1-2@s">
|
||||
<Textbox bind:text={view.name} label="Name" />
|
||||
</div>
|
||||
<div class="uk-width-1-2@s">
|
||||
<Dropdown
|
||||
label="View Type"
|
||||
bind:selected={view.indexType}
|
||||
options={['ancestor', 'reference']} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="allowed-records">
|
||||
<div class="budibase__label--big">
|
||||
Which models would you like to add to this view?
|
||||
</div>
|
||||
{#each indexableModels as model}
|
||||
<input
|
||||
class="uk-checkbox"
|
||||
type="checkbox"
|
||||
checked={model.isallowed}
|
||||
on:change={() => toggleAllowedModel(model)} />
|
||||
<span class="checkbox-model-label">{model.node.name}</span>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<h4 class="budibase__label--big">Snippets</h4>
|
||||
|
@ -98,18 +67,14 @@
|
|||
<CodeArea bind:text={view.map} label="Map" />
|
||||
{:else if currentSnippetEditor === SNIPPET_EDITORS.FILTER}
|
||||
<CodeArea bind:text={view.filter} label="Filter" />
|
||||
{:else if currentSnippetEditor === SNIPPET_EDITORS.SHARD}
|
||||
<CodeArea bind:text={view.getShardName} label="Shard Name" />
|
||||
{:else if currentSnippetEditor === SNIPPET_EDITORS.REDUCE}
|
||||
<CodeArea bind:text={view.reduce} label="Reduce" />
|
||||
{/if}
|
||||
|
||||
<ActionButton color="secondary" on:click={store.saveCurrentNode}>
|
||||
<ActionButton color="secondary" on:click={saveView}>
|
||||
Save
|
||||
</ActionButton>
|
||||
|
||||
{#if !$store.currentNodeIsNew}
|
||||
<ActionButton alert on:click={store.deleteCurrentNode}>Delete</ActionButton>
|
||||
{/if}
|
||||
|
||||
<ActionButton alert on:click={deleteView}>Delete</ActionButton>
|
||||
</form>
|
||||
|
||||
<style>
|
||||
|
@ -118,14 +83,6 @@
|
|||
padding: 15px;
|
||||
}
|
||||
|
||||
.allowed-records {
|
||||
margin: 20px 0px;
|
||||
}
|
||||
|
||||
.allowed-records > span {
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.snippet-selector__heading {
|
||||
margin-right: 20px;
|
||||
opacity: 0.7;
|
||||
|
@ -135,10 +92,6 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.checkbox-model-label {
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0 0 0 10px;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
export let value = ""
|
||||
export let label
|
||||
export let errors = []
|
||||
export let className = "uk-input"
|
||||
|
||||
let checked = type === "checkbox" ? value : false;
|
||||
|
||||
const handleInput = event => {
|
||||
if (event.target.type === "checkbox") {
|
||||
|
@ -21,8 +24,9 @@
|
|||
|
||||
<label>{label}</label>
|
||||
<input
|
||||
class="uk-input"
|
||||
class={className}
|
||||
class:uk-form-danger={errors.length > 0}
|
||||
{checked}
|
||||
{type}
|
||||
{value}
|
||||
on:input={handleInput}
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
CreateEditModelModal,
|
||||
CreateEditViewModal,
|
||||
} from "components/database/ModelDataTable/modals"
|
||||
import api from "builderStore/api"
|
||||
|
||||
const { open, close } = getContext("simple-modal")
|
||||
|
||||
// export let level = 0
|
||||
export let node
|
||||
export let type
|
||||
export let onSelect
|
||||
|
||||
let navActive = ""
|
||||
|
||||
|
@ -20,51 +21,25 @@
|
|||
index: "ri-eye-line",
|
||||
model: "ri-list-settings-line",
|
||||
}
|
||||
|
||||
store.subscribe(state => {
|
||||
if (state.currentNode) {
|
||||
navActive = node.nodeId === state.currentNode.nodeId
|
||||
}
|
||||
})
|
||||
|
||||
function selectModel(model) {
|
||||
backendUiStore.update(state => {
|
||||
state.selectedModel = model
|
||||
state.selectedView = `all_${model._id}`
|
||||
return state;
|
||||
})
|
||||
// store.selectExistingNode(node.nodeId)
|
||||
// const modalType =
|
||||
// node.type === "index" ? CreateEditViewModal : CreateEditModelModal
|
||||
// open(
|
||||
// modalType,
|
||||
// {
|
||||
// onClosed: close,
|
||||
// },
|
||||
// { styleContent: { padding: "0" } }
|
||||
// )
|
||||
}
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<div
|
||||
on:click={() => selectModel(node)}
|
||||
on:click={() => onSelect(node)}
|
||||
class="budibase__nav-item hierarchy-item"
|
||||
class:capitalized={type === 'model'}
|
||||
class:selected={$backendUiStore.selectedModel._id === node._id}>
|
||||
class:selected={$backendUiStore.selectedView === `all_${node._id}`}>
|
||||
<i class={ICON_MAP[type]} />
|
||||
<span style="margin-left: 1rem">{node.name}</span>
|
||||
<!-- <i
|
||||
class="ri-edit-line hoverable"
|
||||
on:click={editModel}
|
||||
/>
|
||||
<i
|
||||
class="ri-delete-bin-7-line hoverable"
|
||||
on:click={deleteModel}
|
||||
/> -->
|
||||
</div>
|
||||
<!-- {#if node.children}
|
||||
{#each node.children as child}
|
||||
<svelte:self node={child} level={level + 1} type="model" />
|
||||
{/each}
|
||||
{/if}
|
||||
{#if node.indexes}
|
||||
{#each node.indexes as index}
|
||||
<svelte:self node={index} level={level + 1} type="index" />
|
||||
{/each}
|
||||
{/if} -->
|
||||
</div>
|
||||
|
||||
<style>
|
||||
|
|
|
@ -13,6 +13,17 @@
|
|||
|
||||
const { open, close } = getContext("simple-modal")
|
||||
|
||||
function editModel() {
|
||||
open(
|
||||
CreateEditModelModal,
|
||||
{
|
||||
model: node,
|
||||
onClosed: close,
|
||||
},
|
||||
{ styleContent: { padding: "0" } }
|
||||
)
|
||||
}
|
||||
|
||||
function newModel() {
|
||||
open(
|
||||
CreateEditModelModal,
|
||||
|
@ -24,7 +35,6 @@
|
|||
}
|
||||
|
||||
function newView() {
|
||||
// store.newRootIndex()
|
||||
open(
|
||||
CreateEditViewModal,
|
||||
{
|
||||
|
@ -33,6 +43,32 @@
|
|||
{ styleContent: { padding: "0" } }
|
||||
)
|
||||
}
|
||||
|
||||
function selectModel(model) {
|
||||
backendUiStore.update(state => {
|
||||
state.selectedModel = model
|
||||
state.selectedView = `all_${model._id}`
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
async function deleteModel(modelToDelete) {
|
||||
const DELETE_MODEL_URL = `/api/${instanceId}/models/${node._id}/${node._rev}`
|
||||
const response = await api.delete(DELETE_MODEL_URL)
|
||||
backendUiStore.update(state => {
|
||||
state.models = state.models.filter(model => model._id !== modelToDelete._id)
|
||||
state.selectedView = {}
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
function selectView(view) {
|
||||
backendUiStore.update(state => {
|
||||
state.selectedView = view.name
|
||||
return state
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="items-root">
|
||||
|
@ -41,28 +77,40 @@
|
|||
<div class="nav-group-header">
|
||||
<div class="hierarchy-title">Models</div>
|
||||
<div class="uk-inline">
|
||||
<i class="ri-add-line hoverable" />
|
||||
<div uk-dropdown="mode: click;">
|
||||
<ul class="uk-nav uk-dropdown-nav">
|
||||
<li class="hoverable" on:click={newModel}>Model</li>
|
||||
<li class="hoverable" on:click={newView}>View</li>
|
||||
</ul>
|
||||
</div>
|
||||
<i class="ri-add-line hoverable" on:click={newModel} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hierarchy-items-container">
|
||||
{#each $backendUiStore.models as model}
|
||||
<HierarchyRow node={model} type="model" />
|
||||
{/each}
|
||||
<!-- {#each $store.hierarchy.children as model}
|
||||
<HierarchyRow node={model} type="model" />
|
||||
<HierarchyRow
|
||||
onSelect={selectModel}
|
||||
node={model}
|
||||
type="model"
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#each $store.hierarchy.indexes as index}
|
||||
<HierarchyRow node={index} type="index" />
|
||||
{/each} -->
|
||||
<div class="hierarchy">
|
||||
<div class="components-list-container">
|
||||
<div class="nav-group-header">
|
||||
<div class="hierarchy-title">Views</div>
|
||||
<div class="uk-inline">
|
||||
<i class="ri-add-line hoverable" on:click={newView} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hierarchy-items-container">
|
||||
{#each $backendUiStore.views as view}
|
||||
<HierarchyRow
|
||||
onSelect={selectView}
|
||||
node={view}
|
||||
type="view"
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
<div class="database-actions">
|
||||
<div class="budibase__label--big">{breadcrumbs}</div>
|
||||
{#if $backendUiStore.selectedDatabase.id}
|
||||
{#if $backendUiStore.selectedModel._id}
|
||||
<ActionButton primary on:click={createNewRecord}>
|
||||
Create new record
|
||||
</ActionButton>
|
||||
|
|
|
@ -8,7 +8,7 @@ module.exports = {
|
|||
type: "string",
|
||||
describe:
|
||||
"your apps directory - directory will be created if it does not exist",
|
||||
default: "~/budibase",
|
||||
default: "~/.budibase",
|
||||
alias: "d",
|
||||
})
|
||||
yargs.positional("database", {
|
||||
|
|
|
@ -6,7 +6,7 @@ const { join } = require("path")
|
|||
const initialiseClientDb = require("@budibase/server/db/initialiseClientDb")
|
||||
const Sqrl = require("squirrelly")
|
||||
const uuid = require("uuid")
|
||||
const CouchDb = require("@budibase/server/db/client")
|
||||
const CouchDB = require("@budibase/server/db/client")
|
||||
|
||||
module.exports = opts => {
|
||||
run(opts)
|
||||
|
@ -16,7 +16,7 @@ const run = async opts => {
|
|||
try {
|
||||
await ensureAppDir(opts)
|
||||
await prompts(opts)
|
||||
await createClientDatabse(opts)
|
||||
await createClientDatabase(opts)
|
||||
await createDevEnvFile(opts)
|
||||
console.log(chalk.green("Budibase successfully initialised."))
|
||||
} catch (error) {
|
||||
|
@ -55,12 +55,9 @@ const prompts = async opts => {
|
|||
}
|
||||
}
|
||||
|
||||
//https://admin:password@localhost:5984
|
||||
|
||||
const createClientDatabse = async opts => {
|
||||
const couch = CouchDb()
|
||||
const createClientDatabase = async opts => {
|
||||
if (opts.clientId === "new") {
|
||||
const existing = await couch.allDbs()
|
||||
const existing = await CouchDB.allDbs()
|
||||
|
||||
let i = 0
|
||||
let isExisting = true
|
||||
|
@ -71,8 +68,7 @@ const createClientDatabse = async opts => {
|
|||
}
|
||||
}
|
||||
|
||||
const db = new couch(`client-${opts.clientId}`)
|
||||
console.log(await db.info())
|
||||
const db = new CouchDB(`client-${opts.clientId}`)
|
||||
await initialiseClientDb(db)
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module.exports = {
|
|||
type: "string",
|
||||
describe: "budibase apps directory",
|
||||
alias: "d",
|
||||
default: "~/budibase",
|
||||
default: "~/.budibase",
|
||||
})
|
||||
},
|
||||
handler,
|
||||
|
|
|
@ -10,7 +10,7 @@ module.exports = {
|
|||
type: "string",
|
||||
describe: "your budibase apps directory",
|
||||
alias: "d",
|
||||
default: "~/budibase",
|
||||
default: "~/.budibase",
|
||||
})
|
||||
},
|
||||
handler,
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
const { resolve, join } = require("path")
|
||||
const { cwd } = require("process")
|
||||
const buildAppContext = require("@budibase/server/initialise/buildAppContext")
|
||||
const { homedir } = require("os")
|
||||
const buildAppContext = require("@budibase/server/initialise/buildAppContext")
|
||||
|
||||
module.exports.serverFileName = relativePath =>
|
||||
resolve(__dirname, "..", "node_modules", "@budibase", "server", relativePath)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -5,8 +5,7 @@ var getNewRecord = function getNewRecord(schema, modelName) {
|
|||
|
||||
var record = {
|
||||
_id: (0, _shortid.generate)(),
|
||||
modelId: model._id
|
||||
};
|
||||
modelId: model._id };
|
||||
|
||||
|
||||
for (var field in model.schema.properties) {
|
||||
|
|
|
@ -4,3 +4,4 @@ myapps/
|
|||
/builder/*
|
||||
!/builder/assets/
|
||||
public/
|
||||
db/dev.db/
|
|
@ -1,14 +1,17 @@
|
|||
const PouchDB = require("pouchdb")
|
||||
const allDbs = require("pouchdb-all-dbs")
|
||||
const os = require("os");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = () => {
|
||||
const COUCH_DB_URL =
|
||||
process.env.COUCH_DB_URL || "http://admin:password@localhost:5984"
|
||||
const DATABASE_TYPE = process.env.DATABASE_TYPE || "couch"
|
||||
const BUDIBASE_DIR = path.join(os.homedir(), ".budibase");
|
||||
|
||||
const pouch = PouchDB.defaults({
|
||||
prefix: COUCH_DB_URL,
|
||||
})
|
||||
allDbs(pouch)
|
||||
return pouch
|
||||
}
|
||||
const COUCH_DB_URL = process.env.COUCH_DB_URL || `leveldb://${BUDIBASE_DIR}/`;
|
||||
const DATABASE_TYPE = process.env.DATABASE_TYPE || "couch";
|
||||
|
||||
const Pouch = PouchDB.defaults({
|
||||
prefix: COUCH_DB_URL,
|
||||
});
|
||||
|
||||
allDbs(Pouch);
|
||||
|
||||
module.exports = Pouch;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
const client = require("./client")
|
||||
|
||||
module.exports = client()
|
||||
module.exports = client
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module.exports = async db => {
|
||||
await db.put({
|
||||
const doc = await db.put({
|
||||
_id: "_design/client",
|
||||
views: {
|
||||
by_type: {
|
||||
|
@ -8,5 +8,6 @@ module.exports = async db => {
|
|||
}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
console.log(doc);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
const CouchDB = require("../../db");
|
||||
|
||||
exports.getClientId = async function(ctx) {
|
||||
ctx.body = process.env.CLIENT_ID;
|
||||
};
|
||||
|
||||
exports.create = async function(ctx) {
|
||||
const clientId = `client-${ctx.request.body.clientId}`;
|
||||
const db = new CouchDB(clientId);
|
||||
|
|
|
@ -7,7 +7,9 @@ exports.save = async function(ctx) {
|
|||
|
||||
// validation with ajv
|
||||
const model = await db.get(record.modelId)
|
||||
const validate = schemaValidator.compile(model.schema)
|
||||
const validate = schemaValidator.compile({
|
||||
properties: model.schema
|
||||
});
|
||||
const valid = validate(record)
|
||||
|
||||
if (!valid) {
|
||||
|
@ -49,7 +51,7 @@ exports.save = async function(ctx) {
|
|||
exports.fetch = async function(ctx) {
|
||||
const db = new CouchDB(ctx.params.instanceId)
|
||||
const response = await db.query(
|
||||
`database/${ctx.params.modelId}`,
|
||||
`database/${ctx.params.viewName}`,
|
||||
{
|
||||
include_docs: true
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ const { resolve } = require("path")
|
|||
const builderPath = resolve(process.cwd(), "builder")
|
||||
|
||||
exports.serveBuilder = async function(ctx) {
|
||||
console.log(ctx.file);
|
||||
await send(ctx, ctx.file, { root: builderPath })
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
const CouchDB = require("../../db");
|
||||
|
||||
const controller = {
|
||||
query: async ctx => {
|
||||
|
||||
},
|
||||
fetch: async ctx => {
|
||||
const db = new CouchDB(ctx.params.instanceId);
|
||||
const designDoc = await db.get("_design/database");
|
||||
ctx.body = designDoc.views;
|
||||
const response = [];
|
||||
|
||||
for (let name in designDoc.views) {
|
||||
if (!name.startsWith("all") && name !== "by_type") {
|
||||
response.push({
|
||||
name,
|
||||
...designDoc.views[name]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
ctx.body = response
|
||||
},
|
||||
create: async ctx => {
|
||||
const db = new CouchDB(ctx.params.instanceId);
|
||||
|
@ -18,7 +32,10 @@ const controller = {
|
|||
const newView = await db.put(designDoc);
|
||||
|
||||
ctx.body = {
|
||||
...newView,
|
||||
view: {
|
||||
...ctx.request.body,
|
||||
...newView
|
||||
},
|
||||
message: `View ${name} created successfully.`,
|
||||
status: 200,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ const Router = require("@koa/router")
|
|||
const session = require("./session")
|
||||
const StatusCodes = require("../utilities/statusCodes")
|
||||
const { resolve } = require("path")
|
||||
const { homedir } = require("os")
|
||||
const send = require("koa-send")
|
||||
const routeHandlers = require("./routeHandlers")
|
||||
const {
|
||||
|
@ -24,18 +25,17 @@ const modelsRoutes = require("./routes/neo/model");
|
|||
const viewsRoutes = require("./routes/neo/view");
|
||||
const staticRoutes = require("./routes/neo/static");
|
||||
|
||||
const builderPath = resolve(__dirname, "../builder")
|
||||
|
||||
module.exports = app => {
|
||||
const router = new Router()
|
||||
|
||||
router
|
||||
.use(session(app))
|
||||
// .use(session(app))
|
||||
.use(async (ctx, next) => {
|
||||
// TODO: temp dev middleware
|
||||
// ctx.sessionId = ctx.session._sessCtx.externalKey
|
||||
// ctx.session.accessed = true
|
||||
ctx.isAuthenticated = true;
|
||||
ctx.config = { latestPackagesFolder: resolve(homedir(), ".budibase") }
|
||||
await next();
|
||||
});
|
||||
// .use(async (ctx, next) => {
|
||||
|
|
|
@ -4,6 +4,7 @@ const controller = require("../../controllers/client");
|
|||
const router = Router();
|
||||
|
||||
router
|
||||
.get("/api/client/id", controller.getClientId)
|
||||
.post("/api/clients", controller.create)
|
||||
.delete("/api/clients/:clientId", controller.destroy);
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ const controller = require("../../controllers/record")
|
|||
const router = Router()
|
||||
|
||||
router
|
||||
.get("/api/:instanceId/:modelId/records", controller.fetch)
|
||||
.get("/api/:instanceId/:viewName/records", controller.fetch)
|
||||
.get("/api/:instanceId/records/:recordId", controller.find)
|
||||
.post("/api/:instanceId/records", controller.save)
|
||||
.delete("/api/:instanceId/records/:recordId/:revId", controller.destroy)
|
||||
|
|
|
@ -5,7 +5,7 @@ const router = Router();
|
|||
|
||||
router
|
||||
.param("file", async (file, ctx, next) => {
|
||||
ctx.file = file || "index.html";
|
||||
ctx.file = file && file.includes(".") ? file : "index.html";
|
||||
await next();
|
||||
})
|
||||
.get("/_builder/:file*", controller.serveBuilder)
|
||||
|
|
|
@ -12,6 +12,7 @@ const { join, dirname, resolve } = require("path")
|
|||
const { $ } = require("@budibase/core").common
|
||||
const { intersection, map, values, flatten } = require("lodash/fp")
|
||||
const { merge } = require("lodash")
|
||||
const { homedir } = require("os");
|
||||
|
||||
const { componentLibraryInfo } = require("./componentLibraryInfo")
|
||||
const buildPage = require("./buildPage")
|
||||
|
@ -28,7 +29,7 @@ const getAppDefinition = async appPath =>
|
|||
await readJSON(`${appPath}/appDefinition.json`)
|
||||
|
||||
module.exports.getPackageForBuilder = async (config, application) => {
|
||||
const appPath = resolve(process.cwd(), config.latestPackagesFolder, application._id);
|
||||
const appPath = resolve(config.latestPackagesFolder, application._id);
|
||||
|
||||
const pages = await getPages(appPath)
|
||||
|
||||
|
@ -42,6 +43,8 @@ module.exports.getPackageForBuilder = async (config, application) => {
|
|||
components: await getComponentDefinitions(appPath, pages),
|
||||
|
||||
application,
|
||||
|
||||
clientId: process.env.CLIENT_ID
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@ module.exports.LATEST_VERSIONID = LATEST_VERSIONID
|
|||
|
||||
module.exports.runtimePackagesDirectory = runtimePackagesDirectory
|
||||
|
||||
module.exports.getRuntimePackageDirectory = (appContext, appName, versionId) =>
|
||||
module.exports.getRuntimePackageDirectory = (appId, versionId) =>
|
||||
versionId === LATEST_VERSIONID
|
||||
? getLatestDirectory(appContext, appName)
|
||||
? getLatestDirectory(appId)
|
||||
: join(getRuntimeAppsDirectory(appName), versionId)
|
||||
|
||||
module.exports.getRuntimeAppsDirectory = getRuntimeAppsDirectory
|
||||
|
|
Loading…
Reference in New Issue