Update create view button to be a popover instead of modal
This commit is contained in:
parent
8d87395a98
commit
57da6d8cac
|
@ -38,7 +38,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<DetailPopover title="Automations" minWidth={400} bind:this={popover}>
|
||||
<DetailPopover title="Automations" bind:this={popover}>
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
<ActionButton
|
||||
icon="JourneyVoyager"
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
<script>
|
||||
import { getContext } from "svelte"
|
||||
import { Modal, ActionButton, TooltipType, TempTooltip } from "@budibase/bbui"
|
||||
import GridCreateViewModal from "../../modals/grid/GridCreateViewModal.svelte"
|
||||
|
||||
const { filter } = getContext("grid")
|
||||
|
||||
let modal
|
||||
let firstFilterUsage = false
|
||||
|
||||
$: {
|
||||
if ($filter?.length && !firstFilterUsage) {
|
||||
firstFilterUsage = true
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<TempTooltip
|
||||
text="Create a view to save your filters"
|
||||
type={TooltipType.Info}
|
||||
condition={firstFilterUsage}
|
||||
>
|
||||
<ActionButton icon="CollectionAdd" quiet on:click={modal.show}>
|
||||
Create view
|
||||
</ActionButton>
|
||||
</TempTooltip>
|
||||
<Modal bind:this={modal}>
|
||||
<GridCreateViewModal />
|
||||
</Modal>
|
|
@ -89,7 +89,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<DetailPopover title="Generate" bind:this={popover} minWidth={400}>
|
||||
<DetailPopover title="Generate" bind:this={popover}>
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
<ActionButton selected={open}>
|
||||
<div class="center">
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<DetailPopover title="Row actions" minWidth={400} maxWidth={400}>
|
||||
<DetailPopover title="Row actions">
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
<ActionButton
|
||||
icon="Engagement"
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<DetailPopover title="Screens" minWidth={400} bind:this={popover}>
|
||||
<DetailPopover title="Screens" bind:this={popover}>
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
<ActionButton
|
||||
icon="WebPage"
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
|
||||
export let title
|
||||
export let align = "left"
|
||||
export let minWidth
|
||||
export let maxWidth
|
||||
export let showPopover
|
||||
|
||||
let popover
|
||||
|
@ -24,11 +22,13 @@
|
|||
<Popover
|
||||
bind:this={popover}
|
||||
bind:open
|
||||
minWidth={minWidth || 300}
|
||||
minWidth={400}
|
||||
maxWidth={400}
|
||||
{anchor}
|
||||
{align}
|
||||
{maxWidth}
|
||||
{showPopover}
|
||||
on:open
|
||||
on:close
|
||||
>
|
||||
<div class="detail-popover">
|
||||
<div class="detail-popover__header">
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
<script>
|
||||
import DetailPopover from "components/common/DetailPopover.svelte"
|
||||
import { Input, notifications, Button, Icon } from "@budibase/bbui"
|
||||
import { goto } from "@roxi/routify"
|
||||
import { viewsV2 } from "stores/builder"
|
||||
|
||||
export let table
|
||||
export let firstView = false
|
||||
|
||||
let name
|
||||
let popover
|
||||
|
||||
$: views = Object.keys(table?.views || {}).map(x => x.toLowerCase())
|
||||
$: trimmedName = name?.trim()
|
||||
$: nameExists = views.includes(trimmedName?.toLowerCase())
|
||||
$: nameValid = trimmedName?.length && !nameExists
|
||||
|
||||
export const show = () => {
|
||||
popover?.show()
|
||||
}
|
||||
|
||||
const enrichSchema = schema => {
|
||||
// We need to sure that "visible" is set to true for any fields which have
|
||||
// not yet been saved with grid metadata attached
|
||||
const cloned = { ...schema }
|
||||
Object.entries(cloned).forEach(([field, fieldSchema]) => {
|
||||
if (fieldSchema.visible == null) {
|
||||
cloned[field] = { ...cloned[field], visible: true }
|
||||
}
|
||||
})
|
||||
return cloned
|
||||
}
|
||||
|
||||
const saveView = async () => {
|
||||
popover.hide()
|
||||
try {
|
||||
const newView = await viewsV2.create({
|
||||
name: trimmedName,
|
||||
tableId: table._id,
|
||||
schema: enrichSchema(table.schema),
|
||||
primaryDisplay: table.primaryDisplay,
|
||||
})
|
||||
notifications.success(`View ${name} created`)
|
||||
$goto(`./${newView.id}`)
|
||||
} catch (error) {
|
||||
notifications.error("Error creating view")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<DetailPopover
|
||||
title="Create view"
|
||||
bind:this={popover}
|
||||
on:open={() => (name = null)}
|
||||
>
|
||||
<svelte:fragment slot="anchor" let:open>
|
||||
{#if firstView}
|
||||
<Button cta>Create a view</Button>
|
||||
{:else}
|
||||
<div class="icon" class:open>
|
||||
<Icon
|
||||
name="Add"
|
||||
size="L"
|
||||
color="var(--spectrum-global-color-gray-600)"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</svelte:fragment>
|
||||
<Input
|
||||
label="Name"
|
||||
thin
|
||||
bind:value={name}
|
||||
error={nameExists ? "A view already exists with that name" : null}
|
||||
autofocus
|
||||
/>
|
||||
<div>
|
||||
<Button cta on:click={saveView} disabled={nameExists || !nameValid}>
|
||||
Create view
|
||||
</Button>
|
||||
</div>
|
||||
</DetailPopover>
|
||||
|
||||
<style>
|
||||
.icon {
|
||||
height: 32px;
|
||||
padding: 0 8px;
|
||||
border-radius: 4px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
transition: background 130ms ease-out;
|
||||
}
|
||||
.icon:hover,
|
||||
.icon:active,
|
||||
.icon.open {
|
||||
background: var(--spectrum-global-color-gray-300);
|
||||
cursor: pointer;
|
||||
}
|
||||
.icon:hover :global(.spectrum-Icon),
|
||||
.icon:active :global(.spectrum-Icon),
|
||||
.icon.open :global(.spectrum-Icon) {
|
||||
color: var(--spectrum-global-color-gray-900) !important;
|
||||
}
|
||||
</style>
|
|
@ -1,64 +1,2 @@
|
|||
<script>
|
||||
import { Modal, Input, notifications, ModalContent } from "@budibase/bbui"
|
||||
import { goto } from "@roxi/routify"
|
||||
import { viewsV2 } from "stores/builder"
|
||||
|
||||
export let table
|
||||
|
||||
let name
|
||||
let modal
|
||||
|
||||
$: views = Object.keys(table?.views || {}).map(x => x.toLowerCase())
|
||||
$: trimmedName = name?.trim()
|
||||
$: nameExists = views.includes(trimmedName?.toLowerCase())
|
||||
$: nameValid = trimmedName?.length && !nameExists
|
||||
|
||||
export const show = () => {
|
||||
name = null
|
||||
modal?.show()
|
||||
}
|
||||
|
||||
const enrichSchema = schema => {
|
||||
// We need to sure that "visible" is set to true for any fields which have
|
||||
// not yet been saved with grid metadata attached
|
||||
const cloned = { ...schema }
|
||||
Object.entries(cloned).forEach(([field, fieldSchema]) => {
|
||||
if (fieldSchema.visible == null) {
|
||||
cloned[field] = { ...cloned[field], visible: true }
|
||||
}
|
||||
})
|
||||
return cloned
|
||||
}
|
||||
|
||||
const saveView = async () => {
|
||||
try {
|
||||
const newView = await viewsV2.create({
|
||||
name: trimmedName,
|
||||
tableId: table._id,
|
||||
schema: enrichSchema(table.schema),
|
||||
primaryDisplay: table.primaryDisplay,
|
||||
})
|
||||
notifications.success(`View ${name} created`)
|
||||
name = null
|
||||
$goto(`./${newView.id}`)
|
||||
} catch (error) {
|
||||
notifications.error("Error creating view")
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<Modal bind:this={modal}>
|
||||
<ModalContent
|
||||
title="Create view"
|
||||
confirmText="Create view"
|
||||
onConfirm={saveView}
|
||||
disabled={!nameValid}
|
||||
>
|
||||
<Input
|
||||
label="View name"
|
||||
thin
|
||||
bind:value={name}
|
||||
error={nameExists ? "A view already exists with that name" : null}
|
||||
/>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
</script>
|
||||
|
||||
<Modal bind:this={editorModal} on:show={initForm}>
|
||||
<ModalContent title="Edit View" onConfirm={save} confirmText="Save">
|
||||
<Input label="View Name" thin bind:value={updatedName} />
|
||||
<ModalContent title="Edit view" onConfirm={save} confirmText="Save">
|
||||
<Input label="Name" thin bind:value={updatedName} />
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
import CreateViewModal from "./CreateViewModal.svelte"
|
||||
import { onDestroy } from "svelte"
|
||||
import { derived } from "svelte/store"
|
||||
import CreateViewButton from "./CreateViewButton.svelte"
|
||||
|
||||
// View overflow
|
||||
let observer
|
||||
|
@ -34,7 +35,6 @@
|
|||
let overflowMenu
|
||||
|
||||
// Editing table
|
||||
let createViewModal
|
||||
let editTableModal
|
||||
let deleteTableModal
|
||||
|
||||
|
@ -268,7 +268,7 @@
|
|||
</div>
|
||||
{/if}
|
||||
{#if !hasViews && tableEditable}
|
||||
<Button cta on:click={createViewModal?.show}>Create a view</Button>
|
||||
<CreateViewButton firstView {table} />
|
||||
<span>
|
||||
To create subsets of data, control access and more, create a view.
|
||||
</span>
|
||||
|
@ -311,19 +311,11 @@
|
|||
</ActionMenu>
|
||||
{/if}
|
||||
{#if hasViews}
|
||||
<Icon
|
||||
name="Add"
|
||||
size="L"
|
||||
hoverable
|
||||
color="var(--spectrum-global-color-gray-600)"
|
||||
hoverColor="var(--spectrum-global-color-gray-900)"
|
||||
on:click={createViewModal?.show}
|
||||
/>
|
||||
<CreateViewButton firstView={false} {table} />
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if table && tableEditable}
|
||||
<CreateViewModal {table} bind:this={createViewModal} />
|
||||
<EditTableModal {table} bind:this={editTableModal} />
|
||||
<DeleteTableModal {table} bind:this={deleteTableModal} />
|
||||
{/if}
|
||||
|
@ -343,7 +335,7 @@
|
|||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
padding: 0 var(--spacing-xl);
|
||||
gap: 12px;
|
||||
gap: 8px;
|
||||
}
|
||||
.nav__views {
|
||||
flex: 0 1 auto;
|
||||
|
@ -353,7 +345,6 @@
|
|||
align-items: center;
|
||||
overflow: hidden;
|
||||
gap: 8px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
|
||||
/* Table and view items */
|
||||
|
|
Loading…
Reference in New Issue