Merge branch 'feat/user-groups-tab' of github.com:Budibase/budibase into feat/user-groups-tab

This commit is contained in:
Peter Clement 2022-07-11 15:30:31 +01:00
commit c084412a8d
5 changed files with 178 additions and 78 deletions

View File

@ -10,6 +10,7 @@
import Detail from "../../Typography/Detail.svelte" import Detail from "../../Typography/Detail.svelte"
export let primaryLabel = "" export let primaryLabel = ""
export let primaryValue = null
export let id = null export let id = null
export let placeholder = "Choose an option or type" export let placeholder = "Choose an option or type"
export let disabled = false export let disabled = false
@ -73,6 +74,11 @@
primaryOpen = false primaryOpen = false
} }
const onClearPrimary = () => {
dispatch("pickprimary", null)
primaryOpen = false
}
const onPickSecondary = newValue => { const onPickSecondary = newValue => {
dispatch("picksecondary", newValue) dispatch("picksecondary", newValue)
secondaryOpen = false secondaryOpen = false
@ -123,7 +129,7 @@
class:is-invalid={!!error} class:is-invalid={!!error}
class:is-disabled={disabled} class:is-disabled={disabled}
class:is-focused={focus} class:is-focused={focus}
style="width: 70%" class:is-full-width={!secondaryOptions.length}
> >
{#if iconData} {#if iconData}
<svg <svg
@ -153,6 +159,21 @@
class="spectrum-Textfield-input spectrum-InputGroup-input" class="spectrum-Textfield-input spectrum-InputGroup-input"
class:labelPadding={iconData} class:labelPadding={iconData}
/> />
{#if primaryValue}
<button
on:click={() => onClearPrimary()}
type="reset"
class="spectrum-ClearButton spectrum-Search-clearButton"
>
<svg
class="spectrum-Icon spectrum-UIIcon-Cross75"
focusable="false"
aria-hidden="true"
>
<use xlink:href="#spectrum-css-icon-Cross75" />
</svg>
</button>
{/if}
</div> </div>
{#if primaryOpen} {#if primaryOpen}
<div <div
@ -160,7 +181,7 @@
transition:fly|local={{ y: -20, duration: 200 }} transition:fly|local={{ y: -20, duration: 200 }}
class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open" class="spectrum-Popover spectrum-Popover--bottom spectrum-Picker-popover is-open"
class:auto-width={autoWidth} class:auto-width={autoWidth}
style="width: 70%" class:is-full-width={!secondaryOptions.length}
> >
<ul class="spectrum-Menu" role="listbox"> <ul class="spectrum-Menu" role="listbox">
{#if placeholderOption} {#if placeholderOption}
@ -250,6 +271,7 @@
</ul> </ul>
</div> </div>
{/if} {/if}
{#if secondaryOptions.length}
<div style="width: 30%"> <div style="width: 30%">
<button <button
{id} {id}
@ -302,7 +324,9 @@
> >
{#if getSecondaryOptionColour(option, idx)} {#if getSecondaryOptionColour(option, idx)}
<span class="option-left"> <span class="option-left">
<StatusLight color={getSecondaryOptionColour(option, idx)} /> <StatusLight
color={getSecondaryOptionColour(option, idx)}
/>
</span> </span>
{/if} {/if}
@ -322,6 +346,7 @@
</div> </div>
{/if} {/if}
</div> </div>
{/if}
</div> </div>
<style> <style>
@ -381,4 +406,25 @@
.labelPadding { .labelPadding {
padding-left: calc(1em + 10px + 8px); padding-left: calc(1em + 10px + 8px);
} }
.spectrum-Textfield.spectrum-InputGroup-textfield {
width: 70%;
}
.spectrum-Textfield.spectrum-InputGroup-textfield.is-full-width {
width: 100%;
}
.spectrum-Textfield.spectrum-InputGroup-textfield.is-full-width input {
border-right-width: thin;
}
.spectrum-Popover.spectrum-Popover--bottom.spectrum-Picker-popover.is-open {
width: 70%;
}
.spectrum-Popover.spectrum-Popover--bottom.spectrum-Picker-popover.is-open.is-full-width {
width: 100%;
}
.spectrum-Search-clearButton {
position: absolute;
}
</style> </style>

View File

@ -71,9 +71,9 @@
} }
const onPickPrimary = e => { const onPickPrimary = e => {
primaryLabel = e.detail.label primaryLabel = e?.detail?.label || null
primaryValue = e.detail.value primaryValue = e?.detail?.value || null
dispatch("pickprimary", e.detail.value) dispatch("pickprimary", e?.detail?.value || {})
} }
const onPickSecondary = e => { const onPickSecondary = e => {

View File

@ -0,0 +1,43 @@
<script>
import { PickerDropdown, notifications } from "@budibase/bbui"
import { groups } from "stores/portal"
import { onMount, createEventDispatcher } from "svelte"
const dispatch = createEventDispatcher()
$: optionSections = {
groups: {
data: $groups,
getLabel: group => group.name,
getValue: group => group._id,
getIcon: group => group.icon,
getColour: group => group.color,
},
}
$: appData = [{ id: "", role: "" }]
$: onChange = selected => {
const { detail } = selected
if (!detail) return
const groupSelected = $groups.find(x => x._id === detail)
const appIds = groupSelected?.apps.map(x => x.appId) || null
dispatch("change", appIds)
}
onMount(async () => {
try {
await groups.actions.init()
} catch (error) {
notifications.error("Error")
}
})
</script>
<PickerDropdown
autocomplete
primaryOptions={optionSections}
placeholder={"Filter by access"}
on:pickprimary={onChange}
/>

View File

@ -20,12 +20,13 @@
import { store, automationStore } from "builderStore" import { store, automationStore } from "builderStore"
import { API } from "api" import { API } from "api"
import { onMount } from "svelte" import { onMount } from "svelte"
import { apps, auth, admin, templates } from "stores/portal" import { apps, auth, admin, templates, groups } from "stores/portal"
import download from "downloadjs" import download from "downloadjs"
import { goto } from "@roxi/routify" import { goto } from "@roxi/routify"
import AppRow from "components/start/AppRow.svelte" import AppRow from "components/start/AppRow.svelte"
import { AppStatus } from "constants" import { AppStatus } from "constants"
import Logo from "assets/bb-space-man.svg" import Logo from "assets/bb-space-man.svg"
import AccessFilter from "./_components/AcessFilter.svelte"
let sortBy = "name" let sortBy = "name"
let template let template
@ -39,6 +40,7 @@
let cloud = $admin.cloud let cloud = $admin.cloud
let creatingFromTemplate = false let creatingFromTemplate = false
let automationErrors let automationErrors
let accessFilterList = null
const resolveWelcomeMessage = (auth, apps) => { const resolveWelcomeMessage = (auth, apps) => {
const userWelcome = auth?.user?.firstName const userWelcome = auth?.user?.firstName
@ -56,8 +58,10 @@
: "Start from scratch" : "Start from scratch"
$: enrichedApps = enrichApps($apps, $auth.user, sortBy) $: enrichedApps = enrichApps($apps, $auth.user, sortBy)
$: filteredApps = enrichedApps.filter(app => $: filteredApps = enrichedApps.filter(
app?.name?.toLowerCase().includes(searchTerm.toLowerCase()) app =>
app?.name?.toLowerCase().includes(searchTerm.toLowerCase()) &&
(accessFilterList !== null ? accessFilterList.includes(app?.appId) : true)
) )
$: lockedApps = filteredApps.filter(app => app?.lockedYou || app?.lockedOther) $: lockedApps = filteredApps.filter(app => app?.lockedYou || app?.lockedOther)
@ -202,6 +206,10 @@
$goto(`../../app/${app.devId}`) $goto(`../../app/${app.devId}`)
} }
const accessFilterAction = accessFilter => {
accessFilterList = accessFilter.detail
}
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("/")
@ -347,6 +355,9 @@
</Button> </Button>
{/if} {/if}
<div class="filter"> <div class="filter">
{#if $groups.length}
<AccessFilter on:change={accessFilterAction} />
{/if}
<Select <Select
quiet quiet
autoWidth autoWidth

View File

@ -42,7 +42,7 @@
<PickerDropdown <PickerDropdown
autocomplete autocomplete
primaryOptions={optionSections} primaryOptions={optionSections}
primaryPlaceholder={"Search Users"} placeholder={"Search Users"}
secondaryOptions={$roles} secondaryOptions={$roles}
bind:primaryValue={input.id} bind:primaryValue={input.id}
bind:secondaryValue={input.role} bind:secondaryValue={input.role}