Standardise sizing of all settings and design properties
This commit is contained in:
parent
3b869d2ff4
commit
4e4aa5c525
|
@ -48,7 +48,7 @@
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="no-design">
|
<div class="no-design">
|
||||||
This component does not have any design properties.
|
This component doesn't have any design properties.
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -61,13 +61,7 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
gap: var(--spacing-m);
|
gap: var(--spacing-l);
|
||||||
}
|
|
||||||
.design-view-container :global(.property-group-name .name) {
|
|
||||||
font-size: var(--font-size-xs);
|
|
||||||
}
|
|
||||||
.design-view-container :global(.property-group-container) {
|
|
||||||
padding: 4px 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.design-view-state-categories {
|
.design-view-state-categories {
|
||||||
|
@ -85,10 +79,15 @@
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
margin: 0 -20px;
|
margin: 0 -20px;
|
||||||
padding: 0 20px;
|
padding: 0 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: flex-start;
|
||||||
|
align-items: stretch;
|
||||||
|
gap: var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-design {
|
.no-design {
|
||||||
font-size: var(--font-size-s);
|
font-size: var(--font-size-xs);
|
||||||
color: var(--grey-6);
|
color: var(--grey-5);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -15,11 +15,11 @@
|
||||||
return [
|
return [
|
||||||
...$store.screens
|
...$store.screens
|
||||||
.filter(
|
.filter(
|
||||||
screen =>
|
(screen) =>
|
||||||
screen.props._component.endsWith("/rowdetail") ||
|
screen.props._component.endsWith("/rowdetail") ||
|
||||||
screen.route.endsWith(":id")
|
screen.route.endsWith(":id")
|
||||||
)
|
)
|
||||||
.map(screen => ({
|
.map((screen) => ({
|
||||||
name: screen.props._instanceName,
|
name: screen.props._instanceName,
|
||||||
url: screen.route,
|
url: screen.route,
|
||||||
sort: screen.props._component,
|
sort: screen.props._component,
|
||||||
|
@ -29,7 +29,13 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<DataList editable secondary thin on:blur={handleBlur} on:change bind:value>
|
<DataList
|
||||||
|
editable
|
||||||
|
secondary
|
||||||
|
extraThin
|
||||||
|
on:blur={handleBlur}
|
||||||
|
on:change
|
||||||
|
bind:value>
|
||||||
<option value="" />
|
<option value="" />
|
||||||
{#each urls as url}
|
{#each urls as url}
|
||||||
<option value={url.url}>{url.name}</option>
|
<option value={url.url}>{url.name}</option>
|
||||||
|
|
|
@ -1,291 +1,291 @@
|
||||||
<script>
|
<script>
|
||||||
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
import { DropdownMenu, Button, Input } from "@budibase/bbui"
|
||||||
import { createEventDispatcher, tick } from "svelte"
|
import { createEventDispatcher, tick } from "svelte"
|
||||||
|
|
||||||
import icons from "./icons.js"
|
import icons from "./icons.js"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value = ""
|
export let value = ""
|
||||||
export let maxIconsPerPage = 30
|
export let maxIconsPerPage = 30
|
||||||
|
|
||||||
let searchTerm = ""
|
let searchTerm = ""
|
||||||
let selectedLetter = "A"
|
let selectedLetter = "A"
|
||||||
|
|
||||||
let currentPage = 1
|
let currentPage = 1
|
||||||
let filteredIcons = findIconByTerm(selectedLetter)
|
let filteredIcons = findIconByTerm(selectedLetter)
|
||||||
|
|
||||||
$: dispatch("change", value)
|
$: dispatch("change", value)
|
||||||
|
|
||||||
const alphabet = [
|
const alphabet = [
|
||||||
"A",
|
"A",
|
||||||
"B",
|
"B",
|
||||||
"C",
|
"C",
|
||||||
"D",
|
"D",
|
||||||
"E",
|
"E",
|
||||||
"F",
|
"F",
|
||||||
"G",
|
"G",
|
||||||
"H",
|
"H",
|
||||||
"I",
|
"I",
|
||||||
"J",
|
"J",
|
||||||
"K",
|
"K",
|
||||||
"L",
|
"L",
|
||||||
"M",
|
"M",
|
||||||
"N",
|
"N",
|
||||||
"O",
|
"O",
|
||||||
"P",
|
"P",
|
||||||
"Q",
|
"Q",
|
||||||
"R",
|
"R",
|
||||||
"S",
|
"S",
|
||||||
"T",
|
"T",
|
||||||
"U",
|
"U",
|
||||||
"V",
|
"V",
|
||||||
"W",
|
"W",
|
||||||
"X",
|
"X",
|
||||||
"Y",
|
"Y",
|
||||||
"Z",
|
"Z",
|
||||||
]
|
]
|
||||||
let buttonAnchor, dropdown
|
let buttonAnchor, dropdown
|
||||||
let loading = false
|
let loading = false
|
||||||
|
|
||||||
function findIconByTerm(term) {
|
function findIconByTerm(term) {
|
||||||
const r = new RegExp(`\^${term}`, "i")
|
const r = new RegExp(`\^${term}`, "i")
|
||||||
return icons.filter(i => r.test(i.label))
|
return icons.filter((i) => r.test(i.label))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function switchLetter(letter) {
|
async function switchLetter(letter) {
|
||||||
currentPage = 1
|
currentPage = 1
|
||||||
searchTerm = ""
|
searchTerm = ""
|
||||||
loading = true
|
loading = true
|
||||||
selectedLetter = letter
|
selectedLetter = letter
|
||||||
filteredIcons = findIconByTerm(letter)
|
filteredIcons = findIconByTerm(letter)
|
||||||
await tick() //svg icons do not update without tick
|
await tick() //svg icons do not update without tick
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function findIconOnPage() {
|
async function findIconOnPage() {
|
||||||
loading = true
|
loading = true
|
||||||
const iconIdx = filteredIcons.findIndex(i => i.value === value)
|
const iconIdx = filteredIcons.findIndex((i) => i.value === value)
|
||||||
if (iconIdx !== -1) {
|
if (iconIdx !== -1) {
|
||||||
currentPage = Math.ceil(iconIdx / maxIconsPerPage)
|
currentPage = Math.ceil(iconIdx / maxIconsPerPage)
|
||||||
}
|
}
|
||||||
await tick() //svg icons do not update without tick
|
await tick() //svg icons do not update without tick
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setSelectedUI() {
|
async function setSelectedUI() {
|
||||||
if (value) {
|
if (value) {
|
||||||
const letter = displayValue.substring(0, 1)
|
const letter = displayValue.substring(0, 1)
|
||||||
await switchLetter(letter)
|
await switchLetter(letter)
|
||||||
await findIconOnPage()
|
await findIconOnPage()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function pageClick(next) {
|
async function pageClick(next) {
|
||||||
loading = true
|
loading = true
|
||||||
if (next && currentPage < totalPages) {
|
if (next && currentPage < totalPages) {
|
||||||
currentPage++
|
currentPage++
|
||||||
} else if (!next && currentPage > 1) {
|
} else if (!next && currentPage > 1) {
|
||||||
currentPage--
|
currentPage--
|
||||||
}
|
}
|
||||||
await tick() //svg icons do not update without tick
|
await tick() //svg icons do not update without tick
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
async function searchForIcon(e) {
|
async function searchForIcon(e) {
|
||||||
currentPage = 1
|
currentPage = 1
|
||||||
loading = true
|
loading = true
|
||||||
filteredIcons = findIconByTerm(searchTerm)
|
filteredIcons = findIconByTerm(searchTerm)
|
||||||
await tick() //svg icons do not update without tick
|
await tick() //svg icons do not update without tick
|
||||||
loading = false
|
loading = false
|
||||||
}
|
}
|
||||||
|
|
||||||
$: displayValue = value ? value.substring(7) : "Pick Icon"
|
$: displayValue = value ? value.substring(7) : "Pick Icon"
|
||||||
|
|
||||||
$: totalPages = Math.ceil(filteredIcons.length / maxIconsPerPage)
|
$: totalPages = Math.ceil(filteredIcons.length / maxIconsPerPage)
|
||||||
$: pageEndIdx = maxIconsPerPage * currentPage
|
$: pageEndIdx = maxIconsPerPage * currentPage
|
||||||
$: pagedIcons = filteredIcons.slice(pageEndIdx - maxIconsPerPage, pageEndIdx)
|
$: pagedIcons = filteredIcons.slice(pageEndIdx - maxIconsPerPage, pageEndIdx)
|
||||||
|
|
||||||
$: pagerText = `Page ${currentPage} of ${totalPages}`
|
$: pagerText = `Page ${currentPage} of ${totalPages}`
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={buttonAnchor}>
|
<div bind:this={buttonAnchor}>
|
||||||
<Button secondary on:click={dropdown.show}>{displayValue}</Button>
|
<Button secondary small on:click={dropdown.show}>{displayValue}</Button>
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu
|
<DropdownMenu
|
||||||
bind:this={dropdown}
|
bind:this={dropdown}
|
||||||
on:open={setSelectedUI}
|
on:open={setSelectedUI}
|
||||||
anchor={buttonAnchor}>
|
anchor={buttonAnchor}>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="search-area">
|
<div class="search-area">
|
||||||
<div class="alphabet-area">
|
<div class="alphabet-area">
|
||||||
{#each alphabet as letter, idx}
|
{#each alphabet as letter, idx}
|
||||||
<span
|
<span
|
||||||
class="letter"
|
class="letter"
|
||||||
class:letter-selected={letter === selectedLetter}
|
class:letter-selected={letter === selectedLetter}
|
||||||
on:click={() => switchLetter(letter)}>
|
on:click={() => switchLetter(letter)}>
|
||||||
{letter}
|
{letter}
|
||||||
</span>
|
</span>
|
||||||
{#if idx !== alphabet.length - 1}<span>-</span>{/if}
|
{#if idx !== alphabet.length - 1}<span>-</span>{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<div class="search-input">
|
<div class="search-input">
|
||||||
<div class="input-wrapper">
|
<div class="input-wrapper">
|
||||||
<Input bind:value={searchTerm} thin placeholder="Search Icon" />
|
<Input bind:value={searchTerm} thin placeholder="Search Icon" />
|
||||||
</div>
|
</div>
|
||||||
<Button secondary on:click={searchForIcon}>Search</Button>
|
<Button secondary on:click={searchForIcon}>Search</Button>
|
||||||
</div>
|
</div>
|
||||||
<div class="page-area">
|
<div class="page-area">
|
||||||
<div class="pager">
|
<div class="pager">
|
||||||
<span on:click={() => pageClick(false)}>
|
<span on:click={() => pageClick(false)}>
|
||||||
<i class="page-btn fas fa-chevron-left" />
|
<i class="page-btn fas fa-chevron-left" />
|
||||||
</span>
|
</span>
|
||||||
<span>{pagerText}</span>
|
<span>{pagerText}</span>
|
||||||
<span on:click={() => pageClick(true)}>
|
<span on:click={() => pageClick(true)}>
|
||||||
<i class="page-btn fas fa-chevron-right" />
|
<i class="page-btn fas fa-chevron-right" />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if pagedIcons.length > 0}
|
{#if pagedIcons.length > 0}
|
||||||
<div class="icon-area">
|
<div class="icon-area">
|
||||||
{#if !loading}
|
{#if !loading}
|
||||||
{#each pagedIcons as icon}
|
{#each pagedIcons as icon}
|
||||||
<div
|
<div
|
||||||
class="icon-container"
|
class="icon-container"
|
||||||
class:selected={value === icon.value}
|
class:selected={value === icon.value}
|
||||||
on:click={() => (value = icon.value)}>
|
on:click={() => (value = icon.value)}>
|
||||||
<div class="icon-preview">
|
<div class="icon-preview">
|
||||||
<i class={`${icon.value} fa-3x`} />
|
<i class={`${icon.value} fa-3x`} />
|
||||||
</div>
|
</div>
|
||||||
<div class="icon-label">{icon.label}</div>
|
<div class="icon-label">{icon.label}</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="no-icons">
|
<div class="no-icons">
|
||||||
<h5>
|
<h5>
|
||||||
{`There is no icons for this ${searchTerm ? 'search' : 'page'}`}
|
{`There is no icons for this ${searchTerm ? 'search' : 'page'}`}
|
||||||
</h5>
|
</h5>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.container {
|
.container {
|
||||||
width: 610px;
|
width: 610px;
|
||||||
height: 350px;
|
height: 350px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 10px 0px 10px 15px;
|
padding: 10px 0px 10px 15px;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-area {
|
.search-area {
|
||||||
flex: 0 0 80px;
|
flex: 0 0 80px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-area {
|
.icon-area {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(5, 1fr);
|
||||||
grid-gap: 5px;
|
grid-gap: 5px;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-icons {
|
.no-icons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.alphabet-area {
|
.alphabet-area {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row wrap;
|
flex-flow: row wrap;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading-container {
|
.loading-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-input {
|
.search-input {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding-right: 15px;
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.input-wrapper {
|
.input-wrapper {
|
||||||
width: 510px;
|
width: 510px;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-area {
|
.page-area {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.letter {
|
.letter {
|
||||||
color: var(--blue);
|
color: var(--blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.letter:hover {
|
.letter:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.letter-selected {
|
.letter-selected {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-container {
|
.icon-container {
|
||||||
height: 100px;
|
height: 100px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: var(--border-dark);
|
border: var(--border-dark);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-container:hover {
|
.icon-container:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background: var(--grey-2);
|
background: var(--grey-2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background: var(--grey-3);
|
background: var(--grey-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-preview {
|
.icon-preview {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-label {
|
.icon-label {
|
||||||
flex: 0 0 20px;
|
flex: 0 0 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-btn {
|
.page-btn {
|
||||||
color: var(--blue);
|
color: var(--blue);
|
||||||
}
|
}
|
||||||
|
|
||||||
.page-btn:hover {
|
.page-btn:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -175,7 +175,7 @@
|
||||||
.bb-select-anchor {
|
.bb-select-anchor {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: var(--spacing-m);
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
background-color: var(--grey-2);
|
background-color: var(--grey-2);
|
||||||
border-radius: var(--border-radius-m);
|
border-radius: var(--border-radius-m);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -147,7 +147,7 @@
|
||||||
height: 90%;
|
height: 90%;
|
||||||
width: 2rem;
|
width: 2rem;
|
||||||
background: var(--grey-2);
|
background: var(--grey-2);
|
||||||
right: 10px;
|
right: 4px;
|
||||||
--spacing-s: 0;
|
--spacing-s: 0;
|
||||||
border-left: 0.5px solid var(--grey-3);
|
border-left: 0.5px solid var(--grey-3);
|
||||||
outline-color: var(--blue);
|
outline-color: var(--blue);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
$: style = componentInstance["_styles"][styleCategory] || {}
|
$: style = componentInstance["_styles"][styleCategory] || {}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<DetailSummary {name} on:open show={open}>
|
<DetailSummary {name} on:open show={open} thin>
|
||||||
<div>
|
<div>
|
||||||
{#each properties as props}
|
{#each properties as props}
|
||||||
<PropertyControl
|
<PropertyControl
|
||||||
|
@ -34,6 +34,5 @@
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
gap: var(--spacing-s);
|
gap: var(--spacing-s);
|
||||||
margin-top: var(--spacing-m);
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -8,4 +8,4 @@
|
||||||
export let name, value, placeholder, type
|
export let name, value, placeholder, type
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Input {name} {value} {placeholder} {type} thin on:change />
|
<Input {name} {value} {placeholder} {type} extraThin on:change />
|
||||||
|
|
|
@ -1,88 +1,94 @@
|
||||||
<script>
|
<script>
|
||||||
import { DataList } from "@budibase/bbui"
|
import { DataList } from "@budibase/bbui"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import { store, backendUiStore } from "builderStore"
|
import { store, backendUiStore } from "builderStore"
|
||||||
import fetchBindableProperties from "builderStore/fetchBindableProperties"
|
import fetchBindableProperties from "builderStore/fetchBindableProperties"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value = ""
|
export let value = ""
|
||||||
|
|
||||||
$: urls = getUrls()
|
$: urls = getUrls()
|
||||||
|
|
||||||
const handleBlur = () => dispatch("change", value)
|
const handleBlur = () => dispatch("change", value)
|
||||||
|
|
||||||
// this will get urls of all screens, but only
|
// this will get urls of all screens, but only
|
||||||
// choose detail screens that are usable in the current context
|
// choose detail screens that are usable in the current context
|
||||||
// and substitute the :id param for the actual {{ ._id }} binding
|
// and substitute the :id param for the actual {{ ._id }} binding
|
||||||
const getUrls = () => {
|
const getUrls = () => {
|
||||||
const urls = [
|
const urls = [
|
||||||
...$store.screens
|
...$store.screens
|
||||||
.filter(screen => !screen.props._component.endsWith("/rowdetail"))
|
.filter((screen) => !screen.props._component.endsWith("/rowdetail"))
|
||||||
.map(screen => ({
|
.map((screen) => ({
|
||||||
name: screen.props._instanceName,
|
name: screen.props._instanceName,
|
||||||
url: screen.route,
|
url: screen.route,
|
||||||
sort: screen.props._component,
|
sort: screen.props._component,
|
||||||
})),
|
})),
|
||||||
]
|
]
|
||||||
|
|
||||||
const bindableProperties = fetchBindableProperties({
|
const bindableProperties = fetchBindableProperties({
|
||||||
componentInstanceId: $store.currentComponentInfo._id,
|
componentInstanceId: $store.currentComponentInfo._id,
|
||||||
components: $store.components,
|
components: $store.components,
|
||||||
screen: $store.currentPreviewItem,
|
screen: $store.currentPreviewItem,
|
||||||
tables: $backendUiStore.tables,
|
tables: $backendUiStore.tables,
|
||||||
})
|
})
|
||||||
|
|
||||||
const detailScreens = $store.screens.filter(screen =>
|
const detailScreens = $store.screens.filter((screen) =>
|
||||||
screen.props._component.endsWith("/rowdetail")
|
screen.props._component.endsWith("/rowdetail")
|
||||||
)
|
)
|
||||||
|
|
||||||
for (let detailScreen of detailScreens) {
|
for (let detailScreen of detailScreens) {
|
||||||
const idBinding = bindableProperties.find(p => {
|
const idBinding = bindableProperties.find((p) => {
|
||||||
if (
|
if (
|
||||||
p.type === "context" &&
|
p.type === "context" &&
|
||||||
p.runtimeBinding.endsWith("._id") &&
|
p.runtimeBinding.endsWith("._id") &&
|
||||||
p.table
|
p.table
|
||||||
) {
|
) {
|
||||||
const tableId =
|
const tableId =
|
||||||
typeof p.table === "string" ? p.table : p.table.tableId
|
typeof p.table === "string" ? p.table : p.table.tableId
|
||||||
return tableId === detailScreen.props.table
|
return tableId === detailScreen.props.table
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
})
|
})
|
||||||
|
|
||||||
if (idBinding) {
|
if (idBinding) {
|
||||||
urls.push({
|
urls.push({
|
||||||
name: detailScreen.props._instanceName,
|
name: detailScreen.props._instanceName,
|
||||||
url: detailScreen.route.replace(
|
url: detailScreen.route.replace(
|
||||||
":id",
|
":id",
|
||||||
`{{ ${idBinding.runtimeBinding} }}`
|
`{{ ${idBinding.runtimeBinding} }}`
|
||||||
),
|
),
|
||||||
sort: detailScreen.props._component,
|
sort: detailScreen.props._component,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return urls
|
return urls
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<DataList editable secondary thin on:blur={handleBlur} on:change bind:value>
|
<DataList
|
||||||
<option value="" />
|
editable
|
||||||
{#each urls as url}
|
secondary
|
||||||
<option value={url.url}>{url.name}</option>
|
extraThin
|
||||||
{/each}
|
on:blur={handleBlur}
|
||||||
</DataList>
|
on:change
|
||||||
</div>
|
bind:value>
|
||||||
|
<option value="" />
|
||||||
<style>
|
{#each urls as url}
|
||||||
div {
|
<option value={url.url}>{url.name}</option>
|
||||||
flex: 1 1 auto;
|
{/each}
|
||||||
display: flex;
|
</DataList>
|
||||||
flex-direction: row;
|
</div>
|
||||||
}
|
|
||||||
div :global(> div) {
|
<style>
|
||||||
flex: 1 1 auto;
|
div {
|
||||||
}
|
flex: 1 1 auto;
|
||||||
</style>
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
div :global(> div) {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -125,7 +125,9 @@
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="empty">This component does not have any settings.</div>
|
<div class="empty">
|
||||||
|
This component doesn't have any additional settings.
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -139,9 +141,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
font-size: var(--font-size-s);
|
font-size: var(--font-size-xs);
|
||||||
margin-top: var(--spacing-m);
|
margin-top: var(--spacing-m);
|
||||||
color: var(--grey-6);
|
color: var(--grey-5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.duplicate-name {
|
.duplicate-name {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<Select thin secondary wide on:change {value}>
|
<Select extraThin secondary wide on:change {value}>
|
||||||
<option value="">Choose a table</option>
|
<option value="">Choose a table</option>
|
||||||
{#each $backendUiStore.tables as table}
|
{#each $backendUiStore.tables as table}
|
||||||
<option value={table._id}>{table.name}</option>
|
<option value={table._id}>{table.name}</option>
|
||||||
|
|
|
@ -1,163 +1,163 @@
|
||||||
<script>
|
<script>
|
||||||
import { Button, Icon, DropdownMenu, Spacer, Heading } from "@budibase/bbui"
|
import { Button, Icon, DropdownMenu, Spacer, Heading } from "@budibase/bbui"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import { store, backendUiStore } from "builderStore"
|
import { store, backendUiStore } from "builderStore"
|
||||||
import fetchBindableProperties from "../../builderStore/fetchBindableProperties"
|
import fetchBindableProperties from "../../builderStore/fetchBindableProperties"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let anchorRight, dropdownRight
|
let anchorRight, dropdownRight
|
||||||
|
|
||||||
export let value = {}
|
export let value = {}
|
||||||
|
|
||||||
function handleSelected(selected) {
|
function handleSelected(selected) {
|
||||||
dispatch("change", selected)
|
dispatch("change", selected)
|
||||||
dropdownRight.hide()
|
dropdownRight.hide()
|
||||||
}
|
}
|
||||||
|
|
||||||
$: tables = $backendUiStore.tables.map(m => ({
|
$: tables = $backendUiStore.tables.map((m) => ({
|
||||||
label: m.name,
|
label: m.name,
|
||||||
name: `all_${m._id}`,
|
name: `all_${m._id}`,
|
||||||
tableId: m._id,
|
tableId: m._id,
|
||||||
type: "table",
|
type: "table",
|
||||||
}))
|
}))
|
||||||
|
|
||||||
$: views = $backendUiStore.tables.reduce((acc, cur) => {
|
$: views = $backendUiStore.tables.reduce((acc, cur) => {
|
||||||
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
let viewsArr = Object.entries(cur.views).map(([key, value]) => ({
|
||||||
label: key,
|
label: key,
|
||||||
name: key,
|
name: key,
|
||||||
...value,
|
...value,
|
||||||
type: "view",
|
type: "view",
|
||||||
}))
|
}))
|
||||||
return [...acc, ...viewsArr]
|
return [...acc, ...viewsArr]
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
$: bindableProperties = fetchBindableProperties({
|
$: bindableProperties = fetchBindableProperties({
|
||||||
componentInstanceId: $store.currentComponentInfo._id,
|
componentInstanceId: $store.currentComponentInfo._id,
|
||||||
components: $store.components,
|
components: $store.components,
|
||||||
screen: $store.currentPreviewItem,
|
screen: $store.currentPreviewItem,
|
||||||
tables: $backendUiStore.tables,
|
tables: $backendUiStore.tables,
|
||||||
})
|
})
|
||||||
|
|
||||||
$: links = bindableProperties
|
$: links = bindableProperties
|
||||||
.filter(x => x.fieldSchema.type === "link")
|
.filter((x) => x.fieldSchema.type === "link")
|
||||||
.map(property => ({
|
.map((property) => ({
|
||||||
label: property.readableBinding,
|
label: property.readableBinding,
|
||||||
fieldName: property.fieldSchema.name,
|
fieldName: property.fieldSchema.name,
|
||||||
name: `all_${property.fieldSchema.tableId}`,
|
name: `all_${property.fieldSchema.tableId}`,
|
||||||
tableId: property.fieldSchema.tableId,
|
tableId: property.fieldSchema.tableId,
|
||||||
type: "link",
|
type: "link",
|
||||||
}))
|
}))
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="dropdownbutton"
|
class="dropdownbutton"
|
||||||
bind:this={anchorRight}
|
bind:this={anchorRight}
|
||||||
on:click={dropdownRight.show}>
|
on:click={dropdownRight.show}>
|
||||||
<span>{value.label ? value.label : 'Table / View'}</span>
|
<span>{value.label ? value.label : 'Table / View'}</span>
|
||||||
<Icon name="arrowdown" />
|
<Icon name="arrowdown" />
|
||||||
</div>
|
</div>
|
||||||
<DropdownMenu bind:this={dropdownRight} anchor={anchorRight}>
|
<DropdownMenu bind:this={dropdownRight} anchor={anchorRight}>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading extraSmall>Tables</Heading>
|
<Heading extraSmall>Tables</Heading>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{#each tables as table}
|
{#each tables as table}
|
||||||
<li
|
<li
|
||||||
class:selected={value === table}
|
class:selected={value === table}
|
||||||
on:click={() => handleSelected(table)}>
|
on:click={() => handleSelected(table)}>
|
||||||
{table.label}
|
{table.label}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading extraSmall>Views</Heading>
|
<Heading extraSmall>Views</Heading>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{#each views as view}
|
{#each views as view}
|
||||||
<li
|
<li
|
||||||
class:selected={value === view}
|
class:selected={value === view}
|
||||||
on:click={() => handleSelected(view)}>
|
on:click={() => handleSelected(view)}>
|
||||||
{view.label}
|
{view.label}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading extraSmall>Relationships</Heading>
|
<Heading extraSmall>Relationships</Heading>
|
||||||
</div>
|
</div>
|
||||||
<ul>
|
<ul>
|
||||||
{#each links as link}
|
{#each links as link}
|
||||||
<li
|
<li
|
||||||
class:selected={value === link}
|
class:selected={value === link}
|
||||||
on:click={() => handleSelected(link)}>
|
on:click={() => handleSelected(link)}>
|
||||||
{link.label}
|
{link.label}
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dropdownbutton {
|
.dropdownbutton {
|
||||||
background-color: var(--grey-2);
|
background-color: var(--grey-2);
|
||||||
border: var(--border-transparent);
|
border: var(--border-transparent);
|
||||||
padding: var(--spacing-m);
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
border-radius: var(--border-radius-m);
|
border-radius: var(--border-radius-m);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
.dropdownbutton:hover {
|
.dropdownbutton:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: var(--grey-3);
|
background-color: var(--grey-3);
|
||||||
}
|
}
|
||||||
.dropdownbutton span {
|
.dropdownbutton span {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
font-size: var(--font-size-xs);
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
.dropdownbutton :global(svg) {
|
.dropdownbutton :global(svg) {
|
||||||
margin: -4px 0;
|
margin: -4px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown {
|
.dropdown {
|
||||||
padding: var(--spacing-m) 0;
|
padding: var(--spacing-m) 0;
|
||||||
z-index: 99999999;
|
z-index: 99999999;
|
||||||
}
|
}
|
||||||
.title {
|
.title {
|
||||||
padding: 0 var(--spacing-m) var(--spacing-xs) var(--spacing-m);
|
padding: 0 var(--spacing-m) var(--spacing-xs) var(--spacing-m);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
margin: var(--spacing-m) 0 var(--spacing-xl) 0;
|
margin: var(--spacing-m) 0 var(--spacing-xl) 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding-left: 0px;
|
padding-left: 0px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
li {
|
li {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
padding: var(--spacing-s) var(--spacing-m);
|
padding: var(--spacing-s) var(--spacing-m);
|
||||||
font-size: var(--font-size-xs);
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selected {
|
.selected {
|
||||||
background-color: var(--grey-4);
|
background-color: var(--grey-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
li:hover {
|
li:hover {
|
||||||
background-color: var(--grey-4);
|
background-color: var(--grey-4);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in New Issue