Page MenuHomeSealhub

deep-reverse-single-reference-table.ts
No OneTemporary

deep-reverse-single-reference-table.ts

import {
FieldTypes as SealiousFieldTypes,
Field as SealiousField,
CollectionItem,
} from "sealious";
import { TextBasedSimpleField } from "./fields.js";
import { sealiousToFormField } from "./get-field-for-sealious.js";
import { Table, TableFieldParsed } from "./table.js";
import { Table as TableControl } from "../controls/table.js";
import { Context } from "koa";
import { FormDataValue, FormData } from "../form-types.js";
import { FormControlContext } from "../controls/form-control.js";
function getReferencingFields(
sealious_field: SealiousFieldTypes.DeepReverseSingleReference
): Record<string, SealiousField<unknown>> {
const referencing_collection =
sealious_field.collection.app.collections[
sealious_field.referencing_collection
];
if (!referencing_collection) {
throw new Error(
"Unknown collection: " + sealious_field.referencing_collection
);
}
return referencing_collection.fields;
}
export class DeepReverseSingleReferenceTable extends Table<any> {
constructor(
public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
) {
super({
selected: new Boolean(false),
[sealious_field.referencing_field]: new TextBasedSimpleField(true),
[sealious_field.intermediary_field_that_points_there]:
new TextBasedSimpleField(true),
...Object.fromEntries(
Object.values(getReferencingFields(sealious_field))
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [field.name, sealiousToFormField(field)])
),
});
}
getControl(): TableControl<any> {
return new TableControl(this, {
label: this.name,
allow_adding: false,
render_fields: {
selected: (fctx, name, value) => /* HTML */ `<input
type="checkbox"
name=${name}
${value?.toString() == "true" ? "checked" : ""}
form="${fctx.form_id}"
autocomplete="off"
/>`,
[this.sealious_field.referencing_field]: (
fctx,
name,
value
) => /* HTML */ `<input
type="hidden"
name=${name}
value="${value}"
form="${fctx.form_id}"
/>`,
[this.sealious_field.intermediary_field_that_points_there]: (
fctx,
name,
value
) => /* HTML */ `<input
type="hidden"
name="\${name}"
value="\${value}"
form="\${fctx.form_id}"
/>`,
...Object.fromEntries(
Object.values(getReferencingFields(this.sealious_field))
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [
field.name,
(fctx, name, value) => /* HTML */ `<input
name=${name}
value="${value}"
form="${fctx.form_id}"
autocomplete="off"
/>`,
])
),
},
});
}
getSealiousCreateValue(fctx: FormControlContext): Promise<unknown> {
throw new Error("Method not implemented.");
}
async postSealiousCreate(
ctx: Context,
created_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {
// First, we remove links refering to current item
const { items: to_delete } = await ctx.$app.collections[
"${toKebabCase(referencing_collection)}"
]
.list(ctx.$context)
.filter({ "${referencing_field}": created_item.id })
.fetch();
await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
// Then, we iterate over all selected values and insert appropriate entries for the subcategories relation
const referencing_fields = getReferencingFields(this.sealious_field);
const { parsed: value } = await this.getParsedValue(
ctx,
form_data.raw_values,
false
);
const promises = (value || [])
.filter((s) => s.selected == true)
.map(async (link_info) => {
await ctx.$app.collections[
"${toKebabCase(referencing_collection)}"
].create(ctx.$context, {
"${referencing_field}": created_item.id,
"${intermediary_field_that_points_there}": String(
link_info["${intermediary_field_that_points_there}"]
),
...Object.fromEntries(
Object.values(referencing_fields)
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [field.name, link_info[field.name]])
),
});
});
await Promise.all(promises);
}
postSealiousEdit(
ctx: Context,
edited_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {
return this.postSealiousCreate(ctx, edited_item, form_data);
}
async sealiousValueToForm(
ctx: Context,
value: string[],
item: CollectionItem<any>
): Promise<FormDataValue> {
// convert from an array to array-like object
const referencing_fields = getReferencingFields(this.sealious_field);
return Object.fromEntries(
await Promise.all([
this.sealious_field.collection.list(ctx.$context).fetch(),
this.sealious_field
.getReferencingCollection()
.list(ctx.$context)
.fetch(),
]).then(([{ items: targets }, { items: links }]) =>
targets
.map((target) => {
return {
selected: (
(item.get(
this.sealious_field.name
) as string[]) || []
).includes(target.id)
? "on"
: "off",
[this.sealious_field.referencing_field]: item.id,
[this.sealious_field
.intermediary_field_that_points_there]:
target.id,
...Object.fromEntries(
Object.values(referencing_fields)
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [
field.name,
links
.find(
(e) =>
e.get(
this.sealious_field
.intermediary_field_that_points_there
) == target.id &&
e.get(
this.sealious_field
.referencing_field
) == item.id
)
?.get("rank") || 0,
])
),
};
})
.entries()
)
) as FormDataValue;
}
}

File Metadata

Mime Type
text/x-java
Expires
Sun, Nov 2, 18:00 (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1029156
Default Alt Text
deep-reverse-single-reference-table.ts (5 KB)

Event Timeline