Remove all obscure error handling from stores and move it to the display level

This commit is contained in:
Andrew Kingston 2022-01-24 18:40:06 +00:00
parent 492ea41536
commit 7e90c3de43
19 changed files with 312 additions and 243 deletions

View File

@ -86,8 +86,8 @@ export const getFrontendStore = () => {
description: application.description,
appId: application.appId,
url: application.url,
layouts,
screens,
layouts: layouts || [],
screens: screens || [],
theme: application.theme || "spectrum--light",
customTheme: application.customTheme,
hasAppPackage: true,
@ -109,49 +109,36 @@ export const getFrontendStore = () => {
theme: {
save: async theme => {
const appId = get(store).appId
try {
await API.saveAppMetadata({
appId,
metadata: { theme },
})
store.update(state => {
state.theme = theme
return state
})
} catch (error) {
notifications.error("Error updating theme")
}
await API.saveAppMetadata({
appId,
metadata: { theme },
})
store.update(state => {
state.theme = theme
return state
})
},
},
customTheme: {
save: async customTheme => {
const appId = get(store).appId
try {
await API.saveAppMetadata({
appId,
metadata: { customTheme },
})
store.update(state => {
state.customTheme = customTheme
return state
})
} catch (error) {
notifications.error("Error updating custom theme")
}
await API.saveAppMetadata({
appId,
metadata: { customTheme },
})
store.update(state => {
state.customTheme = customTheme
return state
})
},
},
routing: {
fetch: async () => {
try {
const routes = await API.getAppRoutes()
console.log(routes)
store.update(state => {
state.routes = routes.routes
return state
})
} catch (error) {
notifications.error("Error fetching app routes")
}
const response = await API.fetchAppRoutes()
store.update(state => {
state.routes = response.routes
return state
})
},
},
screens: {
@ -174,50 +161,41 @@ export const getFrontendStore = () => {
})
},
create: async screen => {
try {
const savedScreen = await API.saveScreen(screen)
store.update(state => {
state.selectedScreenId = savedScreen._id
state.selectedComponentId = savedScreen.props._id
state.currentFrontEndType = FrontendTypes.SCREEN
selectedAccessRole.set(savedScreen.routing.roleId)
return savedScreen
})
const savedScreen = await API.saveScreen(screen)
store.update(state => {
state.screens.push(savedScreen)
state.selectedScreenId = savedScreen._id
state.selectedComponentId = savedScreen.props._id
state.currentFrontEndType = FrontendTypes.SCREEN
selectedAccessRole.set(savedScreen.routing.roleId)
return state
})
// Refresh routes
await store.actions.routing.fetch()
return savedScreen
} catch (error) {
notifications.error("Error creating screen")
return null
}
// Refresh routes
await store.actions.routing.fetch()
return savedScreen
},
save: async screen => {
try {
const creatingNewScreen = screen._id === undefined
const savedScreen = await API.saveScreen(screen)
store.update(state => {
const idx = state.screens.findIndex(x => x._id === savedScreen._id)
if (idx !== -1) {
state.screens.splice(idx, 1, savedScreen)
} else {
state.screens.push(savedScreen)
}
return state
})
// Refresh routes
await store.actions.routing.fetch()
// Select the new screen if creating a new one
if (creatingNewScreen) {
store.actions.screens.select(savedScreen._id)
const creatingNewScreen = screen._id === undefined
const savedScreen = await API.saveScreen(screen)
store.update(state => {
const idx = state.screens.findIndex(x => x._id === savedScreen._id)
if (idx !== -1) {
state.screens.splice(idx, 1, savedScreen)
} else {
state.screens.push(savedScreen)
}
return savedScreen
} catch (error) {
notifications.error("Error saving screen")
return null
return state
})
// Refresh routes
await store.actions.routing.fetch()
// Select the new screen if creating a new one
if (creatingNewScreen) {
store.actions.screens.select(savedScreen._id)
}
return savedScreen
},
delete: async screens => {
const screensToDelete = Array.isArray(screens) ? screens : [screens]
@ -241,23 +219,22 @@ export const getFrontendStore = () => {
)
})
try {
await Promise.all(promises)
const deletedIds = screensToDelete.map(screen => screen._id)
store.update(state => {
// Remove deleted screens from state
state.screens = state.screens.filter(screen => {
return !deletedIds.includes(screen._id)
})
// Deselect the current screen if it was deleted
if (deletedIds.includes(state.selectedScreenId)) {
state.selectedScreenId = null
}
return state
await Promise.all(promises)
const deletedIds = screensToDelete.map(screen => screen._id)
store.update(state => {
// Remove deleted screens from state
state.screens = state.screens.filter(screen => {
return !deletedIds.includes(screen._id)
})
} catch (error) {
notifications.error("Error deleting screens")
}
// Deselect the current screen if it was deleted
if (deletedIds.includes(state.selectedScreenId)) {
state.selectedScreenId = null
}
return state
})
// Refresh routes
await store.actions.routing.fetch()
},
},
preview: {
@ -291,28 +268,23 @@ export const getFrontendStore = () => {
})
},
save: async layout => {
try {
const creatingNewLayout = layout._id === undefined
const savedLayout = await API.saveLayout(layout)
store.update(state => {
const idx = state.layouts.findIndex(x => x._id === savedLayout._id)
if (idx !== -1) {
state.layouts.splice(idx, 1, savedLayout)
} else {
state.layouts.push(savedLayout)
}
return state
})
// Select layout if creating a new one
if (creatingNewLayout) {
store.actions.layouts.select(savedLayout._id)
const creatingNewLayout = layout._id === undefined
const savedLayout = await API.saveLayout(layout)
store.update(state => {
const idx = state.layouts.findIndex(x => x._id === savedLayout._id)
if (idx !== -1) {
state.layouts.splice(idx, 1, savedLayout)
} else {
state.layouts.push(savedLayout)
}
return savedLayout
} catch (error) {
notifications.error("Error saving layout")
return null
return state
})
// Select layout if creating a new one
if (creatingNewLayout) {
store.actions.layouts.select(savedLayout._id)
}
return savedLayout
},
find: layoutId => {
if (!layoutId) {
@ -325,22 +297,18 @@ export const getFrontendStore = () => {
if (!layout?._id) {
return
}
try {
await API.deleteLayout({
layoutId: layout._id,
layoutRev: layout._rev,
})
store.update(state => {
// Select main layout if we deleted the selected layout
if (layout._id === state.selectedLayoutId) {
state.selectedLayoutId = get(mainLayout)._id
}
state.layouts = state.layouts.filter(x => x._id !== layout._id)
return state
})
} catch (error) {
notifications.error("Failed to delete layout")
}
await API.deleteLayout({
layoutId: layout._id,
layoutRev: layout._rev,
})
store.update(state => {
// Select main layout if we deleted the selected layout
if (layout._id === state.selectedLayoutId) {
state.selectedLayoutId = get(mainLayout)._id
}
state.layouts = state.layouts.filter(x => x._id !== layout._id)
return state
})
},
},
components: {
@ -622,11 +590,6 @@ export const getFrontendStore = () => {
selected._styles.custom = style
await store.actions.preview.saveSelected()
},
resetStyles: async () => {
const selected = get(selectedComponent)
selected._styles = { normal: {}, hover: {}, active: {} }
await store.actions.preview.saveSelected()
},
updateConditions: async conditions => {
const selected = get(selectedComponent)
selected._conditions = conditions

View File

@ -1,5 +1,5 @@
<script>
import { Select } from "@budibase/bbui"
import { notifications, Select } from "@budibase/bbui"
import { store } from "builderStore"
import { get } from "svelte/store"
@ -23,14 +23,18 @@
]
const onChangeTheme = async theme => {
await store.actions.theme.save(theme)
await store.actions.customTheme.save({
...get(store).customTheme,
navBackground:
theme === "spectrum--light"
? "var(--spectrum-global-color-gray-50)"
: "var(--spectrum-global-color-gray-100)",
})
try {
await store.actions.theme.save(theme)
await store.actions.customTheme.save({
...get(store).customTheme,
navBackground:
theme === "spectrum--light"
? "var(--spectrum-global-color-gray-50)"
: "var(--spectrum-global-color-gray-100)",
})
} catch (error) {
notifications.error("Error updating theme")
}
}
</script>

View File

@ -1,5 +1,11 @@
<script>
import { ActionMenu, ActionButton, MenuItem, Icon } from "@budibase/bbui"
import {
ActionMenu,
ActionButton,
MenuItem,
Icon,
notifications,
} from "@budibase/bbui"
import { store, currentAssetName, selectedComponent } from "builderStore"
import structure from "./componentStructure.json"
@ -36,7 +42,11 @@
const onItemChosen = async item => {
if (!item.isCategory) {
await store.actions.components.create(item.component)
try {
await store.actions.components.create(item.component)
} catch (error) {
notifications.error("Error creating component")
}
}
}
</script>

View File

@ -146,44 +146,49 @@
}
})
const handleBudibaseEvent = event => {
const handleBudibaseEvent = async event => {
const { type, data } = event.data || event.detail
if (!type) {
return
}
if (type === "select-component" && data.id) {
store.actions.components.select({ _id: data.id })
} else if (type === "update-prop") {
store.actions.components.updateProp(data.prop, data.value)
} else if (type === "delete-component" && data.id) {
confirmDeleteComponent(data.id)
} else if (type === "preview-loaded") {
// Wait for this event to show the client library if intelligent
// loading is supported
loading = false
} else if (type === "move-component") {
const { componentId, destinationComponentId } = data
const rootComponent = get(currentAsset).props
try {
if (type === "select-component" && data.id) {
store.actions.components.select({ _id: data.id })
} else if (type === "update-prop") {
await store.actions.components.updateProp(data.prop, data.value)
} else if (type === "delete-component" && data.id) {
confirmDeleteComponent(data.id)
} else if (type === "preview-loaded") {
// Wait for this event to show the client library if intelligent
// loading is supported
loading = false
} else if (type === "move-component") {
const { componentId, destinationComponentId } = data
const rootComponent = get(currentAsset).props
// Get source and destination components
const source = findComponent(rootComponent, componentId)
const destination = findComponent(rootComponent, destinationComponentId)
// Get source and destination components
const source = findComponent(rootComponent, componentId)
const destination = findComponent(rootComponent, destinationComponentId)
// Stop if the target is a child of source
const path = findComponentPath(source, destinationComponentId)
const ids = path.map(component => component._id)
if (ids.includes(data.destinationComponentId)) {
return
// Stop if the target is a child of source
const path = findComponentPath(source, destinationComponentId)
const ids = path.map(component => component._id)
if (ids.includes(data.destinationComponentId)) {
return
}
// Cut and paste the component to the new destination
if (source && destination) {
store.actions.components.copy(source, true)
await store.actions.components.paste(destination, data.mode)
}
} else {
console.warn(`Client sent unknown event type: ${type}`)
}
// Cut and paste the component to the new destination
if (source && destination) {
store.actions.components.copy(source, true)
store.actions.components.paste(destination, data.mode)
}
} else {
console.warn(`Client sent unknown event type: ${type}`)
} catch (error) {
console.warn(error)
notifications.error("Error handling event from app preview")
}
}
@ -196,7 +201,7 @@
try {
await store.actions.components.delete({ _id: idToDelete })
} catch (error) {
notifications.error(error)
notifications.error("Error deleting component")
}
idToDelete = null
}

View File

@ -9,6 +9,7 @@
Label,
Select,
Button,
notifications,
} from "@budibase/bbui"
import { store } from "builderStore"
import AppThemeSelect from "./AppThemeSelect.svelte"
@ -43,23 +44,31 @@
]
const updateProperty = property => {
return e => {
store.actions.customTheme.save({
...get(store).customTheme,
[property]: e.detail,
})
return async e => {
try {
store.actions.customTheme.save({
...get(store).customTheme,
[property]: e.detail,
})
} catch (error) {
notifications.error("Error updating custom theme")
}
}
}
const resetTheme = () => {
const theme = get(store).theme
store.actions.customTheme.save({
...defaultTheme,
navBackground:
theme === "spectrum--light"
? "var(--spectrum-global-color-gray-50)"
: "var(--spectrum-global-color-gray-100)",
})
try {
const theme = get(store).theme
store.actions.customTheme.save({
...defaultTheme,
navBackground:
theme === "spectrum--light"
? "var(--spectrum-global-color-gray-50)"
: "var(--spectrum-global-color-gray-100)",
})
} catch (error) {
notifications.error("Error saving custom theme")
}
}
</script>

View File

@ -29,10 +29,14 @@
if (currentIndex === 0) {
return
}
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex - 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
try {
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex - 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) {
notifications.error("Error saving screen")
}
}
const moveDownComponent = () => {
@ -45,10 +49,14 @@
if (currentIndex === parent._children.length - 1) {
return
}
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex + 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
try {
const newChildren = parent._children.filter(c => c !== component)
newChildren.splice(currentIndex + 1, 0, component)
parent._children = newChildren
store.actions.preview.saveSelected()
} catch (error) {
notifications.error("Error saving screen")
}
}
const duplicateComponent = () => {
@ -60,7 +68,7 @@
try {
await store.actions.components.delete(component)
} catch (error) {
notifications.error(error)
notifications.error("Error deleting component")
}
}
@ -70,8 +78,12 @@
}
const pasteComponent = (mode, preserveBindings = false) => {
// lives in store - also used by drag drop
store.actions.components.paste(component, mode, preserveBindings)
try {
// lives in store - also used by drag drop
store.actions.components.paste(component, mode, preserveBindings)
} catch (error) {
notifications.error("Error saving component")
}
}
</script>

View File

@ -4,6 +4,7 @@
import ComponentDropdownMenu from "../ComponentDropdownMenu.svelte"
import NavItem from "components/common/NavItem.svelte"
import { capitalise } from "helpers"
import { notifications } from "@budibase/bbui"
export let components = []
export let currentComponent
@ -62,6 +63,14 @@
}
closedNodes = closedNodes
}
const onDrop = async () => {
try {
await dragDropStore.actions.drop()
} catch (error) {
notifications.error("Error saving component")
}
}
</script>
<ul>
@ -69,7 +78,7 @@
<li on:click|stopPropagation={() => selectComponent(component)}>
{#if $dragDropStore?.targetComponent === component && $dragDropStore.dropPosition === DropPosition.ABOVE}
<div
on:drop={dragDropStore.actions.drop}
on:drop={onDrop}
ondragover="return false"
ondragenter="return false"
class="drop-item"
@ -83,7 +92,7 @@
on:dragstart={dragstart(component)}
on:dragover={dragover(component, index)}
on:iconClick={() => toggleNodeOpen(component._id)}
on:drop={dragDropStore.actions.drop}
on:drop={onDrop}
text={getComponentText(component)}
withArrow
indentLevel={level + 1}
@ -105,7 +114,7 @@
{#if $dragDropStore?.targetComponent === component && ($dragDropStore.dropPosition === DropPosition.INSIDE || $dragDropStore.dropPosition === DropPosition.BELOW)}
<div
on:drop={dragDropStore.actions.drop}
on:drop={onDrop}
ondragover="return false"
ondragenter="return false"
class="drop-item"

View File

@ -21,9 +21,9 @@
const deleteLayout = async () => {
try {
await store.actions.layouts.delete(layout)
notifications.success(`Layout ${layout.name} deleted successfully.`)
notifications.success("Layout deleted successfully")
} catch (err) {
notifications.error(`Error deleting layout: ${err.message}`)
notifications.error("Error deleting layout")
}
}
@ -32,9 +32,9 @@
const layoutToSave = cloneDeep(layout)
layoutToSave.name = name
await store.actions.layouts.save(layoutToSave)
notifications.success(`Layout saved successfully.`)
notifications.success("Layout saved successfully")
} catch (err) {
notifications.error(`Error saving layout: ${err.message}`)
notifications.error("Error saving layout")
}
}
</script>

View File

@ -13,7 +13,6 @@
const deleteScreen = async () => {
try {
await store.actions.screens.delete(screen)
await store.actions.routing.fetch()
$goto("../")
notifications.success("Deleted screen successfully.")
} catch (err) {

View File

@ -72,7 +72,7 @@ export default function () {
return state
})
},
drop: () => {
drop: async () => {
const state = get(store)
// Stop if the target and source are the same
@ -92,7 +92,7 @@ export default function () {
// Cut and paste the component
frontendStore.actions.components.copy(state.dragged, true)
frontendStore.actions.components.paste(
await frontendStore.actions.components.paste(
state.targetComponent,
state.dropPosition
)

View File

@ -11,7 +11,15 @@
import ComponentNavigationTree from "components/design/NavigationPanel/ComponentNavigationTree/index.svelte"
import Layout from "components/design/NavigationPanel/Layout.svelte"
import NewLayoutModal from "components/design/NavigationPanel/NewLayoutModal.svelte"
import { Icon, Modal, Select, Search, Tabs, Tab } from "@budibase/bbui"
import {
Icon,
Modal,
Select,
Search,
Tabs,
Tab,
notifications,
} from "@budibase/bbui"
export let showModal
@ -58,8 +66,12 @@
selectedAccessRole.set(role)
}
onMount(() => {
store.actions.routing.fetch()
onMount(async () => {
try {
await store.actions.routing.fetch()
} catch (error) {
notifications.error("Error fetching routes")
}
})
</script>

View File

@ -9,8 +9,8 @@
try {
await store.actions.layouts.save({ name })
notifications.success(`Layout ${name} created successfully`)
} catch (err) {
notifications.error(`Error creating layout ${name}.`)
} catch (error) {
notifications.error("Error creating layout")
}
}
</script>

View File

@ -2,7 +2,7 @@
import ScreenDetailsModal from "components/design/NavigationPanel/ScreenDetailsModal.svelte"
import NewScreenModal from "components/design/NavigationPanel/NewScreenModal.svelte"
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
import { Modal } from "@budibase/bbui"
import { Modal, notifications } from "@budibase/bbui"
import { store, selectedAccessRole, allScreens } from "builderStore"
import analytics, { Events } from "analytics"
@ -29,15 +29,19 @@
const save = async () => {
showProgressCircle = true
await createScreens()
for (let screen of createdScreens) {
await saveScreens(screen)
try {
await createScreens()
for (let screen of createdScreens) {
await saveScreens(screen)
}
await store.actions.routing.fetch()
selectedScreens = []
createdScreens = []
screenName = ""
url = ""
} catch (error) {
notifications.error("Error creating screens")
}
await store.actions.routing.fetch()
selectedScreens = []
createdScreens = []
screenName = ""
url = ""
showProgressCircle = false
}
@ -73,10 +77,14 @@
await store.actions.screens.create(draftScreen)
if (draftScreen.props._instanceName.endsWith("List")) {
await store.actions.components.links.save(
draftScreen.routing.route,
draftScreen.routing.route.split("/")[1]
)
try {
await store.actions.components.links.save(
draftScreen.routing.route,
draftScreen.routing.route.split("/")[1]
)
} catch (error) {
notifications.error("Error creating link to screen")
}
}
}
}

View File

@ -1,6 +1,6 @@
<script>
import { isEmpty } from "lodash/fp"
import { Input, DetailSummary } from "@budibase/bbui"
import { Input, DetailSummary, notifications } from "@budibase/bbui"
import { store } from "builderStore"
import PropertyControl from "./PropertyControls/PropertyControl.svelte"
import LayoutSelect from "./PropertyControls/LayoutSelect.svelte"
@ -40,7 +40,13 @@
]
}
const updateProp = store.actions.components.updateProp
const updateProp = async (key, value) => {
try {
await store.actions.components.updateProp(key, value)
} catch (error) {
notifications.error("Error updating component prop")
}
}
const canRenderControl = setting => {
const control = getComponentForSettingType(setting?.type)

View File

@ -1,5 +1,11 @@
<script>
import { DetailSummary, ActionButton, Drawer, Button } from "@budibase/bbui"
import {
DetailSummary,
ActionButton,
Drawer,
Button,
notifications,
} from "@budibase/bbui"
import { store } from "builderStore"
import ConditionalUIDrawer from "./PropertyControls/ConditionalUIDrawer.svelte"
@ -14,8 +20,12 @@
drawer.show()
}
const save = () => {
store.actions.components.updateConditions(tempValue)
const save = async () => {
try {
await store.actions.components.updateConditions(tempValue)
} catch (error) {
notifications.error("Error updating conditions")
}
drawer.hide()
}
</script>

View File

@ -8,6 +8,7 @@
Layout,
Body,
Button,
notifications,
} from "@budibase/bbui"
import { store } from "builderStore"
@ -21,8 +22,12 @@
drawer.show()
}
const save = () => {
store.actions.components.updateCustomStyle(tempValue)
const save = async () => {
try {
await store.actions.components.updateCustomStyle(tempValue)
} catch (error) {
notifications.error("Error updating custom style")
}
drawer.hide()
}
</script>

View File

@ -1,5 +1,5 @@
<script>
import { ActionButton } from "@budibase/bbui"
import { ActionButton, notifications } from "@budibase/bbui"
import { currentAsset, store } from "builderStore"
import { findClosestMatchingComponent } from "builderStore/componentUtils"
import { makeDatasourceFormComponents } from "builderStore/store/screenTemplates/utils/commonComponents"
@ -9,7 +9,7 @@
let confirmResetFieldsDialog
const resetFormFields = () => {
const resetFormFields = async () => {
const form = findClosestMatchingComponent(
$currentAsset.props,
componentInstance._id,
@ -17,10 +17,14 @@
)
const dataSource = form?.dataSource
const fields = makeDatasourceFormComponents(dataSource)
store.actions.components.updateProp(
"_children",
fields.map(field => field.json())
)
try {
await store.actions.components.updateProp(
"_children",
fields.map(field => field.json())
)
} catch (error) {
notifications.error("Error resetting form fields")
}
}
</script>

View File

@ -1,7 +1,7 @@
<script>
import { get } from "svelte/store"
import { get as deepGet, setWith } from "lodash"
import { Input, DetailSummary } from "@budibase/bbui"
import { Input, DetailSummary, notifications } from "@budibase/bbui"
import PropertyControl from "./PropertyControls/PropertyControl.svelte"
import LayoutSelect from "./PropertyControls/LayoutSelect.svelte"
import RoleSelect from "./PropertyControls/RoleSelect.svelte"
@ -29,7 +29,12 @@
}
return state
})
store.actions.preview.saveSelected()
try {
store.actions.preview.saveSelected()
} catch (error) {
notifications.error("Error saving settings")
}
}
const screenSettings = [

View File

@ -1,6 +1,6 @@
<script>
import PropertyControl from "./PropertyControls/PropertyControl.svelte"
import { DetailSummary } from "@budibase/bbui"
import { DetailSummary, notifications } from "@budibase/bbui"
import { store } from "builderStore"
export let name
@ -23,6 +23,14 @@
delete controlProps.control
return controlProps
}
const updateStyle = async (key, val) => {
try {
await store.actions.components.updateStyle(key, val)
} catch (error) {
notifications.error("Error updating style")
}
}
</script>
<DetailSummary collapsible={false} name={`${name}${changed ? " *" : ""}`}>
@ -34,7 +42,7 @@
control={prop.control}
key={prop.key}
value={style[prop.key]}
onChange={val => store.actions.components.updateStyle(prop.key, val)}
onChange={val => updateStyle(prop.key, val)}
props={getControlProps(prop)}
{bindings}
/>