wip(webui): use (new) attr constants
parent
0eec69b219
commit
641f42f785
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* Attribute denoting (hierarchical) relation, in the "upwards" direction. For example, a file `IN` a group, an image `IN` photos, etc.
|
||||
*/
|
||||
export const ATTR_IN = "IN";
|
||||
|
||||
/**
|
||||
* Attribute denoting that an entry belongs to the set relating to a given (hierarchical) relation.
|
||||
* For example, a data blob may have a label entry, and to qualify that label within the context of belonging to a given hierarchical group, that label entry and the hierarchical entry will be linked with `BY`.
|
||||
*/
|
||||
export const ATTR_BY = "BY";
|
||||
|
||||
/**
|
||||
* Attribute denoting that an attribute belongs to a given "tagging" entity. If an entity belongs to (`IN`) a "tagging" entity, it is expected to have attributes that are `OF` that entity.
|
||||
*/
|
||||
export const ATTR_OF = "OF";
|
||||
|
||||
/**
|
||||
* Attribute denoting a human readable label.
|
||||
*/
|
||||
export const ATTR_LABEL = "LBL";
|
||||
|
||||
/**
|
||||
* Attribute denoting the date & time an entity was noted in the database.
|
||||
* (TODO: This info can be trivially derived from existing entry timestamps, while at the same time the "Introduction problem" is still open.)
|
||||
*/
|
||||
export const ATTR_ADDED = "ADDED";
|
||||
|
||||
/**
|
||||
* Attribute for cross-vault unambiguous referencing of non-hashable (e.g. UUID) entities.
|
||||
*/
|
||||
export const ATTR_KEY = "KEY";
|
|
@ -19,6 +19,7 @@
|
|||
import EntryList from "./widgets/EntryList.svelte";
|
||||
import api from "../lib/api";
|
||||
import Gallery from "./widgets/Gallery.svelte";
|
||||
import { ATTR_IN, ATTR_LABEL, ATTR_KEY } from "upend/constants";
|
||||
const dispatch = createEventDispatcher();
|
||||
const params = useParams();
|
||||
|
||||
|
@ -76,9 +77,9 @@
|
|||
$: filteredUntypedAttributes = untypedAttributes.filter(
|
||||
(entry) =>
|
||||
![
|
||||
"LBL",
|
||||
"OF",
|
||||
"KEY",
|
||||
ATTR_LABEL,
|
||||
ATTR_IN,
|
||||
ATTR_KEY,
|
||||
"NOTE",
|
||||
"LAST_VISITED",
|
||||
"NUM_VISITED",
|
||||
|
@ -94,14 +95,14 @@
|
|||
(editable
|
||||
? $entity?.backlinks
|
||||
: $entity?.backlinks.filter(
|
||||
(entry) => !["OF"].includes(entry.attribute)
|
||||
(entry) => ![ATTR_IN].includes(entry.attribute)
|
||||
)) || [];
|
||||
|
||||
$: groups = ($entity?.attr["OF"] || []).map((e) => [
|
||||
$: groups = ($entity?.attr[ATTR_IN] || []).map((e) => [
|
||||
e.value.c as string,
|
||||
e.address,
|
||||
]);
|
||||
$: tagged = $entity?.attr["~OF"] || [];
|
||||
$: tagged = $entity?.attr[`~${ATTR_IN}`] || [];
|
||||
|
||||
let attributesUsed: UpEntry[] = [];
|
||||
$: {
|
||||
|
@ -149,7 +150,7 @@
|
|||
await api.putEntry([
|
||||
{
|
||||
entity: address,
|
||||
attribute: "OF",
|
||||
attribute: ATTR_IN,
|
||||
value: {
|
||||
t: "Address",
|
||||
c: String(groupToAdd.c),
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
import { getTypes } from "../../util/mediatypes";
|
||||
import { formatDuration } from "../../util/fragments/time";
|
||||
import { concurrentImage } from "../imageQueue";
|
||||
import { ATTR_IN } from "upend/constants";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let address: string;
|
||||
|
@ -38,14 +39,14 @@
|
|||
let failedChildren: string[] = [];
|
||||
let loadedChildren: string[] = [];
|
||||
$: groupChildren = $entity?.backlinks
|
||||
.filter((e) => e.attribute === "OF")
|
||||
.filter((e) => e.attribute === ATTR_IN)
|
||||
.map((e) => String(e.entity))
|
||||
.filter(
|
||||
(addr) =>
|
||||
!failedChildren
|
||||
.slice(
|
||||
0,
|
||||
$entity?.backlinks.filter((e) => e.attribute === "OF").length - 4
|
||||
$entity?.backlinks.filter((e) => e.attribute === ATTR_IN).length - 4
|
||||
)
|
||||
.includes(addr)
|
||||
)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
import UpObject from "../../display/UpObject.svelte";
|
||||
import Spinner from "../../utils/Spinner.svelte";
|
||||
import { i18n } from "../../../i18n";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
|
||||
export let address: string;
|
||||
export let detail: boolean;
|
||||
|
@ -51,7 +52,7 @@
|
|||
color: annotation.get("COLOR") || DEFAULT_ANNOTATION_COLOR,
|
||||
attributes: {
|
||||
"upend-address": annotation.address,
|
||||
label: annotation.get("LBL"),
|
||||
label: annotation.get(ATTR_LABEL),
|
||||
},
|
||||
data: (annotation.attr["NOTE"] || [])[0]?.value,
|
||||
...fragment,
|
||||
|
@ -92,7 +93,7 @@
|
|||
} as any); // incorrect types, `update()` does take `attributes`
|
||||
}
|
||||
|
||||
await api.putEntityAttribute(entity, "LBL", {
|
||||
await api.putEntityAttribute(entity, ATTR_LABEL, {
|
||||
t: "String",
|
||||
c: region.attributes["label"],
|
||||
});
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
import IconButton from "../../utils/IconButton.svelte";
|
||||
import Spinner from "../../utils/Spinner.svelte";
|
||||
import UpObject from "../UpObject.svelte";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
|
||||
export let address: string;
|
||||
export let editable: boolean;
|
||||
|
@ -58,7 +59,7 @@
|
|||
if (annotation.get("W3C_FRAGMENT_SELECTOR")) {
|
||||
anno.addAnnotation({
|
||||
type: "Annotation",
|
||||
body: annotation.attr["LBL"].map((e) => {
|
||||
body: annotation.attr[ATTR_LABEL].map((e) => {
|
||||
return {
|
||||
type: "TextualBody",
|
||||
value: String(e.value.c),
|
||||
|
@ -134,7 +135,7 @@
|
|||
...annotation.body.map((body) => {
|
||||
return {
|
||||
entity: uuid,
|
||||
attribute: "LBL",
|
||||
attribute: ATTR_LABEL,
|
||||
value: {
|
||||
t: "String",
|
||||
c: body.value,
|
||||
|
@ -146,9 +147,9 @@
|
|||
anno.on("updateAnnotation", async (annotation) => {
|
||||
const annotationObject = await api.fetchEntity(annotation.id);
|
||||
await Promise.all(
|
||||
annotationObject.attr["LBL"]
|
||||
.concat(annotationObject.attr["W3C_FRAGMENT_SELECTOR"])
|
||||
.map(async (e) => api.deleteEntry(e.address))
|
||||
annotationObject.attr[ATTR_LABEL].concat(
|
||||
annotationObject.attr["W3C_FRAGMENT_SELECTOR"]
|
||||
).map(async (e) => api.deleteEntry(e.address))
|
||||
);
|
||||
await api.putEntry([
|
||||
{
|
||||
|
@ -162,7 +163,7 @@
|
|||
...annotation.body.map((body) => {
|
||||
return {
|
||||
entity: annotation.id,
|
||||
attribute: "LBL",
|
||||
attribute: ATTR_LABEL,
|
||||
value: {
|
||||
t: "String",
|
||||
c: body.value,
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
const dispatch = createEventDispatcher();
|
||||
import { matchSorter } from "match-sorter";
|
||||
import api from "../../lib/api";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
|
||||
const MAX_OPTIONS = 25;
|
||||
|
||||
|
@ -150,7 +151,7 @@
|
|||
}
|
||||
|
||||
const validOptions = searchResult.entries
|
||||
.filter((e) => e.attribute === "LBL")
|
||||
.filter((e) => e.attribute === ATTR_LABEL)
|
||||
.filter((e) => !exactHits.includes(e.entity));
|
||||
|
||||
const sortedOptions = matchSorter(validOptions, inputValue, {
|
||||
|
@ -197,7 +198,7 @@
|
|||
entity: { t: "Attribute", c: option.attribute.name },
|
||||
});
|
||||
// Second, label it.
|
||||
await api.putEntityAttribute(address, "LBL", {
|
||||
await api.putEntityAttribute(address, ATTR_LABEL, {
|
||||
t: "String",
|
||||
c: option.labelToCreate,
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
import { formatDuration } from "../../util/fragments/time";
|
||||
import { i18n } from "../../i18n";
|
||||
import UpLink from "../display/UpLink.svelte";
|
||||
import { ATTR_ADDED, ATTR_LABEL } from "upend/constants";
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
export let columns: string | undefined = undefined;
|
||||
|
@ -87,7 +88,9 @@
|
|||
|
||||
const addressesString = addresses.map((addr) => `@${addr}`).join(" ");
|
||||
|
||||
labelListing = query(`(matches (in ${addressesString}) "LBL" ? )`).result;
|
||||
labelListing = query(
|
||||
`(matches (in ${addressesString}) "${ATTR_LABEL}" ? )`
|
||||
).result;
|
||||
}
|
||||
|
||||
// Sorting
|
||||
|
@ -159,7 +162,7 @@
|
|||
switch (attribute) {
|
||||
case "FILE_SIZE":
|
||||
return filesize(parseInt(String(value), 10), { base: 2 });
|
||||
case "ADDED":
|
||||
case ATTR_ADDED:
|
||||
case "LAST_VISITED":
|
||||
return formatRelative(
|
||||
fromUnixTime(parseInt(String(value), 10)),
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
import { query } from "../../lib/entity";
|
||||
import UpObject from "../display/UpObject.svelte";
|
||||
import UpObjectCard from "../display/UpObjectCard.svelte";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
|
||||
export let entities: Address[];
|
||||
export let thumbnails = true;
|
||||
|
@ -49,7 +50,9 @@
|
|||
|
||||
const addressesString = addresses.map((addr) => `@${addr}`).join(" ");
|
||||
|
||||
labelListing = query(`(matches (in ${addressesString}) "LBL" ? )`).result;
|
||||
labelListing = query(
|
||||
`(matches (in ${addressesString}) "${ATTR_LABEL}" ? )`
|
||||
).result;
|
||||
}
|
||||
|
||||
function sortEntities() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
"ADDED": "Added at",
|
||||
"LAST_VISITED": "Last visited at",
|
||||
"NUM_VISITED": "Times visited",
|
||||
"LBL": "Label",
|
||||
"ATTR_LABEL": "Label",
|
||||
"IS": "Type",
|
||||
"TYPE": "Type ID",
|
||||
"MEDIA_DURATION": "Duration"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import type { EntityInfo } from "upend/types";
|
||||
import type { UpObject } from "upend";
|
||||
import { ATTR_IN } from "upend/constants";
|
||||
|
||||
export function getTypes(entity: UpObject, entityInfo: EntityInfo) {
|
||||
const mimeType = String(entity?.get("FILE_MIME"));
|
||||
|
@ -22,7 +23,7 @@ export function getTypes(entity: UpObject, entityInfo: EntityInfo) {
|
|||
const web = entityInfo?.t == "Url";
|
||||
const fragment = Boolean(entity?.get("ANNOTATES"));
|
||||
|
||||
const group = entity?.backlinks.some((e) => e.attribute == "OF");
|
||||
const group = entity?.backlinks.some((e) => e.attribute == ATTR_IN);
|
||||
|
||||
return {
|
||||
mimeType,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import type { PutInput } from "upend/types";
|
||||
import { query as queryFn } from "../lib/entity";
|
||||
import api from "../lib/api";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
|
||||
export function baseSearch(query: string) {
|
||||
return queryFn(
|
||||
|
@ -26,7 +27,7 @@ export async function createLabelled(label: string) {
|
|||
} else {
|
||||
// TODO - don't create invariants, create UUIDs instead, maybe with keys?
|
||||
body = {
|
||||
attribute: "LBL",
|
||||
attribute: ATTR_LABEL,
|
||||
value: {
|
||||
t: "String",
|
||||
c: label,
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
import { vaultInfo } from "../util/info";
|
||||
import { updateTitle } from "../util/title";
|
||||
import { i18n } from "../i18n";
|
||||
import { ATTR_ADDED, ATTR_LABEL } from "upend/constants";
|
||||
|
||||
const roots = (async () => {
|
||||
const data = await api.fetchRoots();
|
||||
const listing = new UpListing(data);
|
||||
return Object.values(listing.objects)
|
||||
.filter((obj) => Boolean(obj.attr["LBL"]))
|
||||
.filter((obj) => Boolean(obj.attr[ATTR_LABEL]))
|
||||
.map((obj) => [obj.address, obj.identify().join(" | ")])
|
||||
.sort(([_, i1], [__, i2]) => i1.localeCompare(i2));
|
||||
})();
|
||||
|
@ -34,7 +35,7 @@
|
|||
.sort((a, b) => (b.value.c as number) - (a.value.c as number))
|
||||
.slice(0, 25);
|
||||
|
||||
const { result: latestQuery } = query(`(matches ? "ADDED" ?)`);
|
||||
const { result: latestQuery } = query(`(matches ? "${ATTR_ADDED}" ?)`);
|
||||
$: latest = ($latestQuery?.entries || [])
|
||||
.filter((e) => e.value.t == "Number")
|
||||
.sort((a, b) => (b.value.c as number) - (a.value.c as number))
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
import api from "../lib/api";
|
||||
import Gallery from "../components/widgets/Gallery.svelte";
|
||||
import { matchSorter } from "match-sorter";
|
||||
import { ATTR_LABEL } from "upend/constants";
|
||||
const navigate = useNavigate();
|
||||
|
||||
export let query: string;
|
||||
|
@ -35,7 +36,9 @@
|
|||
exactHits = [];
|
||||
}
|
||||
|
||||
$: objects = ($result?.entries || []).filter((e) => e.attribute === "LBL");
|
||||
$: objects = ($result?.entries || []).filter(
|
||||
(e) => e.attribute === ATTR_LABEL
|
||||
);
|
||||
$: sortedObjects = matchSorter(objects, debouncedQuery, {
|
||||
keys: ["value.c"],
|
||||
});
|
||||
|
@ -44,7 +47,7 @@
|
|||
$: {
|
||||
const addressesString = objects.map((e) => `@${e.entity}`).join(" ");
|
||||
api
|
||||
.query(`(matches (in ${addressesString}) "LBL" ? )`)
|
||||
.query(`(matches (in ${addressesString}) "${ATTR_LABEL}" ? )`)
|
||||
.then((labelListing) => {
|
||||
exactHits = labelListing.entries
|
||||
.filter(
|
||||
|
|
|
@ -12585,11 +12585,11 @@ __metadata:
|
|||
|
||||
"upend@file:../tools/upend_js::locator=upend-kestrel%40workspace%3A.":
|
||||
version: 0.0.1
|
||||
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=88616b&locator=upend-kestrel%40workspace%3A."
|
||||
resolution: "upend@file:../tools/upend_js#../tools/upend_js::hash=cda57f&locator=upend-kestrel%40workspace%3A."
|
||||
dependencies:
|
||||
debug: ^4.3.4
|
||||
lru-cache: ^7.0.0
|
||||
checksum: c73ce133f42c9669f15b5d38b2d552722d9df56ec1daa61d31b41d8a0ec6c9064a9424c6e5589d53edeebfc75c447464f10110539b8237c19bf9597987bd6d06
|
||||
checksum: 551abb5f6c2d07e1350993d27ca835fea005172ad66889e41fa5a9793ad414788ecfce2c966f526d3347d08e1731f1945c695e95aae15dd334ca17b1bc1fd195
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
Loading…
Reference in New Issue