put inspect table into its own widget
This commit is contained in:
parent
55fa1de059
commit
d8ee5aa82a
3 changed files with 154 additions and 105 deletions
103
ui/src/components/widgets/Table.vue
Normal file
103
ui/src/components/widgets/Table.vue
Normal 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>
|
|
@ -30,3 +30,22 @@ export interface VaultInfo {
|
||||||
name: string | null;
|
name: string | null;
|
||||||
location: string;
|
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
|
||||||
|
}
|
|
@ -20,87 +20,18 @@
|
||||||
/>
|
/>
|
||||||
{{ types[typeAddr]?.name || "???" }}
|
{{ types[typeAddr]?.name || "???" }}
|
||||||
</h3>
|
</h3>
|
||||||
<table>
|
<Table :attributes="attributes" @change="processChange" />
|
||||||
<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>
|
|
||||||
</section>
|
</section>
|
||||||
<section class="untyped-attribute-list">
|
<section class="untyped-attribute-list">
|
||||||
<h3>
|
<h3>
|
||||||
<sl-icon name="question-diamond" />
|
<sl-icon name="question-diamond" />
|
||||||
Other attributes
|
Other attributes
|
||||||
</h3>
|
</h3>
|
||||||
<table>
|
<Table
|
||||||
<colgroup>
|
insertable
|
||||||
<col class="attr-action-col" />
|
:attributes="untypedAttributes"
|
||||||
<col />
|
@change="processChange"
|
||||||
<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>
|
|
||||||
</section>
|
</section>
|
||||||
<template v-if="backlinks.length">
|
<template v-if="backlinks.length">
|
||||||
<section class="backlinks">
|
<section class="backlinks">
|
||||||
|
@ -134,9 +65,10 @@
|
||||||
import Address from "@/components/Address.vue";
|
import Address from "@/components/Address.vue";
|
||||||
import BlobPreview from "@/components/BlobPreview.vue";
|
import BlobPreview from "@/components/BlobPreview.vue";
|
||||||
import Marquee from "@/components/Marquee.vue";
|
import Marquee from "@/components/Marquee.vue";
|
||||||
|
import Table from "@/components/widgets/Table.vue";
|
||||||
import { query, useEntity } from "@/lib/entity";
|
import { query, useEntity } from "@/lib/entity";
|
||||||
import { UpType } from "@/lib/types";
|
import { UpType } from "@/lib/types";
|
||||||
import { IEntry } from "@/types/base";
|
import { AttributeChange, IEntry } from "@/types/base";
|
||||||
import { computed, defineComponent, reactive, watch } from "vue";
|
import { computed, defineComponent, reactive, watch } from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
@ -145,6 +77,7 @@ export default defineComponent({
|
||||||
Address,
|
Address,
|
||||||
BlobPreview,
|
BlobPreview,
|
||||||
Marquee,
|
Marquee,
|
||||||
|
Table,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
address: {
|
address: {
|
||||||
|
@ -152,37 +85,31 @@ export default defineComponent({
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data: () => {
|
|
||||||
return {
|
|
||||||
newEntryAttribute: "",
|
|
||||||
newEntryValue: "",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
async removeEntry(id: string) {
|
async processChange(change: AttributeChange) {
|
||||||
if (confirm("Are you sure you want to remove the attribute?")) {
|
switch (change.type) {
|
||||||
await fetch(`/api/obj/${id}`, { method: "DELETE" });
|
case "create":
|
||||||
await this.mutate();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async addEntry() {
|
|
||||||
await fetch(`/api/obj`, {
|
await fetch(`/api/obj`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
entity: this.address,
|
entity: this.address,
|
||||||
attribute: this.newEntryAttribute,
|
attribute: change.attribute,
|
||||||
value: {
|
value: {
|
||||||
t: "Value",
|
t: "Value",
|
||||||
c: this.newEntryValue,
|
c: change.value,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
break;
|
||||||
|
case "delete":
|
||||||
|
await fetch(`/api/obj/${change.id}`, { method: "DELETE" });
|
||||||
await this.mutate();
|
await this.mutate();
|
||||||
|
break;
|
||||||
this.newEntryAttribute = "";
|
default:
|
||||||
this.newEntryValue = "";
|
console.error(`Unimplemented: ${change}`);
|
||||||
|
}
|
||||||
|
this.mutate();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
Loading…
Reference in a new issue