Merge branch 'wip'

This commit is contained in:
rxdn 2023-04-13 19:43:01 +01:00
commit 1ab3f1d45a
9 changed files with 203 additions and 191 deletions

View File

@ -10,7 +10,7 @@
</button> </button>
<script> <script>
export let icon; export let icon = undefined;
export let fullWidth = false; export let fullWidth = false;
export let disabled = false; export let disabled = false;
export let type = "submit"; export let type = "submit";

View File

@ -3,7 +3,7 @@
export let fill = true; export let fill = true;
export let footerRight = false; export let footerRight = false;
export let dropdown = false; export let dropdown = false;
export let ref; export let ref = undefined;
let dropdownActive = false; let dropdownActive = false;
</script> </script>

View File

@ -1,6 +1,8 @@
<div style="margin-bottom: 8px"> <div style="margin-bottom: 8px">
<div style="cursor: pointer;" class="inline" on:click={toggle}> <div class="inline" class:pointer={!forceAlwaysOpen} on:click={() => toggle(false)}>
{#if expanded} {#if forceAlwaysOpen}
<i class="fas fa-chevron-right"></i>
{:else if expanded}
<i class="{retractIcon}"></i> <i class="{retractIcon}"></i>
{:else} {:else}
<i class="{expandIcon}"></i> <i class="{expandIcon}"></i>
@ -36,13 +38,15 @@
<script> <script>
import {onMount} from "svelte"; import {onMount} from "svelte";
import Tooltip from "svelte-tooltip"; import Tooltip from "svelte-tooltip";
import { createEventDispatcher } from 'svelte';
export let retractIcon = "fas fa-minus"; export let retractIcon = "fas fa-minus";
export let expandIcon = "fas fa-plus"; export let expandIcon = "fas fa-plus";
export let forceAlwaysOpen = false;
export let defaultOpen = false; export let defaultOpen = false;
export let tooltip; export let tooltip = undefined;
export let tooltipUrl; export let tooltipUrl = undefined;
let expanded = false; let expanded = false;
let showOverflow = true; let showOverflow = true;
@ -52,7 +56,13 @@
let innerWidth; let innerWidth;
$: innerWidth, updateIfExpanded(); $: innerWidth, updateIfExpanded();
export function toggle() { const dispatch = createEventDispatcher();
export function toggle(force) {
if (forceAlwaysOpen && !force) {
return;
}
if (expanded) { if (expanded) {
content.style.maxHeight = 0; content.style.maxHeight = 0;
} else { } else {
@ -62,7 +72,7 @@
expanded = !expanded; expanded = !expanded;
} }
export function updateSize() { function updateSize() {
content.style.maxHeight = `${content.scrollHeight}px`; content.style.maxHeight = `${content.scrollHeight}px`;
} }
@ -73,10 +83,17 @@
} }
onMount(() => { onMount(() => {
content.addEventListener('DOMNodeInserted', updateIfExpanded); // content.addEventListener('DOMNodeInserted', updateIfExpanded);
content.addEventListener('DOMNodeRemoved', updateIfExpanded); // content.addEventListener('DOMNodeRemoved', updateIfExpanded);
if (defaultOpen) toggle(); const observer = new MutationObserver(() => {
updateIfExpanded();
setTimeout(updateIfExpanded, 300); // TODO: Move with transition height
});
observer.observe(content, { childList: true, subtree: true });
if (defaultOpen || forceAlwaysOpen) toggle(true);
}); });
</script> </script>
@ -105,4 +122,8 @@
width: 100%; width: 100%;
flex: 1; flex: 1;
} }
.pointer {
cursor: pointer;
}
</style> </style>

View File

@ -1,74 +1,76 @@
<form class="form-wrapper" on:submit|preventDefault> {#if data}
<div class="row"> <form class="form-wrapper" on:submit|preventDefault>
<Colour col3 label="Embed Colour" bind:value={data.colour}/> <div class="row">
<Input col3 label="Title" placeholder="Embed Title" bind:value={data.title}/> <Colour col3 label="Embed Colour" bind:value={data.colour}/>
<Input col3 label="Title URL (Optional)" placeholder="https://example.com" bind:value={data.url}/> <Input col3 label="Title" placeholder="Embed Title" bind:value={data.title}/>
</div> <Input col3 label="Title URL (Optional)" placeholder="https://example.com" bind:value={data.url}/>
</div>
<div class="row"> <div class="row">
<Textarea col1 label="Description" placeholder="Large text area, up to 4096 characters" <Textarea col1 label="Description" placeholder="Large text area, up to 4096 characters"
bind:value={data.description}/> bind:value={data.description}/>
</div>
<Collapsible>
<span slot="header">Author</span>
<div slot="content" class="row">
<Input col3 label="Author Name" placeholder="Author Name" bind:value={data.author.name}/>
<Input col3 label="Author Icon URL (Optional)" placeholder="https://example.com/image.png"
tooltipText="Small icon displayed in the top left" bind:value={data.author.icon_url}/>
<Input col3 label="Author URL (Optional)" placeholder="https://example.com"
tooltipText="Hyperlink on the author's name" bind:value={data.author.url}/>
</div> </div>
</Collapsible>
<Collapsible> <Collapsible forceAlwaysOpen>
<span slot="header">Images</span> <span slot="header">Author</span>
<div slot="content" class="row">
<Input col2 label="Large Image URL" placeholder="https://example.com/image.png"
bind:value={data.image_url}/>
<Input col2 label="Small Image URL" placeholder="https://example.com/image.png"
bind:value={data.thumbnail_url}/>
</div>
</Collapsible>
<Collapsible> <div slot="content" class="row">
<span slot="header">Footer</span> <Input col3 label="Author Name" placeholder="Author Name" bind:value={data.author.name}/>
<div slot="content" class="row"> <Input col3 label="Author Icon URL (Optional)" placeholder="https://example.com/image.png"
{#if footerPremiumOnly} tooltipText="Small icon displayed in the top left" bind:value={data.author.icon_url}/>
<Input col3 label="Footer Text" placeholder="Footer Text" badge="Premium" bind:value={data.footer.text}/> <Input col3 label="Author URL (Optional)" placeholder="https://example.com"
<Input col3 label="Footer Icon URL (Optional)" badge="Premium" placeholder="https://example.com/image.png" tooltipText="Hyperlink on the author's name" bind:value={data.author.url}/>
bind:value={data.footer.icon_url}/> </div>
{:else} </Collapsible>
<Input col3 label="Footer Text" placeholder="Footer Text" bind:value={data.footer.text}/>
<Input col3 label="Footer Icon URL (Optional)" placeholder="https://example.com/image.png"
bind:value={data.footer.icon_url}/>
{/if}
<DateTimePicker col3 label="Footer Timestamp (Optional)" bind:value={data.timestamp}/>
</div>
</Collapsible>
<Collapsible> <Collapsible forceAlwaysOpen>
<span slot="header">Fields</span> <span slot="header">Images</span>
<div slot="content" class="col-1"> <div slot="content" class="row">
{#each data.fields as field, i} <Input col2 label="Large Image URL" placeholder="https://example.com/image.png"
<div class="row" style="justify-content: flex-start; gap: 10px"> bind:value={data.image_url}/>
<Input col2 label="Field Name" placeholder="Field Name" bind:value={field.name}/> <Input col2 label="Small Image URL" placeholder="https://example.com/image.png"
<Checkbox label="Inline" bind:value={field.inline}/> bind:value={data.thumbnail_url}/>
</div>
</Collapsible>
<div style="margin-top: 18px; display: flex; align-self: center"> <Collapsible forceAlwaysOpen>
<Button danger icon="fas fa-trash-can" on:click={() => deleteField(i)}>Delete</Button> <span slot="header">Footer</span>
<div slot="content" class="row">
{#if footerPremiumOnly}
<Input col3 label="Footer Text" placeholder="Footer Text" badge="Premium" bind:value={data.footer.text}/>
<Input col3 label="Footer Icon URL (Optional)" badge="Premium" placeholder="https://example.com/image.png"
bind:value={data.footer.icon_url}/>
{:else}
<Input col3 label="Footer Text" placeholder="Footer Text" bind:value={data.footer.text}/>
<Input col3 label="Footer Icon URL (Optional)" placeholder="https://example.com/image.png"
bind:value={data.footer.icon_url}/>
{/if}
<DateTimePicker col3 label="Footer Timestamp (Optional)" bind:value={data.timestamp}/>
</div>
</Collapsible>
<Collapsible forceAlwaysOpen>
<span slot="header">Fields</span>
<div slot="content" class="col-1">
{#each data.fields as field, i}
<div class="row" style="justify-content: flex-start; gap: 10px">
<Input col2 label="Field Name" placeholder="Field Name" bind:value={field.name}/>
<Checkbox label="Inline" bind:value={field.inline}/>
<div style="margin-top: 18px; display: flex; align-self: center">
<Button danger icon="fas fa-trash-can" on:click={() => deleteField(i)}>Delete</Button>
</div>
</div> </div>
</div> <div class="row">
<div class="row">
<Textarea col1 label="Field Value" placeholder="Large text area, up to 1024 characters" <Textarea col1 label="Field Value" placeholder="Large text area, up to 1024 characters"
bind:value={field.value}/> bind:value={field.value}/>
</div> </div>
{/each} {/each}
<Button type="button" icon="fas fa-plus" fullWidth on:click={addField}>Add Field</Button> <Button type="button" icon="fas fa-plus" fullWidth on:click={addField}>Add Field</Button>
</div> </div>
</Collapsible> </Collapsible>
</form> </form>
{/if}
<style> <style>
.form-wrapper { .form-wrapper {
@ -98,19 +100,16 @@
import Button from "./Button.svelte"; import Button from "./Button.svelte";
export let data; export let data;
$: data = data ?? {
fields: [],
colour: '#2ECC71',
author: {},
footer: {},
};
export let footerPremiumOnly = true; export let footerPremiumOnly = true;
if (data === undefined || data === null) {
if (!data) {
data = {};
}
data.fields = [];
data.colour = '#2ECC71';
data.author = {};
data.footer = {};
}
function addField() { function addField() {
data.fields.push({name: '', value: '', inline: false}); data.fields.push({name: '', value: '', inline: false});
data = data; data = data;
@ -120,4 +119,4 @@
data.fields.splice(i, 1); data.fields.splice(i, 1);
data = data; data = data;
} }
</script> </script>

View File

@ -18,7 +18,7 @@
<script> <script>
export let icon; export let icon;
export let link; export let link = undefined;
</script> </script>
<style> <style>

View File

@ -14,8 +14,8 @@
<script> <script>
export let value; export let value;
export let label; export let label = undefined;
export let placeholder; export let placeholder = undefined;
export let disabled = false; export let disabled = false;
export let col1 = false; export let col1 = false;

View File

@ -31,7 +31,7 @@
export let value; export let value;
export let label; export let label;
export let placeholder; export let placeholder;
export let badge; export let badge = undefined;
export let disabled = false; export let disabled = false;
export let tooltipText = undefined; export let tooltipText = undefined;

View File

@ -5,105 +5,9 @@
{/if} {/if}
<form class="settings-form" on:submit|preventDefault> <form class="settings-form" on:submit|preventDefault>
<div class="row"> <Collapsible defaultOpen>
<div class="col-1-3"> <span slot="header">Ticket Properties</span>
<Input label="Panel Title" placeholder="Open a ticket!" col1=true bind:value={data.title}/> <div slot="content" class="col-1">
</div>
<div class="col-2-3">
<Textarea col1=true label="Panel Content" placeholder="By clicking the button, a ticket will be opened for you."
bind:value={data.content}/>
</div>
</div>
<div class="row">
<Colour col4=true label="Panel Colour" on:change={updateColour} bind:value={tempColour}/>
<ChannelDropdown label="Panel Channel" allowAnnouncementChannel col4 {channels} bind:value={data.channel_id}/>
<CategoryDropdown label="Ticket Category" col4 {channels} bind:value={data.category_id}/>
<Dropdown col4=true label="Form" bind:value={data.form_id}>
<option value=null>None</option>
{#each forms as form}
<option value={form.form_id}>{form.title}</option>
{/each}
</Dropdown>
</div>
<div class="row">
<Dropdown col4=true label="Button Colour" bind:value={data.button_style}>
<option value="1">Blue</option>
<option value="2">Grey</option>
<option value="3">Green</option>
<option value="4">Red</option>
</Dropdown>
<Input col4={true} label="Button Text" placeholder="Open a ticket!" bind:value={data.button_label} />
<div class="col-2" style="z-index: 1">
<label for="emoji-pick-wrapper" class="form-label">Button Emoji</label>
<div id="emoji-pick-wrapper" class="row">
<div class="col-2">
<label class="form-label" style="margin-bottom: 0 !important;">Custom Emoji</label>
<Toggle hideLabel
toggledColor="#66bb6a"
untoggledColor="#ccc"
bind:toggled={data.use_custom_emoji}
on:toggle={handleEmojiTypeChange} />
</div>
{#if data.use_custom_emoji}
<div class="multiselect-super">
<Select items={emojis}
Item={EmojiItem}
selectedValue={data.emote}
optionIdentifier="id"
getSelectionLabel={emojiNameMapper}
getOptionLabel={emojiNameMapper}
placeholderAlwaysShow={true}
on:select={handleCustomEmojiChange} />
</div>
{:else}
<EmojiInput col1=true bind:value={data.emote}/>
{/if}
</div>
</div>
</div>
<div class="row" style="justify-content: center">
<div class="col-3">
<Button icon="fas fa-sliders-h" fullWidth=true type="button"
on:click={toggleAdvancedSettings}>Toggle Advanced Settings
</Button>
</div>
</div>
<div class="row advanced-settings" class:advanced-settings-show={advancedSettings}
class:advanced-settings-hide={!advancedSettings} class:show-overflow={overflowShow}>
<div class="inner" class:inner-show={advancedSettings} class:absolute={advancedSettings && !overflowShow} >
<div class="row">
<div class="col-2">
<label class="form-label">Welcome Message</label>
<div class="row" style="justify-content: flex-start; gap: 10px">
<Button icon="fas fa-brush" on:click={openWelcomeMessageBuilder}>Open Editor</Button>
<Button icon="fas fa-trash-can" danger
on:click={() => data.welcome_message = null}>Clear</Button>
</div>
</div>
<div class="col-2">
<label for="naming-scheme-wrapper" class="form-label">Naming Scheme</label>
<div class="row" id="naming-scheme-wrapper">
<div>
<label class="form-label">Use Server Default</label>
<Toggle hideLabel
toggledColor="#66bb6a"
untoggledColor="#ccc"
bind:toggled={data.use_server_default_naming_scheme} />
</div>
<div class="col-fill">
{#if !data.use_server_default_naming_scheme}
<Input label="Naming Scheme"
bind:value={data.naming_scheme}
placeholder="ticket-%id%"
tooltipText="Click here for the full placeholder list"
tooltipLink="https://docs.ticketsbot.net" />
{/if}
</div>
</div>
</div>
</div>
<div class="row"> <div class="row">
<div class="col-2"> <div class="col-2">
<label class="form-label">Mention On Open</label> <label class="form-label">Mention On Open</label>
@ -132,11 +36,35 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row"> <div class="incomplete-row">
<Input col2={true} label="Large Image URL" bind:value={data.image_url} placeholder="https://example.com/image.png" /> <CategoryDropdown label="Ticket Category" col3 {channels} bind:value={data.category_id}/>
<Input col2={true} label="Small Image URL" bind:value={data.thumbnail_url} placeholder="https://example.com/image.png" />
<Dropdown col4 label="Form" bind:value={data.form_id}>
<option value=null>None</option>
{#each forms as form}
<option value={form.form_id}>{form.title}</option>
{/each}
</Dropdown>
</div> </div>
</div>
</Collapsible>
<Collapsible defaultOpen>
<span slot="header">Panel Message</span>
<div slot="content" class="col-1">
<div class="row"> <div class="row">
<div class="col-1-3">
<Input label="Panel Title" placeholder="Open a ticket!" col1=true bind:value={data.title}/>
</div>
<div class="col-2-3">
<Textarea col1=true label="Panel Content" placeholder="By clicking the button, a ticket will be opened for you."
bind:value={data.content}/>
</div>
</div>
<div class="row">
<Colour col4=true label="Panel Colour" on:change={updateColour} bind:value={tempColour}/>
<ChannelDropdown label="Panel Channel" allowAnnouncementChannel col4 {channels} bind:value={data.channel_id}/>
<div class="col-2"> <div class="col-2">
<div class="row" style="justify-content: flex-start; gap: 10px"> <div class="row" style="justify-content: flex-start; gap: 10px">
<div style="white-space: nowrap"> <div style="white-space: nowrap">
@ -148,8 +76,62 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<Dropdown col4=true label="Button Colour" bind:value={data.button_style}>
<option value="1">Blue</option>
<option value="2">Grey</option>
<option value="3">Green</option>
<option value="4">Red</option>
</Dropdown>
<Input col4={true} label="Button Text" placeholder="Open a ticket!" bind:value={data.button_label} />
<div class="col-2" style="z-index: 1">
<label for="emoji-pick-wrapper" class="form-label">Button Emoji</label>
<div id="emoji-pick-wrapper" class="row">
<div class="col-2">
<label class="form-label" style="margin-bottom: 0 !important;">Custom Emoji</label>
<Toggle hideLabel
toggledColor="#66bb6a"
untoggledColor="#ccc"
bind:toggled={data.use_custom_emoji}
on:toggle={handleEmojiTypeChange} />
</div>
{#if data.use_custom_emoji}
<div class="multiselect-super">
<Select items={emojis}
Item={EmojiItem}
selectedValue={data.emote}
optionIdentifier="id"
getSelectionLabel={emojiNameMapper}
getOptionLabel={emojiNameMapper}
placeholderAlwaysShow={true}
on:select={handleCustomEmojiChange} />
</div>
{:else}
<EmojiInput col1=true bind:value={data.emote}/>
{/if}
</div>
</div>
</div>
<div class="row">
<Input col2={true} label="Large Image URL" badge="Optional" bind:value={data.image_url} placeholder="https://example.com/image.png" />
<Input col2={true} label="Small Image URL" badge="Optional" bind:value={data.thumbnail_url} placeholder="https://example.com/image.png" />
</div>
</div> </div>
</div> </Collapsible>
<Collapsible>
<span slot="header">Welcome Message</span>
<div slot="content" class="col-1">
<div class="row">
<EmbedForm bind:data={data.welcome_message} />
</div>
</div>
</Collapsible>
</form> </form>
<script> <script>
@ -169,6 +151,8 @@
import Dropdown from "../form/Dropdown.svelte"; import Dropdown from "../form/Dropdown.svelte";
import Toggle from "svelte-toggle"; import Toggle from "svelte-toggle";
import Checkbox from "../form/Checkbox.svelte"; import Checkbox from "../form/Checkbox.svelte";
import Collapsible from "../Collapsible.svelte";
import EmbedForm from "../EmbedForm.svelte";
export let guildId; export let guildId;
export let seedDefault = true; export let seedDefault = true;
@ -346,6 +330,14 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
.incomplete-row {
display: flex;
flex-direction: row;
gap: 10px;
width: 100%;
margin-bottom: 10px;
}
form { form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@ -13,7 +13,7 @@
<!--<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet">--> <!--<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700" rel="stylesheet">-->
<!-- Icons --> <!-- Icons -->
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.1.1/css/all.css"> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v6.4.0/css/all.css">
<!-- GA --> <!-- GA -->
<script async src='https://www.google-analytics.com/analytics.js' <script async src='https://www.google-analytics.com/analytics.js'