Skip to content
Merged

Deploy #1776

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions apps/frontend/shared/components/forms/Button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script lang="ts">
import type { ChildrenProp } from '@/types/props';

type Props = ChildrenProp & {
cls?: string;
disabled?: boolean;
onclick?: (e: Event) => void;
};
let { children, cls, disabled, onclick }: Props = $props();
</script>

<style lang="scss">
button {
background: var(--button-background);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
cursor: pointer;
display: block;

&:disabled {
cursor: inherit;
opacity: 0.7;
}
}
</style>

<button class={cls} {disabled} {onclick}>
{@render children?.()}
</button>
18 changes: 18 additions & 0 deletions apps/frontend/shared/components/forms/TextArea.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts">
type Props = {
value: string;
disabled?: boolean;
placeholder?: string;
rows?: number;
onclick?: (e: Event) => void;
};
let { value = $bindable(), disabled, placeholder, rows = 4, onclick }: Props = $props();
</script>

<style lang="scss">
textarea {
width: 100%;
}
</style>

<textarea {disabled} {placeholder} {rows} {onclick} bind:value />
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<script lang="ts">
import cloneDeep from 'lodash/cloneDeep';
import { onMount } from 'svelte';

import { settingsState } from '@/shared/state/settings.svelte';
Expand All @@ -17,6 +18,8 @@

let { params }: { params: { viewId: string } } = $props();

let copied = $state(false);

let view = $derived.by(() =>
(settingsState.value.views || []).find((view) => view.id === params.viewId)
);
Expand All @@ -25,6 +28,28 @@
view.homeFields = (e as CustomEvent<string[]>).detail;
};

const copyView = () => {
const copy = cloneDeep(view);

copy.id = '';
copy.choreFilters = {};

// Reset disabledChores for any non-active tasks
const tasks = Object.keys(copy.homeTasks).map((key) => key.split('|')[0]);
const taskKeys = Object.keys(copy.disabledChores);
for (const taskKey of taskKeys) {
if (!tasks.includes(taskKey)) {
delete copy.disabledChores[taskKey];
}
}

const json = JSON.stringify(copy);
navigator.clipboard.writeText(json);

copied = true;
setTimeout(() => (copied = false), 5000);
};

onMount(() => {
document.addEventListener('homeFieldsUpdated', onHomeFieldsUpdated);
return () => {
Expand All @@ -44,6 +69,15 @@
background: var(--color-highlight-background);
}
}
button {
background: #0f2f0f;
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
cursor: pointer;
display: block;
font-size: 1.2rem;
margin: 1rem auto 0;
}
</style>

{#if view}
Expand All @@ -64,6 +98,15 @@
bind:value={view.characterFilter}
/>
</div>
<div class="export">
<button disabled={copied} onclick={copyView}>
{#if copied}
Copied to clipboard!
{:else}
Copy view to clipboard
{/if}
</button>
</div>
</div>

<div class="settings-block">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,50 @@
import { settingsState } from '@/shared/state/settings.svelte';
import type { SettingsView } from '@/shared/stores/settings/types';

import Button from '@/shared/components/forms/Button.svelte';
import IconifyWrapper from '@/shared/components/images/IconifyWrapper.svelte';
import TextArea from '@/shared/components/forms/TextArea.svelte';

let deleting = $state<string>(null);
let importJson = $state<string>('');

const newView = () => {
let importEnabled = $derived.by(() => {
if (!importJson) {
return false;
}

let parsed: SettingsView;
try {
parsed = JSON.parse(importJson);
} catch {
return false;
}

return (
parsed &&
typeof parsed === 'object' &&
typeof parsed.name === 'string' &&
typeof parsed.characterFilter === 'string' &&
typeof parsed.showCompletedUntrackedChores === 'boolean' &&
typeof parsed.choreFilters === 'object' &&
typeof parsed.disabledChores === 'object' &&
[
'groups',
'groupBy',
'sortBy',
'commonFields',
'homeCurrencies',
'homeFields',
'homeItems',
'homeLockouts',
'homeProfessionsV2',
'homeProgress',
'homeTasks',
].every((k) => Array.isArray(parsed[k as keyof SettingsView]))
);
});

const newView = (changeView = true) => {
const view: SettingsView = {
id: crypto.randomUUID(),
name: 'NEW',
Expand All @@ -18,8 +57,8 @@
groupBy: [],
sortBy: [],
commonFields: settingsState.value.views[0].commonFields,
homeFields: [],
homeCurrencies: [],
homeFields: [],
homeItems: [],
homeLockouts: [],
homeProfessionsV2: [],
Expand All @@ -33,7 +72,34 @@
newCustomViews.push(view);

settingsState.value.views = newCustomViews;
browserState.current.settings.selectedView = view.id;

if (changeView) {
browserState.current.settings.selectedView = view.id;
}

return view;
};

const importView = () => {
const parsed = JSON.parse(importJson);

const view = newView(false);
view.name = `${parsed.name} [IMPORT]`;
view.characterFilter = parsed.characterFilter;
view.showCompletedUntrackedChores = parsed.showCompletedUntrackedChores;
view.groups = parsed.groups;
view.groupBy = parsed.groupBy;
view.sortBy = parsed.sortBy;
view.commonFields = parsed.commonFields;
view.homeCurrencies = parsed.homeCurrencies;
view.homeFields = parsed.homeFields;
view.homeItems = parsed.homeItems;
view.homeLockouts = parsed.homeLockouts;
view.homeProfessionsV2 = parsed.homeProfessionsV2;
view.homeProgress = parsed.homeProgress;
view.homeTasks = parsed.homeTasks;
view.choreFilters = parsed.choreFilters;
view.disabledChores = parsed.disabledChores;
};

const moveUpClick = (index: number) => {
Expand Down Expand Up @@ -94,15 +160,11 @@
cursor: pointer;
}
}
button {
cursor: pointer;
margin-top: 0.75rem;
}
</style>

<div class="settings-block">
<h3>Views</h3>
<h2>Views</h2>

<div class="settings-block">
<p>
The first View will be used as your default grouping/sorting on pages other than Home, don't
set it to anything that will annoy you.
Expand Down Expand Up @@ -162,8 +224,17 @@
</table>

{#if settingsState.value.views.length < 10}
<button class="group-entry bg-success border b-success b-radius" onclick={newView}>
<button class="group-entry bg-success border b-success b-radius" onclick={() => newView()}>
New View
</button>
{/if}
</div>

<div class="settings-block">
<TextArea placeholder="Paste view JSON here" rows={8} bind:value={importJson} />
<Button
cls={importEnabled ? 'bg-success border-success' : 'bg-warn border-warn'}
disabled={!importEnabled}
onclick={importView}>Import View</Button
>
</div>
Loading