add option to change icon / colour
This commit is contained in:
parent
53557e1bb1
commit
efb50f0050
|
@ -6,6 +6,7 @@
|
||||||
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"
|
||||||
|
|
||||||
export let id = null
|
export let id = null
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
|
@ -159,17 +160,21 @@
|
||||||
>
|
>
|
||||||
{#if getOptionIcon(option, idx)}
|
{#if getOptionIcon(option, idx)}
|
||||||
<span class="icon-Padding">
|
<span class="icon-Padding">
|
||||||
<img
|
{#if getOptionIcon(option, idx).includes("assets")}
|
||||||
src={getOptionIcon(option, idx)}
|
<img
|
||||||
alt="icon"
|
src={getOptionIcon(option, idx)}
|
||||||
width="20"
|
alt="icon"
|
||||||
height="15"
|
width="20"
|
||||||
/>
|
height="15"
|
||||||
|
/>
|
||||||
|
{:else}<Icon name={getOptionIcon(option, idx)} />{/if}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
{#if getOptionLabel(option, idx)}
|
||||||
|
<span class="spectrum-Menu-itemLabel">
|
||||||
|
{getOptionLabel(option, idx)}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
<span class="spectrum-Menu-itemLabel">
|
|
||||||
{getOptionLabel(option, idx)}
|
|
||||||
</span>
|
|
||||||
<svg
|
<svg
|
||||||
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
|
class="spectrum-Icon spectrum-UIIcon-Checkmark100 spectrum-Menu-checkmark spectrum-Menu-itemIcon"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let id = null
|
export let id = null
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
|
export let quiet = false
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
let focus = false
|
let focus = false
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
||||||
<div class="spectrum-Search" class:is-disabled={disabled}>
|
<div class="spectrum-Search" class:is-disabled={disabled}>
|
||||||
<div
|
<div
|
||||||
class="spectrum-Textfield"
|
class="spectrum-Textfield"
|
||||||
|
class:spectrum-Textfield--quiet={quiet}
|
||||||
class:is-focused={focus}
|
class:is-focused={focus}
|
||||||
class:is-disabled={disabled}
|
class:is-disabled={disabled}
|
||||||
>
|
>
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
export let placeholder = null
|
export let placeholder = null
|
||||||
export let disabled = false
|
export let disabled = false
|
||||||
export let updateOnChange = true
|
export let updateOnChange = true
|
||||||
|
export let quiet = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
const onChange = e => {
|
const onChange = e => {
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
{disabled}
|
{disabled}
|
||||||
{value}
|
{value}
|
||||||
{placeholder}
|
{placeholder}
|
||||||
|
{quiet}
|
||||||
on:change={onChange}
|
on:change={onChange}
|
||||||
on:click
|
on:click
|
||||||
on:input
|
on:input
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
import { gradient } from "actions"
|
|
||||||
import { Heading, Button, Icon, ActionMenu, MenuItem } from "@budibase/bbui"
|
import { Heading, Button, Icon, ActionMenu, MenuItem } from "@budibase/bbui"
|
||||||
|
import { apps } from "stores/portal"
|
||||||
|
|
||||||
export let app
|
export let app
|
||||||
export let exportApp
|
export let exportApp
|
||||||
|
@ -10,14 +10,23 @@
|
||||||
export let deleteApp
|
export let deleteApp
|
||||||
export let unpublishApp
|
export let unpublishApp
|
||||||
export let releaseLock
|
export let releaseLock
|
||||||
|
export let editIcon
|
||||||
|
$: color = $apps.filter(filtered_app => app?.appId === filtered_app.appId)[0]
|
||||||
|
.icon?.color
|
||||||
|
$: name = $apps.filter(filtered_app => app?.appId === filtered_app.appId)[0]
|
||||||
|
.icon?.name
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<div class="preview" use:gradient={{ seed: app.name }} />
|
<div style="display: flex;">
|
||||||
<div class="name" on:click={() => editApp(app)}>
|
<div style="color: {color || ''}">
|
||||||
<Heading size="XS">
|
<Icon size="XL" name={name || "Apps"} />
|
||||||
{app.name}
|
</div>
|
||||||
</Heading>
|
<div class="name" on:click={() => editApp(app)}>
|
||||||
|
<Heading size="XS">
|
||||||
|
{app.name}
|
||||||
|
</Heading>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="desktop" />
|
<div class="desktop" />
|
||||||
|
@ -53,15 +62,11 @@
|
||||||
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
|
<MenuItem on:click={() => updateApp(app)} icon="Edit">Edit</MenuItem>
|
||||||
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
<MenuItem on:click={() => deleteApp(app)} icon="Delete">Delete</MenuItem>
|
||||||
{/if}
|
{/if}
|
||||||
|
<MenuItem on:click={() => editIcon(app)} icon="Edit">Edit Icon</MenuItem>
|
||||||
</ActionMenu>
|
</ActionMenu>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.preview {
|
|
||||||
height: 40px;
|
|
||||||
width: 40px;
|
|
||||||
border-radius: var(--border-radius-s);
|
|
||||||
}
|
|
||||||
.name {
|
.name {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -70,6 +75,7 @@
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
margin-left: calc(1.5 * var(--spacing-xl));
|
||||||
}
|
}
|
||||||
.title :global(h1:hover) {
|
.title :global(h1:hover) {
|
||||||
color: var(--spectrum-global-color-blue-600);
|
color: var(--spectrum-global-color-blue-600);
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
Input,
|
||||||
|
ModalContent,
|
||||||
|
Body,
|
||||||
|
Modal,
|
||||||
|
Icon,
|
||||||
|
ColorPicker,
|
||||||
|
Label,
|
||||||
|
} from "@budibase/bbui"
|
||||||
|
import { apps } from "stores/portal"
|
||||||
|
|
||||||
|
export let app
|
||||||
|
let modal
|
||||||
|
let dirty
|
||||||
|
let selectedIcon
|
||||||
|
let selectedColor
|
||||||
|
|
||||||
|
let iconsList = [
|
||||||
|
{ icon: "Actions", color: "" },
|
||||||
|
{ icon: "Algorithm", color: "" },
|
||||||
|
{ icon: "App", color: "" },
|
||||||
|
{ icon: "Briefcase", color: "" },
|
||||||
|
{ icon: "Money", color: "" },
|
||||||
|
{ icon: "ShoppingCart", color: "" },
|
||||||
|
{ icon: "Form", color: "" },
|
||||||
|
{ icon: "Help", color: "" },
|
||||||
|
{ icon: "Monitoring", color: "" },
|
||||||
|
{ icon: "Sandbox", color: "" },
|
||||||
|
{ icon: "Project", color: "" },
|
||||||
|
{ icon: "Organisations", color: "" },
|
||||||
|
{ icon: "Magnify", color: "" },
|
||||||
|
{ icon: "Launch", color: "" },
|
||||||
|
]
|
||||||
|
export const show = () => {
|
||||||
|
modal.show()
|
||||||
|
}
|
||||||
|
export const hide = () => {
|
||||||
|
modal.hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
hide()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onShow = () => {
|
||||||
|
dirty = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeColor = val => {
|
||||||
|
selectedColor = val
|
||||||
|
}
|
||||||
|
|
||||||
|
const save = async () => {
|
||||||
|
await apps.updateIcon(app.instance._id, {
|
||||||
|
name: selectedIcon,
|
||||||
|
color: selectedColor,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Modal bind:this={modal} on:hide={onCancel} on:show={onShow}>
|
||||||
|
<ModalContent
|
||||||
|
title={"Edit Icon"}
|
||||||
|
confirmText={"Save"}
|
||||||
|
onConfirm={() => save()}
|
||||||
|
>
|
||||||
|
<div class="scrollable-icons">
|
||||||
|
<div class="title-spacing">
|
||||||
|
<Label>Select an Icon:</Label>
|
||||||
|
</div>
|
||||||
|
<div class="grid">
|
||||||
|
{#each iconsList as item}
|
||||||
|
<div
|
||||||
|
class="icon-item"
|
||||||
|
style="color: {item.icon === selectedIcon ? selectedColor : ''}"
|
||||||
|
on:click={() => (selectedIcon = item.icon)}
|
||||||
|
>
|
||||||
|
<Icon name={item.icon} />
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="color-selection">
|
||||||
|
<div>
|
||||||
|
<Label>Select a Color:</Label>
|
||||||
|
</div>
|
||||||
|
<div class="color-selection-item">
|
||||||
|
<ColorPicker
|
||||||
|
value={selectedColor}
|
||||||
|
on:change={e => changeColor(e.detail)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ModalContent>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.scrollable-icons {
|
||||||
|
overflow-y: auto;
|
||||||
|
height: 120px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 20px;
|
||||||
|
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selection {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-selection-item {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-spacing {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,15 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import { writable, get as svelteGet } from "svelte/store"
|
import { writable, get as svelteGet } from "svelte/store"
|
||||||
import {
|
|
||||||
notifications,
|
import { notifications, Input, ModalContent, Dropzone } from "@budibase/bbui"
|
||||||
Input,
|
|
||||||
ModalContent,
|
|
||||||
Dropzone,
|
|
||||||
Body,
|
|
||||||
Checkbox,
|
|
||||||
} from "@budibase/bbui"
|
|
||||||
import { store, automationStore, hostingStore } from "builderStore"
|
import { store, automationStore, hostingStore } from "builderStore"
|
||||||
import { admin, auth } from "stores/portal"
|
import { admin, auth, users } from "stores/portal"
|
||||||
import { string, mixed, object } from "yup"
|
import { string, mixed, object } from "yup"
|
||||||
import api, { get, post } from "builderStore/api"
|
import api, { get, post } from "builderStore/api"
|
||||||
import analytics, { Events } from "analytics"
|
import analytics, { Events } from "analytics"
|
||||||
|
@ -21,7 +15,6 @@
|
||||||
|
|
||||||
export let template
|
export let template
|
||||||
export let inline
|
export let inline
|
||||||
|
|
||||||
const values = writable({ name: null })
|
const values = writable({ name: null })
|
||||||
const errors = writable({})
|
const errors = writable({})
|
||||||
const touched = writable({})
|
const touched = writable({})
|
||||||
|
@ -147,16 +140,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getModalTitle() {
|
|
||||||
let title = "Create App"
|
|
||||||
if (template.fromFile) {
|
|
||||||
title = "Import App"
|
|
||||||
} else if (template.key) {
|
|
||||||
title = "Create app from template"
|
|
||||||
}
|
|
||||||
return title
|
|
||||||
}
|
|
||||||
|
|
||||||
async function onCancel() {
|
async function onCancel() {
|
||||||
template = null
|
template = null
|
||||||
await auth.setInitInfo({})
|
await auth.setInitInfo({})
|
||||||
|
@ -187,7 +170,7 @@
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
{:else}
|
{:else}
|
||||||
<ModalContent
|
<ModalContent
|
||||||
title={getModalTitle()}
|
title={"Name your app"}
|
||||||
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
confirmText={template?.fromFile ? "Import app" : "Create app"}
|
||||||
onConfirm={createNewApp}
|
onConfirm={createNewApp}
|
||||||
onCancel={inline ? onCancel : null}
|
onCancel={inline ? onCancel : null}
|
||||||
|
@ -207,16 +190,12 @@
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
<Body size="S">
|
|
||||||
Give your new app a name, and choose which groups have access (paid plans
|
|
||||||
only).
|
|
||||||
</Body>
|
|
||||||
<Input
|
<Input
|
||||||
bind:value={$values.name}
|
bind:value={$values.name}
|
||||||
error={$touched.name && $errors.name}
|
error={$touched.name && $errors.name}
|
||||||
on:blur={() => ($touched.name = true)}
|
on:blur={() => ($touched.name = true)}
|
||||||
label="Name"
|
label="Name"
|
||||||
|
placeholder={`${$auth.user.firstName}'s first app`}
|
||||||
/>
|
/>
|
||||||
<Checkbox label="Group access" disabled value={true} text="All users" />
|
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,46 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { Heading, Layout, Icon, Body } from "@budibase/bbui"
|
import { Heading, Layout, Icon } from "@budibase/bbui"
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
|
||||||
import api from "builderStore/api"
|
|
||||||
|
|
||||||
export let onSelect
|
export let onSelect
|
||||||
|
|
||||||
async function fetchTemplates() {
|
|
||||||
const response = await api.get("/api/templates?type=app")
|
|
||||||
return await response.json()
|
|
||||||
}
|
|
||||||
|
|
||||||
let templatesPromise = fetchTemplates()
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Layout gap="XS" noPadding>
|
<Layout gap="XS" noPadding>
|
||||||
{#await templatesPromise}
|
|
||||||
<div class="spinner-container">
|
|
||||||
<Spinner size="30" />
|
|
||||||
</div>
|
|
||||||
{:then templates}
|
|
||||||
{#if templates?.length > 0}
|
|
||||||
<Body size="M">Select a template below, or start from scratch.</Body>
|
|
||||||
{:else}
|
|
||||||
<Body size="M">Start your app from scratch below.</Body>
|
|
||||||
{/if}
|
|
||||||
<div class="templates">
|
|
||||||
{#each templates as template}
|
|
||||||
<div class="template" on:click={() => onSelect(template)}>
|
|
||||||
<div
|
|
||||||
class="background-icon"
|
|
||||||
style={`background: ${template.background};`}
|
|
||||||
>
|
|
||||||
<Icon name={template.icon} />
|
|
||||||
</div>
|
|
||||||
<Heading size="XS">{template.name}</Heading>
|
|
||||||
<p class="detail">{template?.category?.toUpperCase()}</p>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{:catch err}
|
|
||||||
<h1 style="color:red">{err}</h1>
|
|
||||||
{/await}
|
|
||||||
<div class="template start-from-scratch" on:click={() => onSelect(null)}>
|
<div class="template start-from-scratch" on:click={() => onSelect(null)}>
|
||||||
<div
|
<div
|
||||||
class="background-icon"
|
class="background-icon"
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
import Spinner from "components/common/Spinner.svelte"
|
import Spinner from "components/common/Spinner.svelte"
|
||||||
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
import CreateAppModal from "components/start/CreateAppModal.svelte"
|
||||||
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
import UpdateAppModal from "components/start/UpdateAppModal.svelte"
|
||||||
|
import ChooseIconModal from "components/start/ChooseIconModal.svelte"
|
||||||
|
|
||||||
import { store, automationStore } from "builderStore"
|
import { store, automationStore } from "builderStore"
|
||||||
import api, { del, post, get } from "builderStore/api"
|
import api, { del, post, get } from "builderStore/api"
|
||||||
import { onMount } from "svelte"
|
import { onMount } from "svelte"
|
||||||
|
@ -34,6 +36,7 @@
|
||||||
let updatingModal
|
let updatingModal
|
||||||
let deletionModal
|
let deletionModal
|
||||||
let unpublishModal
|
let unpublishModal
|
||||||
|
let iconModal
|
||||||
let creatingApp = false
|
let creatingApp = false
|
||||||
let loaded = false
|
let loaded = false
|
||||||
let searchTerm = ""
|
let searchTerm = ""
|
||||||
|
@ -170,6 +173,11 @@
|
||||||
$goto(`../../app/${app.devId}`)
|
$goto(`../../app/${app.devId}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editIcon = app => {
|
||||||
|
selectedApp = app
|
||||||
|
iconModal.show()
|
||||||
|
}
|
||||||
|
|
||||||
const exportApp = app => {
|
const exportApp = app => {
|
||||||
const id = app.deployed ? app.prodId : app.devId
|
const id = app.deployed ? app.prodId : app.devId
|
||||||
const appName = encodeURIComponent(app.name)
|
const appName = encodeURIComponent(app.name)
|
||||||
|
@ -279,7 +287,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Page wide>
|
<Page wide>
|
||||||
<Layout gap="S" noPadding>
|
<Layout noPadding>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<Heading size="S">Welcome to Budibase</Heading>
|
<Heading size="S">Welcome to Budibase</Heading>
|
||||||
|
|
||||||
|
@ -287,32 +295,45 @@
|
||||||
{#if cloud}
|
{#if cloud}
|
||||||
<Button secondary on:click={initiateAppsExport}>Export apps</Button>
|
<Button secondary on:click={initiateAppsExport}>Export apps</Button>
|
||||||
{/if}
|
{/if}
|
||||||
<Button secondary on:click={initiateAppImport}>Import app</Button>
|
<Button icon="Import" quiet secondary on:click={initiateAppImport}
|
||||||
<Button cta on:click={initiateAppCreation}>Create app</Button>
|
>Import app</Button
|
||||||
|
>
|
||||||
|
<Button icon="Add" cta on:click={initiateAppCreation}>Create app</Button
|
||||||
|
>
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</div>
|
</div>
|
||||||
<Body size="XS">Manage your apps and get a head start with templates</Body>
|
|
||||||
|
|
||||||
|
<div class="title-text">
|
||||||
|
<Body size="XS">Manage your apps and get a head start with templates</Body
|
||||||
|
>
|
||||||
|
</div>
|
||||||
<Detail>Quick Start Templates</Detail>
|
<Detail>Quick Start Templates</Detail>
|
||||||
<div class="grid">
|
<div class="grid">
|
||||||
{#each templates as val}
|
{#each templates as item}
|
||||||
<div class="template-card">
|
<div
|
||||||
|
on:click={() => {
|
||||||
|
template = item
|
||||||
|
creationModal.show()
|
||||||
|
creatingApp = true
|
||||||
|
}}
|
||||||
|
class="template-card"
|
||||||
|
>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div style="color: {val.background}" class="iconAlign">
|
<div style="color: {item.background}" class="iconAlign">
|
||||||
<svg
|
<svg
|
||||||
width="26px"
|
width="26px"
|
||||||
height="26px"
|
height="26px"
|
||||||
class="spectrum-Icon"
|
class="spectrum-Icon"
|
||||||
style="color:{val.background};"
|
style="color:{item.background};"
|
||||||
focusable="false"
|
focusable="false"
|
||||||
>
|
>
|
||||||
<use xlink:href="#spectrum-icon-18-{val.icon}" />
|
<use xlink:href="#spectrum-icon-18-{item.icon}" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<div class="iconAlign">
|
<div class="iconAlign">
|
||||||
<Body weight="900" size="XS">{val.name}</Body>
|
<Body weight="900" size="XS">{item.name}</Body>
|
||||||
<div style="font-size: 10px;">
|
<div style="font-size: 10px;">
|
||||||
<Body size="XS">{val.category.toUpperCase()}</Body>
|
<Body size="XS">{item.category.toUpperCase()}</Body>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -326,6 +347,7 @@
|
||||||
<div class="filter">
|
<div class="filter">
|
||||||
<div class="select">
|
<div class="select">
|
||||||
<Select
|
<Select
|
||||||
|
quiet
|
||||||
autoWidth
|
autoWidth
|
||||||
bind:value={sortBy}
|
bind:value={sortBy}
|
||||||
placeholder={null}
|
placeholder={null}
|
||||||
|
@ -336,7 +358,7 @@
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
<div class="desktop-search">
|
<div class="desktop-search">
|
||||||
<Search placeholder="Search" bind:value={searchTerm} />
|
<Search quiet placeholder="Search" bind:value={searchTerm} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -348,6 +370,7 @@
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={AppRow}
|
this={AppRow}
|
||||||
{releaseLock}
|
{releaseLock}
|
||||||
|
{editIcon}
|
||||||
{app}
|
{app}
|
||||||
{unpublishApp}
|
{unpublishApp}
|
||||||
{viewApp}
|
{viewApp}
|
||||||
|
@ -374,6 +397,7 @@
|
||||||
{/if}
|
{/if}
|
||||||
</Layout>
|
</Layout>
|
||||||
</Page>
|
</Page>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
bind:this={creationModal}
|
bind:this={creationModal}
|
||||||
padding={false}
|
padding={false}
|
||||||
|
@ -409,6 +433,7 @@
|
||||||
</ConfirmDialog>
|
</ConfirmDialog>
|
||||||
|
|
||||||
<UpdateAppModal app={selectedApp} bind:this={updatingModal} />
|
<UpdateAppModal app={selectedApp} bind:this={updatingModal} />
|
||||||
|
<ChooseIconModal app={selectedApp} bind:this={iconModal} />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.title,
|
.title,
|
||||||
|
@ -440,6 +465,11 @@
|
||||||
border-radius: var(--border-radius-s);
|
border-radius: var(--border-radius-s);
|
||||||
margin-bottom: var(--spacing-m);
|
margin-bottom: var(--spacing-m);
|
||||||
border: 1px solid var(--spectrum-global-color-gray-300);
|
border: 1px solid var(--spectrum-global-color-gray-300);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-text {
|
||||||
|
margin-top: calc(var(--spacing-xl) * -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-body {
|
.card-body {
|
||||||
|
@ -459,8 +489,8 @@
|
||||||
|
|
||||||
.select {
|
.select {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: auto auto;
|
||||||
grid-gap: 10px;
|
grid-gap: 50px;
|
||||||
}
|
}
|
||||||
.filter :global(.spectrum-ActionGroup) {
|
.filter :global(.spectrum-ActionGroup) {
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
@ -509,4 +539,8 @@
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.template-card:hover {
|
||||||
|
background: var(--spectrum-alias-background-color-tertiary);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -65,6 +65,27 @@ export function createAppStore() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function updateIcon(appId, icon) {
|
||||||
|
const response = await api.put(`/api/applications/${appId}`, { icon })
|
||||||
|
if (response.status === 200) {
|
||||||
|
store.update(state => {
|
||||||
|
const updatedAppIndex = state.findIndex(
|
||||||
|
app => app.instance._id === appId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (updatedAppIndex !== -1) {
|
||||||
|
const updatedApp = state[updatedAppIndex]
|
||||||
|
updatedApp.icon = icon
|
||||||
|
state.apps = state.splice(updatedAppIndex, 1, updatedApp)
|
||||||
|
}
|
||||||
|
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
throw new Error("Error updating icon")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function update(appId, name) {
|
async function update(appId, name) {
|
||||||
const response = await api.put(`/api/applications/${appId}`, { name })
|
const response = await api.put(`/api/applications/${appId}`, { name })
|
||||||
if (response.status === 200) {
|
if (response.status === 200) {
|
||||||
|
@ -88,6 +109,7 @@ export function createAppStore() {
|
||||||
subscribe: store.subscribe,
|
subscribe: store.subscribe,
|
||||||
load,
|
load,
|
||||||
update,
|
update,
|
||||||
|
updateIcon,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue