2023-07-29 11:21:34 +02:00
|
|
|
<script lang="ts">
|
2023-07-29 19:26:00 +02:00
|
|
|
import UpObjectDisplay from "./display/UpObject.svelte";
|
2023-07-29 11:21:34 +02:00
|
|
|
import Selector from "./utils/Selector.svelte";
|
|
|
|
import IconButton from "./utils/IconButton.svelte";
|
|
|
|
import type { IValue } from "upend/types";
|
|
|
|
import api from "../lib/api";
|
|
|
|
import { ATTR_IN } from "upend/constants";
|
|
|
|
import { createEventDispatcher } from "svelte";
|
|
|
|
import { i18n } from "../i18n";
|
2023-07-29 19:26:00 +02:00
|
|
|
import type { UpObject } from "upend";
|
|
|
|
import type { Readable } from "svelte/store";
|
2023-09-05 20:57:01 +02:00
|
|
|
import LabelBorder from "./utils/LabelBorder.svelte";
|
2023-07-29 11:21:34 +02:00
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
|
2023-07-29 19:26:00 +02:00
|
|
|
export let entity: Readable<UpObject>;
|
2023-09-03 11:56:03 +02:00
|
|
|
|
|
|
|
let adding = false;
|
|
|
|
let groupSelector: Selector;
|
|
|
|
|
|
|
|
$: if (adding && groupSelector) groupSelector.focus();
|
2023-07-29 11:21:34 +02:00
|
|
|
|
2023-07-29 19:26:00 +02:00
|
|
|
$: groups = ($entity?.attr[ATTR_IN] || []).map(
|
2023-09-03 11:56:03 +02:00
|
|
|
(e) => [e.value.c as string, e.address] as [string, string],
|
2023-07-29 19:26:00 +02:00
|
|
|
);
|
|
|
|
|
2023-07-29 11:21:34 +02:00
|
|
|
let groupToAdd: IValue | undefined;
|
|
|
|
async function addGroup() {
|
|
|
|
if (!groupToAdd) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
await api.putEntry([
|
|
|
|
{
|
2023-07-29 19:26:00 +02:00
|
|
|
entity: $entity.address,
|
2023-07-29 11:21:34 +02:00
|
|
|
attribute: ATTR_IN,
|
|
|
|
value: {
|
|
|
|
t: "Address",
|
|
|
|
c: String(groupToAdd.c),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
dispatch("change");
|
|
|
|
groupToAdd = undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function removeGroup(groupAddress: string) {
|
2023-09-03 11:56:03 +02:00
|
|
|
if (confirm($i18n.t("Are you sure you want to remove this group?"))) {
|
|
|
|
await api.deleteEntry(groupAddress);
|
|
|
|
dispatch("change");
|
|
|
|
}
|
2023-07-29 11:21:34 +02:00
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
<LabelBorder hide={groups.length === 0}>
|
|
|
|
<span slot="header">{$i18n.t("Groups")}</span>
|
2023-09-03 11:56:03 +02:00
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
{#if adding}
|
|
|
|
<div class="selector">
|
|
|
|
<Selector
|
|
|
|
bind:this={groupSelector}
|
|
|
|
type="value"
|
|
|
|
valueTypes={["Address"]}
|
|
|
|
bind:value={groupToAdd}
|
|
|
|
on:input={addGroup}
|
|
|
|
on:focus={(ev) => {
|
|
|
|
if (!ev.detail) adding = false;
|
|
|
|
}}
|
|
|
|
placeholder={$i18n.t("Choose an entity...")}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
{/if}
|
|
|
|
|
|
|
|
<div class="body">
|
|
|
|
<div class="group-list">
|
|
|
|
{#each groups as [groupAddress, groupEntryAddress]}
|
|
|
|
<div
|
|
|
|
class="group"
|
|
|
|
on:mouseenter={() => dispatch("highlighted", groupAddress)}
|
|
|
|
on:mouseleave={() => dispatch("highlighted", undefined)}
|
|
|
|
>
|
|
|
|
<UpObjectDisplay address={groupAddress} link />
|
2023-09-03 11:56:03 +02:00
|
|
|
<IconButton
|
2023-09-05 20:57:01 +02:00
|
|
|
subdued
|
|
|
|
name="x-circle"
|
|
|
|
on:click={() => removeGroup(groupEntryAddress)}
|
2023-07-29 11:21:34 +02:00
|
|
|
/>
|
2023-07-29 19:26:00 +02:00
|
|
|
</div>
|
2023-09-05 20:57:01 +02:00
|
|
|
{:else}
|
|
|
|
<div class="no-groups">
|
|
|
|
{$i18n.t("Object is not in any groups.")}
|
|
|
|
</div>
|
|
|
|
{/each}
|
2023-07-29 19:26:00 +02:00
|
|
|
</div>
|
2023-09-05 20:57:01 +02:00
|
|
|
{#if !adding}
|
|
|
|
<div class="add-button">
|
|
|
|
<IconButton
|
|
|
|
outline
|
|
|
|
small
|
|
|
|
name="folder-plus"
|
|
|
|
on:click={() => (adding = true)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
{/if}
|
2023-09-03 11:56:03 +02:00
|
|
|
</div>
|
2023-09-05 20:57:01 +02:00
|
|
|
</LabelBorder>
|
2023-07-29 11:21:34 +02:00
|
|
|
|
|
|
|
<style lang="scss">
|
2023-09-05 20:57:01 +02:00
|
|
|
.group-list {
|
|
|
|
display: flex;
|
|
|
|
flex-wrap: wrap;
|
|
|
|
gap: 0.25rem 0.2rem;
|
|
|
|
align-items: center;
|
|
|
|
}
|
2023-07-29 11:21:34 +02:00
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
.group {
|
|
|
|
display: inline-flex;
|
|
|
|
align-items: center;
|
|
|
|
}
|
2023-07-29 11:21:34 +02:00
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
.body {
|
|
|
|
display: flex;
|
|
|
|
align-items: start;
|
2023-09-03 11:56:03 +02:00
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
.group-list {
|
|
|
|
flex-grow: 1;
|
2023-09-03 11:56:03 +02:00
|
|
|
}
|
2023-09-05 20:57:01 +02:00
|
|
|
}
|
2023-09-03 11:56:03 +02:00
|
|
|
|
2023-09-05 20:57:01 +02:00
|
|
|
.selector {
|
|
|
|
width: 100%;
|
|
|
|
margin-bottom: 0.5rem;
|
2023-07-29 11:21:34 +02:00
|
|
|
}
|
2023-09-03 11:56:03 +02:00
|
|
|
|
|
|
|
.no-groups {
|
|
|
|
opacity: 0.66;
|
|
|
|
}
|
2023-07-29 11:21:34 +02:00
|
|
|
</style>
|