UI structure

This commit is contained in:
Martin McKeaveney 2020-03-12 14:23:29 +00:00
parent d905677faf
commit 8cb49fb27e
29 changed files with 576 additions and 212 deletions

View File

@ -47,6 +47,7 @@
"safe-buffer": "^5.1.2",
"shortid": "^2.2.8",
"string_decoder": "^1.2.0",
"svelte-routing": "^1.4.2",
"uikit": "^3.1.7"
},
"devDependencies": {

View File

@ -165,7 +165,7 @@ export default {
svelte({
// enable run-time checks when not in production
dev: !production,
include: "src/**/*.svelte",
include: ["src/**/*.svelte", "node_modules/**/*.svelte"],
// we'll extract any component CSS out into
// a separate file — better for performance
css: css => {

View File

@ -29,16 +29,16 @@
{/await}
<!--
<div class="settings">
<IconButton icon="settings"
on:click={store.showSettings}/>
</div>
<div class="settings">
<IconButton icon="settings"
on:click={store.showSettings}/>
</div>
{#if $store.useAnalytics}
<iframe src="https://marblekirby.github.io/bb-analytics.html" width="0" height="0" style="visibility:hidden;display:none"/>
{/if}
-->
{#if $store.useAnalytics}
<iframe src="https://marblekirby.github.io/bb-analytics.html" width="0" height="0" style="visibility:hidden;display:none"/>
{/if}
-->
</main>
<style>

View File

@ -8,11 +8,9 @@
import ComingSoon from "./common/ComingSoon.svelte"
import { store } from "./builderStore"
import { setContext } from 'svelte';
import { setContext } from "svelte"
let activeNav = "database";
setContext("activeNav", activeNav);
let activeNav = "database"
</script>
<div class="root">
@ -20,14 +18,13 @@
<BackendNav />
</div>
<div class="content">
<!-- {#if activeNav === 'database'} -->
<Database />
<!-- {:else if activeNav === 'actions'}
<Database />
</div>
<!-- {:else if activeNav === 'actions'}
<ActionsAndTriggers />
{:else if activeNav === 'access levels'}
<AccessLevels />
{/if} -->
</div>
<div class="nav">
<SchemaManagementDrawer />
</div>

View File

@ -98,4 +98,24 @@
background: #fff;
border-radius: 5px;
box-shadow: 0 0px 6px rgba(0, 0, 0, 0.05);
}
.budibase__table {
border: 1px solid #ccc;
background: #fff;
border-radius: 2px;
}
.budibase__table thead {
background: var(--background-button);
}
.budibase__table th {
color: var(--button-text);
text-transform: capitalize;
font-weight: 500;
}
.budibase__table tr {
border-bottom: 1px solid #ccc;
}

View File

@ -148,8 +148,6 @@ export const getStore = () => {
store.addStylesheet = addStylesheet(store)
store.removeStylesheet = removeStylesheet(store)
store.savePage = savePage(store)
// store.showFrontend = showFrontend(store)
// store.showBackend = showBackend(store)
store.showSettings = showSettings(store)
store.useAnalytics = useAnalytics(store)
store.createGeneratedComponents = createGeneratedComponents(store)

View File

@ -2,24 +2,17 @@
import { JavaScriptIcon } from "../common/Icons"
// todo: use https://ace.c9.io
export let text = ""
export let label = ""
export let javascript = false
</script>
<div class="header">
{#if javascript}
<JavaScriptIcon />
{/if}
<span>{label}</span>
</div>
<textarea class="uk-textarea" bind:value={text} />
<style>
textarea {
padding: 3px;
padding: 10px;
margin-top: 5px;
margin-bottom: 10px;
background: var(--lightslate);
background: var(--primary100);
color: var(--white);
font-family: "Courier New", Courier, monospace;
width: 95%;
height: 100px;

View File

@ -1,10 +1,18 @@
<script>
import getIcon from "./icon"
export let icon
export let value
</script>
<div class="select-container">
<select on:change bind:value>
{#if icon}
<i class={icon} />
{/if}
<select
class:adjusted={icon}
on:change bind:value
>
<slot />
</select>
<span class="arrow">
@ -22,6 +30,16 @@
min-width: 200px;
}
.adjusted {
padding-left: 2.5em;
}
i {
position: absolute;
left: 8px;
top: 8px;
}
select {
height: 35px;
display: block;

View File

@ -0,0 +1,45 @@
<script>
export let data = []
export let headers = []
</script>
<table class="uk-table">
<thead>
<tr>
<th>Edit</th>
{#each headers as header}
<th>{header}</th>
{/each}
</tr>
</thead>
<tbody>
{#each data as row}
<tr>
<td>
<div class="uk-inline">
<i class="ri-more-line" />
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav">
<li>
<div>View</div>
</li>
<li>
<div>Edit</div>
</li>
<li>
<div on:click={() => (deleteRecordModal = true)}>Delete</div>
</li>
<li>
<div>Duplicate</div>
</li>
</ul>
</div>
</div>
</td>
{#each headers as header}
<td>{row[header]}</td>
{/each}
</tr>
{/each}
</tbody>
</table>

View File

@ -1,12 +1,13 @@
<script>
import HierarchyRow from "./HierarchyRow.svelte"
import RecordView from "./RecordView.svelte"
import ModelView from "./ModelView.svelte"
import IndexView from "./IndexView.svelte"
import ModelDataTable from "./ModelDataTable"
import ActionsHeader from "./ActionsHeader.svelte"
import { store } from "../builderStore"
import getIcon from "../common/icon"
import DropdownButton from "../common/DropdownButton.svelte"
import Modal from "../common/Modal.svelte"
import { hierarchy as hierarchyFunctions } from "../../../core/src"
const hierarchyWidth = "200px"
@ -53,18 +54,24 @@
</script>
<div class="root">
<div class="actions-header">
<!-- <div class="actions-header">
{#if $store.currentNode}
<ActionsHeader left={hierarchyWidth} />
<ActionsHeader />
{/if}
</div>
</div> -->
<div class="node-view">
{#if !$store.currentNode}
<ModelDataTable />
{:else if $store.currentNode.type === 'record'}
<RecordView />
{:else}
<IndexView />
<div class="breadcrumbs">{$store.currentlySelectedDatabase}</div>
<ModelDataTable />
{#if $store.currentNode}
<Modal isOpen={$store.currentNode}>
{#if $store.currentNode.type === 'record'}
<ModelView />
<ActionsHeader />
{:else}
<IndexView />
<ActionsHeader />
{/if}
</Modal>
{/if}
</div>
</div>

View File

@ -68,20 +68,14 @@
<ErrorsBox {errors} />
<form class="uk-form-horizontal">
<form class="uk-form-stacked">
<Textbox label="Name" bind:text={clonedField.name} />
<Dropdown
label="Type"
bind:selected={clonedField.type}
options={keys(allTypes)}
on:change={typeChanged} />
{#if isNew}
<Textbox label="Field Name" bind:text={clonedField.name} />
{:else}
<div style="font-weight: bold">{clonedField.name}</div>
{/if}
<Textbox label="Label" bind:text={clonedField.label} />
{#if clonedField.type === 'string'}
@ -89,7 +83,7 @@
label="Max Length"
bind:value={clonedField.typeOptions.maxLength} />
<ValuesList
label="Values (options)"
label="Categories"
bind:values={clonedField.typeOptions.values} />
<Checkbox
label="Declared Values Only"

View File

@ -9,20 +9,30 @@
const pipe = common.$
const SNIPPET_EDITORS = {
MAP: "Map",
FILTER: "Filter",
SHARD: "Shard Name",
}
let index
let indexableRecords = []
let currentSnippetEditor = SNIPPET_EDITORS.MAP
store.subscribe($store => {
index = $store.currentNode
indexableRecords = pipe($store.hierarchy, [
hierarchyFunctions.getFlattenedHierarchy,
filter(hierarchyFunctions.isDecendant(index.parent())),
filter(hierarchyFunctions.isRecord),
map(n => ({
node: n,
isallowed: some(id => n.nodeId === id)(index.allowedRecordNodeIds),
})),
])
indexableRecords = pipe(
$store.hierarchy,
[
hierarchyFunctions.getFlattenedHierarchy,
filter(hierarchyFunctions.isDecendant(index.parent())),
filter(hierarchyFunctions.isRecord),
map(n => ({
node: n,
isallowed: some(id => n.nodeId === id)(index.allowedRecordNodeIds),
})),
]
)
})
const toggleAllowedRecord = record => {
@ -36,11 +46,28 @@
}
</script>
<form class="uk-form-horizontal root">
<Textbox bind:text={index.name} label="Name" />
<h3 class="budibase__title--3">
<i class="ri-eye-line" />
Create / Edit View
</h3>
<form class="uk-form-stacked root">
<h4 class="budibase__label--big">Settings</h4>
<div class="uk-grid-small" uk-grid>
<div class="uk-width-1-2@s">
<Textbox bind:text={index.name} label="Name" />
</div>
<div class="uk-width-1-2@s">
<Dropdown
label="View Type"
bind:selected={index.indexType}
options={['ancestor', 'reference']} />
</div>
</div>
<div class="allowed-records">
<div class="index-label">Records to Index</div>
<div class="budibase__label--big">
Which models would you like to add to this view?
</div>
{#each indexableRecords as rec}
<input
type="checkbox"
@ -50,14 +77,22 @@
{/each}
</div>
<Dropdown
label="Index Type"
bind:selected={index.indexType}
options={['ancestor', 'reference']} />
<CodeArea bind:text={index.map} javascript label="Map" />
<CodeArea bind:text={index.filter} javascript label="Filter" />
<CodeArea javascript bind:text={index.getShardName} label="Shard Name" />
<h4 class="budibase__label--big">Snippets</h4>
{#each Object.values(SNIPPET_EDITORS) as snippetType}
<span
class="snippet-selector__heading hoverable"
class:highlighted={currentSnippetEditor === snippetType}
on:click={() => (currentSnippetEditor = snippetType)}>
{snippetType}
</span>
{/each}
{#if currentSnippetEditor === SNIPPET_EDITORS.MAP}
<CodeArea bind:text={index.map} label="Map" />
{:else if currentSnippetEditor === SNIPPET_EDITORS.FILTER}
<CodeArea bind:text={index.filter} label="Filter" />
{:else if currentSnippetEditor === SNIPPET_EDITORS.SHARD}
<CodeArea bind:text={index.getShardName} label="Shard Name" />
{/if}
</form>
@ -79,4 +114,13 @@
color: #333;
font-size: 0.875rem;
}
.snippet-selector__heading {
margin-right: 20px;
opacity: 0.7;
}
.highlighted {
opacity: 1;
}
</style>

View File

@ -1,6 +1,11 @@
<script>
import { store } from "../../builderStore"
import Select from "../../common/Select.svelte"
import { CreateEditRecordModal, DeleteRecordModal } from "./modals"
import ActionButton from "../../common/ActionButton.svelte"
import TablePagination from "./TablePagination.svelte"
import * as api from "./api"
import { getIndexSchema } from "../../common/core"
let pages = [1, 2, 3]
@ -10,14 +15,31 @@
{ name: "Martin", inStock: true },
]
export let headers = ["name", "inStock"]
export let pageSize = 10
// export let pageSize = 10
let selectedView = ""
let modalOpen = false
let deleteRecordModal = false
$: indexes = $store.hierarchy.indexes
const getSchema = getIndexSchema($store.hierarchy)
</script>
<CreateEditRecordModal bind:modalOpen />
<DeleteRecordModal modalOpen={deleteRecordModal} />
<section>
<h4 class="budibase__title--3">Shoe database</h4>
<div class="table-controls">
<Select />
<ActionButton primary>Create new record</ActionButton>
<h4 class="budibase__title--3">Shoe database</h4>
<Select
icon="ri-eye-line"
on:change={e => api.fetchDataForView(e.target.value)}>
{#each indexes as index}
({console.log(getSchema(index))})
<option value={index.name}>{index.name}</option>
{/each}
</Select>
</div>
<table class="uk-table">
<thead>
@ -32,7 +54,25 @@
{#each data as row}
<tr>
<td>
<i class="ri-more-line" />
<div class="uk-inline">
<i class="ri-more-line" />
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav">
<li>
<div>View</div>
</li>
<li>
<div on:click={() => (modalOpen = true)}>Edit</div>
</li>
<li>
<div on:click={() => (deleteRecordModal = true)}>Delete</div>
</li>
<li>
<div>Duplicate</div>
</li>
</ul>
</div>
</div>
</td>
{#each headers as header}
<td>{row[header]}</td>
@ -41,13 +81,7 @@
{/each}
</tbody>
</table>
<div class="pagination">
<button>Previous</button>
<button>Next</button>
<!-- {#each data as page}
<button>{page}</button>
{/each} -->
</div>
<TablePagination {data} />
</section>
<style>
@ -76,4 +110,8 @@
justify-content: space-between;
align-items: center;
}
.ri-more-line:hover, .uk-dropdown-nav li:hover{
cursor: pointer;
}
</style>

View File

@ -0,0 +1,44 @@
<script>
export let data = []
</script>
<div class="pagination">
<div class="pagination__buttons">
<button>Previous</button>
<button>Next</button>
{#each data as page, idx}
<button>{idx + 1}</button>
{/each}
</div>
<p>Showing 10 (hardcoded, update this) of {data.length} entries</p>
</div>
<style>
.pagination {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.pagination__buttons button {
display: inline-block;
padding: 10px;
margin: 0;
background: #fff;
border: 1px solid #ccc;
text-transform: capitalize;
border-radius: 5px;
font-family: Roboto;
min-width: 20px;
}
.pagination__buttons button:hover {
cursor: pointer;
}
.ri-more-line:hover {
cursor: pointer;
}
</style>

View File

@ -0,0 +1,24 @@
import api from "../../builderStore/api";
export async function deleteRecord(appName, appInstanceId, record) {
const DELETE_RECORDS_URL = `/_builder/instance/${appName}/${appInstanceId}/api/record/${record.name}/${record.id}`
const response = await api.delete({
url: DELETE_RECORDS_URL
});
}
export async function createNewRecord(record) {
console.log(record);
}
export async function fetchDataForView(viewName) {
console.log(viewName);
// const FETCH_RECORDS_URL = `/_builder/instance/${}/${}/api/listRecords/`
// const response = await api.get({ url: FETCH_RECORDS_URL });
// console.log(response);
// GET /_builder/instance/:appname/:instanceid/api/listRecords/contacts/abcd1234/all_deals
}

View File

@ -0,0 +1,23 @@
<script>
import Modal from "../../common/Modal.svelte"
import ActionButton from "../../common/ActionButton.svelte"
import * as api from "./api"
export let modalOpen = false
let recordInfo = {}
const onClosed = () => (modalOpen = false)
</script>
<Modal {onClosed} bind:isOpen={modalOpen} title={"Create / Edit Field"}>
<div class="actions">
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
<ActionButton
disabled={false}
on:click={() => api.createNewRecord(recordInfo)}>
Save
</ActionButton>
</div>
</Modal>

View File

@ -0,0 +1,23 @@
<script>
import Modal from "../../common/Modal.svelte"
import ActionButton from "../../common/ActionButton.svelte"
import * as api from "./api"
export let modalOpen = false
let recordInfo = {}
const onClosed = () => (modalOpen = false)
</script>
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
<h4 class="budibase__title--4">Create / Edit Record</h4>
<div class="actions">
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
<ActionButton
disabled={false}
on:click={() => api.createNewRecord(recordInfo)}>
Save
</ActionButton>
</div>
</Modal>

View File

@ -0,0 +1,60 @@
<script>
import Modal from "../../../common/Modal.svelte"
import ActionButton from "../../../common/ActionButton.svelte"
import * as api from "../api"
export let modalOpen = false
export let model = {}
const onClosed = () => (modalOpen = false)
</script>
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
<h4 class="budibase__title--4">Create / Edit Record</h4>
<div class="actions">
<form>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-text">Text</label>
<div class="uk-form-controls">
<input
class="uk-input"
id="form-stacked-text"
type="text"
placeholder="Some text..." />
</div>
</div>
<div class="uk-margin">
<label class="uk-form-label" for="form-stacked-select">Select</label>
<div class="uk-form-controls">
<select class="uk-select" id="form-stacked-select">
<option>Option 01</option>
<option>Option 02</option>
</select>
</div>
</div>
<div class="uk-margin">
<div class="uk-form-label">Radio</div>
<div class="uk-form-controls">
<label>
<input class="uk-radio" type="radio" name="radio1" />
Option 01
</label>
<br />
<label>
<input class="uk-radio" type="radio" name="radio1" />
Option 02
</label>
</div>
</div>
</form>
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
<ActionButton
disabled={false}
on:click={() => api.createNewRecord(recordInfo)}>
Save
</ActionButton>
</div>
</Modal>

View File

@ -0,0 +1,23 @@
<script>
import Modal from "../../common/Modal.svelte"
import ActionButton from "../../common/ActionButton.svelte"
import * as api from "./api"
export let modalOpen = false
let recordInfo = {}
const onClosed = () => (modalOpen = false)
</script>
<Modal {onClosed} bind:isOpen={modalOpen} title={'Record'}>
<div class="actions">
<ActionButton alert on:click={onClosed}>Cancel</ActionButton>
<ActionButton
disabled={false}
on:click={() => api.createNewRecord(recordInfo)}>
Save
</ActionButton>
</div>
</Modal>

View File

@ -0,0 +1,24 @@
<script>
import Modal from "../../../common/Modal.svelte"
import ActionButton from "../../../common/ActionButton.svelte"
import * as api from "../api"
export let modalOpen = false
let recordInfo = {}
const onClosed = () => (modalOpen = false)
</script>
<Modal {onClosed} bind:isOpen={modalOpen} title={"Delete Record?"}>
<h4 class="budibase__title--4">Delete Record</h4>
Are you sure you want to delete this record? All of your data will be permanently removed. This action cannot be undone.
<div class="modal-actions">
<ActionButton on:click={onClosed}>Cancel</ActionButton>
<ActionButton
alert
on:click={() => api.deleteRecord(recordInfo)}>
Delete
</ActionButton>
</div>
</Modal>

View File

@ -0,0 +1,2 @@
export { default as DeleteRecordModal } from "./DeleteRecord.svelte";
export { default as CreateEditRecordModal } from "./CreateEditRecord.svelte";

View File

@ -24,11 +24,14 @@
record = $store.currentNode
const flattened = h.getFlattenedHierarchy($store.hierarchy)
getIndexAllowedRecords = index =>
pipe(index.allowedRecordNodeIds, [
filter(id => some(n => n.nodeId === id)(flattened)),
map(id => find(n => n.nodeId === id)(flattened).name),
join(", "),
])
pipe(
index.allowedRecordNodeIds,
[
filter(id => some(n => n.nodeId === id)(flattened)),
map(id => find(n => n.nodeId === id)(flattened).name),
join(", "),
]
)
newField = () => {
isNewField = true
@ -72,16 +75,19 @@
}
let getTypeOptions = typeOptions =>
pipe(typeOptions, [
keys,
map(
k =>
`<span style="color:var(--slate)">${k}: </span>${getTypeOptionsValueText(
typeOptions[k]
)}`
),
join("<br>"),
])
pipe(
typeOptions,
[
keys,
map(
k =>
`<span style="color:var(--slate)">${k}: </span>${getTypeOptionsValueText(
typeOptions[k]
)}`
),
join("<br>"),
]
)
const nameChanged = ev => {
const pluralName = n => `${n}s`
@ -93,68 +99,78 @@
<div class="root">
<form class="uk-form-horizontal">
<h3 class="budibase__title--3">Settings</h3>
<form class="uk-form-stacked">
<h3 class="budibase__title--3">
<i class="ri-list-settings-line" />
Create / Edit Model
</h3>
<Textbox label="Name:" bind:text={record.name} on:change={nameChanged} />
<h3 class="budibase__label--big">Settings</h3>
<Textbox label="Name" bind:text={record.name} on:change={nameChanged} />
{#if !record.isSingle}
<Textbox label="Collection Name:" bind:text={record.collectionName} />
<Textbox label="Collection Name" bind:text={record.collectionName} />
<Textbox
label="Estimated Record Count:"
label="Estimated Record Count"
bind:text={record.estimatedRecordCount} />
{/if}
<div class="recordkey">{record.nodeKey()}</div>
</form>
<h3 class="budibase__title--3">
<div class="table-controls">
<span class="budibase__label--big">Fields</span>
<h4 class="hoverable" on:click={newField}>Add new field</h4>
</div>
<!-- <h3 class="budibase__label--big">
Fields
<span class="add-field-button" on:click={newField}>
{@html getIcon('plus')}
</span>
</h3>
</h3> -->
{#if record.fields.length > 0}
<table class="fields-table uk-table">
<thead>
<table class="fields-table uk-table budibase__table">
<thead>
<tr>
<th>Edit</th>
<th>Name</th>
<th>Type</th>
<th>Values</th>
<th />
</tr>
</thead>
<tbody>
{#each record.fields as field}
<tr>
<th>Name</th>
<th>Type</th>
<th>Options</th>
<th />
<td>
<i class="ri-more-line" on:click={() => editField(field)} />
</td>
<td>
<div>{field.name}</div>
</td>
<td>{field.type}</td>
<td>({console.log(field.typeOptions)}) {field.typeOptions.values}</td>
<td>
<!-- <span class="edit-button" on:click={() => editField(field)}>
{@html getIcon('edit')}
</span> -->
<span class="edit-button" on:click={() => deleteField(field)}>
{@html getIcon('trash')}
</span>
</td>
</tr>
</thead>
<tbody>
{#each record.fields as field}
<tr>
<td>
<div class="field-label">{field.label}</div>
<div style="font-size: 0.8em; color: var(--slate)">
{field.name}
</div>
</td>
<td>{field.type}</td>
<td>
{@html getTypeOptions(field.typeOptions)}
</td>
<td>
<span class="edit-button" on:click={() => editField(field)}>
{@html getIcon('edit')}
</span>
<span class="edit-button" on:click={() => deleteField(field)}>
{@html getIcon('trash')}
</span>
</td>
</tr>
{/each}
</tbody>
</table>
{:else}(no fields added){/if}
{/each}
</tbody>
</table>
{#if editingField}
<Modal
title="Manage Index Fields"
bind:isOpen={editingField}
onClosed={() => onFinishedFieldEdit(false)}>
<h3 class="budibase__title--3">
<i class="ri-file-list-line" />
Create / Edit Field
</h3>
<FieldView
field={fieldToEdit}
onFinished={onFinishedFieldEdit}
@ -163,9 +179,9 @@
</Modal>
{/if}
<h3 class="budibase__title--3">Indexes</h3>
<!-- <h3 class="budibase__title--3">Indexes</h3> -->
{#each record.indexes as index}
<!-- {#each record.indexes as index}
<div class="index-container">
<div class="index-name">
{index.name}
@ -192,7 +208,7 @@
</div>
{:else}
<div class="no-indexes">No indexes added.</div>
{/each}
{/each} -->
</div>
@ -213,10 +229,6 @@
border-collapse: collapse;
}
.add-field-button {
cursor: pointer;
}
.edit-button {
cursor: pointer;
color: var(--secondary25);
@ -227,35 +239,6 @@
color: var(--secondary75);
}
th {
text-align: left;
}
td {
padding: 1rem 5rem 1rem 0rem;
margin: 0;
font-size: 14px;
font-weight: 500;
}
.field-label {
font-size: 14px;
font-weight: 500;
}
thead > tr {
border-width: 0px 0px 1px 0px;
border-style: solid;
border-color: var(--secondary75);
margin-bottom: 20px;
}
tbody > tr {
border-width: 0px 0px 1px 0px;
border-style: solid;
border-color: var(--primary10);
}
tbody > tr:hover {
background-color: var(--primary10);
}
@ -264,38 +247,17 @@
color: var(--secondary75);
}
.index-container {
border-style: solid;
border-width: 0 0 1px 0;
border-color: var(--secondary25);
padding: 10px;
margin-bottom: 5px;
.table-controls {
display: flex;
justify-content: space-between;
align-items: center;
}
.index-label {
color: var(--slate);
.ri-more-line:hover {
cursor: pointer;
}
.index-name {
font-weight: bold;
color: var(--primary100);
}
.index-container code {
h4 {
margin: 0;
display: inline;
background-color: var(--primary10);
color: var(--secondary100);
padding: 3px;
}
.index-field-row {
margin: 1rem 0rem 0rem 0rem;
}
.no-indexes {
margin: 1rem 0rem 0rem 0rem;
font-family: var(--fontnormal);
font-size: 14px;
}
</style>

View File

@ -102,4 +102,8 @@ h5 {
font-family: var(--fontblack);
font-size: 12pt;
color: var(--darkslate);
}
.hoverable:hover {
cursor: pointer;
}

View File

@ -15,5 +15,5 @@ import "codemirror/theme/monokai.css"
/* eslint-disable */
const app = new App({
target: document.getElementById("app"),
target: document.getElementById("app")
})

View File

@ -1,5 +1,5 @@
<script>
import { setContext } from "svelte"
import { getContext } from "svelte"
import { store } from "../builderStore"
import HierarchyRow from "./HierarchyRow.svelte"
import DatabasesList from "./DatabasesList.svelte"
@ -35,7 +35,7 @@
// let newChildActions = defaultNewChildActions
const setActiveNav = name => () => setContext("activeNav", name)
const setActiveNav = name => () => getContext("navigation").setActiveNav(name);
// store.subscribe(db => {
// if (!db.currentNode || hierarchyFunctions.isIndex(db.currentNode)) {

View File

@ -1,9 +1,18 @@
<script>
import { navigate } from "svelte-routing"
import { store } from "../builderStore"
import getIcon from "../common/icon"
import { CheckIcon } from "../common/Icons"
$: instances = $store.appInstances
function selectDatabase(databaseId) {
store.update(state => {
state.currentlySelectedDatabase = databaseId
return state
})
navigate("/database", { replace: true })
}
</script>
<div class="root">
@ -11,14 +20,14 @@
{#each $store.appInstances as { id, name }}
<li>
<span class="icon">
{#if id === $store.currentPageName}
{#if id === $store.currentlySelectedDatabase}
<CheckIcon />
{/if}
</span>
<button
class:active={id === $store.currentPageName}
on:click={() => store.setCurrentPage(id)}>
class:active={id === $store.currentlySelectedDatabase}
on:click={() => selectDatabase(id)}>
{name}
</button>
</li>

View File

@ -16,8 +16,7 @@
store.subscribe(state => {
if (state.currentNode) {
navActive =
getContext("activeNav") === "database" && node.nodeId === state.currentNode.nodeId
navActive = node.nodeId === state.currentNode.nodeId
}
})
</script>

View File

@ -70,7 +70,19 @@
<div class="components-list-container">
<div class="nav-group-header">
<div class="hierarchy-title">Schema</div>
<DropdownButton iconName="plus" actions={newChildActions} />
<div class="uk-inline">
<i class="ri-add-line" />
<div uk-dropdown="mode: click">
<ul class="uk-nav uk-dropdown-nav">
<li>
Model
</li>
<li>
View
</li>
</ul>
</div>
</div>
</div>
</div>

View File

@ -44,7 +44,7 @@ export const generateSchema = (hierarchy, indexNode) => {
keys,
map(k => ({ name: k, type: schema[k].name })),
filter(s => s.name !== "sortKey"),
orderBy("name", ["desc"]), // reverse aplha
orderBy("name", ["desc"]), // reverse alpha
concat([{ name: "sortKey", type: all.string.name }]), // sortKey on end
reverse, // sortKey first, then rest are alphabetical
])