2021-11-09 10:33:34 +01:00
|
|
|
<script>
|
|
|
|
import { ModalContent, Body, Detail } from "@budibase/bbui"
|
2021-11-10 17:04:27 +01:00
|
|
|
import { store, selectedAccessRole, allScreens } from "builderStore"
|
2021-11-11 12:07:55 +01:00
|
|
|
import { cloneDeep } from "lodash/fp"
|
2021-11-11 13:09:36 +01:00
|
|
|
import sanitizeUrl from "builderStore/store/screenTemplates/utils/sanitizeUrl"
|
2021-11-15 12:03:09 +01:00
|
|
|
import { onDestroy } from "svelte"
|
2021-11-09 10:33:34 +01:00
|
|
|
|
2021-11-10 17:04:27 +01:00
|
|
|
export let screenNameModal
|
|
|
|
export let selectedScreens
|
|
|
|
export let modal
|
2021-11-11 13:09:36 +01:00
|
|
|
export let screenName
|
2021-11-15 12:03:09 +01:00
|
|
|
export let url
|
|
|
|
|
2021-11-10 17:04:27 +01:00
|
|
|
let roleId = $selectedAccessRole || "BASIC"
|
|
|
|
|
|
|
|
let routeError
|
2021-11-09 10:33:34 +01:00
|
|
|
let selectedNav
|
2021-11-10 17:04:27 +01:00
|
|
|
let createdScreens = []
|
|
|
|
$: {
|
|
|
|
selectedScreens.forEach(screen => {
|
|
|
|
createdScreens = [...createdScreens, screen.create()]
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
$: blankSelected = selectedScreens.find(x => x.id === "createFromScratch")
|
|
|
|
|
2021-11-11 12:07:55 +01:00
|
|
|
const save = async screens => {
|
2021-11-15 12:03:09 +01:00
|
|
|
for (let screen of screens) {
|
|
|
|
await saveScreens(screen)
|
|
|
|
}
|
2021-11-11 12:07:55 +01:00
|
|
|
|
|
|
|
let navLayout = cloneDeep(
|
|
|
|
$store.layouts.find(layout => layout._id === "layout_private_master")
|
|
|
|
)
|
|
|
|
navLayout.props.navigation = selectedNav
|
2021-11-15 12:03:09 +01:00
|
|
|
|
|
|
|
await store.actions.routing.fetch()
|
2021-11-11 12:07:55 +01:00
|
|
|
await store.actions.layouts.save(navLayout)
|
2021-11-15 12:03:09 +01:00
|
|
|
selectedScreens = []
|
|
|
|
screenName = ""
|
|
|
|
url = ""
|
2021-11-11 12:07:55 +01:00
|
|
|
}
|
|
|
|
const saveScreens = async draftScreen => {
|
2021-11-15 12:03:09 +01:00
|
|
|
let existingScreenCount = $store.screens.filter(
|
|
|
|
s => s.props._instanceName == draftScreen.props._instanceName
|
|
|
|
).length
|
2021-11-11 13:55:04 +01:00
|
|
|
|
2021-11-15 12:03:09 +01:00
|
|
|
if (existingScreenCount > 0) {
|
|
|
|
let oldUrlArr = draftScreen.routing.route.split("/")
|
|
|
|
oldUrlArr[1] = `${oldUrlArr[1]}-${existingScreenCount + 1}`
|
|
|
|
draftScreen.routing.route = oldUrlArr.join("/")
|
|
|
|
}
|
|
|
|
|
|
|
|
let route = url ? sanitizeUrl(`${url}`) : draftScreen.routing.route
|
2021-11-11 09:28:42 +01:00
|
|
|
if (draftScreen) {
|
2021-11-11 13:09:36 +01:00
|
|
|
if (!route) {
|
2021-11-11 09:28:42 +01:00
|
|
|
routeError = "URL is required"
|
2021-11-10 17:04:27 +01:00
|
|
|
} else {
|
2021-11-11 13:09:36 +01:00
|
|
|
if (routeExists(route, roleId)) {
|
2021-11-11 09:28:42 +01:00
|
|
|
routeError = "This URL is already taken for this access role"
|
|
|
|
} else {
|
|
|
|
routeError = ""
|
|
|
|
}
|
2021-11-10 17:04:27 +01:00
|
|
|
}
|
2021-11-11 13:55:04 +01:00
|
|
|
|
2021-11-11 09:28:42 +01:00
|
|
|
if (routeError) return false
|
2021-11-10 17:04:27 +01:00
|
|
|
|
2021-11-15 12:03:09 +01:00
|
|
|
if (screenName) {
|
|
|
|
draftScreen.props._instanceName = screenName
|
|
|
|
}
|
|
|
|
|
2021-11-11 13:09:36 +01:00
|
|
|
draftScreen.routing.route = route
|
2021-11-15 12:03:09 +01:00
|
|
|
|
2021-11-11 09:28:42 +01:00
|
|
|
await store.actions.screens.create(draftScreen)
|
2021-11-15 12:03:09 +01:00
|
|
|
if (draftScreen.props._instanceName.endsWith("List")) {
|
2021-11-11 12:07:55 +01:00
|
|
|
await store.actions.components.links.save(
|
|
|
|
draftScreen.routing.route,
|
2021-11-15 12:03:09 +01:00
|
|
|
draftScreen.routing.route.split("/")[1]
|
2021-11-11 12:07:55 +01:00
|
|
|
)
|
|
|
|
}
|
2021-11-10 17:04:27 +01:00
|
|
|
}
|
|
|
|
}
|
2021-11-11 09:28:42 +01:00
|
|
|
|
|
|
|
const routeExists = (route, roleId) => {
|
|
|
|
return $allScreens.some(
|
|
|
|
screen =>
|
|
|
|
screen.routing.route.toLowerCase() === route.toLowerCase() &&
|
|
|
|
screen.routing.roleId === roleId
|
|
|
|
)
|
|
|
|
}
|
2021-11-15 12:03:09 +01:00
|
|
|
|
|
|
|
onDestroy(() => {
|
|
|
|
selectedScreens = []
|
|
|
|
screenName = ""
|
|
|
|
url = ""
|
|
|
|
})
|
2021-11-09 10:33:34 +01:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<ModalContent
|
|
|
|
title="Select navigation"
|
|
|
|
cancelText="Back"
|
2021-11-10 17:04:27 +01:00
|
|
|
onCancel={() => (blankSelected ? screenNameModal.show() : modal.show())}
|
2021-11-09 10:33:34 +01:00
|
|
|
size="M"
|
2021-11-10 17:04:27 +01:00
|
|
|
onConfirm={() => {
|
2021-11-11 12:07:55 +01:00
|
|
|
save(createdScreens)
|
2021-11-10 17:04:27 +01:00
|
|
|
}}
|
2021-11-09 10:33:34 +01:00
|
|
|
disabled={!selectedNav}
|
|
|
|
>
|
|
|
|
<Body size="S"
|
|
|
|
>Please select your preferred layout for the new application:</Body
|
|
|
|
>
|
|
|
|
|
|
|
|
<div class="wrapper">
|
|
|
|
<div
|
2021-11-15 12:03:09 +01:00
|
|
|
data-cy="left-nav"
|
2021-11-11 12:07:55 +01:00
|
|
|
on:click={() => (selectedNav = "Left")}
|
|
|
|
class:unselected={selectedNav && selectedNav !== "Left"}
|
2021-11-09 10:33:34 +01:00
|
|
|
>
|
|
|
|
<div class="box">
|
|
|
|
<div class="side-nav" />
|
|
|
|
</div>
|
|
|
|
<div><Detail>Side Nav</Detail></div>
|
|
|
|
</div>
|
|
|
|
<div
|
2021-11-11 12:07:55 +01:00
|
|
|
on:click={() => (selectedNav = "Top")}
|
|
|
|
class:unselected={selectedNav && selectedNav !== "Top"}
|
2021-11-09 10:33:34 +01:00
|
|
|
>
|
|
|
|
<div class="box">
|
|
|
|
<div class="top-nav" />
|
|
|
|
</div>
|
|
|
|
<div><Detail>Top Nav</Detail></div>
|
|
|
|
</div>
|
|
|
|
<div
|
2021-11-11 12:07:55 +01:00
|
|
|
on:click={() => (selectedNav = "None")}
|
|
|
|
class:unselected={selectedNav && selectedNav !== "None"}
|
2021-11-09 10:33:34 +01:00
|
|
|
>
|
|
|
|
<div class="box" />
|
|
|
|
<div><Detail>No Nav</Detail></div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</ModalContent>
|
|
|
|
|
|
|
|
<style>
|
|
|
|
.side-nav {
|
|
|
|
float: left;
|
|
|
|
background: #d3d3d3 0% 0% no-repeat padding-box;
|
|
|
|
border-radius: 2px 0px 0px 2px;
|
|
|
|
height: 100%;
|
|
|
|
width: 10%;
|
|
|
|
}
|
|
|
|
|
|
|
|
.top-nav {
|
|
|
|
background: #d3d3d3 0% 0% no-repeat padding-box;
|
|
|
|
vertical-align: top;
|
|
|
|
width: 100%;
|
|
|
|
height: 15%;
|
|
|
|
}
|
|
|
|
.box {
|
|
|
|
display: inline-block;
|
|
|
|
background: #eaeaea 0% 0% no-repeat padding-box;
|
|
|
|
border: 1px solid #d3d3d3;
|
|
|
|
border-radius: 2px;
|
|
|
|
opacity: 1;
|
|
|
|
width: 120px;
|
|
|
|
height: 70px;
|
|
|
|
margin-right: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.wrapper {
|
|
|
|
display: flex;
|
|
|
|
padding-top: 4%;
|
|
|
|
list-style-type: none;
|
|
|
|
margin: 0;
|
|
|
|
padding: 0;
|
|
|
|
margin-right: 5%;
|
|
|
|
}
|
|
|
|
.unselected {
|
|
|
|
opacity: 0.3;
|
|
|
|
}
|
|
|
|
</style>
|