Refactoring: port MapRoulette-set-status to svelte

This commit is contained in:
Pieter Vander Vennet 2023-12-09 16:52:15 +01:00
parent 2147661601
commit 389cd7ddc0
4 changed files with 156 additions and 126 deletions

View file

@ -238,7 +238,7 @@
"cs": "Označit jako příliš těžké" "cs": "Označit jako příliš těžké"
}, },
"status": "6", "status": "6",
"image": "not_found" "image": "./assets/svg/not_found.svg"
} }
} }
} }

View file

@ -24,6 +24,9 @@
import Gps_arrow from "../../assets/svg/Gps_arrow.svelte"; import Gps_arrow from "../../assets/svg/Gps_arrow.svelte";
import { HeartIcon } from "@babeard/svelte-heroicons/solid"; import { HeartIcon } from "@babeard/svelte-heroicons/solid";
import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline"; import { HeartIcon as HeartOutlineIcon } from "@babeard/svelte-heroicons/outline";
import Confirm from "../../assets/svg/Confirm.svelte";
import Not_found from "../../assets/svg/Not_found.svelte";
import { twMerge } from "tailwind-merge";
/** /**
* Renders a single icon. * Renders a single icon.
@ -32,71 +35,75 @@
*/ */
export let icon: string | undefined; export let icon: string | undefined;
export let color: string | undefined = undefined export let color: string | undefined = undefined;
export let clss: string | undefined = undefined export let clss: string | undefined = undefined;
</script> </script>
{#if icon} {#if icon}
{#if icon === "pin"} {#if icon === "pin"}
<Pin {color} class={clss}/> <Pin {color} class={clss} />
{:else if icon === "square"} {:else if icon === "square"}
<Square {color} class={clss}/> <Square {color} class={clss} />
{:else if icon === "circle"} {:else if icon === "circle"}
<Circle {color} class={clss}/> <Circle {color} class={clss} />
{:else if icon === "checkmark"} {:else if icon === "checkmark"}
<Checkmark {color} class={clss}/> <Checkmark {color} class={clss} />
{:else if icon === "clock"} {:else if icon === "clock"}
<Clock {color} class={clss}/> <Clock {color} class={clss} />
{:else if icon === "close"} {:else if icon === "close"}
<Close {color} class={clss}/> <Close {color} class={clss} />
{:else if icon === "crosshair"} {:else if icon === "crosshair"}
<Crosshair {color} class={clss}/> <Crosshair {color} class={clss} />
{:else if icon === "help"} {:else if icon === "help"}
<Help {color} class={clss}/> <Help {color} class={clss} />
{:else if icon === "home"} {:else if icon === "home"}
<Home {color} class={clss}/> <Home {color} class={clss} />
{:else if icon === "invalid"} {:else if icon === "invalid"}
<Invalid {color} class={clss}/> <Invalid {color} class={clss} />
{:else if icon === "location"} {:else if icon === "location"}
<Location {color} class={clss}/> <Location {color} class={clss} />
{:else if icon === "location_empty"} {:else if icon === "location_empty"}
<Location_empty {color} class={clss}/> <Location_empty {color} class={clss} />
{:else if icon === "location_locked"} {:else if icon === "location_locked"}
<Location_locked {color} class={clss}/> <Location_locked {color} class={clss} />
{:else if icon === "note"} {:else if icon === "note"}
<Note {color} class={clss}/> <Note {color} class={clss} />
{:else if icon === "resolved"} {:else if icon === "resolved"}
<Resolved {color} class={clss}/> <Resolved {color} class={clss} />
{:else if icon === "ring"} {:else if icon === "ring"}
<Ring {color} class={clss}/> <Ring {color} class={clss} />
{:else if icon === "scissors"} {:else if icon === "scissors"}
<Scissors {color} class={clss}/> <Scissors {color} class={clss} />
{:else if icon === "teardrop"} {:else if icon === "teardrop"}
<Teardrop {color} class={clss}/> <Teardrop {color} class={clss} />
{:else if icon === "teardrop_with_hole_green"} {:else if icon === "teardrop_with_hole_green"}
<Teardrop_with_hole_green {color} class={clss}/> <Teardrop_with_hole_green {color} class={clss} />
{:else if icon === "triangle"} {:else if icon === "triangle"}
<Triangle {color} class={clss}/> <Triangle {color} class={clss} />
{:else if icon === "brick_wall_square"} {:else if icon === "brick_wall_square"}
<Brick_wall_square {color} class={clss}/> <Brick_wall_square {color} class={clss} />
{:else if icon === "brick_wall_round"} {:else if icon === "brick_wall_round"}
<Brick_wall_round {color} class={clss}/> <Brick_wall_round {color} class={clss} />
{:else if icon === "gps_arrow"} {:else if icon === "gps_arrow"}
<Gps_arrow {color} class={clss}/> <Gps_arrow {color} class={clss} />
{:else if icon === "checkmark"} {:else if icon === "checkmark"}
<Checkmark {color} class={clss}/> <Checkmark {color} class={clss} />
{:else if icon === "help"} {:else if icon === "help"}
<Help {color} class={clss}/> <Help {color} class={clss} />
{:else if icon === "close"} {:else if icon === "close"}
<Close {color} class={clss}/> <Close {color} class={clss} />
{:else if icon === "invalid"} {:else if icon === "invalid"}
<Invalid {color} class={clss}/> <Invalid {color} class={clss} />
{:else if icon === "heart"} {:else if icon === "heart"}
<HeartIcon class={clss}/> <HeartIcon class={clss} />
{:else if icon === "heart_outline"} {:else if icon === "heart_outline"}
<HeartOutlineIcon class={clss}/> <HeartOutlineIcon class={clss} />
{:else} {:else if icon === "confirm"}
<img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true" <Confirm class={clss} {color} />
alt="" /> {:else if icon === "not_found"}
{/if} <Not_found class={twMerge(clss, "no-image-background")} {color} />
{:else}
<img class={clss ?? "h-full w-full"} src={icon} aria-hidden="true"
alt="" />
{/if}
{/if} {/if}

View file

@ -0,0 +1,73 @@
<script lang="ts">
import type { SpecialVisualizationState } from "../SpecialVisualization";
import { Store, UIEventSource } from "../../Logic/UIEventSource";
import Loading from "../../assets/svg/Loading.svelte";
import Tr from "../Base/Tr.svelte";
import Translations from "../i18n/Translations";
import Icon from "../Map/Icon.svelte";
import Maproulette from "../../Logic/Maproulette";
/**
* A UI-element to change the status of a maproulette-task
*/
export let state: SpecialVisualizationState;
export let tags: UIEventSource<Record<string, string>>;
export let message: string;
export let image: string;
export let message_closed: string;
export let statusToSet: string;
export let maproulette_id_key: string;
let applying = false;
let failed = false;
/** Current status of the task*/
let status: Store<number> = tags
.map((tgs) => {
if (tgs["status"]) {
return tgs["status"];
}
return Maproulette.codeToIndex(tgs["mr_taskStatus"]);
}).map(Number);
async function apply() {
const maproulette_id =
tags.data[maproulette_id_key] ??
tags.data.mr_taskId ??
tags.data.id;
try {
await Maproulette.singleton.closeTask(
Number(maproulette_id),
Number(statusToSet),
{
tags: `MapComplete MapComplete:${state.layout.id}`
}
);
tags.data["mr_taskStatus"] =
Maproulette.STATUS_MEANING[Number(statusToSet)];
tags.data.status = statusToSet;
tags.ping();
} catch (e) {
console.error(e);
failed = true;
}
}
</script>
{#if failed}
<div class="alert">
ERROR - could not close the MapRoulette task
</div>
{:else if applying}
<Loading>
<Tr t={Translations.t.general.loading} />
</Loading>
{:else if $status === Maproulette.STATUS_OPEN}
<button class="w-full p-4 no-image-background" on:click={() => apply()}>
<Icon clss="w-8 h-8 mr-2" icon={image} />
{message}
</button>
{:else}
{message_closed}
{/if}

View file

@ -83,6 +83,7 @@ import NearbyImages from "./Image/NearbyImages.svelte"
import NearbyImagesCollapsed from "./Image/NearbyImagesCollapsed.svelte" import NearbyImagesCollapsed from "./Image/NearbyImagesCollapsed.svelte"
import { svelte } from "@sveltejs/vite-plugin-svelte" import { svelte } from "@sveltejs/vite-plugin-svelte"
import MoveWizard from "./Popup/MoveWizard.svelte" import MoveWizard from "./Popup/MoveWizard.svelte"
import MaprouletteSetStatus from "./MapRoulette/MaprouletteSetStatus.svelte"
class NearbyImageVis implements SpecialVisualization { class NearbyImageVis implements SpecialVisualization {
// Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests
@ -1141,73 +1142,22 @@ export default class SpecialVisualizations {
}, },
], ],
constr: (state, tagsSource, args) => { constr: (state, tagsSource, args) => {
let [message, image, message_closed, status, maproulette_id_key] = args let [message, image, message_closed, statusToSet, maproulette_id_key] = args
if (image === "") { if (image === "") {
image = "confirm" image = "confirm"
} }
if (maproulette_id_key === "" || maproulette_id_key === undefined) { if (maproulette_id_key === "" || maproulette_id_key === undefined) {
maproulette_id_key = "mr_taskId" maproulette_id_key = "mr_taskId"
} }
const failed = new UIEventSource(false) return new SvelteUIElement(MaprouletteSetStatus, {
state,
const closeButton = new SubtleButton(image, message).OnClickWithLoading( tags: tagsSource,
Translations.t.general.loading, message,
async () => { image,
const maproulette_id = message_closed,
tagsSource.data[maproulette_id_key] ?? statusToSet,
tagsSource.data.mr_taskId ?? maproulette_id_key,
tagsSource.data.id })
try {
await Maproulette.singleton.closeTask(
Number(maproulette_id),
Number(status),
{
tags: `MapComplete MapComplete:${state.layout.id}`,
}
)
tagsSource.data["mr_taskStatus"] =
Maproulette.STATUS_MEANING[Number(status)]
tagsSource.data.status = status
tagsSource.ping()
} catch (e) {
console.error(e)
failed.setData(true)
}
}
)
let message_closed_element = undefined
if (message_closed !== undefined && message_closed !== "") {
message_closed_element = new FixedUiElement(message_closed)
}
return new VariableUiElement(
tagsSource
.map((tgs) => {
if (tgs["status"]) {
return tgs["status"]
}
const code = tgs["mr_taskStatus"]
console.log("Code is", code, Maproulette.codeToIndex(code))
return Maproulette.codeToIndex(code)
})
.map(Number)
.map(
(status) => {
console.log("Close MR button: status is", status)
if (failed.data) {
return new FixedUiElement(
"ERROR - could not close the MapRoulette task"
).SetClass("block alert")
}
if (status === Maproulette.STATUS_OPEN) {
return closeButton
}
return message_closed_element ?? "Closed!"
},
[failed]
)
)
}, },
}, },
{ {