Merge remote-tracking branch 'origin/cheeks-lab-day-portal-redesign' into feature/environment-variables

This commit is contained in:
Peter Clement 2023-01-12 16:00:07 +00:00
commit e8e29ddc8c
27 changed files with 359 additions and 357 deletions

View File

@ -1,4 +1,4 @@
const ignoredClasses = [".flatpickr-calendar", ".modal-container"] const ignoredClasses = [".flatpickr-calendar"]
let clickHandlers = [] let clickHandlers = []
/** /**

View File

@ -1,75 +1,69 @@
export default function positionDropdown(element, { anchor, align, maxWidth }) { export default function positionDropdown(
let positionSide = "top" element,
let maxHeight = 0 { anchor, align, maxWidth, useAnchorWidth }
let dimensions = getDimensions(anchor) ) {
const update = () => {
console.log("update")
const anchorBounds = anchor.getBoundingClientRect()
const elementBounds = element.getBoundingClientRect()
let styles = {
maxHeight: null,
minWidth: null,
maxWidth,
left: null,
top: null,
}
function getDimensions() { // Determine vertical styles
const { if (window.innerHeight - anchorBounds.bottom < 100) {
bottom, styles.top = anchorBounds.top - elementBounds.height - 5
top: spaceAbove,
left,
width,
} = anchor.getBoundingClientRect()
const spaceBelow = window.innerHeight - bottom
const containerRect = element.getBoundingClientRect()
let y
if (spaceAbove > spaceBelow) {
positionSide = "bottom"
maxHeight = spaceAbove - 20
y = window.innerHeight - spaceAbove + 5
} else { } else {
positionSide = "top" styles.top = anchorBounds.bottom + 5
y = bottom + 5 styles.maxHeight = window.innerHeight - anchorBounds.bottom - 20
maxHeight = spaceBelow - 20
} }
return { // Determine horizontal styles
[positionSide]: y, if (!maxWidth && useAnchorWidth) {
left, styles.maxWidth = anchorBounds.width
width,
containerWidth: containerRect.width,
} }
if (useAnchorWidth) {
styles.minWidth = anchorBounds.width
} }
if (align === "right") {
function calcLeftPosition() { styles.left = anchorBounds.left + anchorBounds.width - elementBounds.width
let left } else if (align === "right-side") {
styles.left = anchorBounds.left + anchorBounds.width
if (align == "right") {
left = dimensions.left + dimensions.width - dimensions.containerWidth
} else if (align == "right-side") {
left = dimensions.left + dimensions.width
} else { } else {
left = dimensions.left styles.left = anchorBounds.left
} }
return left // Apply styles
Object.entries(styles).forEach(([style, value]) => {
if (value) {
element.style[style] = `${value.toFixed(0)}px`
} else {
element.style[style] = null
}
})
} }
// Apply initial styles which don't need to change
element.style.position = "absolute" element.style.position = "absolute"
element.style.zIndex = "9999" element.style.zIndex = "9999"
if (maxWidth) {
element.style.maxWidth = `${maxWidth}px`
}
element.style.minWidth = `${dimensions.width}px`
element.style.maxHeight = `${maxHeight.toFixed(0)}px`
element.style.transformOrigin = `center ${positionSide}`
element.style[positionSide] = `${dimensions[positionSide]}px`
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
// Observe both anchor and element and resize the popover as appropriate
const resizeObserver = new ResizeObserver(entries => { const resizeObserver = new ResizeObserver(entries => {
entries.forEach(() => { entries.forEach(update)
dimensions = getDimensions()
element.style[positionSide] = `${dimensions[positionSide]}px`
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
})
}) })
resizeObserver.observe(anchor) resizeObserver.observe(anchor)
resizeObserver.observe(element) resizeObserver.observe(element)
document.addEventListener("scroll", update, true)
return { return {
destroy() { destroy() {
resizeObserver.disconnect() resizeObserver.disconnect()
document.removeEventListener("scroll", update, true)
}, },
} }
} }

View File

@ -2,12 +2,12 @@
import "@spectrum-css/picker/dist/index-vars.css" import "@spectrum-css/picker/dist/index-vars.css"
import "@spectrum-css/popover/dist/index-vars.css" import "@spectrum-css/popover/dist/index-vars.css"
import "@spectrum-css/menu/dist/index-vars.css" import "@spectrum-css/menu/dist/index-vars.css"
import { fly } from "svelte/transition"
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import clickOutside from "../../Actions/click_outside" import clickOutside from "../../Actions/click_outside"
import Search from "./Search.svelte" import Search from "./Search.svelte"
import Icon from "../../Icon/Icon.svelte" import Icon from "../../Icon/Icon.svelte"
import StatusLight from "../../StatusLight/StatusLight.svelte" import StatusLight from "../../StatusLight/StatusLight.svelte"
import Popover from "../../Popover/Popover.svelte"
export let id = null export let id = null
export let disabled = false export let disabled = false
@ -33,7 +33,10 @@
export let sort = false export let sort = false
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
let searchTerm = null let searchTerm = null
let button
let popover
$: sortedOptions = getSortedOptions(options, getOptionLabel, sort) $: sortedOptions = getSortedOptions(options, getOptionLabel, sort)
$: filteredOptions = getFilteredOptions( $: filteredOptions = getFilteredOptions(
@ -76,7 +79,6 @@
} }
</script> </script>
<div use:clickOutside={() => (open = false)}>
<button <button
{id} {id}
class="spectrum-Picker spectrum-Picker--sizeM" class="spectrum-Picker spectrum-Picker--sizeM"
@ -86,6 +88,8 @@
class:is-open={open} class:is-open={open}
aria-haspopup="listbox" aria-haspopup="listbox"
on:click={onClick} on:click={onClick}
use:clickOutside={() => (open = false)}
bind:this={button}
> >
{#if fieldIcon} {#if fieldIcon}
<span class="option-extra icon"> <span class="option-extra icon">
@ -122,12 +126,18 @@
<use xlink:href="#spectrum-css-icon-Chevron100" /> <use xlink:href="#spectrum-css-icon-Chevron100" />
</svg> </svg>
</button> </button>
{#if open}
<div <Popover
transition:fly|local={{ y: -20, duration: 200 }} anchor={button}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open" align="left"
class:auto-width={autoWidth} portalTarget={document.documentElement}
bind:this={popover}
{open}
on:close={() => (open = false)}
useAnchorWidth={!autoWidth}
maxWidth={autoWidth ? 400 : null}
> >
<div class="popover-content" class:auto-width={autoWidth}>
{#if autocomplete} {#if autocomplete}
<Search <Search
value={searchTerm} value={searchTerm}
@ -192,24 +202,9 @@
{/if} {/if}
</ul> </ul>
</div> </div>
{/if} </Popover>
</div>
<style> <style>
.spectrum-Popover {
max-height: 240px;
z-index: 999;
top: 100%;
}
.spectrum-Popover:not(.auto-width) {
width: 100%;
}
.spectrum-Popover.auto-width :global(.spectrum-Menu-itemLabel) {
max-width: 400px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.spectrum-Picker { .spectrum-Picker {
width: 100%; width: 100%;
box-shadow: none; box-shadow: none;
@ -229,9 +224,6 @@
.spectrum-Picker-label.auto-width.is-placeholder { .spectrum-Picker-label.auto-width.is-placeholder {
padding-right: 2px; padding-right: 2px;
} }
.auto-width .spectrum-Menu-item {
padding-right: var(--spacing-xl);
}
/* Icon and colour alignment */ /* Icon and colour alignment */
.spectrum-Menu-checkmark { .spectrum-Menu-checkmark {
@ -245,26 +237,44 @@
margin: 0 -1px; margin: 0 -1px;
} }
.spectrum-Popover :global(.spectrum-Search) { /* Popover */
.popover-content {
display: contents;
}
.popover-content.auto-width .spectrum-Menu-itemLabel {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.popover-content:not(.auto-width) .spectrum-Menu-itemLabel {
width: 0;
flex: 1 1 auto;
}
.popover-content.auto-width .spectrum-Menu-item {
padding-right: var(--spacing-xl);
}
.spectrum-Menu-item.is-disabled {
pointer-events: none;
}
/* Search styles inside popover */
.popover-content :global(.spectrum-Search) {
margin-top: -1px; margin-top: -1px;
margin-left: -1px; margin-left: -1px;
width: calc(100% + 2px); width: calc(100% + 2px);
} }
.spectrum-Popover :global(.spectrum-Search input) { .popover-content :global(.spectrum-Search input) {
height: auto; height: auto;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
padding-top: var(--spectrum-global-dimension-size-100); padding-top: var(--spectrum-global-dimension-size-100);
padding-bottom: var(--spectrum-global-dimension-size-100); padding-bottom: var(--spectrum-global-dimension-size-100);
} }
.spectrum-Popover :global(.spectrum-Search .spectrum-ClearButton) { .popover-content :global(.spectrum-Search .spectrum-ClearButton) {
right: 1px; right: 1px;
top: 2px; top: 2px;
} }
.spectrum-Popover :global(.spectrum-Search .spectrum-Textfield-icon) { .popover-content :global(.spectrum-Search .spectrum-Textfield-icon) {
top: 9px; top: 9px;
} }
.spectrum-Menu-item.is-disabled {
pointer-events: none;
}
</style> </style>

View File

@ -4,6 +4,7 @@
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import positionDropdown from "../Actions/position_dropdown" import positionDropdown from "../Actions/position_dropdown"
import clickOutside from "../Actions/click_outside" import clickOutside from "../Actions/click_outside"
import { fly } from "svelte/transition"
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
@ -12,9 +13,10 @@
export let portalTarget export let portalTarget
export let dataCy export let dataCy
export let maxWidth export let maxWidth
export let direction = "bottom" export let direction = "bottom"
export let showTip = false export let showTip = false
export let open = false
export let useAnchorWidth = false
let tipSvg = let tipSvg =
'<svg xmlns="http://www.w3.org/svg/2000" width="23" height="12" class="spectrum-Popover-tip" > <path class="spectrum-Popover-tip-triangle" d="M 0.7071067811865476 0 L 11.414213562373096 10.707106781186548 L 22.121320343559645 0" /> </svg>' '<svg xmlns="http://www.w3.org/svg/2000" width="23" height="12" class="spectrum-Popover-tip" > <path class="spectrum-Popover-tip-triangle" d="M 0.7071067811865476 0 L 11.414213562373096 10.707106781186548 L 22.121320343559645 0" /> </svg>'
@ -35,13 +37,22 @@
const handleOutsideClick = e => { const handleOutsideClick = e => {
if (open) { if (open) {
// Stop propagation if the source is the anchor
let node = e.target
let fromAnchor = false
while (!fromAnchor && node && node.parentNode) {
fromAnchor = node === anchor
node = node.parentNode
}
if (fromAnchor) {
e.stopPropagation() e.stopPropagation()
}
// Hide the popover
hide() hide()
} }
} }
let open = null
function handleEscape(e) { function handleEscape(e) {
if (open && e.key === "Escape") { if (open && e.key === "Escape") {
hide() hide()
@ -53,12 +64,13 @@
<Portal target={portalTarget}> <Portal target={portalTarget}>
<div <div
tabindex="0" tabindex="0"
use:positionDropdown={{ anchor, align, maxWidth }} use:positionDropdown={{ anchor, align, maxWidth, useAnchorWidth }}
use:clickOutside={handleOutsideClick} use:clickOutside={handleOutsideClick}
on:keydown={handleEscape} on:keydown={handleEscape}
class={"spectrum-Popover is-open " + (tooltipClasses || "")} class={"spectrum-Popover is-open " + (tooltipClasses || "")}
role="presentation" role="presentation"
data-cy={dataCy} data-cy={dataCy}
transition:fly|local={{ y: -20, duration: 200 }}
> >
{#if showTip} {#if showTip}
{@html tipSvg} {@html tipSvg}

View File

@ -280,6 +280,9 @@
styles[field] += styles[field] +=
"border-right: 1px solid var(--spectrum-global-color-gray-200);" "border-right: 1px solid var(--spectrum-global-color-gray-200);"
} }
if (schema[field].minWidth) {
styles[field] += `min-width: ${schema[field].minWidth};`
}
}) })
return styles return styles
} }
@ -450,6 +453,7 @@
--table-bg: var(--spectrum-global-color-gray-50); --table-bg: var(--spectrum-global-color-gray-50);
--table-border: 1px solid var(--spectrum-alias-border-color-mid); --table-border: 1px solid var(--spectrum-alias-border-color-mid);
--cell-padding: var(--spectrum-global-dimension-size-250); --cell-padding: var(--spectrum-global-dimension-size-250);
overflow: auto;
} }
.wrapper--quiet { .wrapper--quiet {
--table-bg: var(--spectrum-alias-background-color-transparent); --table-bg: var(--spectrum-alias-background-color-transparent);

View File

@ -25,7 +25,6 @@
export let loading = false export let loading = false
export let hideAutocolumns export let hideAutocolumns
export let rowCount export let rowCount
export let type
export let disableSorting = false export let disableSorting = false
export let customPlaceholder = false export let customPlaceholder = false

View File

@ -141,8 +141,4 @@
gap: var(--spacing-s); gap: var(--spacing-s);
max-width: 175px; max-width: 175px;
} }
.lock-status-text {
font-weight: 400;
color: var(--spectrum-global-color-gray-800);
}
</style> </style>

View File

@ -1,6 +1,6 @@
<script> <script>
import { ModalContent } from "@budibase/bbui" import { ModalContent } from "@budibase/bbui"
import { Label, Select } from "@budibase/bbui" import { Select } from "@budibase/bbui"
import { themeStore } from "builderStore" import { themeStore } from "builderStore"
import { Constants } from "@budibase/frontend-core" import { Constants } from "@budibase/frontend-core"
</script> </script>

View File

@ -1,14 +1,35 @@
<script> <script>
import { Heading, Body, Button, Icon } from "@budibase/bbui" import { Heading, Body, Button, Icon, notifications } from "@budibase/bbui"
import AppLockModal from "../common/AppLockModal.svelte" import AppLockModal from "../common/AppLockModal.svelte"
import { processStringSync } from "@budibase/string-templates" import { processStringSync } from "@budibase/string-templates"
import { goto } from "@roxi/routify"
export let app export let app
export let editApp
export let appOverview const handleDefaultClick = () => {
if (window.innerWidth < 640) {
goToOverview()
} else {
goToBuilder()
}
}
const goToBuilder = () => {
if (app.lockedOther) {
notifications.error(
`App locked by ${app.lockedBy.email}. Please allow lock to expire or have them unlock this app.`
)
return
}
$goto(`../../app/${app.devId}`)
}
const goToOverview = () => {
$goto(`../overview/${app.devId}`)
}
</script> </script>
<div class="app-row" on:click={() => editApp(app)}> <div class="app-row" on:click={handleDefaultClick}>
<div class="title" data-cy={`${app.devId}`}> <div class="title" data-cy={`${app.devId}`}>
<div class="app-icon"> <div class="app-icon">
<Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} /> <Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} />
@ -35,23 +56,14 @@
<Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body> <Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body>
</div> </div>
<div data-cy={`row_actions_${app.appId}`}> <div class="app-row-actions" data-cy={`row_actions_${app.appId}`}>
<div class="app-row-actions">
<AppLockModal {app} buttonSize="M" /> <AppLockModal {app} buttonSize="M" />
<Button size="S" secondary on:click={() => appOverview(app)}> <Button size="S" secondary on:click={goToOverview}>Manage</Button>
Manage <Button size="S" primary disabled={app.lockedOther} on:click={goToBuilder}>
</Button>
<Button
size="S"
primary
disabled={app.lockedOther}
on:click={() => editApp(app)}
>
Edit Edit
</Button> </Button>
</div> </div>
</div> </div>
</div>
<style> <style>
.app-row { .app-row {
@ -139,5 +151,8 @@
.app-row { .app-row {
padding: 20px; padding: 20px;
} }
.app-row-actions {
display: none;
}
} }
</style> </style>

View File

@ -263,6 +263,7 @@
orderMap[component.component]} orderMap[component.component]}
on:click={() => addComponent(component.component)} on:click={() => addComponent(component.component)}
on:mouseover={() => (selectedIndex = null)} on:mouseover={() => (selectedIndex = null)}
on:focus
> >
<Icon name={component.icon} /> <Icon name={component.icon} />
<Body size="XS">{component.name}</Body> <Body size="XS">{component.name}</Body>

View File

@ -20,6 +20,7 @@
class="container" class="container"
on:mouseover={() => (showTooltip = true)} on:mouseover={() => (showTooltip = true)}
on:mouseleave={() => (showTooltip = false)} on:mouseleave={() => (showTooltip = false)}
on:focus
style="--color: {color};" style="--color: {color};"
> >
<StatusLight square {color} /> <StatusLight square {color} />

View File

@ -8,12 +8,11 @@
Detail, Detail,
Link, Link,
TooltipWrapper, TooltipWrapper,
Page,
} from "@budibase/bbui" } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import { admin, auth, licensing } from "../../../../stores/portal" import { admin, auth, licensing } from "stores/portal"
import { Constants } from "@budibase/frontend-core" import { Constants } from "@budibase/frontend-core"
import { DashCard, Usage } from "../../../../components/usage" import { DashCard, Usage } from "components/usage"
let staticUsage = [] let staticUsage = []
let monthlyUsage = [] let monthlyUsage = []

View File

@ -4,7 +4,8 @@
import { onMount } from "svelte" import { onMount } from "svelte"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
let loaded = false // Don't block loading if we've already hydrated state
let loaded = $apps.length > 0
onMount(async () => { onMount(async () => {
try { try {

View File

@ -77,31 +77,3 @@
<CreateAppModal {template} /> <CreateAppModal {template} />
</Modal> </Modal>
<AppLimitModal bind:this={appLimitModal} /> <AppLimitModal bind:this={appLimitModal} />
<style>
.title .welcome > .buttons {
padding-top: 30px;
}
.title {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
gap: var(--spacing-xl);
flex-wrap: wrap;
}
.buttons {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
gap: var(--spacing-xl);
flex-wrap: wrap;
}
@media (max-width: 640px) {
.buttons {
flex-direction: row-reverse;
justify-content: flex-end;
}
}
</style>

View File

@ -178,20 +178,6 @@
creatingApp = false creatingApp = false
} }
const appOverview = app => {
$goto(`../overview/${app.devId}`)
}
const editApp = app => {
if (app.lockedOther) {
notifications.error(
`App locked by ${app.lockedBy.email}. Please allow lock to expire or have them unlock this app.`
)
return
}
$goto(`../../app/${app.devId}`)
}
function createAppFromTemplateUrl(templateKey) { function createAppFromTemplateUrl(templateKey) {
// validate the template key just to make sure // validate the template key just to make sure
const templateParts = templateKey.split("/") const templateParts = templateKey.split("/")
@ -309,7 +295,7 @@
<div class="app-table"> <div class="app-table">
{#each filteredApps as app (app.appId)} {#each filteredApps as app (app.appId)}
<AppRow {app} {editApp} {appOverview} /> <AppRow {app} />
{/each} {/each}
</div> </div>
</Layout> </Layout>
@ -399,7 +385,7 @@
display: none; display: none;
} }
.app-actions > :global(*) { .app-actions > :global(*) {
flex: 0 0 50%; flex: 1 1 auto;
} }
} }
</style> </style>

View File

@ -1,5 +1,5 @@
<script> <script>
import { url, isActive, params, goto } from "@roxi/routify" import { url, isActive, goto } from "@roxi/routify"
import { import {
Page, Page,
Layout, Layout,
@ -20,7 +20,7 @@
Breadcrumb, Breadcrumb,
Header, Header,
} from "components/portal/page" } from "components/portal/page"
import { apps, auth, groups, overview } from "stores/portal" import { apps, auth, overview } from "stores/portal"
import { AppStatus } from "constants" import { AppStatus } from "constants"
import analytics, { Events, EventSource } from "analytics" import analytics, { Events, EventSource } from "analytics"
import { store } from "builderStore" import { store } from "builderStore"
@ -29,7 +29,7 @@
import { API } from "api" import { API } from "api"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import ExportAppModal from "components/start/ExportAppModal.svelte" import ExportAppModal from "components/start/ExportAppModal.svelte"
import { syncURLToState } from "../../../../../helpers/urlStateSync" import { syncURLToState } from "helpers/urlStateSync"
import * as routify from "@roxi/routify" import * as routify from "@roxi/routify"
import { onDestroy } from "svelte" import { onDestroy } from "svelte"

View File

@ -36,7 +36,7 @@
}, },
role: { role: {
displayName: "Access", displayName: "Access",
width: "150px", width: "160px",
borderLeft: true, borderLeft: true,
}, },
} }

View File

@ -27,7 +27,6 @@
let pageInfo = createPaginationStore() let pageInfo = createPaginationStore()
let runHistory = null let runHistory = null
let showPanel = false
let selectedHistory = null let selectedHistory = null
let automationOptions = [] let automationOptions = []
let automationId = null let automationId = null
@ -155,6 +154,7 @@
</Layout> </Layout>
<Divider /> <Divider />
<div class="controls">
<div class="search"> <div class="search">
<div class="select"> <div class="select">
<Select <Select
@ -190,12 +190,11 @@
}} }}
/> />
</div> </div>
</div>
{#if (licensePlan?.type !== Constants.PlanType.ENTERPRISE && $auth.user.accountPortalAccess) || !$admin.cloud} {#if (licensePlan?.type !== Constants.PlanType.ENTERPRISE && $auth.user.accountPortalAccess) || !$admin.cloud}
<div class="pro-upgrade">
<Button secondary on:click={$licensing.goToUpgradePage()}> <Button secondary on:click={$licensing.goToUpgradePage()}>
Get more history Get more history
</Button> </Button>
</div>
{/if} {/if}
</div> </div>
@ -236,14 +235,24 @@
{/if} {/if}
<style> <style>
.controls {
display: flex;
flex-direction: row;
gap: var(--spacing-xl);
align-items: flex-end;
flex-wrap: wrap;
}
.search { .search {
display: flex; display: flex;
gap: var(--spacing-xl); gap: var(--spacing-xl);
width: 100%; align-items: flex-start;
align-items: flex-end; flex: 1 0 auto;
max-width: 100%;
} }
.select { .select {
flex-basis: 150px; flex: 1 1 0;
max-width: 150px;
min-width: 80px;
} }
.pagination { .pagination {
display: flex; display: flex;
@ -251,10 +260,4 @@
justify-content: flex-end; justify-content: flex-end;
margin-top: var(--spacing-xl); margin-top: var(--spacing-xl);
} }
.pro-upgrade {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
</style> </style>

View File

@ -14,7 +14,6 @@
Tags, Tags,
Tag, Tag,
Table, Table,
Page,
} from "@budibase/bbui" } from "@budibase/bbui"
import { backups, licensing, auth, admin, overview } from "stores/portal" import { backups, licensing, auth, admin, overview } from "stores/portal"
import { createPaginationStore } from "helpers/pagination" import { createPaginationStore } from "helpers/pagination"
@ -223,6 +222,7 @@
</div> </div>
{:else if loaded} {:else if loaded}
<Layout noPadding gap="M" alignContent="start"> <Layout noPadding gap="M" alignContent="start">
<div class="controls">
<div class="search"> <div class="search">
<div class="select"> <div class="select">
<Select <Select
@ -244,8 +244,8 @@
} }
}} }}
/> />
</div>
<div class="split-buttons"> <div>
<ActionButton on:click={modal.show} icon="SaveAsFloppy"> <ActionButton on:click={modal.show} icon="SaveAsFloppy">
Create new backup Create new backup
</ActionButton> </ActionButton>
@ -291,15 +291,29 @@
gap: var(--spacing-xl); gap: var(--spacing-xl);
} }
.controls {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: flex-end;
gap: var(--spacing-xl);
flex-wrap: wrap;
}
.search { .search {
flex: 1 1 auto;
display: flex; display: flex;
gap: var(--spacing-xl); gap: var(--spacing-xl);
width: 100%;
align-items: flex-end; align-items: flex-end;
} }
.search :global(.spectrum-InputGroup) {
min-width: 100px;
}
.select { .select {
flex-basis: 160px; flex-basis: 160px;
width: 0;
min-width: 100px;
} }
.pagination { .pagination {
@ -309,13 +323,6 @@
margin-top: var(--spacing-xl); margin-top: var(--spacing-xl);
} }
.split-buttons {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
.title { .title {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -16,15 +16,12 @@
import clientPackage from "@budibase/client/package.json" import clientPackage from "@budibase/client/package.json"
import { processStringSync } from "@budibase/string-templates" import { processStringSync } from "@budibase/string-templates"
import { users, auth, apps, groups, overview } from "stores/portal" import { users, auth, apps, groups, overview } from "stores/portal"
import { createEventDispatcher } from "svelte"
import { fetchData } from "@budibase/frontend-core" import { fetchData } from "@budibase/frontend-core"
import { API } from "api" import { API } from "api"
import GroupIcon from "../../users/groups/_components/GroupIcon.svelte" import GroupIcon from "../../users/groups/_components/GroupIcon.svelte"
import ConfirmDialog from "components/common/ConfirmDialog.svelte" import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { checkIncomingDeploymentStatus } from "components/deploy/utils" import { checkIncomingDeploymentStatus } from "components/deploy/utils"
const dispatch = createEventDispatcher()
let appEditor let appEditor
let unpublishModal let unpublishModal
let deployments let deployments
@ -180,7 +177,7 @@
- -
<Link <Link
on:click={() => { on:click={() => {
$goto("../version") $goto("./version")
}} }}
> >
Update Update

View File

@ -20,6 +20,7 @@
const schema = { const schema = {
name: { name: {
width: "2fr", width: "2fr",
minWidth: "200px",
}, },
version: { version: {
width: "1fr", width: "1fr",
@ -28,6 +29,7 @@
width: "1fr", width: "1fr",
displayName: "Type", displayName: "Type",
capitalise: true, capitalise: true,
minWidth: "120px",
}, },
edit: { edit: {
width: "auto", width: "auto",
@ -119,8 +121,19 @@
display: flex; display: flex;
gap: var(--spacing-xl); gap: var(--spacing-xl);
justify-content: space-between; justify-content: space-between;
flex-wrap: wrap;
} }
.controls :global(.spectrum-Search) { .controls :global(.spectrum-Search) {
width: 200px; width: 200px;
} }
@media (max-width: 640px) {
.filters {
display: grid;
grid-template-columns: 1fr 1fr;
}
.controls :global(.spectrum-Search) {
width: auto;
}
}
</style> </style>

View File

@ -2,16 +2,14 @@
import { onMount, tick } from "svelte" import { onMount, tick } from "svelte"
import { import {
Button, Button,
Detail,
Heading, Heading,
ActionButton,
Body, Body,
Layout, Layout,
notifications, notifications,
Tabs, Tabs,
Tab, Tab,
} from "@budibase/bbui" } from "@budibase/bbui"
import { goto, url } from "@roxi/routify" import { url } from "@roxi/routify"
import { email } from "stores/portal" import { email } from "stores/portal"
import Editor from "components/integration/QueryEditor.svelte" import Editor from "components/integration/QueryEditor.svelte"
import TemplateBindings from "./_components/TemplateBindings.svelte" import TemplateBindings from "./_components/TemplateBindings.svelte"

View File

@ -110,12 +110,6 @@
} }
} }
const getRoleLabel = appId => {
const roleId = group?.roles?.[apps.getProdAppID(appId)]
const role = $roles.find(x => x._id === roleId)
return role?.name || "Custom role"
}
async function deleteGroup() { async function deleteGroup() {
try { try {
await groups.actions.delete(group) await groups.actions.delete(group)

View File

@ -40,7 +40,7 @@
] ]
$: schema = { $: schema = {
name: { displayName: "Group", width: "2fr" }, name: { displayName: "Group", width: "2fr", minWidth: "200px" },
users: { sortable: false, width: "1fr" }, users: { sortable: false, width: "1fr" },
roles: { sortable: false, displayName: "Apps", width: "1fr" }, roles: { sortable: false, displayName: "Apps", width: "1fr" },
} }

View File

@ -8,8 +8,6 @@
Heading, Heading,
Body, Body,
Label, Label,
List,
ListItem,
Icon, Icon,
Input, Input,
MenuItem, MenuItem,

View File

@ -57,6 +57,7 @@
email: { email: {
sortable: false, sortable: false,
width: "2fr", width: "2fr",
minWidth: "200px",
}, },
role: { role: {
sortable: false, sortable: false,
@ -296,6 +297,8 @@
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
flex-wrap: wrap;
gap: var(--spacing-xl);
} }
.controls-right { .controls-right {

View File

@ -2,7 +2,6 @@
export let title = "" export let title = ""
export let favicon = "" export let favicon = ""
export let metaImage = "" export let metaImage = ""
export let url = ""
export let clientLibPath export let clientLibPath
export let usedPlugins export let usedPlugins