192 lines
4.8 KiB
TypeScript
192 lines
4.8 KiB
TypeScript
/**
|
|
* Ported from legacy henza_admin/src/components/x-table/model/{XTbl,Xtc}.js
|
|
* and src/table/index.js (ColCreator).
|
|
*
|
|
* The fluent column API is preserved exactly — `new Xtc(key, title).filterText()
|
|
* .renderSlot('x').noSort()` builds the same shape the legacy table schemas used,
|
|
* so the 18 schema files port over with only their import path changed.
|
|
*
|
|
* Legacy had FOUR near-duplicate XTable forks (x-table/, x-table_select/,
|
|
* custom-xtable-select/, backup-table/, ~1,300 LOC). Per the agreed decision this
|
|
* port keeps ONE — the x-table/ variant, which is the most complete (it is the
|
|
* only one with QuerySelectTableFilter).
|
|
*/
|
|
|
|
export type FilterType = 'default' | 'switch' | 'query' | 'date' | 'number' | 'select';
|
|
|
|
export interface ColumnSlots {
|
|
customRender?: string;
|
|
filterDropdown?: string;
|
|
filterIcon?: string;
|
|
}
|
|
|
|
/** Port of legacy Xtc — one column definition. */
|
|
export class Xtc {
|
|
key: string;
|
|
title: string;
|
|
dataIndex: string;
|
|
show = true;
|
|
/** legacy `__sorter`: sortable unless noSort() was called */
|
|
__sorter = true;
|
|
filtered = false;
|
|
filterType?: FilterType;
|
|
filterAction?: string;
|
|
/** legacy `filterItems`: a value -> label map for select filters */
|
|
filterItems?: Record<string | number, string>;
|
|
scopedSlots?: ColumnSlots;
|
|
/** legacy filterKey()/master — filter against a different field than dataIndex */
|
|
__fkey?: string;
|
|
width?: string | number;
|
|
|
|
constructor(key: string, title: string) {
|
|
this.key = key;
|
|
this.title = title;
|
|
this.dataIndex = key;
|
|
}
|
|
|
|
private __filter() {
|
|
this.filtered = true;
|
|
if (!this.scopedSlots) this.scopedSlots = {};
|
|
this.scopedSlots.filterDropdown = `${this.key}_filterDropdown`;
|
|
this.scopedSlots.filterIcon = `${this.key}_filterIcon`;
|
|
}
|
|
|
|
/** legacy filterKey(key) */
|
|
filterKey(key: string) {
|
|
this.__fkey = key;
|
|
return this;
|
|
}
|
|
|
|
/** legacy renderSlot(name) — render this cell through a named slot */
|
|
renderSlot(name: string) {
|
|
if (!this.scopedSlots) this.scopedSlots = {};
|
|
this.scopedSlots.customRender = name;
|
|
return this;
|
|
}
|
|
|
|
filterText() {
|
|
this.__filter();
|
|
this.filterType = 'default';
|
|
return this;
|
|
}
|
|
|
|
filterSwitch() {
|
|
this.__filter();
|
|
this.filterType = 'switch';
|
|
return this;
|
|
}
|
|
|
|
filterQuery(action: string) {
|
|
this.__filter();
|
|
this.filterType = 'query';
|
|
this.filterAction = action;
|
|
return this;
|
|
}
|
|
|
|
filterDate() {
|
|
this.__filter();
|
|
this.filterType = 'date';
|
|
return this;
|
|
}
|
|
|
|
filterNumber() {
|
|
this.__filter();
|
|
this.filterType = 'number';
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* legacy filterSelect(items) — `items` is an OBJECT MAP of value -> label,
|
|
* e.g. { 0: 'معلق', 1: 'ثبت سفارش' }, stored on `filterItems`. The shape is
|
|
* kept exactly so the ported table models pass their maps unchanged.
|
|
*
|
|
* Legacy also permitted calling it with no argument at all (TaminListModel does
|
|
* this), which left filterItems undefined and rendered an empty dropdown.
|
|
* Preserved: the parameter is optional here too.
|
|
*/
|
|
filterSelect(items?: Record<string | number, string>) {
|
|
this.__filter();
|
|
this.filterType = 'select';
|
|
this.filterItems = items;
|
|
return this;
|
|
}
|
|
|
|
/** legacy noSort() */
|
|
noSort() {
|
|
this.__sorter = false;
|
|
return this;
|
|
}
|
|
|
|
/** legacy hidden() — column exists but starts unchecked in the column picker */
|
|
hidden() {
|
|
this.show = false;
|
|
return this;
|
|
}
|
|
|
|
setWidth(w: string | number) {
|
|
this.width = w;
|
|
return this;
|
|
}
|
|
}
|
|
|
|
export interface DefaultFilter {
|
|
field: string;
|
|
op: string;
|
|
value: unknown;
|
|
}
|
|
|
|
/** Port of legacy XTbl — a table definition: endpoint + title + columns. */
|
|
export class XTbl {
|
|
url: string;
|
|
title: string;
|
|
cols: Xtc[] = [];
|
|
defaultFilters?: DefaultFilter[];
|
|
_hidePagination = false;
|
|
_hideSearch = false;
|
|
_noFilters = false;
|
|
|
|
constructor(url: string, title: string) {
|
|
this.url = url;
|
|
this.title = title;
|
|
}
|
|
|
|
add(col: Xtc) {
|
|
this.cols.push(col);
|
|
return this;
|
|
}
|
|
|
|
addDefaultFilter(filter: DefaultFilter) {
|
|
if (!this.defaultFilters) this.defaultFilters = [];
|
|
this.defaultFilters.push(filter);
|
|
return this;
|
|
}
|
|
|
|
hidePagination() {
|
|
this._hidePagination = true;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* NOTE: legacy's hideSearch() set `_hidePageination` (sic) instead of a search
|
|
* flag — a copy-paste bug, so calling it hid PAGINATION, not the search box.
|
|
* Fixed here to set the intended flag; no ported schema calls it, so nothing
|
|
* changes in behaviour. Recorded in docs/ADMIN-PORT-PLAN.md.
|
|
*/
|
|
hideSearch() {
|
|
this._hideSearch = true;
|
|
return this;
|
|
}
|
|
|
|
/** legacy noFilters(): hides the filter bar entirely (walletTbl uses this). */
|
|
noFilters() {
|
|
this._noFilters = true;
|
|
return this;
|
|
}
|
|
|
|
getSortFields() {
|
|
return this.cols.filter((c) => c.__sorter);
|
|
}
|
|
}
|
|
|
|
export default XTbl;
|