Merge remote-tracking branch 'origin/master' into mike-fixes

This commit is contained in:
Michael Shanks 2020-10-15 09:18:04 +01:00
commit 8f0be4c44c
20 changed files with 325 additions and 196 deletions

View File

@ -27,6 +27,8 @@ context("Create a Table", () => {
cy.get(".actions input")
.first()
.type("updated")
// Unset table display column
cy.contains("display column").click()
cy.contains("Save Column").click()
cy.contains("nameupdated").should("have.text", "nameupdated")
})

View File

@ -87,6 +87,8 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
cy.get("input")
.first()
.type(columnName)
// Unset table display column
cy.contains("display column").click()
cy.get("select").select(type)
cy.contains("Save").click()
})

View File

@ -91,10 +91,11 @@ export const getBackendUiStore = () => {
return state
})
},
saveField: ({ originalName, field }) => {
saveField: ({ originalName, field, primaryDisplay = false }) => {
store.update(state => {
// delete the original if renaming
if (originalName) {
// need to handle if the column had no name, empty string
if (originalName || originalName === "") {
delete state.draftTable.schema[originalName]
state.draftTable._rename = {
old: originalName,
@ -102,8 +103,12 @@ export const getBackendUiStore = () => {
}
}
state.draftTable.schema[field.name] = cloneDeep(field)
// Optionally set display column
if (primaryDisplay) {
state.draftTable.primaryDisplay = field.name
}
state.draftTable.schema[field.name] = cloneDeep(field)
store.actions.tables.save(state.draftTable)
return state
})

View File

@ -33,7 +33,7 @@
function deleteColumn() {
if (field.name === $backendUiStore.selectedTable.primaryDisplay) {
notifier.danger("You cannot delete the primary display column")
notifier.danger("You cannot delete the display column")
} else {
backendUiStore.actions.tables.deleteField(field)
notifier.success("Column deleted")
@ -43,7 +43,11 @@
function sort(direction, column) {
backendUiStore.update(state => {
state.sort = { direction, column }
if (direction !== "none") {
state.sort = { direction, column }
} else {
state.sort = undefined
}
return state
})
hideEditor()
@ -70,6 +74,12 @@
<Icon name="delete" />
Delete
</li>
{#if sortDirection === 'desc' || sortDirection === 'asc'}
<li on:click={() => sort('none', field.name)}>
<Icon name="close" />
Remove sort
</li>
{/if}
{#if sortDirection === 'desc' || sortColumn !== field.name}
<li on:click={() => sort('asc', field.name)}>
<Icon name="sortascending" />

View File

@ -28,9 +28,15 @@
export let field = {
type: "string",
constraints: fieldDefinitions.STRING.constraints,
// Initial value for column name in other table for linked records
fieldName: $backendUiStore.selectedTable.name,
}
let originalName = field.name
let primaryDisplay =
$backendUiStore.selectedTable.primaryDisplay == null ||
$backendUiStore.selectedTable.primaryDisplay === field.name
$: tableOptions = $backendUiStore.tables.filter(
table => table._id !== $backendUiStore.draftTable._id
)
@ -41,6 +47,7 @@
backendUiStore.actions.tables.saveField({
originalName,
field,
primaryDisplay,
})
return state
})
@ -86,6 +93,13 @@
text="Required" />
{/if}
{#if field.type !== 'link'}
<Toggle
bind:checked={primaryDisplay}
thin
text="Use as table display column" />
{/if}
{#if field.type === 'string'}
<Input
thin

View File

@ -78,16 +78,6 @@
bind:value={table.name}
on:input={checkValid}
{error} />
<Select
label="Primary Display Column"
thin
secondary
bind:value={table.primaryDisplay}>
<option value="">Choose an option</option>
{#each fields as field}
<option value={field}>{field}</option>
{/each}
</Select>
<footer>
<Button secondary on:click={hideEditor}>Cancel</Button>
<Button primary disabled={error} on:click={save}>Save</Button>

View File

@ -36,7 +36,7 @@
{#if linkedTable.primaryDisplay == null}
<Label extraSmall grey>{label}</Label>
<Label small black>
Please choose a primary display column for the
Please choose a display column for the
<b>{linkedTable.name}</b>
table.
</Label>

View File

@ -20,7 +20,7 @@ export default `<html>
border-style: dashed !important;
border-width: 1px;
color: #000000;
background: #fafafa;
background-color: rgba(0, 0, 0, 0.05);
flex: 1 1 auto;
}
.container-screenslot-placeholder span {

View File

@ -95,7 +95,6 @@
onChange={onScreenPropChange}
props={{ ...excludeProps(def, ['control', 'label']) }} />
{/each}
<hr />
{/if}
{#if displayNameField}

View File

@ -523,6 +523,31 @@ export const background = [
label: "Plum Plate",
value: "linear-gradient(135deg, #667eea 0%, #764ba2 100%);",
},
{
label: "Peach Kiss",
value:
"radial-gradient(circle farthest-corner at 50% 100%,rgba(255,173,138,.50), rgba(255,248,247,1) 100%);",
},
{
label: "Flamingo Sunrise",
value:
"-webkit-radial-gradient(center top, rgb(255, 250, 245), rgb(255, 242, 242))",
},
{
label: "Budi Mist",
value:
"radial-gradient(circle, rgba(252,215,212,1) 0%, rgba(255,227,214,1) 50%, rgba(207,218,255,1) 100%);",
},
{
label: "Ballet Slipper",
value:
"linear-gradient(135deg, rgba(252,215,212,1) 20%, rgba(207,218,255,1) 100%);",
},
{
label: "Black Noir",
value:
"linear-gradient(312deg, rgba(60,60,60,1) 0%, rgba(42,42,42,1) 100%);",
},
],
},
{

View File

@ -1190,12 +1190,7 @@ export default {
children: [],
properties: {
design: { ...all },
settings: [
{ label: "Logo URL", key: "logoUrl", control: Input },
{ label: "Title", key: "title", control: Input },
{ label: "Color", key: "color", control: Input },
{ label: "Background", key: "backgroundColor", control: Input },
],
settings: [{ label: "Logo URL", key: "logoUrl", control: Input }],
},
},
{

View File

@ -4,17 +4,20 @@ import { parseAppIdFromCookie } from "./getAppId"
export const screenRouter = ({ screens, onScreenSelected, window }) => {
const makeRootedPath = url => {
if (
window.location &&
(window.location.hostname === "localhost" ||
window.location.hostname === "127.0.0.1")
) {
const appId = parseAppIdFromCookie(window.document.cookie)
if (url) {
if (url.startsWith(appId)) return url
return `/${appId}${url.startsWith("/") ? "" : "/"}${url}`
const hostname = window.location && window.location.hostname
if (hostname) {
if (
hostname === "localhost" ||
hostname === "127.0.0.1" ||
hostname.startsWith("192.168")
) {
const appId = parseAppIdFromCookie(window.document.cookie)
if (url) {
if (url.startsWith(appId)) return url
return `/${appId}${url.startsWith("/") ? "" : "/"}${url}`
}
return appId
}
return appId
}
return url
}

View File

@ -36,14 +36,23 @@ exports.save = async function(ctx) {
let renameDocs = []
// if the table obj had an _id then it will have been retrieved
const oldTable = ctx.preExisting
let oldTable
if (ctx.request.body && ctx.request.body._id) {
oldTable = await db.get(ctx.request.body._id)
}
// Don't rename if the name is the same
let { _rename } = tableToSave
if (_rename && _rename.old === _rename.updated) {
_rename = null
delete tableToSave._rename
}
// rename row fields when table column is renamed
const { _rename } = tableToSave
if (_rename && tableToSave.schema[_rename.updated].type === "link") {
throw "Cannot rename a linked field."
} else if (_rename && tableToSave.primaryDisplay === _rename.old) {
throw "Cannot rename the primary display field."
throw "Cannot rename the display column."
} else if (_rename) {
const rows = await db.allDocs(
getRowParams(tableToSave._id, null, {

View File

@ -1,59 +1,97 @@
{
"componentLibraries": [
"@budibase/standard-components"
],
"title": "{{ name }}",
"favicon": "./_shared/favicon.png",
"stylesheets": [],
"componentLibraries": ["@budibase/standard-components"],
"props": {
"_id": "private-master-root",
"_component": "@budibase/standard-components/container",
"_children": [
{
"_id": "49e0e519-9e5e-4127-885a-ee6a0a49e2c1",
"_component": "@budibase/standard-components/Navigation",
"_id": "c74f07266980c4b6eafc33e2a6caa783d",
"_component": "@budibase/standard-components/container",
"_styles": {
"normal": {},
"normal": {
"display": "flex",
"flex-direction": "row",
"justify-content": "flex-start",
"align-items": "flex-start",
"background": "#fff",
"width": "100%"
},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"logoUrl": "http://acmelogos.com/images/logo-8.svg",
"title": "",
"backgroundColor": "",
"color": "",
"borderWidth": "",
"borderColor": "",
"borderStyle": "",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Navigation",
"className": "",
"onLoad": [],
"type": "div",
"_instanceId": "inst_app_80b_f158d4057d2c4bedb0042d42fda8abaf",
"_instanceName": "Header",
"_children": [
{
"_id": "48b35328-4c91-4343-a6a3-1a1fd77b3386",
"_component": "@budibase/standard-components/link",
"_id": "49e0e519-9e5e-4127-885a-ee6a0a49e2c1",
"_component": "@budibase/standard-components/Navigation",
"_styles": {
"normal": {
"font-family": "Inter",
"max-width": "1400px",
"margin-left": "auto",
"margin-right": "auto",
"padding": "20px",
"color": "#757575",
"font-weight": "400",
"color": "#000000",
"text-decoration-line": "none",
"font-size": "16px"
"font-size": "16px",
"flex": "1 1 auto"
},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"url": "/",
"openInNewTab": false,
"text": "Home",
"logoUrl": "https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg",
"title": "",
"backgroundColor": "",
"color": "",
"hoverColor": "",
"underline": false,
"fontSize": "",
"fontFamily": "initial",
"borderWidth": "",
"borderColor": "",
"borderStyle": "",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Home Link",
"_children": []
"_instanceName": "Navigation",
"_children": [
{
"_id": "48b35328-4c91-4343-a6a3-1a1fd77b3386",
"_component": "@budibase/standard-components/link",
"_styles": {
"normal": {
"font-family": "Inter",
"font-weight": "400",
"color": "#000000",
"text-decoration-line": "none",
"font-size": "16px"
},
"hover": {
"color": "#4285f4"
},
"active": {},
"selected": {}
},
"_code": "",
"url": "/",
"openInNewTab": false,
"text": "Home",
"color": "",
"hoverColor": "",
"underline": false,
"fontSize": "",
"fontFamily": "initial",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Home Link",
"_children": []
}
]
}
]
},
@ -66,7 +104,12 @@
"display": "flex",
"flex-direction": "column",
"justify-content": "flex-start",
"align-items": "stretch"
"align-items": "stretch",
"max-width": "100%",
"margin-left": "20px",
"margin-right": "20px",
"width": "1400px",
"padding": "20px"
},
"hover": {},
"active": {},
@ -83,11 +126,12 @@
"normal": {
"display": "flex",
"flex-direction": "column",
"align-items": "stretch",
"align-items": "center",
"justify-content": "flex-start",
"margin-right": "auto",
"margin-left": "auto",
"min-height": "100%"
"min-height": "100%",
"background-image": "linear-gradient(135deg, rgba(252,215,212,1) 20%, rgba(207,218,255,1) 100%);"
},
"selected": {}
},
@ -95,6 +139,5 @@
"className": "",
"onLoad": []
},
"_css": "",
"uiFunctions": ""
}

View File

@ -5,7 +5,13 @@
"_id": "d834fea2-1b3e-4320-ab34-f9009f5ecc59",
"_component": "@budibase/standard-components/container",
"_styles": {
"normal": {},
"normal": {
"flex": "1 1 auto",
"display": "flex",
"flex-direction": "column",
"justify-content": "flex-start",
"align-items": "stretch"
},
"hover": {},
"active": {},
"selected": {}
@ -18,40 +24,75 @@
{
"_id": "ef60083f-4a02-4df3-80f3-a0d3d16847e7",
"_component": "@budibase/standard-components/heading",
"_styles": {
"normal": {},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"className": "",
"text": "Home",
"type": "h1",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Heading",
"_children": []
},
{
"_id": "6c256e06-784c-4ac0-a644-ed2f9b91d459",
"_component": "@budibase/standard-components/image",
"_styles": {
"normal": {
"width": "100%"
"text-align": "left"
},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"url": "https://source.unsplash.com/Vun-71Vy2hc",
"className": "",
"description": "",
"height": "",
"width": "",
"text": "Welcome to your Budibase App 👋",
"type": "h2",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Image",
"_instanceName": "Heading",
"_children": []
},
{
"_id": "cbbf41b27c2b44d1abba38bb694880c6a",
"_component": "@budibase/standard-components/container",
"_styles": {
"normal": {
"display": "flex",
"flex-direction": "column",
"justify-content": "center",
"align-items": "stretch",
"flex": "1 1 auto",
"border-width": "4px",
"border-style": "Dashed",
"margin-bottom": "32px"
},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"className": "",
"onLoad": [],
"type": "div",
"_instanceId": "inst_app_2cc_ca3383f896034e9295345c05f7dfca0c",
"_instanceName": "Video Container",
"_children": [
{
"_id": "c07d752cb3e544b418088fa9be84ba2e4",
"_component": "@budibase/standard-components/embed",
"_styles": {
"normal": {
"width": "100%",
"flex": "1 1 auto",
"opacity": "0",
"transition-property": "Opacity",
"transition-duration": "1s",
"transition-timing-function:": "ease-in"
},
"hover": {
"transition-property": "Opacity",
"transition-duration": "1s",
"transition-timing-function:": "ease-out",
"opacity": "1"
},
"active": {},
"selected": {}
},
"_code": "",
"embed": "<iframe width=\"560\" height=\"315\" src=\"https://www.youtube.com/embed/dQw4w9WgXcQ\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen></iframe>",
"_instanceId": "inst_app_2cc_ca3383f896034e9295345c05f7dfca0c",
"_instanceName": "Rick Astley Video",
"_children": []
}
]
}
],
"_instanceName": "Home"

View File

@ -1,41 +0,0 @@
{
"description": "",
"url": "",
"_css": "",
"props": {
"_id": "f684460e-1f79-42b4-8ffd-1f708bca93ed",
"_component": "@budibase/standard-components/container",
"_styles": {
"normal": {},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"className": "",
"onLoad": [],
"type": "div",
"_children": [
{
"_id": "7d1d6b43-b444-46a5-a75c-267fd6b5baf6",
"_component": "@budibase/standard-components/heading",
"_styles": {
"normal": {},
"hover": {},
"active": {},
"selected": {}
},
"_code": "",
"className": "",
"text": "Screen1",
"type": "h1",
"_instanceId": "inst_cf8ace4_69efc0d72e6f443db2d4c902c14d9394",
"_instanceName": "Heading",
"_children": []
}
],
"_instanceName": "Screen 1"
},
"route": "/screen1",
"name": "f684460e-1f79-42b4-8ffd-1f708bca93ed"
}

View File

@ -1,5 +1,7 @@
{
"componentLibraries": ["@budibase/standard-components"],
"componentLibraries": [
"@budibase/standard-components"
],
"title": "{{ name }}",
"favicon": "./_shared/favicon.png",
"stylesheets": [],
@ -11,7 +13,19 @@
"_id": "686c252d-dbf2-4e28-9078-414ba4719759",
"_component": "@budibase/standard-components/login",
"_styles": {
"normal": {},
"normal": {
"padding": "64px",
"background": "rgba(255, 255, 255, 0.4)",
"border-radius": "0.5rem",
"margin-top": "0px",
"margin": "0px",
"line-height": "1",
"box-shadow": "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
"font-size": "16px",
"font-family": "Inter",
"flex": "0 1 auto",
"transform": "0"
},
"hover": {},
"active": {},
"selected": {}
@ -25,20 +39,30 @@
"_instanceName": "Login",
"inputClass": "",
"_children": [],
"title": "Login to {{ name }}",
"buttonText": "Login",
"logo": ""
"title": "Log in to {{ name }}",
"buttonText": "Log In",
"logo": "https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg"
}
],
"type": "div",
"_styles": {
"layout": {},
"position": {}
"active": {},
"hover": {},
"normal": {
"display": "flex",
"flex-direction": "column",
"align-items": "center",
"justify-content": "center",
"margin-right": "auto",
"margin-left": "auto",
"min-height": "100%",
"background-image": "linear-gradient(135deg, rgba(252,215,212,1) 20%, rgba(207,218,255,1) 100%);"
},
"selected": {}
},
"_code": "",
"className": "",
"onLoad": []
},
"_css": "",
"uiFunctions": ""
}

View File

@ -45,7 +45,7 @@
<Label extraSmall grey>{label}</Label>
{/if}
<Label small black>
Please choose a primary display column for the
Please choose a display column for the
<b>{linkedTable.name}</b>
table.
</Label>

View File

@ -1,7 +1,7 @@
<script>
import Button from "./Button.svelte"
export let buttonText = "Login"
export let buttonText = "Log In"
export let logo = ""
export let title = ""
export let buttonClass = ""
@ -46,7 +46,7 @@
{/if}
{#if title}
<h1 class="header-content">{title}</h1>
<h2 class="header-content">{title}</h2>
{/if}
<div class="form-root">
@ -69,7 +69,7 @@
<div class="login-button-container">
<button disabled={loading} on:click={login} class={_buttonClass}>
{buttonText || 'Login'}
{buttonText || 'Log In'}
</button>
</div>
@ -100,7 +100,9 @@
}
.logo-container > img {
height: 80px;
max-width: 200px;
margin-bottom: 20px;
}
.login-button-container {
@ -112,24 +114,24 @@
font-family: Inter;
font-weight: 700;
color: #1f1f1f;
font-size: 48px;
line-height: 72px;
margin-bottom: 30px;
font-size: 32px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
font-feature-settings: "case" "rlig" "calt" 0;
margin: 0 0 20px 0;
}
.incorrect-details-panel {
margin-top: 30px;
margin-top: 26px;
padding: 10px;
border-style: solid;
border-width: 1px;
border-color: maroon;
border-radius: 1px;
border-radius: 4px;
text-align: center;
color: maroon;
background-color: mistyrose;
align-self: stretch;
}
.form-root {

View File

@ -1,28 +1,11 @@
<script>
import { cssVars, createClasses } from "./cssVars"
export let className = ""
export let onLoad
export let backgroundColor
export let color
export let borderWidth
export let borderColor
export let borderStyle
export let logoUrl
export let title
export let _bb
export let title
let itemContainer
let hasLoaded
let currentChildren
$: cssVariables = {
backgroundColor,
color,
borderWidth,
borderColor,
borderStyle,
}
$: {
if (itemContainer) {
@ -33,46 +16,69 @@
}
}
}
const logOut = () => {
document.cookie =
"budibase:token=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT;"
location.reload()
}
</script>
<nav use:cssVars={cssVariables}>
{#if logoUrl}
<div class="nav">
<div class="nav__top">
<a href="/">
<img class="logo" alt="logo" src={logoUrl} height="48" />
<span>{title}</span>
{#if logoUrl}
<img class="logo" alt="logo" src={logoUrl} height="48" />
{/if}
{#if title}<span>{title}</span>{/if}
</a>
{:else}
<div />
{/if}
<div class="menu-items" bind:this={itemContainer} />
</nav>
<div class="nav__controls">
<div on:click={logOut}>Log out</div>
</div>
</div>
<div class="nav__menu" bind:this={itemContainer} />
</div>
<style>
nav {
color: var(--color);
background-color: var(--backgroundColor);
align-items: center;
.nav {
display: flex;
font-weight: bold;
flex-direction: column;
justify-content: flex-start;
align-items: stretch;
}
.nav__top {
display: flex;
flex-direction: row;
justify-content: space-between;
padding: 20px 0px;
}
nav > a {
display: flex;
align-items: center;
font-size: 1.5em;
color: var(--color);
text-decoration: none;
}
nav a img {
.nav__top img {
margin-right: 16px;
}
.menu-items {
.nav__controls {
display: flex;
flex-direction: row;
justify-content: flex-end;
align-items: center;
gap: 16px;
}
.menu-items > :global(*) {
margin: 0 10px;
.nav__controls > div:hover {
cursor: pointer;
color: #4285f4;
}
.nav__menu {
display: flex;
margin-top: 40px;
gap: 16px;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.nav__menu > a {
font-size: 1.5em;
text-decoration: none;
}
</style>