commit
7c870dcfbf
|
@ -155,9 +155,13 @@ Cypress.Commands.add("navigateToFrontend", () => {
|
||||||
Cypress.Commands.add("createScreen", (screenName, route) => {
|
Cypress.Commands.add("createScreen", (screenName, route) => {
|
||||||
cy.contains("Create New Screen").click()
|
cy.contains("Create New Screen").click()
|
||||||
cy.get(".modal").within(() => {
|
cy.get(".modal").within(() => {
|
||||||
cy.get("input:first").type(screenName)
|
cy.get("input")
|
||||||
|
.eq(0)
|
||||||
|
.type(screenName)
|
||||||
if (route) {
|
if (route) {
|
||||||
cy.get("input:last").type(route)
|
cy.get("input")
|
||||||
|
.eq(1)
|
||||||
|
.type(route)
|
||||||
}
|
}
|
||||||
cy.contains("Create Screen").click()
|
cy.contains("Create Screen").click()
|
||||||
})
|
})
|
||||||
|
|
|
@ -27,7 +27,9 @@ import {
|
||||||
regenerateCssForScreen,
|
regenerateCssForScreen,
|
||||||
generateNewIdsForComponent,
|
generateNewIdsForComponent,
|
||||||
getComponentDefinition,
|
getComponentDefinition,
|
||||||
|
findChildComponentType,
|
||||||
} from "../storeUtils"
|
} from "../storeUtils"
|
||||||
|
|
||||||
export const getStore = () => {
|
export const getStore = () => {
|
||||||
const initial = {
|
const initial = {
|
||||||
apps: [],
|
apps: [],
|
||||||
|
@ -56,6 +58,7 @@ export const getStore = () => {
|
||||||
store.setCurrentScreen = setCurrentScreen(store)
|
store.setCurrentScreen = setCurrentScreen(store)
|
||||||
store.deleteScreens = deleteScreens(store)
|
store.deleteScreens = deleteScreens(store)
|
||||||
store.setCurrentPage = setCurrentPage(store)
|
store.setCurrentPage = setCurrentPage(store)
|
||||||
|
store.createLink = createLink(store)
|
||||||
store.createScreen = createScreen(store)
|
store.createScreen = createScreen(store)
|
||||||
store.addStylesheet = addStylesheet(store)
|
store.addStylesheet = addStylesheet(store)
|
||||||
store.removeStylesheet = removeStylesheet(store)
|
store.removeStylesheet = removeStylesheet(store)
|
||||||
|
@ -190,6 +193,58 @@ const createScreen = store => async screen => {
|
||||||
await savePromise
|
await savePromise
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createLink = store => async (url, title) => {
|
||||||
|
let savePromise
|
||||||
|
store.update(state => {
|
||||||
|
// Try to extract a nav component from the master screen
|
||||||
|
const nav = findChildComponentType(
|
||||||
|
state.pages.main,
|
||||||
|
"@budibase/standard-components/Navigation"
|
||||||
|
)
|
||||||
|
if (nav) {
|
||||||
|
let newLink
|
||||||
|
|
||||||
|
// Clone an existing link if one exists
|
||||||
|
if (nav._children && nav._children.length) {
|
||||||
|
// Clone existing link style
|
||||||
|
newLink = cloneDeep(nav._children[0])
|
||||||
|
|
||||||
|
// Manipulate IDs to ensure uniqueness
|
||||||
|
generateNewIdsForComponent(newLink, state, false)
|
||||||
|
|
||||||
|
// Set our new props
|
||||||
|
newLink._instanceName = `${title} Link`
|
||||||
|
newLink.url = url
|
||||||
|
newLink.text = title
|
||||||
|
} else {
|
||||||
|
// Otherwise create vanilla new link
|
||||||
|
const component = getComponentDefinition(
|
||||||
|
state,
|
||||||
|
"@budibase/standard-components/link"
|
||||||
|
)
|
||||||
|
const instanceId = get(backendUiStore).selectedDatabase._id
|
||||||
|
newLink = createProps(component, {
|
||||||
|
url,
|
||||||
|
text: title,
|
||||||
|
_instanceName: `${title} Link`,
|
||||||
|
_instanceId: instanceId,
|
||||||
|
}).props
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save page and regenerate all CSS because otherwise weird things happen
|
||||||
|
nav._children = [...nav._children, newLink]
|
||||||
|
setCurrentPage("main")
|
||||||
|
regenerateCssForScreen(state.pages.main)
|
||||||
|
for (let screen of state.pages.main._screens) {
|
||||||
|
regenerateCssForScreen(screen)
|
||||||
|
}
|
||||||
|
savePromise = _savePage(state)
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
await savePromise
|
||||||
|
}
|
||||||
|
|
||||||
const setCurrentScreen = store => screenName => {
|
const setCurrentScreen = store => screenName => {
|
||||||
store.update(s => {
|
store.update(s => {
|
||||||
const screen = getExactComponent(s.screens, screenName, true)
|
const screen = getExactComponent(s.screens, screenName, true)
|
||||||
|
|
|
@ -84,7 +84,9 @@ export const regenerateCssForScreen = screen => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const regenerateCssForCurrentScreen = state => {
|
export const regenerateCssForCurrentScreen = state => {
|
||||||
|
if (state.currentPreviewItem) {
|
||||||
regenerateCssForScreen(state.currentPreviewItem)
|
regenerateCssForScreen(state.currentPreviewItem)
|
||||||
|
}
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,3 +98,33 @@ export const generateNewIdsForComponent = (c, state, changeName = true) =>
|
||||||
|
|
||||||
export const getComponentDefinition = (state, name) =>
|
export const getComponentDefinition = (state, name) =>
|
||||||
name.startsWith("##") ? getBuiltin(name) : state.components[name]
|
name.startsWith("##") ? getBuiltin(name) : state.components[name]
|
||||||
|
|
||||||
|
export const findChildComponentType = (node, typeToFind) => {
|
||||||
|
// Stop recursion if invalid props
|
||||||
|
if (!node || !typeToFind) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop recursion if this element matches
|
||||||
|
if (node._component === typeToFind) {
|
||||||
|
return node
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise check if any children match
|
||||||
|
// Stop recursion if no valid children to process
|
||||||
|
const children = node._children || (node.props && node.props._children)
|
||||||
|
if (!children || !children.length) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recurse and check each child component
|
||||||
|
for (let child of children) {
|
||||||
|
const childResult = findChildComponentType(child, typeToFind)
|
||||||
|
if (childResult) {
|
||||||
|
return childResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we reach here then no children were valid
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
|
@ -38,21 +38,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
async function saveTable() {
|
async function saveTable() {
|
||||||
|
// Create table
|
||||||
const table = await backendUiStore.actions.tables.save({
|
const table = await backendUiStore.actions.tables.save({
|
||||||
name,
|
name,
|
||||||
schema: dataImport.schema || {},
|
schema: dataImport.schema || {},
|
||||||
dataImport,
|
dataImport,
|
||||||
})
|
})
|
||||||
notifier.success(`Table ${name} created successfully.`)
|
notifier.success(`Table ${name} created successfully.`)
|
||||||
$goto(`./table/${table._id}`)
|
|
||||||
analytics.captureEvent("Table Created", { name })
|
analytics.captureEvent("Table Created", { name })
|
||||||
|
|
||||||
|
// Create auto screens
|
||||||
const screens = screenTemplates($store, [table])
|
const screens = screenTemplates($store, [table])
|
||||||
.filter(template => defaultScreens.includes(template.id))
|
.filter(template => defaultScreens.includes(template.id))
|
||||||
.map(template => template.create())
|
.map(template => template.create())
|
||||||
|
|
||||||
for (let screen of screens) {
|
for (let screen of screens) {
|
||||||
// record the table that created this screen so we can link it later
|
// Record the table that created this screen so we can link it later
|
||||||
screen.autoTableId = table._id
|
screen.autoTableId = table._id
|
||||||
try {
|
try {
|
||||||
await store.createScreen(screen)
|
await store.createScreen(screen)
|
||||||
|
@ -65,6 +65,15 @@
|
||||||
// we should remove this after this has been released
|
// we should remove this after this has been released
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create autolink to newly created list page
|
||||||
|
const listPage = screens.find(screen =>
|
||||||
|
screen.props._instanceName.endsWith("List")
|
||||||
|
)
|
||||||
|
await store.createLink(listPage.route, table.name)
|
||||||
|
|
||||||
|
// Navigate to new table
|
||||||
|
$goto(`./table/${table._id}`)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
<script>
|
<script>
|
||||||
import { goto } from "@sveltech/routify"
|
import { goto } from "@sveltech/routify"
|
||||||
import { store, backendUiStore } from "builderStore"
|
import { store, backendUiStore } from "builderStore"
|
||||||
import { Input, Button, Spacer, Select, ModalContent } from "@budibase/bbui"
|
import {
|
||||||
|
Input,
|
||||||
|
Button,
|
||||||
|
Spacer,
|
||||||
|
Select,
|
||||||
|
ModalContent,
|
||||||
|
Toggle,
|
||||||
|
} from "@budibase/bbui"
|
||||||
import getTemplates from "builderStore/store/screenTemplates"
|
import getTemplates from "builderStore/store/screenTemplates"
|
||||||
import { some } from "lodash/fp"
|
import { some } from "lodash/fp"
|
||||||
import analytics from "analytics"
|
import analytics from "analytics"
|
||||||
|
@ -13,6 +20,7 @@
|
||||||
let baseComponent = CONTAINER
|
let baseComponent = CONTAINER
|
||||||
let templateIndex
|
let templateIndex
|
||||||
let draftScreen
|
let draftScreen
|
||||||
|
let createLink = true
|
||||||
|
|
||||||
$: templates = getTemplates($store, $backendUiStore.tables)
|
$: templates = getTemplates($store, $backendUiStore.tables)
|
||||||
|
|
||||||
|
@ -46,7 +54,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const save = () => {
|
const save = async () => {
|
||||||
if (!route) {
|
if (!route) {
|
||||||
routeError = "Url is required"
|
routeError = "Url is required"
|
||||||
} else {
|
} else {
|
||||||
|
@ -63,7 +71,10 @@
|
||||||
draftScreen.props._component = baseComponent
|
draftScreen.props._component = baseComponent
|
||||||
draftScreen.route = route
|
draftScreen.route = route
|
||||||
|
|
||||||
store.createScreen(draftScreen)
|
await store.createScreen(draftScreen)
|
||||||
|
if (createLink) {
|
||||||
|
await store.createLink(route, name)
|
||||||
|
}
|
||||||
|
|
||||||
if (templateIndex !== undefined) {
|
if (templateIndex !== undefined) {
|
||||||
const template = templates[templateIndex]
|
const template = templates[templateIndex]
|
||||||
|
@ -108,4 +119,6 @@
|
||||||
error={routeError}
|
error={routeError}
|
||||||
bind:value={route}
|
bind:value={route}
|
||||||
on:change={routeChanged} />
|
on:change={routeChanged} />
|
||||||
|
|
||||||
|
<Toggle text="Create link in navigation bar" bind:checked={createLink} />
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
import { params, leftover } from "@sveltech/routify"
|
import { params, leftover, goto } from "@sveltech/routify"
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
|
|
||||||
// Get any leftover params not caught by Routifys params store.
|
// Get any leftover params not caught by Routifys params store.
|
||||||
|
@ -8,7 +8,19 @@
|
||||||
|
|
||||||
// It's a screen, set it to that screen
|
// It's a screen, set it to that screen
|
||||||
if ($params.screen !== "page-layout") {
|
if ($params.screen !== "page-layout") {
|
||||||
store.setCurrentScreen(decodeURI($params.screen))
|
const currentScreenName = decodeURI($params.screen)
|
||||||
|
const validScreen =
|
||||||
|
$store.screens.findIndex(
|
||||||
|
screen => screen.props._instanceName === currentScreenName
|
||||||
|
) !== -1
|
||||||
|
|
||||||
|
if (!validScreen) {
|
||||||
|
// Go to main layout if URL set to invalid screen
|
||||||
|
store.setCurrentPage("main")
|
||||||
|
$goto("../../main")
|
||||||
|
} else {
|
||||||
|
// Otherwise proceed to set screen
|
||||||
|
store.setCurrentScreen(currentScreenName)
|
||||||
|
|
||||||
// There are leftover stuff, like IDs, so navigate the components and find the ID and select it.
|
// There are leftover stuff, like IDs, so navigate the components and find the ID and select it.
|
||||||
if ($leftover) {
|
if ($leftover) {
|
||||||
|
@ -20,6 +32,7 @@
|
||||||
).props._children
|
).props._children
|
||||||
findComponent(componentIds, screenChildren)
|
findComponent(componentIds, screenChildren)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// It's a page, so set the screentype to page.
|
// It's a page, so set the screentype to page.
|
||||||
store.setScreenType("page")
|
store.setScreenType("page")
|
||||||
|
|
Loading…
Reference in New Issue