mirror of
https://github.com/koloml/furbooru-tagging-assistant.git
synced 2025-12-23 23:02:58 +00:00
Added separate menu for bulk exporting of all entities
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import type StorageEntity from "$lib/extension/base/StorageEntity";
|
||||
import { decompressFromEncodedURIComponent } from "lz-string";
|
||||
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from "lz-string";
|
||||
import type { ImportableElementsList, ImportableEntityObject } from "$lib/extension/transporting/importables";
|
||||
import EntitiesTransporter from "$lib/extension/EntitiesTransporter";
|
||||
import MaintenanceProfile from "$entities/MaintenanceProfile";
|
||||
@@ -42,6 +42,30 @@ export default class BulkEntitiesTransporter {
|
||||
);
|
||||
}
|
||||
|
||||
exportToJSON(entities: StorageEntity[]): string {
|
||||
return JSON.stringify({
|
||||
$type: 'list',
|
||||
elements: entities
|
||||
.map(entity => {
|
||||
switch (true) {
|
||||
case entity instanceof MaintenanceProfile:
|
||||
return BulkEntitiesTransporter.#transporters.profiles.exportToObject(entity);
|
||||
case entity instanceof TagGroup:
|
||||
return BulkEntitiesTransporter.#transporters.groups.exportToObject(entity);
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter(value => !!value)
|
||||
} as ImportableElementsList<ImportableEntityObject<StorageEntity>>, null, 2);
|
||||
}
|
||||
|
||||
exportToCompressedJSON(entities: StorageEntity[]): string {
|
||||
return compressToEncodedURIComponent(
|
||||
this.exportToJSON(entities)
|
||||
);
|
||||
}
|
||||
|
||||
static isList(targetObject: any): targetObject is ImportableElementsList<ImportableEntityObject<StorageEntity>> {
|
||||
return targetObject.$type
|
||||
&& targetObject.$type === 'list'
|
||||
|
||||
@@ -32,6 +32,10 @@ export default class EntitiesTransporter<EntityType> {
|
||||
this.#targetEntityConstructor = entityConstructor;
|
||||
}
|
||||
|
||||
isCorrectEntity(entityObject: unknown): entityObject is EntityType {
|
||||
return entityObject instanceof this.#targetEntityConstructor;
|
||||
}
|
||||
|
||||
importFromObject(importedObject: Record<string, any>): EntityType {
|
||||
validateImportedEntity(
|
||||
this.#entityName,
|
||||
@@ -60,8 +64,8 @@ export default class EntitiesTransporter<EntityType> {
|
||||
)
|
||||
}
|
||||
|
||||
exportToJSON(entityObject: EntityType): string {
|
||||
if (!(entityObject instanceof this.#targetEntityConstructor)) {
|
||||
exportToObject(entityObject: EntityType) {
|
||||
if (!this.isCorrectEntity(entityObject)) {
|
||||
throw new TypeError('Transporter should be connected to the same entity to export!');
|
||||
}
|
||||
|
||||
@@ -69,12 +73,18 @@ export default class EntitiesTransporter<EntityType> {
|
||||
throw new TypeError('Only storage entities could be exported!');
|
||||
}
|
||||
|
||||
const exportableObject = exportEntityToObject(
|
||||
return exportEntityToObject(
|
||||
this.#entityName,
|
||||
entityObject
|
||||
);
|
||||
}
|
||||
|
||||
return JSON.stringify(exportableObject, null, 2);
|
||||
exportToJSON(entityObject: EntityType): string {
|
||||
return JSON.stringify(
|
||||
this.exportToObject(entityObject),
|
||||
null,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
exportToCompressedJSON(entityObject: EntityType): string {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
<MenuItem href="/features/maintenance">Tagging Profiles</MenuItem>
|
||||
<MenuItem href="/features/groups">Tag Groups</MenuItem>
|
||||
<hr>
|
||||
<MenuItem href="/transporting">Import/Export</MenuItem>
|
||||
<MenuItem href="/preferences">Preferences</MenuItem>
|
||||
<MenuItem href="/about">About</MenuItem>
|
||||
</Menu>
|
||||
|
||||
10
src/routes/transporting/+page.svelte
Normal file
10
src/routes/transporting/+page.svelte
Normal file
@@ -0,0 +1,10 @@
|
||||
<script lang="ts">
|
||||
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="/transporting/export">Export</MenuItem>
|
||||
</Menu>
|
||||
121
src/routes/transporting/export/+page.svelte
Normal file
121
src/routes/transporting/export/+page.svelte
Normal file
@@ -0,0 +1,121 @@
|
||||
<script lang="ts">
|
||||
import Menu from "$components/ui/menu/Menu.svelte";
|
||||
import MenuItem from "$components/ui/menu/MenuItem.svelte";
|
||||
import { maintenanceProfiles } from "$stores/entities/maintenance-profiles";
|
||||
import MenuCheckboxItem from "$components/ui/menu/MenuCheckboxItem.svelte";
|
||||
import { tagGroups } from "$stores/entities/tag-groups";
|
||||
import BulkEntitiesTransporter from "$lib/extension/BulkEntitiesTransporter";
|
||||
import type StorageEntity from "$lib/extension/base/StorageEntity";
|
||||
import FormControl from "$components/ui/forms/FormControl.svelte";
|
||||
import FormContainer from "$components/ui/forms/FormContainer.svelte";
|
||||
|
||||
const bulkTransporter = new BulkEntitiesTransporter();
|
||||
|
||||
let exportAllProfiles = $state(false);
|
||||
let exportAllGroups = $state(false);
|
||||
|
||||
let displayExportedString = $state(false);
|
||||
let shouldUseCompressed = $state(true);
|
||||
let compressedExport = $state('');
|
||||
let plainExport = $state('');
|
||||
let selectedExportString = $derived(shouldUseCompressed ? compressedExport : plainExport);
|
||||
|
||||
const exportedEntities: Record<keyof App.EntityNamesMap, Record<string, boolean>> = $state({
|
||||
profiles: {},
|
||||
groups: {},
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (displayExportedString) {
|
||||
const elementsToExport: StorageEntity[] = [];
|
||||
|
||||
$maintenanceProfiles.forEach(profile => {
|
||||
if (exportedEntities.profiles[profile.id]) {
|
||||
elementsToExport.push(profile);
|
||||
}
|
||||
});
|
||||
|
||||
$tagGroups.forEach(group => {
|
||||
if (exportedEntities.groups[group.id]) {
|
||||
elementsToExport.push(group);
|
||||
}
|
||||
});
|
||||
|
||||
plainExport = bulkTransporter.exportToJSON(elementsToExport);
|
||||
compressedExport = bulkTransporter.exportToCompressedJSON(elementsToExport);
|
||||
}
|
||||
});
|
||||
|
||||
function refreshAreAllEntitiesChecked() {
|
||||
requestAnimationFrame(() => {
|
||||
exportAllProfiles = $maintenanceProfiles.every(profile => exportedEntities.profiles[profile.id]);
|
||||
exportAllGroups = $tagGroups.every(group => exportedEntities.groups[group.id]);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleSelectionOnUserInput() {
|
||||
requestAnimationFrame(() => {
|
||||
$maintenanceProfiles.forEach(profile => exportedEntities.profiles[profile.id] = exportAllProfiles);
|
||||
$tagGroups.forEach(group => exportedEntities.groups[group.id] = exportAllGroups);
|
||||
});
|
||||
}
|
||||
|
||||
function toggleExportedStringDisplay() {
|
||||
displayExportedString = !displayExportedString;
|
||||
}
|
||||
|
||||
function toggleExportedStringType() {
|
||||
shouldUseCompressed = !shouldUseCompressed;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if !displayExportedString}
|
||||
<Menu>
|
||||
<MenuItem href="/transporting" icon="arrow-left">Back</MenuItem>
|
||||
<hr>
|
||||
{#if $maintenanceProfiles.length}
|
||||
<MenuCheckboxItem bind:checked={exportAllProfiles} oninput={toggleSelectionOnUserInput}>
|
||||
Export All Profiles
|
||||
</MenuCheckboxItem>
|
||||
{#each $maintenanceProfiles as profile}
|
||||
<MenuCheckboxItem bind:checked={exportedEntities.profiles[profile.id]} oninput={refreshAreAllEntitiesChecked}>
|
||||
Profile: {profile.settings.name}
|
||||
</MenuCheckboxItem>
|
||||
{/each}
|
||||
<hr>
|
||||
{/if}
|
||||
{#if $tagGroups.length}
|
||||
<MenuCheckboxItem bind:checked={exportAllGroups} oninput={toggleSelectionOnUserInput}>
|
||||
Export All Groups
|
||||
</MenuCheckboxItem>
|
||||
{#each $tagGroups as group}
|
||||
<MenuCheckboxItem bind:checked={exportedEntities.groups[group.id]} oninput={refreshAreAllEntitiesChecked}>
|
||||
Group: {group.settings.name}
|
||||
</MenuCheckboxItem>
|
||||
{/each}
|
||||
<hr>
|
||||
{/if}
|
||||
<MenuItem icon="file-export" onclick={toggleExportedStringDisplay}>Export Selected</MenuItem>
|
||||
</Menu>
|
||||
{:else}
|
||||
<Menu>
|
||||
<MenuItem onclick={toggleExportedStringDisplay} icon="arrow-left">Back to Selection</MenuItem>
|
||||
<hr>
|
||||
</Menu>
|
||||
<FormContainer>
|
||||
<FormControl label="Export string">
|
||||
<textarea readonly rows="6">{selectedExportString}</textarea>
|
||||
</FormControl>
|
||||
</FormContainer>
|
||||
<Menu>
|
||||
<hr>
|
||||
<MenuItem onclick={toggleExportedStringType}>
|
||||
Switch Format:
|
||||
{#if shouldUseCompressed}
|
||||
Base64-Encoded
|
||||
{:else}
|
||||
Raw JSON
|
||||
{/if}
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user