mirror of
https://github.com/koloml/furbooru-tagging-assistant.git
synced 2025-12-24 07:12:57 +00:00
Refactored profiles related routes & components
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import type MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
* @property {import('$entities/MaintenanceProfile').default} profile
|
||||
*/
|
||||
interface ProfileViewProps {
|
||||
profile: MaintenanceProfile;
|
||||
}
|
||||
|
||||
/** @type {Props} */
|
||||
let { profile } = $props();
|
||||
let { profile }: ProfileViewProps = $props();
|
||||
|
||||
const sortedTagsList = profile.settings.tags.sort((a, b) => a.localeCompare(b));
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
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 MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
|
||||
/** @type {import('$entities/MaintenanceProfile').default|undefined} */
|
||||
let activeProfile = $derived($maintenanceProfiles.find(profile => profile.id === $activeProfileStore));
|
||||
|
||||
let activeProfile = $derived<MaintenanceProfile | null>(
|
||||
$maintenanceProfiles.find(profile => profile.id === $activeProfileStore) || null
|
||||
);
|
||||
|
||||
function turnOffActiveProfile() {
|
||||
$activeProfileStore = null;
|
||||
@@ -15,7 +16,7 @@
|
||||
|
||||
<Menu>
|
||||
{#if activeProfile}
|
||||
<MenuCheckboxItem checked on:input={turnOffActiveProfile} href="/features/maintenance/{activeProfile.id}">
|
||||
<MenuCheckboxItem checked oninput={turnOffActiveProfile} href="/features/maintenance/{activeProfile.id}">
|
||||
Active Profile: {activeProfile.settings.name}
|
||||
</MenuCheckboxItem>
|
||||
<hr>
|
||||
|
||||
@@ -1,25 +1,19 @@
|
||||
<script>
|
||||
import { run } from 'svelte/legacy';
|
||||
<script lang="ts">
|
||||
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 MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
|
||||
/** @type {import('$entities/MaintenanceProfile').default[]} */
|
||||
let profiles = $state([]);
|
||||
|
||||
run(() => {
|
||||
profiles = $maintenanceProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name));
|
||||
});
|
||||
let profiles = $derived<MaintenanceProfile[]>(
|
||||
$maintenanceProfiles.sort((a, b) => a.settings.name.localeCompare(b.settings.name))
|
||||
);
|
||||
|
||||
function resetActiveProfile() {
|
||||
$activeProfileStore = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Event} event
|
||||
*/
|
||||
function enableSelectedProfile(event) {
|
||||
function enableSelectedProfile(event: Event) {
|
||||
const target = event.target;
|
||||
|
||||
if (target instanceof HTMLInputElement && target.checked) {
|
||||
@@ -37,13 +31,13 @@
|
||||
{#each profiles as profile}
|
||||
<MenuRadioItem href="/features/maintenance/{profile.id}"
|
||||
name="active-profile"
|
||||
value="{profile.id}"
|
||||
checked="{$activeProfileStore === profile.id}"
|
||||
on:input={enableSelectedProfile}>
|
||||
value={profile.id}
|
||||
checked={$activeProfileStore === profile.id}
|
||||
oninput={enableSelectedProfile}>
|
||||
{profile.settings.name}
|
||||
</MenuRadioItem>
|
||||
{/each}
|
||||
<hr>
|
||||
<MenuItem href="#" on:click={resetActiveProfile}>Reset Active Profile</MenuItem>
|
||||
<MenuItem href="#" onclick={resetActiveProfile}>Reset Active Profile</MenuItem>
|
||||
<MenuItem href="/features/maintenance/import">Import Profile</MenuItem>
|
||||
</Menu>
|
||||
|
||||
@@ -1,35 +1,39 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
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 { page } from "$app/state";
|
||||
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 MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
import { onMount } from "svelte";
|
||||
|
||||
const profileId = $page.params.id;
|
||||
/** @type {import('$entities/MaintenanceProfile').default|null} */
|
||||
let profile = $state(null);
|
||||
let profileId = $derived(page.params.id);
|
||||
let profile = $derived<MaintenanceProfile|null>(
|
||||
$maintenanceProfiles.find(profile => profile.id === profileId) || null
|
||||
);
|
||||
|
||||
if (profileId === 'new') {
|
||||
goto('/features/maintenance/new/edit');
|
||||
}
|
||||
$effect(() => {
|
||||
if (profileId === 'new') {
|
||||
goto('/features/maintenance/new/edit');
|
||||
return;
|
||||
}
|
||||
|
||||
run(() => {
|
||||
const resolvedProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
|
||||
|
||||
if (resolvedProfile) {
|
||||
profile = resolvedProfile;
|
||||
} else {
|
||||
if (!profile) {
|
||||
console.warn(`Profile ${profileId} not found.`);
|
||||
goto('/features/maintenance');
|
||||
}
|
||||
});
|
||||
|
||||
let isActiveProfile = $state($activeProfileStore === profileId);
|
||||
let isActiveProfile = $state(false);
|
||||
|
||||
run(() => {
|
||||
$effect.pre(() => {
|
||||
isActiveProfile = $activeProfileStore === profileId;
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (isActiveProfile && $activeProfileStore !== profileId) {
|
||||
$activeProfileStore = profileId;
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
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 { page } from "$app/state";
|
||||
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
|
||||
import MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
|
||||
const profileId = $page.params.id;
|
||||
const targetProfile = $maintenanceProfiles.find(profile => profile.id === profileId);
|
||||
const profileId = $derived(page.params.id);
|
||||
const targetProfile = $derived<MaintenanceProfile | null>(
|
||||
$maintenanceProfiles.find(profile => profile.id === profileId) || null
|
||||
);
|
||||
|
||||
if (!targetProfile) {
|
||||
void goto('/features/maintenance');
|
||||
}
|
||||
$effect(() => {
|
||||
if (!targetProfile) {
|
||||
goto('/features/maintenance');
|
||||
}
|
||||
});
|
||||
|
||||
async function deleteProfile() {
|
||||
if (!targetProfile) {
|
||||
@@ -33,7 +38,7 @@
|
||||
</p>
|
||||
<Menu>
|
||||
<hr>
|
||||
<MenuItem on:click={deleteProfile}>Yes</MenuItem>
|
||||
<MenuItem onclick={deleteProfile}>Yes</MenuItem>
|
||||
<MenuItem href="/features/maintenance/{profileId}">No</MenuItem>
|
||||
</Menu>
|
||||
{:else}
|
||||
|
||||
@@ -1,38 +1,42 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
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 { page } from "$app/state";
|
||||
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 profileName = $state('');
|
||||
/** @type {string[]} */
|
||||
let tagsList = $state([]);
|
||||
let profileId = $derived(page.params.id);
|
||||
|
||||
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 {
|
||||
goto('/features/maintenance');
|
||||
let targetProfile = $derived.by<MaintenanceProfile | null>(() => {
|
||||
if (profileId === 'new') {
|
||||
return new MaintenanceProfile(crypto.randomUUID(), {});
|
||||
}
|
||||
}
|
||||
|
||||
return $maintenanceProfiles.find(profile => profile.id === profileId) || null;
|
||||
});
|
||||
|
||||
let profileName = $state('');
|
||||
let tagsList = $state<string[]>([]);
|
||||
|
||||
$effect(() => {
|
||||
if (profileId === 'new') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!targetProfile) {
|
||||
goto('/features/maintenance');
|
||||
return;
|
||||
}
|
||||
|
||||
profileName = targetProfile.settings.name;
|
||||
tagsList = [...targetProfile.settings.tags].sort((a, b) => a.localeCompare(b));
|
||||
});
|
||||
|
||||
async function saveProfile() {
|
||||
if (!targetProfile) {
|
||||
@@ -65,5 +69,5 @@
|
||||
</FormContainer>
|
||||
<Menu>
|
||||
<hr>
|
||||
<MenuItem href="#" on:click={saveProfile}>Save Profile</MenuItem>
|
||||
<MenuItem href="#" onclick={saveProfile}>Save Profile</MenuItem>
|
||||
</Menu>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script>
|
||||
import { page } from "$app/stores";
|
||||
<script lang="ts">
|
||||
import { page } from "$app/state";
|
||||
import { goto } from "$app/navigation";
|
||||
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
|
||||
import Menu from "$components/ui/menu/Menu.svelte";
|
||||
@@ -9,23 +9,24 @@
|
||||
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
|
||||
import MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
|
||||
const profileId = $page.params.id;
|
||||
const profile = $maintenanceProfiles.find(profile => profile.id === profileId);
|
||||
let isCompressedProfileShown = $state(true);
|
||||
|
||||
const profileId = $derived(page.params.id);
|
||||
const profile = $derived<MaintenanceProfile | null>(
|
||||
$maintenanceProfiles.find(profile => profile.id === profileId) || null
|
||||
);
|
||||
|
||||
$effect(() => {
|
||||
if (!profile) {
|
||||
goto('/features/maintenance/');
|
||||
}
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
let isCompressedProfileShown = $state(true);
|
||||
let rawExportedProfile = $derived(profile ? profilesTransporter.exportToJSON(profile) : '');
|
||||
let compressedExportedProfile = $derived(profile ? profilesTransporter.exportToCompressedJSON(profile) : '');
|
||||
let selectedExportString = $derived(isCompressedProfileShown ? compressedExportedProfile : rawExportedProfile);
|
||||
</script>
|
||||
|
||||
<Menu>
|
||||
@@ -36,12 +37,12 @@
|
||||
</Menu>
|
||||
<FormContainer>
|
||||
<FormControl label="Export string">
|
||||
<textarea readonly rows="6">{isCompressedProfileShown ? compressedProfile : exportedProfile}</textarea>
|
||||
<textarea readonly rows="6">{selectedExportString}</textarea>
|
||||
</FormControl>
|
||||
</FormContainer>
|
||||
<Menu>
|
||||
<hr>
|
||||
<MenuItem on:click={() => isCompressedProfileShown = !isCompressedProfileShown}>
|
||||
<MenuItem onclick={() => isCompressedProfileShown = !isCompressedProfileShown}>
|
||||
Switch Format:
|
||||
{#if isCompressedProfileShown}
|
||||
Base64-Encoded
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import Menu from "$components/ui/menu/Menu.svelte";
|
||||
import MenuItem from "$components/ui/menu/MenuItem.svelte";
|
||||
import FormContainer from "$components/ui/forms/FormContainer.svelte";
|
||||
@@ -11,15 +11,11 @@
|
||||
|
||||
const profilesTransporter = new EntitiesTransporter(MaintenanceProfile);
|
||||
|
||||
/** @type {string} */
|
||||
let importedString = $state('');
|
||||
/** @type {string} */
|
||||
let errorMessage = $state('');
|
||||
|
||||
/** @type {MaintenanceProfile|null} */
|
||||
let candidateProfile = $state(null);
|
||||
/** @type {MaintenanceProfile|null} */
|
||||
let existingProfile = $state(null);
|
||||
let candidateProfile = $state<MaintenanceProfile | null>(null);
|
||||
let existingProfile = $state<MaintenanceProfile | null>(null);
|
||||
|
||||
function tryImportingProfile() {
|
||||
candidateProfile = null;
|
||||
@@ -36,9 +32,9 @@
|
||||
try {
|
||||
if (importedString.trim().startsWith('{')) {
|
||||
candidateProfile = profilesTransporter.importFromJSON(importedString);
|
||||
} else {
|
||||
candidateProfile = profilesTransporter.importFromCompressedJSON(importedString)
|
||||
}
|
||||
|
||||
candidateProfile = profilesTransporter.importFromCompressedJSON(importedString);
|
||||
} catch (error) {
|
||||
errorMessage = error instanceof Error
|
||||
? error.message
|
||||
@@ -91,7 +87,7 @@
|
||||
</FormContainer>
|
||||
<Menu>
|
||||
<hr>
|
||||
<MenuItem on:click={tryImportingProfile}>Import</MenuItem>
|
||||
<MenuItem onclick={tryImportingProfile}>Import</MenuItem>
|
||||
</Menu>
|
||||
{:else}
|
||||
{#if existingProfile}
|
||||
@@ -99,16 +95,16 @@
|
||||
This profile will replace the existing "{existingProfile.settings.name}" profile, since it have the same ID.
|
||||
</p>
|
||||
{/if}
|
||||
<ProfileView profile="{candidateProfile}"></ProfileView>
|
||||
<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>
|
||||
<MenuItem onclick={saveProfile}>Replace Existing Profile</MenuItem>
|
||||
<MenuItem onclick={cloneAndSaveProfile}>Save as New Profile</MenuItem>
|
||||
{:else}
|
||||
<MenuItem on:click={saveProfile}>Import New Profile</MenuItem>
|
||||
<MenuItem onclick={saveProfile}>Import New Profile</MenuItem>
|
||||
{/if}
|
||||
<MenuItem on:click={() => candidateProfile = null}>Cancel</MenuItem>
|
||||
<MenuItem onclick={() => candidateProfile = null}>Cancel</MenuItem>
|
||||
</Menu>
|
||||
{/if}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user