put inspect table into its own widget

feat/vaults
Tomáš Mládek 2021-06-26 13:45:05 +02:00
parent 55fa1de059
commit d8ee5aa82a
3 changed files with 154 additions and 105 deletions

View File

@ -0,0 +1,103 @@
<template>
<div class="table">
<table>
<colgroup>
<col class="attr-action-col" />
<col />
<col />
</colgroup>
<tr>
<th></th>
<th>Attribute</th>
<th>Value</th>
</tr>
<tr v-for="[id, entry] in attributes" :key="id">
<td class="attr-action">
<sl-icon-button name="x-circle" @click="removeEntry(id)" />
</td>
<td>
<Marquee>{{ entry.attribute }}</Marquee>
</td>
<td>
<Address
link
v-if="entry.value.t === 'Address'"
:address="entry.value.c"
/>
<template v-else>
<Marquee>
{{ entry.value.c }}
</Marquee>
</template>
</td>
</tr>
<tr v-if="insertable">
<td class="attr-action">
<sl-icon-button name="plus-circle" @click="addEntry()" />
</td>
<td>
<sl-input v-sl-model:newEntryAttribute />
</td>
<td>
<sl-input v-sl-model:newEntryValue />
</td>
</tr>
</table>
</div>
</template>
<script lang="ts">
import Address from "@/components/Address.vue";
import Marquee from "@/components/Marquee.vue";
import { AttributeChange, IEntry } from "@/types/base";
import { defineComponent, PropType } from "vue";
export default defineComponent({
name: "Table",
components: {
Address,
Marquee,
},
emits: ["change"],
props: {
attributes: {
type: Array as PropType<[string, IEntry][]>,
required: true,
},
deletable: {
type: Boolean,
default: true,
},
insertable: {
type: Boolean,
default: false,
},
},
data() {
return {
newEntryAttribute: "",
newEntryValue: "",
};
},
methods: {
async addEntry() {
this.$emit("change", {
type: "create",
attribute: this.newEntryAttribute,
value: this.newEntryValue,
} as AttributeChange);
this.newEntryAttribute = "";
this.newEntryValue = "";
},
async removeEntry(id: string) {
if (confirm("Are you sure you want to remove the attribute?")) {
this.$emit("change", { type: "delete", id } as AttributeChange);
}
},
},
});
</script>
<style lang="scss" scoped>
</style>

View File

@ -29,4 +29,23 @@ export interface IFile {
export interface VaultInfo {
name: string | null;
location: string;
}
export type AttributeChange = AttributeCreate | AttributeUpdate | AttributeDelete;
export interface AttributeCreate {
type: "create",
attribute: string,
value: string
}
export interface AttributeUpdate {
type: "update",
id: string,
value: string
}
export interface AttributeDelete {
type: "delete",
id: string
}

View File

@ -20,87 +20,18 @@
/>
{{ types[typeAddr]?.name || "???" }}
</h3>
<table>
<colgroup>
<col class="attr-action-col" />
<col />
<col />
</colgroup>
<tr>
<th></th>
<th>Attribute</th>
<th>Value</th>
</tr>
<tr v-for="[id, entry] in attributes" :key="id">
<td class="attr-action">
<sl-icon-button name="x-circle" @click="removeEntry(id)" />
</td>
<td>
<Marquee>{{ entry.attribute }}</Marquee>
</td>
<td>
<Marquee>
<Address
link
v-if="entry.value.t === 'Address'"
:address="entry.value.c"
/>
<template v-else>
{{ entry.value.c }}
</template>
</Marquee>
</td>
</tr>
</table>
<Table :attributes="attributes" @change="processChange" />
</section>
<section class="untyped-attribute-list">
<h3>
<sl-icon name="question-diamond" />
Other attributes
</h3>
<table>
<colgroup>
<col class="attr-action-col" />
<col />
<col />
</colgroup>
<tr>
<th></th>
<th>Attribute</th>
<th>Value</th>
</tr>
<tr v-for="[id, entry] in untypedAttributes" :key="id">
<td class="attr-action">
<sl-icon-button name="x-circle" @click="removeEntry(id)" />
</td>
<td>
<Marquee>{{ entry.attribute }}</Marquee>
</td>
<td>
<Address
link
v-if="entry.value.t === 'Address'"
:address="entry.value.c"
/>
<template v-else>
<Marquee>
{{ entry.value.c }}
</Marquee>
</template>
</td>
</tr>
<tr>
<td class="attr-action">
<sl-icon-button name="plus-circle" @click="addEntry()" />
</td>
<td>
<sl-input v-sl-model:newEntryAttribute />
</td>
<td>
<sl-input v-sl-model:newEntryValue />
</td>
</tr>
</table>
<Table
insertable
:attributes="untypedAttributes"
@change="processChange"
/>
</section>
<template v-if="backlinks.length">
<section class="backlinks">
@ -134,9 +65,10 @@
import Address from "@/components/Address.vue";
import BlobPreview from "@/components/BlobPreview.vue";
import Marquee from "@/components/Marquee.vue";
import Table from "@/components/widgets/Table.vue";
import { query, useEntity } from "@/lib/entity";
import { UpType } from "@/lib/types";
import { IEntry } from "@/types/base";
import { AttributeChange, IEntry } from "@/types/base";
import { computed, defineComponent, reactive, watch } from "vue";
export default defineComponent({
@ -145,6 +77,7 @@ export default defineComponent({
Address,
BlobPreview,
Marquee,
Table,
},
props: {
address: {
@ -152,37 +85,31 @@ export default defineComponent({
required: true,
},
},
data: () => {
return {
newEntryAttribute: "",
newEntryValue: "",
};
},
methods: {
async removeEntry(id: string) {
if (confirm("Are you sure you want to remove the attribute?")) {
await fetch(`/api/obj/${id}`, { method: "DELETE" });
await this.mutate();
async processChange(change: AttributeChange) {
switch (change.type) {
case "create":
await fetch(`/api/obj`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
entity: this.address,
attribute: change.attribute,
value: {
t: "Value",
c: change.value,
},
}),
});
break;
case "delete":
await fetch(`/api/obj/${change.id}`, { method: "DELETE" });
await this.mutate();
break;
default:
console.error(`Unimplemented: ${change}`);
}
},
async addEntry() {
await fetch(`/api/obj`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
entity: this.address,
attribute: this.newEntryAttribute,
value: {
t: "Value",
c: this.newEntryValue,
},
}),
});
await this.mutate();
this.newEntryAttribute = "";
this.newEntryValue = "";
this.mutate();
},
},
setup(props) {