1
0
Fork 0
mirror of synced 2024-09-08 21:51:58 +12:00

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 = []
/**

View file

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

View file

@ -2,12 +2,12 @@
import "@spectrum-css/picker/dist/index-vars.css"
import "@spectrum-css/popover/dist/index-vars.css"
import "@spectrum-css/menu/dist/index-vars.css"
import { fly } from "svelte/transition"
import { createEventDispatcher } from "svelte"
import clickOutside from "../../Actions/click_outside"
import Search from "./Search.svelte"
import Icon from "../../Icon/Icon.svelte"
import StatusLight from "../../StatusLight/StatusLight.svelte"
import Popover from "../../Popover/Popover.svelte"
export let id = null
export let disabled = false
@ -33,7 +33,10 @@
export let sort = false
const dispatch = createEventDispatcher()
let searchTerm = null
let button
let popover
$: sortedOptions = getSortedOptions(options, getOptionLabel, sort)
$: filteredOptions = getFilteredOptions(
@ -76,77 +79,117 @@
}
</script>
<div use:clickOutside={() => (open = false)}>
<button
{id}
class="spectrum-Picker spectrum-Picker--sizeM"
class:spectrum-Picker--quiet={quiet}
{disabled}
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:click={onClick}
>
{#if fieldIcon}
<span class="option-extra icon">
<Icon size="S" name={fieldIcon} />
</span>
{/if}
{#if fieldColour}
<span class="option-extra">
<StatusLight square color={fieldColour} />
</span>
{/if}
<span
class="spectrum-Picker-label"
class:is-placeholder={isPlaceholder}
class:auto-width={autoWidth}
>
{fieldText}
<button
{id}
class="spectrum-Picker spectrum-Picker--sizeM"
class:spectrum-Picker--quiet={quiet}
{disabled}
class:is-invalid={!!error}
class:is-open={open}
aria-haspopup="listbox"
on:click={onClick}
use:clickOutside={() => (open = false)}
bind:this={button}
>
{#if fieldIcon}
<span class="option-extra icon">
<Icon size="S" name={fieldIcon} />
</span>
{#if error}
<svg
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder"
>
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
{/if}
{/if}
{#if fieldColour}
<span class="option-extra">
<StatusLight square color={fieldColour} />
</span>
{/if}
<span
class="spectrum-Picker-label"
class:is-placeholder={isPlaceholder}
class:auto-width={autoWidth}
>
{fieldText}
</span>
{#if error}
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
class="spectrum-Icon spectrum-Icon--sizeM spectrum-Picker-validationIcon"
focusable="false"
aria-hidden="true"
aria-label="Folder"
>
<use xlink:href="#spectrum-css-icon-Chevron100" />
<use xlink:href="#spectrum-icon-18-Alert" />
</svg>
</button>
{#if open}
<div
transition:fly|local={{ y: -20, duration: 200 }}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
class:auto-width={autoWidth}
>
{#if autocomplete}
<Search
value={searchTerm}
on:change={event => (searchTerm = event.detail)}
{disabled}
placeholder="Search"
/>
{/if}
<svg
class="spectrum-Icon spectrum-UIIcon-ChevronDown100 spectrum-Picker-menuIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Chevron100" />
</svg>
</button>
<Popover
anchor={button}
align="left"
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}
<Search
value={searchTerm}
on:change={event => (searchTerm = event.detail)}
{disabled}
placeholder="Search"
/>
{/if}
<ul class="spectrum-Menu" role="listbox">
{#if placeholderOption}
<li
class="spectrum-Menu-item placeholder"
class:is-selected={isPlaceholder}
role="option"
aria-selected="true"
tabindex="0"
on:click={() => onSelectOption(null)}
>
<span class="spectrum-Menu-itemLabel">{placeholderOption}</span>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>
{/if}
<ul class="spectrum-Menu" role="listbox">
{#if placeholderOption}
{#if filteredOptions.length}
{#each filteredOptions as option, idx}
<li
class="spectrum-Menu-item placeholder"
class:is-selected={isPlaceholder}
class="spectrum-Menu-item"
class:is-selected={isOptionSelected(getOptionValue(option, idx))}
role="option"
aria-selected="true"
tabindex="0"
on:click={() => onSelectOption(null)}
on:click={() => onSelectOption(getOptionValue(option, idx))}
class:is-disabled={!isOptionEnabled(option)}
>
<span class="spectrum-Menu-itemLabel">{placeholderOption}</span>
{#if getOptionIcon(option, idx)}
<span class="option-extra icon">
<Icon size="S" name={getOptionIcon(option, idx)} />
</span>
{/if}
{#if getOptionColour(option, idx)}
<span class="option-extra">
<StatusLight square color={getOptionColour(option, idx)} />
</span>
{/if}
<span class="spectrum-Menu-itemLabel">
{getOptionLabel(option, idx)}
</span>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
@ -155,61 +198,13 @@
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>
{/if}
{#if filteredOptions.length}
{#each filteredOptions as option, idx}
<li
class="spectrum-Menu-item"
class:is-selected={isOptionSelected(getOptionValue(option, idx))}
role="option"
aria-selected="true"
tabindex="0"
on:click={() => onSelectOption(getOptionValue(option, idx))}
class:is-disabled={!isOptionEnabled(option)}
>
{#if getOptionIcon(option, idx)}
<span class="option-extra icon">
<Icon size="S" name={getOptionIcon(option, idx)} />
</span>
{/if}
{#if getOptionColour(option, idx)}
<span class="option-extra">
<StatusLight square color={getOptionColour(option, idx)} />
</span>
{/if}
<span class="spectrum-Menu-itemLabel">
{getOptionLabel(option, idx)}
</span>
<svg
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Checkmark100" />
</svg>
</li>
{/each}
{/if}
</ul>
</div>
{/if}
</div>
{/each}
{/if}
</ul>
</div>
</Popover>
<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 {
width: 100%;
box-shadow: none;
@ -229,9 +224,6 @@
.spectrum-Picker-label.auto-width.is-placeholder {
padding-right: 2px;
}
.auto-width .spectrum-Menu-item {
padding-right: var(--spacing-xl);
}
/* Icon and colour alignment */
.spectrum-Menu-checkmark {
@ -245,26 +237,44 @@
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-left: -1px;
width: calc(100% + 2px);
}
.spectrum-Popover :global(.spectrum-Search input) {
.popover-content :global(.spectrum-Search input) {
height: auto;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
padding-top: 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;
top: 2px;
}
.spectrum-Popover :global(.spectrum-Search .spectrum-Textfield-icon) {
.popover-content :global(.spectrum-Search .spectrum-Textfield-icon) {
top: 9px;
}
.spectrum-Menu-item.is-disabled {
pointer-events: none;
}
</style>

View file

@ -4,6 +4,7 @@
import { createEventDispatcher } from "svelte"
import positionDropdown from "../Actions/position_dropdown"
import clickOutside from "../Actions/click_outside"
import { fly } from "svelte/transition"
const dispatch = createEventDispatcher()
@ -12,9 +13,10 @@
export let portalTarget
export let dataCy
export let maxWidth
export let direction = "bottom"
export let showTip = false
export let open = false
export let useAnchorWidth = false
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>'
@ -35,13 +37,22 @@
const handleOutsideClick = e => {
if (open) {
e.stopPropagation()
// 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()
}
// Hide the popover
hide()
}
}
let open = null
function handleEscape(e) {
if (open && e.key === "Escape") {
hide()
@ -53,12 +64,13 @@
<Portal target={portalTarget}>
<div
tabindex="0"
use:positionDropdown={{ anchor, align, maxWidth }}
use:positionDropdown={{ anchor, align, maxWidth, useAnchorWidth }}
use:clickOutside={handleOutsideClick}
on:keydown={handleEscape}
class={"spectrum-Popover is-open " + (tooltipClasses || "")}
role="presentation"
data-cy={dataCy}
transition:fly|local={{ y: -20, duration: 200 }}
>
{#if showTip}
{@html tipSvg}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,14 +1,35 @@
<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 { processStringSync } from "@budibase/string-templates"
import { goto } from "@roxi/routify"
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>
<div class="app-row" on:click={() => editApp(app)}>
<div class="app-row" on:click={handleDefaultClick}>
<div class="title" data-cy={`${app.devId}`}>
<div class="app-icon">
<Icon size="L" name={app.icon?.name || "Apps"} color={app.icon?.color} />
@ -35,21 +56,12 @@
<Body size="S">{app.deployed ? "Published" : "Unpublished"}</Body>
</div>
<div data-cy={`row_actions_${app.appId}`}>
<div class="app-row-actions">
<AppLockModal {app} buttonSize="M" />
<Button size="S" secondary on:click={() => appOverview(app)}>
Manage
</Button>
<Button
size="S"
primary
disabled={app.lockedOther}
on:click={() => editApp(app)}
>
Edit
</Button>
</div>
<div class="app-row-actions" data-cy={`row_actions_${app.appId}`}>
<AppLockModal {app} buttonSize="M" />
<Button size="S" secondary on:click={goToOverview}>Manage</Button>
<Button size="S" primary disabled={app.lockedOther} on:click={goToBuilder}>
Edit
</Button>
</div>
</div>
@ -139,5 +151,8 @@
.app-row {
padding: 20px;
}
.app-row-actions {
display: none;
}
}
</style>

View file

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

View file

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

View file

@ -8,12 +8,11 @@
Detail,
Link,
TooltipWrapper,
Page,
} from "@budibase/bbui"
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 { DashCard, Usage } from "../../../../components/usage"
import { DashCard, Usage } from "components/usage"
let staticUsage = []
let monthlyUsage = []

View file

@ -4,7 +4,8 @@
import { onMount } from "svelte"
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 () => {
try {

View file

@ -77,31 +77,3 @@
<CreateAppModal {template} />
</Modal>
<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
}
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) {
// validate the template key just to make sure
const templateParts = templateKey.split("/")
@ -309,7 +295,7 @@
<div class="app-table">
{#each filteredApps as app (app.appId)}
<AppRow {app} {editApp} {appOverview} />
<AppRow {app} />
{/each}
</div>
</Layout>
@ -399,7 +385,7 @@
display: none;
}
.app-actions > :global(*) {
flex: 0 0 50%;
flex: 1 1 auto;
}
}
</style>

View file

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

View file

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

View file

@ -27,7 +27,6 @@
let pageInfo = createPaginationStore()
let runHistory = null
let showPanel = false
let selectedHistory = null
let automationOptions = []
let automationId = null
@ -155,47 +154,47 @@
</Layout>
<Divider />
<div class="search">
<div class="select">
<Select
placeholder="All"
label="Status"
bind:value={status}
options={statusOptions}
/>
</div>
<div class="select">
<Select
placeholder="All"
label="Automation"
bind:value={automationId}
options={automationOptions}
/>
</div>
<div class="select">
<Select
placeholder="All"
label="Date range"
bind:value={timeRange}
options={timeOptions}
isOptionEnabled={x => {
if (licensePlan?.type === Constants.PlanType.FREE) {
return ["1-w", "30-d", "90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.TEAM) {
return ["90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.PRO) {
return ["30-d", "90-d"].indexOf(x.value) < 0
}
return true
}}
/>
<div class="controls">
<div class="search">
<div class="select">
<Select
placeholder="All"
label="Status"
bind:value={status}
options={statusOptions}
/>
</div>
<div class="select">
<Select
placeholder="All"
label="Automation"
bind:value={automationId}
options={automationOptions}
/>
</div>
<div class="select">
<Select
placeholder="All"
label="Date range"
bind:value={timeRange}
options={timeOptions}
isOptionEnabled={x => {
if (licensePlan?.type === Constants.PlanType.FREE) {
return ["1-w", "30-d", "90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.TEAM) {
return ["90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.PRO) {
return ["30-d", "90-d"].indexOf(x.value) < 0
}
return true
}}
/>
</div>
</div>
{#if (licensePlan?.type !== Constants.PlanType.ENTERPRISE && $auth.user.accountPortalAccess) || !$admin.cloud}
<div class="pro-upgrade">
<Button secondary on:click={$licensing.goToUpgradePage()}>
Get more history
</Button>
</div>
<Button secondary on:click={$licensing.goToUpgradePage()}>
Get more history
</Button>
{/if}
</div>
@ -236,14 +235,24 @@
{/if}
<style>
.controls {
display: flex;
flex-direction: row;
gap: var(--spacing-xl);
align-items: flex-end;
flex-wrap: wrap;
}
.search {
display: flex;
gap: var(--spacing-xl);
width: 100%;
align-items: flex-end;
align-items: flex-start;
flex: 1 0 auto;
max-width: 100%;
}
.select {
flex-basis: 150px;
flex: 1 1 0;
max-width: 150px;
min-width: 80px;
}
.pagination {
display: flex;
@ -251,10 +260,4 @@
justify-content: flex-end;
margin-top: var(--spacing-xl);
}
.pro-upgrade {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
</style>

View file

@ -14,7 +14,6 @@
Tags,
Tag,
Table,
Page,
} from "@budibase/bbui"
import { backups, licensing, auth, admin, overview } from "stores/portal"
import { createPaginationStore } from "helpers/pagination"
@ -223,29 +222,30 @@
</div>
{:else if loaded}
<Layout noPadding gap="M" alignContent="start">
<div class="search">
<div class="select">
<Select
placeholder="All"
label="Type"
options={filters}
getOptionValue={filter => filter.value}
getOptionLabel={filter => filter.label}
bind:value={filterOpt}
<div class="controls">
<div class="search">
<div class="select">
<Select
placeholder="All"
label="Type"
options={filters}
getOptionValue={filter => filter.value}
getOptionLabel={filter => filter.label}
bind:value={filterOpt}
/>
</div>
<DatePicker
range={true}
label="Date Range"
on:change={e => {
if (e.detail[0].length > 1) {
startDate = e.detail[0][0].toISOString()
endDate = e.detail[0][1].toISOString()
}
}}
/>
</div>
<DatePicker
range={true}
label="Date Range"
on:change={e => {
if (e.detail[0].length > 1) {
startDate = e.detail[0][0].toISOString()
endDate = e.detail[0][1].toISOString()
}
}}
/>
<div class="split-buttons">
<div>
<ActionButton on:click={modal.show} icon="SaveAsFloppy">
Create new backup
</ActionButton>
@ -291,15 +291,29 @@
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 {
flex: 1 1 auto;
display: flex;
gap: var(--spacing-xl);
width: 100%;
align-items: flex-end;
}
.search :global(.spectrum-InputGroup) {
min-width: 100px;
}
.select {
flex-basis: 160px;
width: 0;
min-width: 100px;
}
.pagination {
@ -309,13 +323,6 @@
margin-top: var(--spacing-xl);
}
.split-buttons {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
.title {
display: flex;
flex-direction: row;

View file

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

View file

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

View file

@ -2,16 +2,14 @@
import { onMount, tick } from "svelte"
import {
Button,
Detail,
Heading,
ActionButton,
Body,
Layout,
notifications,
Tabs,
Tab,
} from "@budibase/bbui"
import { goto, url } from "@roxi/routify"
import { url } from "@roxi/routify"
import { email } from "stores/portal"
import Editor from "components/integration/QueryEditor.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() {
try {
await groups.actions.delete(group)

View file

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

View file

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

View file

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

View file

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