Skip to content

Commit

Permalink
Add back some admin files still needed for now
Browse files Browse the repository at this point in the history
  • Loading branch information
Pierstoval committed Mar 25, 2024
1 parent 070a409 commit d068283
Show file tree
Hide file tree
Showing 21 changed files with 483 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/lib/admin/src/ActionParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Field from './Field';

export default class ActionParams {
private _params: Array<Field> = [];

get params(): Array<Field> {
return this._params;
}

public static id(): ActionParams {
return new ActionParams().and('id');
}

public static with(field: string | Field): ActionParams {
return new ActionParams().and(field);
}

public and(field: string | Field): ActionParams {
if (field instanceof Field) {
this._params.push(field);
} else {
this._params.push(new Field(field));
}

return this;
}
}
12 changes: 12 additions & 0 deletions src/lib/admin/src/AssociatedField.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Field from './Field';
import FieldHtmlProperties from './FieldHtmlProperties';

export default class AssociatedField extends Field {
constructor(
name: string,
associated_field: Field,
field_html_properties: FieldHtmlProperties = FieldHtmlProperties.defaults()
) {
super(name, '', associated_field, field_html_properties);
}
}
11 changes: 11 additions & 0 deletions src/lib/admin/src/AssociatedItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type Field from './Field';

export default class AssociatedItem<T> {
public readonly item: T;
public readonly fields: Field[];

constructor(item: T, fields: Field[]) {
this.item = item;
this.fields = fields;
}
}
14 changes: 14 additions & 0 deletions src/lib/admin/src/CallbackAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import DefaultAction from './DefaultAction';

export default class CallbackAction extends DefaultAction {
private readonly _callback: Function;

constructor(name: string, callback: Function) {
super(name);
this._callback = callback;
}

public call(item: object): string {
return this._callback.call(null, item);
}
}
10 changes: 10 additions & 0 deletions src/lib/admin/src/Collection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export default class Collection<T> extends Array<T> {
constructor(items: T[] = []) {
super();
this.addItems(items);
}

private addItems(items: T[] = []) {
items.forEach((item) => this.push(item));
}
}
23 changes: 23 additions & 0 deletions src/lib/admin/src/CollectionField.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type AssociatedField from './AssociatedField';
import Field from './Field';
import FieldOptions from './FieldOptions';

export default class CollectionField extends Field {
constructor(name: string, text: string, item_field: Field) {
super(name, text, new FieldOptions(item_field));
}

public displayFromItem(item: object | any): any {
let field: Field | AssociatedField;

const items = item[this.name];

if (items.length === 0 || !(items instanceof Array)) {
return null;
}

field = this._associated_field;

return items.map((singleItem) => field.displayFromItem(singleItem));
}
}
34 changes: 34 additions & 0 deletions src/lib/admin/src/ConfigFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import FilterType from './FilterType';
import type FilterWithValue from './FilterWithValue';
import type Filter from '../components/PaginatedTable/Filter.svelte';

export default class ConfigFilter {
public readonly name: string;
public readonly title: string;
public readonly type: FilterType;
public readonly options: { [key: string]: any };
public element: Filter | null;
public value: FilterWithValue | null;

constructor(name: string, title: string, type: FilterType, options?: { [key: string]: any }) {
this.name = name;
this.title = title;
this.type = type;
this.options = options || {};
this.validateOptions();
}

private validateOptions() {
switch (this.type) {
case FilterType.entity:
if (!this.options.entities) {
throw new Error(
'To define a filter of type "entity", you must also specify the "entities" option. This must contain an array that contains elements of type "{name: string, value: string}", or a callable that returns such array, or a promise that resolves to such array.'
);
}
break;
default:
break;
}
}
}
13 changes: 13 additions & 0 deletions src/lib/admin/src/DefaultAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type ItemAction from './ItemAction';

export default abstract class DefaultAction implements ItemAction {
protected readonly _name: string;

protected constructor(name: string) {
this._name = name;
}

get name(): string {
return this._name;
}
}
45 changes: 45 additions & 0 deletions src/lib/admin/src/Field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type AssociatedField from './AssociatedField';
import type FieldHtmlProperties from './FieldHtmlProperties';
import FieldOptions from './FieldOptions';
import SortableField from './SortableField';

export const Sortable = true;

export default class Field {
public readonly name: string;
public readonly text: string;
public readonly field_html_properties: FieldHtmlProperties;
public readonly sortable_field: SortableField | null;
protected readonly _associated_field: null | AssociatedField;

constructor(
name: string,
text: string = '',
options: FieldOptions | null = null,
sortable: boolean = false
) {
if (!options) {
options = FieldOptions.defaults();
}
this.name = name;
this.text = text === '' ? name : text;
this.field_html_properties = options.field_html_properties;
this._associated_field = options.associated_field;
this.sortable_field = sortable
? new SortableField(name, null, options.sortable_property_name || name)
: null;
}

public displayFromItem(item: object | any): any {
let field: Field | AssociatedField;

if (this._associated_field) {
item = item[this.name];
field = this._associated_field;
} else {
field = this;
}

return item[field.name];
}
}
11 changes: 11 additions & 0 deletions src/lib/admin/src/FieldHtmlProperties.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export default class FieldHtmlProperties {
public readonly html_class: string;

constructor(html_class: string = '') {
this.html_class = html_class;
}

static defaults() {
return new FieldHtmlProperties();
}
}
34 changes: 34 additions & 0 deletions src/lib/admin/src/FieldOptions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type AssociatedField from './AssociatedField';
import FieldHtmlProperties from './FieldHtmlProperties';

export default class FieldOptions {
public readonly associated_field: null | AssociatedField;
public readonly field_html_properties: FieldHtmlProperties;
public readonly sortable_property_name: string | null;

constructor(
associated_field: AssociatedField | null = null,
field_html_properties: FieldHtmlProperties | null = null,
sortable_property_name: string | null = null
) {
this.associated_field = associated_field;
this.field_html_properties = field_html_properties || FieldHtmlProperties.defaults();
this.sortable_property_name = sortable_property_name;
}

static defaults(): FieldOptions {
return new FieldOptions();
}

static newWithAssociatedField(field: AssociatedField): FieldOptions {
return new FieldOptions(field);
}

static newWithHtmlProperties(htmlProperties: FieldHtmlProperties): FieldOptions {
return new FieldOptions(null, htmlProperties);
}

static newWithSortName(sortable_property_name: string): FieldOptions {
return new FieldOptions(null, null, sortable_property_name);
}
}
9 changes: 9 additions & 0 deletions src/lib/admin/src/FilterType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
enum FilterType {
text = 'text',
date = 'date',
number = 'number',
entity = 'entity',
boolean = 'boolean'
}

export default FilterType;
28 changes: 28 additions & 0 deletions src/lib/admin/src/FilterWithValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type ConfigFilter from './ConfigFilter';
import type FilterType from './FilterType';

export default class FilterWithValue {
public readonly name: string;
public readonly type: FilterType;
public readonly value: string;

constructor(name: string, type: FilterType, value: string) {
this.name = name;
this.type = type;
this.value = value;
}

public static fromFilter(filter: ConfigFilter, value: string): FilterWithValue {
return new FilterWithValue(filter.name, filter.type, value);
}

public static fromSerialized(filter: Partial<FilterWithValue>): FilterWithValue {
if (!filter.name || !filter.type || !filter.value) {
console.error('Serialized filter is incomplete', filter);

throw new Error('Serialized filter is incomplete');
}

return new FilterWithValue(filter.name, filter.type, filter.value);
}
}
3 changes: 3 additions & 0 deletions src/lib/admin/src/ItemAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default interface ItemAction {
get name(): string;
}
15 changes: 15 additions & 0 deletions src/lib/admin/src/OrderBy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export enum OrderBy {
ASC = 'ASC',
DESC = 'DESC'
}

export function orderByToString(order_by: OrderBy): string {
switch (order_by) {
case OrderBy.ASC:
return 'ASC';
case OrderBy.DESC:
return 'DESC';
default:
throw new Error(`Unsupported order_by type: ${order_by}`);
}
}
39 changes: 39 additions & 0 deletions src/lib/admin/src/PageHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type SortableField from './SortableField';
import type FilterWithValue from './FilterWithValue';

export default class PageHooks {
private readonly _items_callback: Function;
private readonly _count_callback: Function;

private lastPage: number = 1;
private lastField: SortableField | null;
private lastFilters: Array<FilterWithValue> | null;

constructor(items_callback: Function, count_callback: Function = null) {
this._items_callback = items_callback;
this._count_callback = count_callback || null;
}

get hasCountCallback(): boolean {
return this._count_callback !== null;
}

public refresh() {
this.callForItems(this.lastPage, this.lastField, this.lastFilters);
}

public callForItems(
page: number,
field: SortableField | null,
filters: Array<FilterWithValue> | null
): void {
this.lastPage = page;
this.lastField = field;
this.lastFilters = filters;
this._items_callback(page, field, filters);
}

public getCountCallback(): Function {
return this._count_callback;
}
}
28 changes: 28 additions & 0 deletions src/lib/admin/src/SavedFilter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import FilterWithValue from './FilterWithValue';

export default class SavedFilter {
public readonly name: string;
public readonly deserialized_filters: Array<FilterWithValue>;
private readonly filters: string;

constructor(name: string, filters_with_values: Array<FilterWithValue>) {
this.name = name;
this.deserialized_filters = filters_with_values;
this.filters = JSON.stringify(filters_with_values);
}

public static fromSerialized(name: string, filters: string): SavedFilter {
let deserialized_filters: Array<FilterWithValue> = JSON.parse(filters);

if (!Array.isArray(deserialized_filters)) {
console.error('Stored filters are not stored as an array. Resetting them.');
deserialized_filters = [];
}

deserialized_filters = deserialized_filters.map((f: filter) =>
FilterWithValue.fromSerialized(f)
);

return new SavedFilter(name, deserialized_filters);
}
}
21 changes: 21 additions & 0 deletions src/lib/admin/src/SortableField.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { OrderBy } from './OrderBy';

export default class SortableField {
public readonly name: string;
public readonly property_name: string;
public order_by: OrderBy;

constructor(name: string, order: OrderBy = OrderBy.ASC, property_name: string) {
this.name = name;
this.order_by = order;
this.property_name = property_name;
}

get is_asc(): boolean {
return this.order_by === OrderBy.ASC;
}

swapOrder() {
this.order_by = this.order_by === OrderBy.ASC ? OrderBy.DESC : OrderBy.ASC;
}
}
Loading

0 comments on commit d068283

Please sign in to comment.