1
0
mirror of https://github.com/koloml/furbooru-tagging-assistant.git synced 2025-12-24 07:12:57 +00:00

Reformatting all svelte templates to use new rules

This commit is contained in:
2025-02-17 02:07:55 +04:00
parent 762652f795
commit efdd9487ad
40 changed files with 1351 additions and 1383 deletions

View File

@@ -1,26 +1,27 @@
<script lang="ts">
import "../styles/popup.scss";
import Header from "$components/layout/Header.svelte";
import Footer from "$components/layout/Footer.svelte";
interface Props {
children?: import('svelte').Snippet;
}
import "../styles/popup.scss";
import Header from "$components/layout/Header.svelte";
import Footer from "$components/layout/Footer.svelte";
let { children }: Props = $props();
interface Props {
children?: import('svelte').Snippet;
}
// Sort of a hack, detect if we rendered in the browser tab or in the popup.
// Popup will always should have fixed 320px size, otherwise we consider it opened in the tab.
document.body.classList.toggle('is-in-tab', window.innerWidth > 320);
let { children }: Props = $props();
// Sort of a hack, detect if we rendered in the browser tab or in the popup.
// Popup will always should have fixed 320px size, otherwise we consider it opened in the tab.
document.body.classList.toggle('is-in-tab', window.innerWidth > 320);
</script>
<Header/>
<main>
{@render children?.()}
{@render children?.()}
</main>
<Footer/>
<style lang="scss" global>
main {
padding: .5em 24px;
}
<style global lang="scss">
main {
padding: .5em 24px;
}
</style>

View File

@@ -1,29 +1,28 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
/** @type {import('$entities/MaintenanceProfile').default|undefined} */
let activeProfile = $derived($maintenanceProfiles.find(profile => profile.id === $activeProfileStore));
/** @type {import('$entities/MaintenanceProfile').default|undefined} */
let activeProfile = $derived($maintenanceProfiles.find(profile => profile.id === $activeProfileStore));
function turnOffActiveProfile() {
$activeProfileStore = null;
}
function turnOffActiveProfile() {
$activeProfileStore = null;
}
</script>
<Menu>
{#if activeProfile}
<MenuCheckboxItem checked on:input={turnOffActiveProfile} href="/features/maintenance/{activeProfile.id}">
Active Profile: {activeProfile.settings.name}
</MenuCheckboxItem>
<hr>
{/if}
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
<MenuItem href="/features/groups">Tag Groups</MenuItem>
{#if activeProfile}
<MenuCheckboxItem checked on:input={turnOffActiveProfile} href="/features/maintenance/{activeProfile.id}">
Active Profile: {activeProfile.settings.name}
</MenuCheckboxItem>
<hr>
<MenuItem href="/preferences">Preferences</MenuItem>
<MenuItem href="/about">About</MenuItem>
{/if}
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
<MenuItem href="/features/groups">Tag Groups</MenuItem>
<hr>
<MenuItem href="/preferences">Preferences</MenuItem>
<MenuItem href="/about">About</MenuItem>
</Menu>

View File

@@ -1,25 +1,25 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
</script>
<Menu>
<MenuItem icon="arrow-left" href="/">Back</MenuItem>
<hr>
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<h1>
Furbooru Tagging Assistant
Furbooru Tagging Assistant
</h1>
<p>
This is a tool made to help tag images on Furbooru more efficiently. It is currently in development and is not yet
ready for use, but it still can provide some useful functionality.
This is a tool made to help tag images on Furbooru more efficiently. It is currently in development and is not yet
ready for use, but it still can provide some useful functionality.
</p>
<Menu>
<hr>
<MenuItem icon="globe" href="https://furbooru.org" target="_blank">
Visit Furbooru
</MenuItem>
<MenuItem icon="info-circle" href="https://github.com/koloml/furbooru-tagging-assistant" target="_blank">
GitHub Repo
</MenuItem>
<hr>
<MenuItem href="https://furbooru.org" icon="globe" target="_blank">
Visit Furbooru
</MenuItem>
<MenuItem href="https://github.com/koloml/furbooru-tagging-assistant" icon="info-circle" target="_blank">
GitHub Repo
</MenuItem>
</Menu>

View File

@@ -1,10 +1,10 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
</script>
<Menu>
<MenuItem href="/">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
<MenuItem href="/">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
</Menu>

View File

@@ -1,27 +1,26 @@
<script>
import { run } from 'svelte/legacy';
import { run } from 'svelte/legacy';
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
/** @type {import('$entities/TagGroup').default[]} */
let groups = $state([]);
/** @type {import('$entities/TagGroup').default[]} */
let groups = $state([]);
run(() => {
groups = $tagGroups.sort((a, b) => a.settings.name.localeCompare(b.settings.name));
});
run(() => {
groups = $tagGroups.sort((a, b) => a.settings.name.localeCompare(b.settings.name));
});
</script>
<Menu>
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/groups/new/edit" icon="plus">Create New</MenuItem>
{#if groups.length}
<hr>
{#each groups as group}
<MenuItem href="/features/groups/{group.id}">{group.settings.name}</MenuItem>
{/each}
{/if}
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/groups/new/edit" icon="plus">Create New</MenuItem>
{#if groups.length}
<hr>
<MenuItem href="/features/groups/import">Import Group</MenuItem>
{#each groups as group}
<MenuItem href="/features/groups/{group.id}">{group.settings.name}</MenuItem>
{/each}
{/if}
<hr>
<MenuItem href="/features/groups/import">Import Group</MenuItem>
</Menu>

View File

@@ -1,41 +1,40 @@
<script>
import { run } from 'svelte/legacy';
import { run } from 'svelte/legacy';
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import GroupView from "$components/features/GroupView.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import GroupView from "$components/features/GroupView.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
const groupId = $page.params.id;
/** @type {import('$entities/TagGroup').default|null} */
let group = $state(null);
const groupId = $page.params.id;
/** @type {import('$entities/TagGroup').default|null} */
let group = $state(null);
if (groupId === 'new') {
goto('/features/groups/new/edit');
}
if (groupId === 'new') {
goto('/features/groups/new/edit');
run(() => {
group = $tagGroups.find(group => group.id === groupId) || null;
if (!group) {
console.warn(`Group ${groupId} not found.`);
goto('/features/groups');
}
run(() => {
group = $tagGroups.find(group => group.id === groupId) || null;
if (!group) {
console.warn(`Group ${groupId} not found.`);
goto('/features/groups');
}
});
});
</script>
<Menu>
<MenuItem href="/features/groups" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/features/groups" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if group}
<GroupView {group}/>
<GroupView {group}/>
{/if}
<Menu>
<hr>
<MenuItem href="/features/groups/{groupId}/edit" icon="wrench">Edit Group</MenuItem>
<MenuItem href="/features/groups/{groupId}/export" icon="file-export">Export Group</MenuItem>
<MenuItem href="/features/groups/{groupId}/delete" icon="trash">Delete Group</MenuItem>
<hr>
<MenuItem href="/features/groups/{groupId}/edit" icon="wrench">Edit Group</MenuItem>
<MenuItem href="/features/groups/{groupId}/export" icon="file-export">Export Group</MenuItem>
<MenuItem href="/features/groups/{groupId}/delete" icon="trash">Delete Group</MenuItem>
</Menu>

View File

@@ -1,41 +1,41 @@
<script>
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { tagGroups } from "$stores/entities/tag-groups";
const groupId = $page.params.id;
const targetGroup = $tagGroups.find(group => group.id === groupId);
const groupId = $page.params.id;
const targetGroup = $tagGroups.find(group => group.id === groupId);
if (!targetGroup) {
void goto('/features/groups');
}
async function deleteGroup() {
if (!targetGroup) {
void goto('/features/groups');
console.warn('Attempting to delete the group, but the group is not loaded yet.');
return;
}
async function deleteGroup() {
if (!targetGroup) {
console.warn('Attempting to delete the group, but the group is not loaded yet.');
return;
}
await targetGroup.delete();
await goto('/features/groups');
}
await targetGroup.delete();
await goto('/features/groups');
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/features/groups/{groupId}">Back</MenuItem>
<hr>
<MenuItem href="/features/groups/{groupId}" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if targetGroup}
<p>
Do you want to remove group "{targetGroup.settings.name}"? This action is irreversible.
</p>
<Menu>
<hr>
<MenuItem on:click={deleteGroup}>Yes</MenuItem>
<MenuItem href="/features/groups/{groupId}">No</MenuItem>
</Menu>
<p>
Do you want to remove group "{targetGroup.settings.name}"? This action is irreversible.
</p>
<Menu>
<hr>
<MenuItem on:click={deleteGroup}>Yes</MenuItem>
<MenuItem href="/features/groups/{groupId}">No</MenuItem>
</Menu>
{:else}
<p>Loading...</p>
<p>Loading...</p>
{/if}

View File

@@ -1,82 +1,82 @@
<script>
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import TagsColorContainer from "$components/tags/TagsColorContainer.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import TagCategorySelectField from "$components/ui/forms/TagCategorySelectField.svelte";
import TextField from "$components/ui/forms/TextField.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagsEditor from "$components/tags/TagsEditor.svelte";
import TagGroup from "$entities/TagGroup";
import { tagGroups } from "$stores/entities/tag-groups";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import TagsColorContainer from "$components/tags/TagsColorContainer.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import TagCategorySelectField from "$components/ui/forms/TagCategorySelectField.svelte";
import TextField from "$components/ui/forms/TextField.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagsEditor from "$components/tags/TagsEditor.svelte";
import TagGroup from "$entities/TagGroup";
import { tagGroups } from "$stores/entities/tag-groups";
const groupId = $page.params.id;
/** @type {TagGroup|null} */
let targetGroup = null;
const groupId = $page.params.id;
/** @type {TagGroup|null} */
let targetGroup = null;
let groupName = $state('');
/** @type {string[]} */
let tagsList = $state([]);
/** @type {string[]} */
let prefixesList = $state([]);
let tagCategory = $state('');
let groupName = $state('');
/** @type {string[]} */
let tagsList = $state([]);
/** @type {string[]} */
let prefixesList = $state([]);
let tagCategory = $state('');
if (groupId === 'new') {
targetGroup = new TagGroup(crypto.randomUUID(), {});
if (groupId === 'new') {
targetGroup = new TagGroup(crypto.randomUUID(), {});
} else {
targetGroup = $tagGroups.find(group => group.id === groupId) || null;
if (targetGroup) {
groupName = targetGroup.settings.name;
tagsList = [...targetGroup.settings.tags].sort((a, b) => a.localeCompare(b));
prefixesList = [...targetGroup.settings.prefixes].sort((a, b) => a.localeCompare(b));
tagCategory = targetGroup.settings.category;
} else {
targetGroup = $tagGroups.find(group => group.id === groupId) || null;
goto('/features/groups');
}
}
if (targetGroup) {
groupName = targetGroup.settings.name;
tagsList = [...targetGroup.settings.tags].sort((a, b) => a.localeCompare(b));
prefixesList = [...targetGroup.settings.prefixes].sort((a, b) => a.localeCompare(b));
tagCategory = targetGroup.settings.category;
} else {
goto('/features/groups');
}
async function saveGroup() {
if (!targetGroup) {
console.warn('Attempting to save group, but group is not loaded yet.');
return;
}
async function saveGroup() {
if (!targetGroup) {
console.warn('Attempting to save group, but group is not loaded yet.');
return;
}
targetGroup.settings.name = groupName;
targetGroup.settings.tags = [...tagsList];
targetGroup.settings.prefixes = [...prefixesList];
targetGroup.settings.category = tagCategory;
targetGroup.settings.name = groupName;
targetGroup.settings.tags = [...tagsList];
targetGroup.settings.prefixes = [...prefixesList];
targetGroup.settings.category = tagCategory;
await targetGroup.save();
await goto(`/features/groups/${targetGroup.id}`);
}
await targetGroup.save();
await goto(`/features/groups/${targetGroup.id}`);
}
</script>
<Menu>
<MenuItem href="/features/groups/${groupId}" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/features/groups/${groupId}" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl label="Group Name">
<TextField bind:value={groupName} placeholder="Group Name"></TextField>
<FormControl label="Group Name">
<TextField bind:value={groupName} placeholder="Group Name"></TextField>
</FormControl>
<FormControl label="Group Color">
<TagCategorySelectField bind:value={tagCategory}/>
</FormControl>
<TagsColorContainer targetCategory="{tagCategory}">
<FormControl label="Tags">
<TagsEditor bind:tags={tagsList}/>
</FormControl>
<FormControl label="Group Color">
<TagCategorySelectField bind:value={tagCategory}/>
</TagsColorContainer>
<TagsColorContainer targetCategory="{tagCategory}">
<FormControl label="Tag Prefixes">
<TagsEditor bind:tags={prefixesList}/>
</FormControl>
<TagsColorContainer targetCategory="{tagCategory}">
<FormControl label="Tags">
<TagsEditor bind:tags={tagsList}/>
</FormControl>
</TagsColorContainer>
<TagsColorContainer targetCategory="{tagCategory}">
<FormControl label="Tag Prefixes">
<TagsEditor bind:tags={prefixesList}/>
</FormControl>
</TagsColorContainer>
</TagsColorContainer>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={saveGroup}>Save Group</MenuItem>
<hr>
<MenuItem on:click={saveGroup}>Save Group</MenuItem>
</Menu>

View File

@@ -1,50 +1,50 @@
<script>
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagGroup from "$entities/TagGroup";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import { tagGroups } from "$stores/entities/tag-groups";
import { goto } from "$app/navigation";
import { page } from "$app/stores";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagGroup from "$entities/TagGroup";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import { tagGroups } from "$stores/entities/tag-groups";
const groupId = $page.params.id;
const groupTransporter = new EntitiesTransporter(TagGroup);
const group = $tagGroups.find(group => group.id === groupId);
const groupId = $page.params.id;
const groupTransporter = new EntitiesTransporter(TagGroup);
const group = $tagGroups.find(group => group.id === groupId);
/** @type {string} */
let rawExportedGroup = $state();
/** @type {string} */
let encodedExportedGroup = $state();
/** @type {string} */
let rawExportedGroup = $state();
/** @type {string} */
let encodedExportedGroup = $state();
if (!group) {
goto('/features/groups');
} else {
rawExportedGroup = groupTransporter.exportToJSON(group);
encodedExportedGroup = groupTransporter.exportToCompressedJSON(group);
}
if (!group) {
goto('/features/groups');
} else {
rawExportedGroup = groupTransporter.exportToJSON(group);
encodedExportedGroup = groupTransporter.exportToCompressedJSON(group);
}
let isEncodedGroupShown = $state(true);
let isEncodedGroupShown = $state(true);
</script>
<Menu>
<MenuItem href="/features/groups/{groupId}" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/features/groups/{groupId}" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl label="Export string">
<textarea readonly rows="6">{isEncodedGroupShown ? encodedExportedGroup : rawExportedGroup}</textarea>
</FormControl>
<FormControl label="Export string">
<textarea readonly rows="6">{isEncodedGroupShown ? encodedExportedGroup : rawExportedGroup}</textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={() => isEncodedGroupShown = !isEncodedGroupShown}>
Switch Format:
{#if isEncodedGroupShown}
Base64-Encoded
{:else}
Raw JSON
{/if}
</MenuItem>
<hr>
<MenuItem on:click={() => isEncodedGroupShown = !isEncodedGroupShown}>
Switch Format:
{#if isEncodedGroupShown}
Base64-Encoded
{:else}
Raw JSON
{/if}
</MenuItem>
</Menu>

View File

@@ -1,134 +1,134 @@
<script>
import { goto } from "$app/navigation";
import GroupView from "$components/features/GroupView.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagGroup from "$entities/TagGroup";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import { tagGroups } from "$stores/entities/tag-groups";
import { goto } from "$app/navigation";
import GroupView from "$components/features/GroupView.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagGroup from "$entities/TagGroup";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import { tagGroups } from "$stores/entities/tag-groups";
const groupTransporter = new EntitiesTransporter(TagGroup);
const groupTransporter = new EntitiesTransporter(TagGroup);
/** @type {string} */
let importedString = $state('');
/** @type {string} */
let errorMessage = $state('');
/** @type {string} */
let importedString = $state('');
/** @type {string} */
let errorMessage = $state('');
/** @type {TagGroup|null} */
let candidateGroup = $state(null);
/** @type {TagGroup|null} */
let existingGroup = $state(null);
/** @type {TagGroup|null} */
let candidateGroup = $state(null);
/** @type {TagGroup|null} */
let existingGroup = $state(null);
function tryImportingGroup() {
candidateGroup = null;
existingGroup = null;
function tryImportingGroup() {
candidateGroup = null;
existingGroup = null;
errorMessage = '';
importedString = importedString.trim();
errorMessage = '';
importedString = importedString.trim();
if (!importedString) {
errorMessage = 'Nothing to import.';
return;
}
try {
if (importedString.trim().startsWith('{')) {
candidateGroup = groupTransporter.importFromJSON(importedString);
}
candidateGroup = groupTransporter.importFromCompressedJSON(importedString);
} catch (error) {
errorMessage = error instanceof Error
? error.message
: 'Unknown error';
}
if (candidateGroup) {
existingGroup = $tagGroups.find(group => group.id === candidateGroup?.id) ?? null;
}
if (!importedString) {
errorMessage = 'Nothing to import.';
return;
}
function saveGroup() {
if (!candidateGroup) {
return;
}
try {
if (importedString.trim().startsWith('{')) {
candidateGroup = groupTransporter.importFromJSON(importedString);
}
candidateGroup.save().then(() => {
goto(`/features/groups`);
});
candidateGroup = groupTransporter.importFromCompressedJSON(importedString);
} catch (error) {
errorMessage = error instanceof Error
? error.message
: 'Unknown error';
}
function cloneAndSaveGroup() {
if (!candidateGroup) {
return;
}
const clonedProfile = new TagGroup(crypto.randomUUID(), candidateGroup.settings);
clonedProfile.settings.name += ` (Clone ${new Date().toISOString()})`;
clonedProfile.save().then(() => {
goto(`/features/groups`);
});
if (candidateGroup) {
existingGroup = $tagGroups.find(group => group.id === candidateGroup?.id) ?? null;
}
}
function saveGroup() {
if (!candidateGroup) {
return;
}
candidateGroup.save().then(() => {
goto(`/features/groups`);
});
}
function cloneAndSaveGroup() {
if (!candidateGroup) {
return;
}
const clonedProfile = new TagGroup(crypto.randomUUID(), candidateGroup.settings);
clonedProfile.settings.name += ` (Clone ${new Date().toISOString()})`;
clonedProfile.save().then(() => {
goto(`/features/groups`);
});
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/features/groups">Back</MenuItem>
<hr>
<MenuItem href="/features/groups" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if errorMessage}
<p class="error">Failed to import: {errorMessage}</p>
<Menu>
<hr>
</Menu>
<p class="error">Failed to import: {errorMessage}</p>
<Menu>
<hr>
</Menu>
{/if}
{#if !candidateGroup}
<FormContainer>
<FormControl label="Import string">
<textarea bind:value={importedString} rows="6"></textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={tryImportingGroup}>Import</MenuItem>
</Menu>
<FormContainer>
<FormControl label="Import string">
<textarea bind:value={importedString} rows="6"></textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={tryImportingGroup}>Import</MenuItem>
</Menu>
{:else}
{#if existingGroup}
<p class="warning">
This group will replace the existing "{existingGroup.settings.name}" group, since it have the same ID.
</p>
{/if}
<GroupView group="{candidateGroup}"></GroupView>
<Menu>
<hr>
{#if existingGroup}
<p class="warning">
This group will replace the existing "{existingGroup.settings.name}" group, since it have the same ID.
</p>
<MenuItem on:click={saveGroup}>Replace Existing Group</MenuItem>
<MenuItem on:click={cloneAndSaveGroup}>Save as New Group</MenuItem>
{:else}
<MenuItem on:click={saveGroup}>Import New Group</MenuItem>
{/if}
<GroupView group="{candidateGroup}"></GroupView>
<Menu>
<hr>
{#if existingGroup}
<MenuItem on:click={saveGroup}>Replace Existing Group</MenuItem>
<MenuItem on:click={cloneAndSaveGroup}>Save as New Group</MenuItem>
{:else}
<MenuItem on:click={saveGroup}>Import New Group</MenuItem>
{/if}
<MenuItem on:click={() => candidateGroup = null}>Cancel</MenuItem>
</Menu>
<MenuItem on:click={() => candidateGroup = null}>Cancel</MenuItem>
</Menu>
{/if}
<style lang="scss">
@use '$styles/colors';
@use '$styles/colors';
.error, .warning {
padding: 5px 24px;
margin: {
left: -24px;
right: -24px;
}
.error, .warning {
padding: 5px 24px;
margin: {
left: -24px;
right: -24px;
}
}
.error {
background: colors.$error-background;
}
.error {
background: colors.$error-background;
}
.warning {
background: colors.$warning-background;
margin-bottom: .5em;
}
.warning {
background: colors.$warning-background;
margin-bottom: .5em;
}
</style>

View File

@@ -1,50 +1,49 @@
<script>
import { run } from 'svelte/legacy';
import { run } from 'svelte/legacy';
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import MenuRadioItem from "$components/ui/menu/MenuRadioItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import MenuRadioItem from "$components/ui/menu/MenuRadioItem.svelte";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
/** @type {import('$entities/MaintenanceProfile').default[]} */
let profiles = $state([]);
/** @type {import('$entities/MaintenanceProfile').default[]} */
let profiles = $state([]);
run(() => {
profiles = $maintenanceProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name));
});
run(() => {
profiles = $maintenanceProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name));
});
function resetActiveProfile() {
$activeProfileStore = null;
}
function resetActiveProfile() {
$activeProfileStore = null;
}
/**
* @param {Event} event
*/
function enableSelectedProfile(event) {
const target = event.target;
if (target instanceof HTMLInputElement && target.checked) {
activeProfileStore.set(target.value);
}
/**
* @param {Event} event
*/
function enableSelectedProfile(event) {
const target = event.target;
if (target instanceof HTMLInputElement && target.checked) {
activeProfileStore.set(target.value);
}
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/">Back</MenuItem>
<MenuItem icon="plus" href="/features/maintenance/new/edit">Create New</MenuItem>
{#if profiles.length}
<hr>
{/if}
{#each profiles as profile}
<MenuRadioItem href="/features/maintenance/{profile.id}"
name="active-profile"
value="{profile.id}"
checked="{$activeProfileStore === profile.id}"
on:input={enableSelectedProfile}>
{profile.settings.name}
</MenuRadioItem>
{/each}
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<MenuItem href="/features/maintenance/new/edit" icon="plus">Create New</MenuItem>
{#if profiles.length}
<hr>
<MenuItem href="#" on:click={resetActiveProfile}>Reset Active Profile</MenuItem>
<MenuItem href="/features/maintenance/import">Import Profile</MenuItem>
{/if}
{#each profiles as profile}
<MenuRadioItem href="/features/maintenance/{profile.id}"
name="active-profile"
value="{profile.id}"
checked="{$activeProfileStore === profile.id}"
on:input={enableSelectedProfile}>
{profile.settings.name}
</MenuRadioItem>
{/each}
<hr>
<MenuItem href="#" on:click={resetActiveProfile}>Reset Active Profile</MenuItem>
<MenuItem href="/features/maintenance/import">Import Profile</MenuItem>
</Menu>

View File

@@ -1,65 +1,64 @@
<script>
import { run } from 'svelte/legacy';
import { run } from 'svelte/legacy';
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import ProfileView from "$components/features/ProfileView.svelte";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { activeProfileStore, maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import ProfileView from "$components/features/ProfileView.svelte";
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
const profileId = $page.params.id;
/** @type {import('$entities/MaintenanceProfile').default|null} */
let profile = $state(null);
const profileId = $page.params.id;
/** @type {import('$entities/MaintenanceProfile').default|null} */
let profile = $state(null);
if (profileId === 'new') {
goto('/features/maintenance/new/edit');
}
if (profileId === 'new') {
goto('/features/maintenance/new/edit');
run(() => {
const resolvedProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
if (resolvedProfile) {
profile = resolvedProfile;
} else {
console.warn(`Profile ${profileId} not found.`);
goto('/features/maintenance');
}
});
let isActiveProfile = $state($activeProfileStore === profileId);
run(() => {
if (isActiveProfile && $activeProfileStore !== profileId) {
$activeProfileStore = profileId;
}
run(() => {
const resolvedProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
if (resolvedProfile) {
profile = resolvedProfile;
} else {
console.warn(`Profile ${profileId} not found.`);
goto('/features/maintenance');
}
});
let isActiveProfile = $state($activeProfileStore === profileId);
run(() => {
if (isActiveProfile && $activeProfileStore !== profileId) {
$activeProfileStore = profileId;
}
if (!isActiveProfile && $activeProfileStore === profileId) {
$activeProfileStore = null;
}
});
if (!isActiveProfile && $activeProfileStore === profileId) {
$activeProfileStore = null;
}
});
</script>
<Menu>
<MenuItem href="/features/maintenance" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if profile}
<ProfileView {profile}/>
<ProfileView {profile}/>
{/if}
<Menu>
<hr>
<MenuItem icon="wrench" href="/features/maintenance/{profileId}/edit">Edit Profile</MenuItem>
<MenuCheckboxItem bind:checked={isActiveProfile}>
Activate Profile
</MenuCheckboxItem>
<MenuItem icon="file-export" href="/features/maintenance/{profileId}/export">
Export Profile
</MenuItem>
<MenuItem icon="trash" href="/features/maintenance/{profileId}/delete">
Delete Profile
</MenuItem>
<hr>
<MenuItem href="/features/maintenance/{profileId}/edit" icon="wrench">Edit Profile</MenuItem>
<MenuCheckboxItem bind:checked={isActiveProfile}>
Activate Profile
</MenuCheckboxItem>
<MenuItem href="/features/maintenance/{profileId}/export" icon="file-export">
Export Profile
</MenuItem>
<MenuItem href="/features/maintenance/{profileId}/delete" icon="trash">
Delete Profile
</MenuItem>
</Menu>
<style lang="scss">

View File

@@ -1,41 +1,41 @@
<script>
import { goto } from "$app/navigation";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/stores";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { goto } from "$app/navigation";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { page } from "$app/stores";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
const profileId = $page.params.id;
const targetProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
const profileId = $page.params.id;
const targetProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
if (!targetProfile) {
void goto('/features/maintenance');
}
async function deleteProfile() {
if (!targetProfile) {
void goto('/features/maintenance');
console.warn('Attempting to delete the profile, but the profile is not loaded yet.');
return;
}
async function deleteProfile() {
if (!targetProfile) {
console.warn('Attempting to delete the profile, but the profile is not loaded yet.');
return;
}
await targetProfile.delete();
await goto('/features/maintenance');
}
await targetProfile.delete();
await goto('/features/maintenance');
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/features/maintenance/{profileId}">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance/{profileId}" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if targetProfile}
<p>
Do you want to remove profile "{targetProfile.settings.name}"? This action is irreversible.
</p>
<Menu>
<hr>
<MenuItem on:click={deleteProfile}>Yes</MenuItem>
<MenuItem href="/features/maintenance/{profileId}">No</MenuItem>
</Menu>
<p>
Do you want to remove profile "{targetProfile.settings.name}"? This action is irreversible.
</p>
<Menu>
<hr>
<MenuItem on:click={deleteProfile}>Yes</MenuItem>
<MenuItem href="/features/maintenance/{profileId}">No</MenuItem>
</Menu>
{:else}
<p>Loading...</p>
<p>Loading...</p>
{/if}

View File

@@ -1,69 +1,69 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagsEditor from "$components/tags/TagsEditor.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import TextField from "$components/ui/forms/TextField.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import TagsEditor from "$components/tags/TagsEditor.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import TextField from "$components/ui/forms/TextField.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import MaintenanceProfile from "$entities/MaintenanceProfile";
/** @type {string} */
let profileId = $page.params.id;
/** @type {MaintenanceProfile|null} */
let targetProfile = null;
/** @type {string} */
let profileId = $page.params.id;
/** @type {MaintenanceProfile|null} */
let targetProfile = null;
/** @type {string} */
let profileName = $state('');
/** @type {string[]} */
let tagsList = $state([]);
/** @type {string} */
let profileName = $state('');
/** @type {string[]} */
let tagsList = $state([]);
if (profileId === 'new') {
targetProfile = new MaintenanceProfile(crypto.randomUUID(), {});
if (profileId === 'new') {
targetProfile = new MaintenanceProfile(crypto.randomUUID(), {});
} else {
const maybeExistingProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
if (maybeExistingProfile) {
targetProfile = maybeExistingProfile;
profileName = targetProfile.settings.name;
tagsList = [...targetProfile.settings.tags].sort((a, b) => a.localeCompare(b));
} else {
const maybeExistingProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
goto('/features/maintenance');
}
}
if (maybeExistingProfile) {
targetProfile = maybeExistingProfile;
profileName = targetProfile.settings.name;
tagsList = [...targetProfile.settings.tags].sort((a, b) => a.localeCompare(b));
} else {
goto('/features/maintenance');
}
async function saveProfile() {
if (!targetProfile) {
console.warn('Attempting to save the profile, but the profile is not loaded yet.');
return;
}
async function saveProfile() {
if (!targetProfile) {
console.warn('Attempting to save the profile, but the profile is not loaded yet.');
return;
}
targetProfile.settings.name = profileName;
targetProfile.settings.tags = [...tagsList];
targetProfile.settings.temporary = false;
targetProfile.settings.name = profileName;
targetProfile.settings.tags = [...tagsList];
targetProfile.settings.temporary = false;
await targetProfile.save();
await goto('/features/maintenance/' + targetProfile.id);
}
await targetProfile.save();
await goto('/features/maintenance/' + targetProfile.id);
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/features/maintenance{profileId === 'new' ? '' : '/' + profileId}">
Back
</MenuItem>
<hr>
<MenuItem href="/features/maintenance{profileId === 'new' ? '' : '/' + profileId}" icon="arrow-left">
Back
</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl label="Profile Name">
<TextField bind:value={profileName} placeholder="Profile Name"></TextField>
</FormControl>
<FormControl label="Tags">
<TagsEditor bind:tags={tagsList}></TagsEditor>
</FormControl>
<FormControl label="Profile Name">
<TextField bind:value={profileName} placeholder="Profile Name"></TextField>
</FormControl>
<FormControl label="Tags">
<TagsEditor bind:tags={tagsList}></TagsEditor>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem href="#" on:click={saveProfile}>Save Profile</MenuItem>
<hr>
<MenuItem href="#" on:click={saveProfile}>Save Profile</MenuItem>
</Menu>

View File

@@ -1,52 +1,52 @@
<script>
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import MaintenanceProfile from "$entities/MaintenanceProfile";
const profileId = $page.params.id;
const profile = $maintenanceProfiles.find(profile => profile.id === profileId);
const profileId = $page.params.id;
const profile = $maintenanceProfiles.find(profile => profile.id === profileId);
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
/** @type {string} */
let exportedProfile = $state('');
/** @type {string} */
let compressedProfile = $state('');
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
/** @type {string} */
let exportedProfile = $state('');
/** @type {string} */
let compressedProfile = $state('');
if (!profile) {
goto('/features/maintenance/');
} else {
exportedProfile = profilesTransporter.exportToJSON(profile);
compressedProfile = profilesTransporter.exportToCompressedJSON(profile);
}
if (!profile) {
goto('/features/maintenance/');
} else {
exportedProfile = profilesTransporter.exportToJSON(profile);
compressedProfile = profilesTransporter.exportToCompressedJSON(profile);
}
let isCompressedProfileShown = $state(true);
let isCompressedProfileShown = $state(true);
</script>
<Menu>
<MenuItem href="/features/maintenance/{profileId}" icon="arrow-left">
Back
</MenuItem>
<hr>
<MenuItem href="/features/maintenance/{profileId}" icon="arrow-left">
Back
</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl label="Export string">
<textarea readonly rows="6">{isCompressedProfileShown ? compressedProfile : exportedProfile}</textarea>
</FormControl>
<FormControl label="Export string">
<textarea readonly rows="6">{isCompressedProfileShown ? compressedProfile : exportedProfile}</textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={() => isCompressedProfileShown = !isCompressedProfileShown}>
Switch Format:
{#if isCompressedProfileShown}
Base64-Encoded
{:else}
Raw JSON
{/if}
</MenuItem>
<hr>
<MenuItem on:click={() => isCompressedProfileShown = !isCompressedProfileShown}>
Switch Format:
{#if isCompressedProfileShown}
Base64-Encoded
{:else}
Raw JSON
{/if}
</MenuItem>
</Menu>

View File

@@ -1,134 +1,134 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import FormControl from "$components/ui/forms/FormControl.svelte";
import ProfileView from "$components/features/ProfileView.svelte";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { goto } from "$app/navigation";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import MaintenanceProfile from "$entities/MaintenanceProfile";
import FormControl from "$components/ui/forms/FormControl.svelte";
import ProfileView from "$components/features/ProfileView.svelte";
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
import { goto } from "$app/navigation";
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
/** @type {string} */
let importedString = $state('');
/** @type {string} */
let errorMessage = $state('');
/** @type {string} */
let importedString = $state('');
/** @type {string} */
let errorMessage = $state('');
/** @type {MaintenanceProfile|null} */
let candidateProfile = $state(null);
/** @type {MaintenanceProfile|null} */
let existingProfile = $state(null);
/** @type {MaintenanceProfile|null} */
let candidateProfile = $state(null);
/** @type {MaintenanceProfile|null} */
let existingProfile = $state(null);
function tryImportingProfile() {
candidateProfile = null;
existingProfile = null;
function tryImportingProfile() {
candidateProfile = null;
existingProfile = null;
errorMessage = '';
importedString = importedString.trim();
errorMessage = '';
importedString = importedString.trim();
if (!importedString) {
errorMessage = 'Nothing to import.';
return;
}
try {
if (importedString.trim().startsWith('{')) {
candidateProfile = profilesTransporter.importFromJSON(importedString);
}
candidateProfile = profilesTransporter.importFromCompressedJSON(importedString);
} catch (error) {
errorMessage = error instanceof Error
? error.message
: 'Unknown error';
}
if (candidateProfile) {
existingProfile = $maintenanceProfiles.find(profile => profile.id === candidateProfile?.id) ?? null;
}
if (!importedString) {
errorMessage = 'Nothing to import.';
return;
}
function saveProfile() {
if (!candidateProfile) {
return;
}
try {
if (importedString.trim().startsWith('{')) {
candidateProfile = profilesTransporter.importFromJSON(importedString);
}
candidateProfile.save().then(() => {
goto(`/features/maintenance`);
});
candidateProfile = profilesTransporter.importFromCompressedJSON(importedString);
} catch (error) {
errorMessage = error instanceof Error
? error.message
: 'Unknown error';
}
function cloneAndSaveProfile() {
if (!candidateProfile) {
return;
}
const clonedProfile = new MaintenanceProfile(crypto.randomUUID(), candidateProfile.settings);
clonedProfile.settings.name += ` (Clone ${new Date().toISOString()})`;
clonedProfile.save().then(() => {
goto(`/features/maintenance`);
});
if (candidateProfile) {
existingProfile = $maintenanceProfiles.find(profile => profile.id === candidateProfile?.id) ?? null;
}
}
function saveProfile() {
if (!candidateProfile) {
return;
}
candidateProfile.save().then(() => {
goto(`/features/maintenance`);
});
}
function cloneAndSaveProfile() {
if (!candidateProfile) {
return;
}
const clonedProfile = new MaintenanceProfile(crypto.randomUUID(), candidateProfile.settings);
clonedProfile.settings.name += ` (Clone ${new Date().toISOString()})`;
clonedProfile.save().then(() => {
goto(`/features/maintenance`);
});
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/features/maintenance">Back</MenuItem>
<hr>
<MenuItem href="/features/maintenance" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
{#if errorMessage}
<p class="error">Failed to import: {errorMessage}</p>
<Menu>
<hr>
</Menu>
<p class="error">Failed to import: {errorMessage}</p>
<Menu>
<hr>
</Menu>
{/if}
{#if !candidateProfile}
<FormContainer>
<FormControl label="Import string">
<textarea bind:value={importedString} rows="6"></textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={tryImportingProfile}>Import</MenuItem>
</Menu>
<FormContainer>
<FormControl label="Import string">
<textarea bind:value={importedString} rows="6"></textarea>
</FormControl>
</FormContainer>
<Menu>
<hr>
<MenuItem on:click={tryImportingProfile}>Import</MenuItem>
</Menu>
{:else}
{#if existingProfile}
<p class="warning">
This profile will replace the existing "{existingProfile.settings.name}" profile, since it have the same ID.
</p>
{/if}
<ProfileView profile="{candidateProfile}"></ProfileView>
<Menu>
<hr>
{#if existingProfile}
<p class="warning">
This profile will replace the existing "{existingProfile.settings.name}" profile, since it have the same ID.
</p>
<MenuItem on:click={saveProfile}>Replace Existing Profile</MenuItem>
<MenuItem on:click={cloneAndSaveProfile}>Save as New Profile</MenuItem>
{:else}
<MenuItem on:click={saveProfile}>Import New Profile</MenuItem>
{/if}
<ProfileView profile="{candidateProfile}"></ProfileView>
<Menu>
<hr>
{#if existingProfile}
<MenuItem on:click={saveProfile}>Replace Existing Profile</MenuItem>
<MenuItem on:click={cloneAndSaveProfile}>Save as New Profile</MenuItem>
{:else}
<MenuItem on:click={saveProfile}>Import New Profile</MenuItem>
{/if}
<MenuItem on:click={() => candidateProfile = null}>Cancel</MenuItem>
</Menu>
<MenuItem on:click={() => candidateProfile = null}>Cancel</MenuItem>
</Menu>
{/if}
<style lang="scss">
@use '$styles/colors';
@use '$styles/colors';
.error, .warning {
padding: 5px 24px;
margin: {
left: -24px;
right: -24px;
}
.error, .warning {
padding: 5px 24px;
margin: {
left: -24px;
right: -24px;
}
}
.error {
background: colors.$error-background;
}
.error {
background: colors.$error-background;
}
.warning {
background: colors.$warning-background;
margin-bottom: .5em;
}
.warning {
background: colors.$warning-background;
margin-bottom: .5em;
}
</style>

View File

@@ -1,14 +1,14 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
</script>
<Menu>
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/preferences/tags">Tagging</MenuItem>
<MenuItem href="/preferences/search">Search</MenuItem>
<MenuItem href="/preferences/misc">Misc & Tools</MenuItem>
<hr>
<MenuItem href="/preferences/debug">Debug</MenuItem>
<MenuItem href="/" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/preferences/tags">Tagging</MenuItem>
<MenuItem href="/preferences/search">Search</MenuItem>
<MenuItem href="/preferences/misc">Misc & Tools</MenuItem>
<hr>
<MenuItem href="/preferences/debug">Debug</MenuItem>
</Menu>

View File

@@ -1,10 +1,10 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
</script>
<Menu>
<MenuItem href="/preferences" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/preferences/debug/storage">Inspect Storages</MenuItem>
<MenuItem href="/preferences" icon="arrow-left">Back</MenuItem>
<hr>
<MenuItem href="/preferences/debug/storage">Inspect Storages</MenuItem>
</Menu>

View File

@@ -1,13 +1,13 @@
<script>
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import { storagesCollection } from "$stores/debug";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import { storagesCollection } from "$stores/debug";
</script>
<Menu>
<MenuItem href="/preferences/debug" icon="arrow-left">Back</MenuItem>
<hr>
{#each Object.keys($storagesCollection) as storageName}
<MenuItem href="/preferences/debug/storage/{storageName}/">Storage: {storageName}</MenuItem>
{/each}
<MenuItem href="/preferences/debug" icon="arrow-left">Back</MenuItem>
<hr>
{#each Object.keys($storagesCollection) as storageName}
<MenuItem href="/preferences/debug/storage/{storageName}/">Storage: {storageName}</MenuItem>
{/each}
</Menu>

View File

@@ -1,31 +1,30 @@
<script>
import { run } from 'svelte/legacy';
import { run } from 'svelte/legacy';
import StorageViewer from "$components/debugging/StorageViewer.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
import StorageViewer from "$components/debugging/StorageViewer.svelte";
import { page } from "$app/stores";
import { goto } from "$app/navigation";
let pathString = $state('');
/** @type {string[]} */
let pathArray = $state([]);
/** @type {string|undefined} */
let storageName = $state(void 0);
let pathString = $state('');
/** @type {string[]} */
let pathArray = $state([]);
/** @type {string|undefined} */
let storageName = $state(void 0);
run(() => {
pathString = $page.params.path;
pathArray = pathString.length ? pathString.split("/") : [];
storageName = pathArray.shift()
run(() => {
pathString = $page.params.path;
pathArray = pathString.length ? pathString.split("/") : [];
storageName = pathArray.shift()
if (pathArray.length && pathArray[pathArray.length - 1] === '') {
pathArray.pop();
}
if (pathArray.length && pathArray[pathArray.length - 1] === '') {
pathArray.pop();
}
if (!storageName) {
goto("/preferences/debug/storage");
}
});
if (!storageName) {
goto("/preferences/debug/storage");
}
});
</script>
{#if storageName}
<StorageViewer storage="{storageName}" path="{pathArray}"></StorageViewer>
<StorageViewer storage="{storageName}" path="{pathArray}"></StorageViewer>
{/if}

View File

@@ -1,20 +1,20 @@
<script>
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import { fullScreenViewerEnabled } from "$stores/preferences/misc";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import { fullScreenViewerEnabled } from "$stores/preferences/misc";
</script>
<Menu>
<MenuItem icon="arrow-left" href="/preferences">Back</MenuItem>
<hr>
<MenuItem href="/preferences" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl>
<CheckboxField bind:checked={$fullScreenViewerEnabled}>
Enable fullscreen viewer button
</CheckboxField>
</FormControl>
<FormControl>
<CheckboxField bind:checked={$fullScreenViewerEnabled}>
Enable fullscreen viewer button
</CheckboxField>
</FormControl>
</FormContainer>

View File

@@ -1,35 +1,32 @@
<script>
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import {
searchPropertiesSuggestionsEnabled,
searchPropertiesSuggestionsPosition
} from "$stores/preferences/search";
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import SelectField from "$components/ui/forms/SelectField.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import { searchPropertiesSuggestionsEnabled, searchPropertiesSuggestionsPosition } from "$stores/preferences/search";
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import SelectField from "$components/ui/forms/SelectField.svelte";
const propertiesPositions = {
start: "At the start of the list",
end: "At the end of the list",
}
const propertiesPositions = {
start: "At the start of the list",
end: "At the end of the list",
}
</script>
<Menu>
<MenuItem icon="arrow-left" href="/preferences">Back</MenuItem>
<hr>
<MenuItem href="/preferences" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl>
<CheckboxField bind:checked={$searchPropertiesSuggestionsEnabled}>
Auto-complete properties
</CheckboxField>
<FormControl>
<CheckboxField bind:checked={$searchPropertiesSuggestionsEnabled}>
Auto-complete properties
</CheckboxField>
</FormControl>
{#if $searchPropertiesSuggestionsEnabled}
<FormControl label="Show completed properties:">
<SelectField bind:value={$searchPropertiesSuggestionsPosition}
options="{propertiesPositions}"></SelectField>
</FormControl>
{#if $searchPropertiesSuggestionsEnabled}
<FormControl label="Show completed properties:">
<SelectField bind:value={$searchPropertiesSuggestionsPosition}
options="{propertiesPositions}"></SelectField>
</FormControl>
{/if}
{/if}
</FormContainer>

View File

@@ -1,20 +1,20 @@
<script>
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { stripBlacklistedTagsEnabled } from "$stores/preferences/maintenance";
import CheckboxField from "$components/ui/forms/CheckboxField.svelte";
import FormContainer from "$components/ui/forms/FormContainer.svelte";
import FormControl from "$components/ui/forms/FormControl.svelte";
import Menu from "$components/ui/menu/Menu.svelte";
import MenuItem from "$components/ui/menu/MenuItem.svelte";
import { stripBlacklistedTagsEnabled } from "$stores/preferences/maintenance";
</script>
<Menu>
<MenuItem icon="arrow-left" href="/preferences">Back</MenuItem>
<hr>
<MenuItem href="/preferences" icon="arrow-left">Back</MenuItem>
<hr>
</Menu>
<FormContainer>
<FormControl>
<CheckboxField bind:checked={$stripBlacklistedTagsEnabled}>
Automatically remove black-listed tags from the images
</CheckboxField>
</FormControl>
<FormControl>
<CheckboxField bind:checked={$stripBlacklistedTagsEnabled}>
Automatically remove black-listed tags from the images
</CheckboxField>
</FormControl>
</FormContainer>