Instance naming fix for components and screens
This commit is contained in:
parent
6cf34a4ad8
commit
c1e9133424
|
@ -70,6 +70,7 @@ export const getStore = () => {
|
|||
store.getPathToComponent = getPathToComponent(store)
|
||||
store.addTemplatedComponent = addTemplatedComponent(store)
|
||||
store.setMetadataProp = setMetadataProp(store)
|
||||
store.editPageOrScreen = editPageOrScreen(store)
|
||||
return store
|
||||
}
|
||||
|
||||
|
@ -159,7 +160,6 @@ const createScreen = store => (screenName, route, layoutComponentName) => {
|
|||
_css: "",
|
||||
props: createProps(rootComponent).props,
|
||||
}
|
||||
|
||||
newScreen.route = route
|
||||
newScreen.props._instanceName = screenName || ""
|
||||
state.currentPreviewItem = newScreen
|
||||
|
@ -174,7 +174,7 @@ const createScreen = store => (screenName, route, layoutComponentName) => {
|
|||
|
||||
const setCurrentScreen = store => screenName => {
|
||||
store.update(s => {
|
||||
const screen = getExactComponent(s.screens, screenName)
|
||||
const screen = getExactComponent(s.screens, screenName, true)
|
||||
s.currentPreviewItem = screen
|
||||
s.currentFrontEndType = "screen"
|
||||
s.currentView = "detail"
|
||||
|
@ -245,6 +245,7 @@ const setCurrentPage = store => pageName => {
|
|||
const currentPage = state.pages[pageName]
|
||||
|
||||
state.currentFrontEndType = "page"
|
||||
state.currentView = "detail"
|
||||
state.currentPageName = pageName
|
||||
state.screens = Array.isArray(current_screens)
|
||||
? current_screens
|
||||
|
@ -365,12 +366,12 @@ const setComponentProp = store => (name, value) => {
|
|||
|
||||
const setPageOrScreenProp = store => (name, value) => {
|
||||
store.update(state => {
|
||||
if (name === "name" && state.currentFrontEndType === "screen") {
|
||||
state = renameCurrentScreen(value, state)
|
||||
if (name === "_instanceName" && state.currentFrontEndType === "screen") {
|
||||
state.currentPreviewItem.props[name] = value
|
||||
} else {
|
||||
state.currentPreviewItem[name] = value
|
||||
_saveCurrentPreviewItem(state)
|
||||
}
|
||||
_saveCurrentPreviewItem(state)
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
@ -420,6 +421,18 @@ const setScreenType = store => type => {
|
|||
|
||||
state.currentComponentInfo = pageOrScreen ? pageOrScreen.props : null
|
||||
state.currentPreviewItem = pageOrScreen
|
||||
state.currentView = "detail"
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
||||
const editPageOrScreen = store => (key, value, setOnComponent = false) => {
|
||||
store.update(state => {
|
||||
setOnComponent
|
||||
? (state.currentPreviewItem.props[key] = value)
|
||||
: (state.currentPreviewItem[key] = value)
|
||||
_saveCurrentPreviewItem(state)
|
||||
|
||||
return state
|
||||
})
|
||||
}
|
||||
|
|
|
@ -46,8 +46,9 @@ export const saveScreenApi = (screen, s) => {
|
|||
}
|
||||
|
||||
export const renameCurrentScreen = (newname, state) => {
|
||||
const oldname = state.currentPreviewItem.name
|
||||
state.currentPreviewItem.name = newname
|
||||
const oldname = state.currentPreviewItem.props._instanceName
|
||||
state.currentPreviewItem.props._instanceName = newname
|
||||
|
||||
api.patch(
|
||||
`/_builder/api/${state.appId}/pages/${state.currentPageName}/screen`,
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { setContext, onMount } from "svelte"
|
||||
import PropsView from "./PropsView.svelte"
|
||||
|
||||
import { store } from "builderStore"
|
||||
import IconButton from "components/common/IconButton.svelte"
|
||||
import {
|
||||
|
@ -29,7 +30,7 @@
|
|||
let selectedCategory = categories[0]
|
||||
|
||||
$: components = $store.components
|
||||
$: componentInstance = $store.currentComponentInfo
|
||||
$: componentInstance = $store.currentView !== "component" ? {...$store.currentPreviewItem, ...$store.currentComponentInfo} : $store.currentComponentInfo
|
||||
$: componentDefinition = $store.components[componentInstance._component]
|
||||
$: componentPropDefinition =
|
||||
flattenedPanel.find(
|
||||
|
@ -43,9 +44,16 @@
|
|||
componentPropDefinition.properties[selectedCategory.value]
|
||||
|
||||
const onStyleChanged = store.setComponentStyle
|
||||
const onPropChanged = store.setComponentProp
|
||||
|
||||
$: displayName = $store.currentFrontEndType === "screen" && componentInstance._instanceName
|
||||
function onPropChanged(key, value) {
|
||||
if($store.currentView !== "component") {
|
||||
store.setPageOrScreenProp(key, value)
|
||||
return
|
||||
}
|
||||
store.setComponentProp(key, value)
|
||||
}
|
||||
|
||||
$: displayName = ( $store.currentView === "component" || $store.currentFrontEndType === "screen") && componentInstance._instanceName && componentInstance._component !== "##builtin/screenslot"
|
||||
|
||||
function walkProps(component, action) {
|
||||
action(component)
|
||||
|
@ -95,8 +103,7 @@
|
|||
{componentDefinition}
|
||||
{panelDefinition}
|
||||
displayNameField={displayName}
|
||||
onChange={onPropChanged} />
|
||||
onScreenPropChange={store.setPageOrScreenProp}
|
||||
onChange={onPropChanged}
|
||||
screenOrPageInstance={$store.currentView !== "component" && $store.currentPreviewItem} />
|
||||
{:else if selectedCategory.value === 'events'}
|
||||
<EventsEditor component={componentInstance} />
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
import { store } from "builderStore"
|
||||
import { ArrowDownIcon, ShapeIcon } from "components/common/Icons/"
|
||||
|
||||
export let screens = []
|
||||
export let screens = []
|
||||
|
||||
let confirmDeleteDialog
|
||||
let componentToDelete = ""
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
const get_name = s => (!s ? "" : last(s.split("/")))
|
||||
|
||||
const get_capitalised_name = name => pipe(name, [get_name, capitalise])
|
||||
const isScreenslot = name => name === "##builtin/screenslot"
|
||||
|
||||
const selectComponent = component => {
|
||||
// Set current component
|
||||
|
@ -42,7 +43,7 @@
|
|||
style="padding-left: {level * 20 + 53}px">
|
||||
<div class="nav-item">
|
||||
<i class="icon ri-arrow-right-circle-fill" />
|
||||
{component._instanceName}
|
||||
{isScreenslot(component._component) ? "Screenslot" : component._instanceName}
|
||||
</div>
|
||||
<div class="actions">
|
||||
<ComponentDropdownMenu {component} />
|
||||
|
|
|
@ -5,32 +5,24 @@
|
|||
import Colorpicker from "../common/Colorpicker.svelte"
|
||||
import { goto } from "@sveltech/routify"
|
||||
import { excludeProps } from "./propertyCategories.js"
|
||||
import Input from "../common/Input.svelte"
|
||||
|
||||
export let panelDefinition = []
|
||||
export let componentDefinition = {}
|
||||
export let componentInstance = {}
|
||||
export let onChange = () => {}
|
||||
export let displayNameField = false
|
||||
export let onScreenPropChange = () => {}
|
||||
export let screenOrPageInstance
|
||||
|
||||
const propExistsOnComponentDef = prop => prop in componentDefinition.props
|
||||
let pageScreenProps = ["title","favicon", "description", "route"]
|
||||
|
||||
const propExistsOnComponentDef = prop => pageScreenProps.includes(prop) || prop in componentDefinition.props
|
||||
|
||||
function handleChange(key, data) {
|
||||
data.target ? onChange(key, data.target.value) : onChange(key, data)
|
||||
}
|
||||
|
||||
function handleScreenPropChange (name, value) {
|
||||
onScreenPropChange(name,value)
|
||||
if(!isPage && name === "name") {
|
||||
// screen name is changed... change URL
|
||||
$goto(`./:page/${value}`)
|
||||
}
|
||||
}
|
||||
|
||||
const screenDefinition = [
|
||||
{ key: "name", label: "Name", control: Input },
|
||||
{ key: "description", label: "Description", control: Input },
|
||||
{ key: "route", label: "Route", control: Input },
|
||||
]
|
||||
|
@ -45,8 +37,6 @@
|
|||
|
||||
</script>
|
||||
|
||||
<!-- {#if displayNameField}
|
||||
<PropertyControl control={Input} label="Name" key="_instanceName" value={componentInstance._instanceName} {onChange} /> -->
|
||||
{#if screenOrPageInstance}
|
||||
{#each screenOrPageDefinition as def}
|
||||
<PropertyControl
|
||||
|
@ -54,12 +44,16 @@
|
|||
label={def.label}
|
||||
key={def.key}
|
||||
value={screenOrPageInstance[def.key]}
|
||||
onChange={handleScreenPropChange}
|
||||
{onChange}
|
||||
props={{ ...excludeProps(def, ['control', 'label']) }} />
|
||||
{/each}
|
||||
<hr/>
|
||||
{/if}
|
||||
|
||||
{#if displayNameField}
|
||||
<PropertyControl control={Input} label="Name" key="_instanceName" value={componentInstance._instanceName} {onChange} />
|
||||
{/if}
|
||||
|
||||
{#if panelDefinition && panelDefinition.length > 0}
|
||||
{#each panelDefinition as definition}
|
||||
{#if propExistsOnComponentDef(definition.key)}
|
||||
|
|
|
@ -6,7 +6,7 @@ export const rename = (pages, screens, oldname, newname) => {
|
|||
screens = cloneDeep(screens)
|
||||
const changedScreens = []
|
||||
|
||||
const existingWithNewName = getExactComponent(screens, newname)
|
||||
const existingWithNewName = getExactComponent(screens, newname, true)
|
||||
if (existingWithNewName)
|
||||
return {
|
||||
components: screens,
|
||||
|
@ -38,19 +38,19 @@ export const rename = (pages, screens, oldname, newname) => {
|
|||
for (let screen of screens) {
|
||||
let hasEdited = false
|
||||
|
||||
if (screen.name === oldname) {
|
||||
screen.name = newname
|
||||
hasEdited = true
|
||||
}
|
||||
// if (screen.name === oldname) {
|
||||
// screen.name = newname
|
||||
// hasEdited = true
|
||||
// }
|
||||
|
||||
if (screen.props._component === oldname) {
|
||||
screen.props._component = newname
|
||||
if (screen.props.instanceName === oldname) {
|
||||
screen.props.instanceName = newname
|
||||
hasEdited = true
|
||||
}
|
||||
|
||||
hasEdited = traverseProps(screen.props) || hasEdited
|
||||
|
||||
if (hasEdited && screen.name !== newname) changedScreens.push(screen.name)
|
||||
if (hasEdited && screen.props.instanceName !== newname) changedScreens.push(screen.props.instanceName)
|
||||
}
|
||||
|
||||
for (let pageName in pages) {
|
||||
|
|
|
@ -16,7 +16,7 @@ export const searchAllComponents = (components, phrase) => {
|
|||
pipe(vals, [some(v => includes(normalString(phrase))(normalString(v)))])
|
||||
|
||||
const componentMatches = c => {
|
||||
if (hasPhrase(c.name, ...(c.tags || []))) return true
|
||||
if (hasPhrase(c._instanceName, ...(c.tags || []))) return true
|
||||
|
||||
if (isRootComponent(c)) return false
|
||||
|
||||
|
@ -28,10 +28,14 @@ export const searchAllComponents = (components, phrase) => {
|
|||
return filter(componentMatches)(components)
|
||||
}
|
||||
|
||||
export const getExactComponent = (components, name) => {
|
||||
export const getExactComponent = (components, name, isScreen = false) => {
|
||||
const stringEquals = (s1, s2) => normalString(s1) === normalString(s2)
|
||||
return pipe(components, [
|
||||
find(c => stringEquals(c.props._instanceName, name)),
|
||||
find(c =>
|
||||
isScreen
|
||||
? stringEquals(c.props._instanceName, name)
|
||||
: stringEquals(c._instanceName, name)
|
||||
),
|
||||
])
|
||||
}
|
||||
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
import { getExactComponent } from "../src/components/userInterface/pagesParsing/searchComponents"
|
||||
import { rename } from "../src/components/userInterface/pagesParsing/renameScreen"
|
||||
import { componentsAndScreens } from "./testData"
|
||||
|
||||
describe("rename component", () => {
|
||||
it("should change the name of the component, duh", () => {
|
||||
const { screens } = componentsAndScreens()
|
||||
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton")
|
||||
|
||||
const newComponent = getExactComponent(result.screens, "MainButton")
|
||||
const oldComponent = getExactComponent(result.screens, "Primary")
|
||||
expect(oldComponent).toBeUndefined()
|
||||
expect(newComponent).toBeDefined()
|
||||
expect(newComponent.name).toBe("MainButton")
|
||||
})
|
||||
|
||||
/* this may be usefull if we have user defined components
|
||||
it("should change name of nested _components", () => {
|
||||
const {screens} = componentsAndScreens();
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton");
|
||||
|
||||
const buttonGroup = getExactComponent(result.screens, "ButtonGroup");
|
||||
expect(buttonGroup.props.header[0]._component).toBe("MainButton");
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
it("should change name of page appBody", () => {
|
||||
const { screens } = componentsAndScreens()
|
||||
const pages = {
|
||||
main: {
|
||||
appBody: "PrimaryButton",
|
||||
},
|
||||
}
|
||||
|
||||
const result = rename(pages, screens, "PrimaryButton", "MainButton")
|
||||
expect(result.pages.main.appBody).toBe("MainButton")
|
||||
})
|
||||
|
||||
/* this may be usefull if we have user defined components
|
||||
it("should return a list of changed components", () => {
|
||||
const {screens} = componentsAndScreens();
|
||||
const result = rename({}, screens, "PrimaryButton", "MainButton");
|
||||
|
||||
expect(result.changedScreens).toEqual(["ButtonGroup"]);
|
||||
|
||||
const result2 = rename({}, screens, "common/SmallTextbox", "common/TinyTextBox");
|
||||
expect(result2.changedScreens).toEqual(["Field"]);
|
||||
|
||||
});
|
||||
*/
|
||||
})
|
|
@ -4,9 +4,10 @@ import {
|
|||
getAncestorProps,
|
||||
} from "../src/components/userInterface/pagesParsing/searchComponents"
|
||||
import { componentsAndScreens } from "./testData"
|
||||
|
||||
/*
|
||||
//searchAllComponents used in ComponentSearch which is no longer used in the Builder
|
||||
describe("searchAllComponents", () => {
|
||||
it("should match component by name", () => {
|
||||
it.only("should match component by name", () => {
|
||||
const results = searchAllComponents(
|
||||
componentsAndScreens().components,
|
||||
"Textbox"
|
||||
|
@ -25,50 +26,60 @@ describe("searchAllComponents", () => {
|
|||
expect(results.length).toBe(1)
|
||||
expect(results[0].name).toBe("budibase-components/RecordView")
|
||||
})
|
||||
})
|
||||
}) */
|
||||
|
||||
describe("getExactComponent", () => {
|
||||
it("should get component by name", () => {
|
||||
const { components, screens } = componentsAndScreens()
|
||||
const { components } = componentsAndScreens()
|
||||
const result = getExactComponent(
|
||||
[...components, ...screens],
|
||||
"common/SmallTextbox"
|
||||
components,
|
||||
"TextBox"
|
||||
)
|
||||
|
||||
expect(result).toBeDefined()
|
||||
expect(result.name).toBe("common/SmallTextbox")
|
||||
expect(result._instanceName).toBe("TextBox")
|
||||
})
|
||||
|
||||
it("should return nothing when no result (should not fail)", () => {
|
||||
const { components, screens } = componentsAndScreens()
|
||||
const result = getExactComponent([...components, ...screens], "bla/bla/bla")
|
||||
test("Should not find as isScreen is not specified", () => {
|
||||
const { screens } = componentsAndScreens()
|
||||
const result = getExactComponent(screens, "SmallTextbox")
|
||||
|
||||
expect(result).not.toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe("getAncestorProps", () => {
|
||||
it("should return props of root component", () => {
|
||||
const result = getAncestorProps(
|
||||
componentsAndScreens().components,
|
||||
"budibase-components/TextBox"
|
||||
)
|
||||
test("Should find as isScreen is specified", () => {
|
||||
const { screens } = componentsAndScreens()
|
||||
const result = getExactComponent(screens, "SmallTextbox", true)
|
||||
|
||||
expect(result).toEqual([componentsAndScreens().components[0].props])
|
||||
})
|
||||
expect(result).toBeDefined()
|
||||
expect(result.props._instanceName).toBe("SmallTextbox")
|
||||
|
||||
it("should return props of inherited and current component, in order", () => {
|
||||
const { components, screens } = componentsAndScreens()
|
||||
const allComponentsAndScreens = [...components, ...screens]
|
||||
|
||||
const result = getAncestorProps(
|
||||
allComponentsAndScreens,
|
||||
"common/PasswordBox"
|
||||
)
|
||||
|
||||
expect(result).toEqual([
|
||||
allComponentsAndScreens[0].props,
|
||||
{ ...allComponentsAndScreens[5].props },
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
// Commented as not used anywhere
|
||||
//describe("getAncestorProps", () => {
|
||||
// it("should return props of root component", () => {
|
||||
// const result = getAncestorProps(
|
||||
// componentsAndScreens().components,
|
||||
// "budibase-components/TextBox"
|
||||
// )
|
||||
|
||||
// expect(result).toEqual([componentsAndScreens().components[0].props])
|
||||
// })
|
||||
|
||||
// it("should return props of inherited and current component, in order", () => {
|
||||
// const { components, screens } = componentsAndScreens()
|
||||
// const allComponentsAndScreens = [...components, ...screens]
|
||||
|
||||
// const result = getAncestorProps(
|
||||
// allComponentsAndScreens,
|
||||
// "common/PasswordBox"
|
||||
// )
|
||||
|
||||
// expect(result).toEqual([
|
||||
// allComponentsAndScreens[0].props,
|
||||
// { ...allComponentsAndScreens[5].props },
|
||||
// ])
|
||||
// })
|
||||
// })
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
export const componentsAndScreens = () => ({
|
||||
components: [
|
||||
{
|
||||
name: "budibase-components/TextBox",
|
||||
_instanceName: "TextBox",
|
||||
tags: ["Text", "input"],
|
||||
children: false,
|
||||
props: {
|
||||
|
@ -12,7 +12,7 @@ export const componentsAndScreens = () => ({
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "budibase-components/Button",
|
||||
_instanceName: "Button",
|
||||
tags: ["input"],
|
||||
children: true,
|
||||
props: {
|
||||
|
@ -22,14 +22,14 @@ export const componentsAndScreens = () => ({
|
|||
},
|
||||
},
|
||||
{
|
||||
name: "budibase-components/div",
|
||||
_instanceName: "div",
|
||||
tags: ["input"],
|
||||
props: {
|
||||
width: "number",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "budibase-components/RecordView",
|
||||
_instanceName: "Record View",
|
||||
tags: ["record"],
|
||||
props: {
|
||||
data: "state",
|
||||
|
@ -38,9 +38,9 @@ export const componentsAndScreens = () => ({
|
|||
],
|
||||
screens: [
|
||||
{
|
||||
name: "common/SmallTextbox",
|
||||
props: {
|
||||
_component: "budibase-components/TextBox",
|
||||
_instanceName: "SmallTextbox",
|
||||
size: "small",
|
||||
},
|
||||
},
|
||||
|
@ -50,36 +50,40 @@ export const componentsAndScreens = () => ({
|
|||
tags: ["mask"],
|
||||
props: {
|
||||
_component: "budibase-components/TextBox",
|
||||
_instanceName: "PasswordBox",
|
||||
isPassword: true,
|
||||
size: "small",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "PrimaryButton",
|
||||
props: {
|
||||
_component: "budibase-components/Button",
|
||||
_instanceName: "PrimaryButton",
|
||||
css: "btn-primary",
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "Screen 1",
|
||||
{
|
||||
route: "",
|
||||
props: {
|
||||
_component: "budibase-components/div",
|
||||
width: 100,
|
||||
_instanceName: "Screen 1",
|
||||
_children: [
|
||||
{
|
||||
_component: "budibase-components/Button",
|
||||
contentText: "Button 1",
|
||||
_instanceName: "Button 1",
|
||||
},
|
||||
{
|
||||
_component: "budibase-components/Button",
|
||||
contentText: "Button 2",
|
||||
_instanceName: "Button 2",
|
||||
},
|
||||
{
|
||||
_component: "budibase-components/TextBox",
|
||||
_instanceName: "TextBox",
|
||||
isPassword: true,
|
||||
size: "small",
|
||||
},
|
||||
|
@ -88,9 +92,9 @@ export const componentsAndScreens = () => ({
|
|||
},
|
||||
|
||||
{
|
||||
name: "Field",
|
||||
props: {
|
||||
_component: "budibase-components/div",
|
||||
_instanceName: "Field",
|
||||
_children: [
|
||||
{
|
||||
_component: "common/SmallTextbox",
|
||||
|
|
|
@ -41,7 +41,8 @@ const screenPath = (appPath, pageName, name) =>
|
|||
|
||||
module.exports.saveScreen = async (config, appname, pagename, screen) => {
|
||||
const appPath = appPackageFolder(config, appname)
|
||||
const compPath = screenPath(appPath, pagename, screen.name)
|
||||
const compPath = screenPath(appPath, pagename, screen.props._id)
|
||||
|
||||
await ensureDir(dirname(compPath))
|
||||
if (screen._css) {
|
||||
delete screen._css
|
||||
|
|
Loading…
Reference in New Issue