@masterteam/work-center 0.0.62 → 0.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -168,6 +168,22 @@ class ApplyColumnFilters {
|
|
|
168
168
|
this.filters = filters;
|
|
169
169
|
}
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Switches the selected card and drops everything that was scoped to the
|
|
173
|
+
* previous one: advanced filters, in-table column filters, grouping and the
|
|
174
|
+
* sort that grouping implied. Each card brings its own columns and filter
|
|
175
|
+
* schema, so carrying those over would filter on fields the new card doesn't
|
|
176
|
+
* have and group by a column it doesn't show.
|
|
177
|
+
*/
|
|
178
|
+
class SelectCard {
|
|
179
|
+
area;
|
|
180
|
+
selectedCardKey;
|
|
181
|
+
static type = '[WorkCenter] Select Card';
|
|
182
|
+
constructor(area, selectedCardKey) {
|
|
183
|
+
this.area = area;
|
|
184
|
+
this.selectedCardKey = selectedCardKey;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
171
187
|
/**
|
|
172
188
|
* Sets the grouped column. Grouping is expressed to the backend as a single
|
|
173
189
|
* sort on the same field, so this also rewrites `context.sort` and resets
|
|
@@ -220,6 +236,13 @@ const WORK_CENTER_LEVEL_NAME_KEY = 'levelDataName';
|
|
|
220
236
|
const WORK_CENTER_LEVEL_GROUP_FIELD = '__mtLevelGroup';
|
|
221
237
|
/** Rendered in place of a missing / restricted LevelData label. */
|
|
222
238
|
const WORK_CENTER_EMPTY_LABEL = '—';
|
|
239
|
+
/**
|
|
240
|
+
* Bootstrap `group` value meaning "the user turned grouping off". Needed
|
|
241
|
+
* because an absent `group` means "not chosen yet" and falls back to the
|
|
242
|
+
* default grouping — without a distinct value, clearing the group would be
|
|
243
|
+
* undone by the next navigation.
|
|
244
|
+
*/
|
|
245
|
+
const WORK_CENTER_GROUP_NONE = 'none';
|
|
223
246
|
|
|
224
247
|
const AREA_COLORS = ['violet', 'blue', 'emerald', 'amber', 'teal'];
|
|
225
248
|
/** Fallback accent rotation used only when the backend sends no stat color. */
|
|
@@ -306,15 +329,30 @@ function parseSortInput(value) {
|
|
|
306
329
|
: [];
|
|
307
330
|
}
|
|
308
331
|
/**
|
|
309
|
-
* Resolves the grouped column key from bootstrap inputs.
|
|
310
|
-
*
|
|
311
|
-
* whatever
|
|
332
|
+
* Resolves the grouped column key from bootstrap inputs.
|
|
333
|
+
*
|
|
334
|
+
* A missing `group` keeps whatever state already has, so an unrelated
|
|
335
|
+
* navigation doesn't drop the user's grouping. `WORK_CENTER_GROUP_NONE` is the
|
|
336
|
+
* only way to express "turn it off" — a bare `null` can't, because it is also
|
|
337
|
+
* what a host passes for an absent query param.
|
|
312
338
|
*/
|
|
313
339
|
function resolveGroupByFromInputs(current, group) {
|
|
314
|
-
if (hasParamValue(group)) {
|
|
315
|
-
return
|
|
340
|
+
if (!hasParamValue(group) || typeof group !== 'string') {
|
|
341
|
+
return current;
|
|
342
|
+
}
|
|
343
|
+
const parsed = group.trim();
|
|
344
|
+
if (!parsed || parsed === WORK_CENTER_GROUP_NONE) {
|
|
345
|
+
return null;
|
|
316
346
|
}
|
|
317
|
-
return
|
|
347
|
+
return parsed;
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* The card these inputs resolve to — the same rule `buildContextFromInputs`
|
|
351
|
+
* applies, exposed so callers can detect a card switch before building the
|
|
352
|
+
* context (what survives the switch depends on it).
|
|
353
|
+
*/
|
|
354
|
+
function resolveSelectedCardKeyFromInputs(currentContext, inputs = {}) {
|
|
355
|
+
return toSelectedCardKey(inputs.card) ?? currentContext.selectedCardKey;
|
|
318
356
|
}
|
|
319
357
|
function parseFiltersInput(value) {
|
|
320
358
|
const parsed = parseJson(value);
|
|
@@ -543,6 +581,10 @@ function buildKpis(stats, fallbackIcon) {
|
|
|
543
581
|
color: stat.color?.trim() || KPI_COLORS[index % KPI_COLORS.length],
|
|
544
582
|
}));
|
|
545
583
|
}
|
|
584
|
+
/** The backend sort that renders a grouped column as contiguous rows. */
|
|
585
|
+
function sortForGroup(groupBy) {
|
|
586
|
+
return groupBy ? [{ field: groupBy, dir: 'asc' }] : [];
|
|
587
|
+
}
|
|
546
588
|
function createDefaultContext(area) {
|
|
547
589
|
return {
|
|
548
590
|
area,
|
|
@@ -611,7 +653,14 @@ function normalizeContext(context) {
|
|
|
611
653
|
runtimeFilters: sanitizeFilters(context.runtimeFilters),
|
|
612
654
|
};
|
|
613
655
|
}
|
|
614
|
-
function buildContextFromInputs(currentContext, area, inputs = {}
|
|
656
|
+
function buildContextFromInputs(currentContext, area, inputs = {},
|
|
657
|
+
/**
|
|
658
|
+
* Already-resolved grouped column. Grouping is executed as a backend sort,
|
|
659
|
+
* so when the host supplies no explicit `sort` the grouped column defines
|
|
660
|
+
* it — that is what makes the default grouping reach the very first request
|
|
661
|
+
* instead of costing a second round trip.
|
|
662
|
+
*/
|
|
663
|
+
groupBy = null) {
|
|
615
664
|
const parsedCardKey = toSelectedCardKey(inputs.card);
|
|
616
665
|
const parsedTemplateId = toOptionalInt(inputs.templateId);
|
|
617
666
|
const parsedLevelDataId = toOptionalInt(inputs.levelDataId);
|
|
@@ -628,9 +677,11 @@ function buildContextFromInputs(currentContext, area, inputs = {}) {
|
|
|
628
677
|
levelDataId: parsedLevelDataId ?? currentContext.levelDataId,
|
|
629
678
|
sort: hasParamValue(inputs.sort)
|
|
630
679
|
? parseSortInput(inputs.sort)
|
|
631
|
-
:
|
|
632
|
-
?
|
|
633
|
-
:
|
|
680
|
+
: groupBy
|
|
681
|
+
? sortForGroup(groupBy)
|
|
682
|
+
: inputs.sort === null
|
|
683
|
+
? []
|
|
684
|
+
: currentContext.sort,
|
|
634
685
|
runtimeFilters: hasParamValue(inputs.filters)
|
|
635
686
|
? parseFiltersInput(inputs.filters)
|
|
636
687
|
: inputs.filters === null
|
|
@@ -664,8 +715,20 @@ function mapRuntimeResponse(current, response) {
|
|
|
664
715
|
const columns = buildColumns(selectedCard?.columnsConfig ?? selectedCardFromList?.columnsConfig);
|
|
665
716
|
const rows = toDisplayRows(selectedCard?.items ?? [], columns);
|
|
666
717
|
const kpis = buildKpis(selectedCard?.stats ?? [], selectedMenuItem?.icon ?? null);
|
|
718
|
+
// A card that doesn't advertise the grouped column can't be grouped by it —
|
|
719
|
+
// drop it here rather than letting the table discover the stale column and
|
|
720
|
+
// bounce a second request. The sort goes with it when it was the one the
|
|
721
|
+
// grouping asked for.
|
|
722
|
+
const groupBy = current.groupBy && columns.some((column) => column.key === current.groupBy)
|
|
723
|
+
? current.groupBy
|
|
724
|
+
: null;
|
|
725
|
+
const droppedGroup = !groupBy && current.groupBy;
|
|
726
|
+
const sort = droppedGroup && isSortForGroup(current.context.sort, current.groupBy)
|
|
727
|
+
? []
|
|
728
|
+
: current.context.sort;
|
|
667
729
|
return {
|
|
668
730
|
...current,
|
|
731
|
+
groupBy,
|
|
669
732
|
menuItems,
|
|
670
733
|
rows,
|
|
671
734
|
columns,
|
|
@@ -679,11 +742,16 @@ function mapRuntimeResponse(current, response) {
|
|
|
679
742
|
context: {
|
|
680
743
|
...current.context,
|
|
681
744
|
selectedCardKey,
|
|
745
|
+
sort,
|
|
682
746
|
page: selectedCard?.pagination.page ?? current.context.page,
|
|
683
747
|
pageSize: selectedCard?.pagination.pageSize ?? current.context.pageSize,
|
|
684
748
|
},
|
|
685
749
|
};
|
|
686
750
|
}
|
|
751
|
+
/** True when `sort` is exactly the single rule a grouping would produce. */
|
|
752
|
+
function isSortForGroup(sort, groupBy) {
|
|
753
|
+
return !!groupBy && sort.length === 1 && sort[0].field === groupBy;
|
|
754
|
+
}
|
|
687
755
|
|
|
688
756
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
689
757
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -784,8 +852,19 @@ let WorkCenterState = class WorkCenterState {
|
|
|
784
852
|
setParams(ctx, action) {
|
|
785
853
|
const state = ctx.getState();
|
|
786
854
|
const current = state.byArea[action.area];
|
|
787
|
-
|
|
788
|
-
|
|
855
|
+
// A card switch invalidates everything scoped to the previous card. The
|
|
856
|
+
// host usually drops those query params too, but a stale URL must not be
|
|
857
|
+
// able to re-apply a filter on a field the new card doesn't have.
|
|
858
|
+
const cardChanged = resolveSelectedCardKeyFromInputs(current.context, action.inputs) !==
|
|
859
|
+
current.context.selectedCardKey;
|
|
860
|
+
// Resolve grouping first: with no explicit `sort` input it is what defines
|
|
861
|
+
// the backend sort.
|
|
862
|
+
const nextGroupBy = resolveGroupByFromInputs(cardChanged ? null : current.groupBy, action.inputs?.group);
|
|
863
|
+
const builtContext = buildContextFromInputs(current.context, action.area, action.inputs, nextGroupBy);
|
|
864
|
+
const filtersFromInputs = action.inputs?.filters !== undefined;
|
|
865
|
+
const nextContext = cardChanged && !filtersFromInputs
|
|
866
|
+
? { ...builtContext, runtimeFilters: [] }
|
|
867
|
+
: builtContext;
|
|
789
868
|
const areaChanged = state.activeArea !== action.area;
|
|
790
869
|
const contextChanged = !isSameContext(current.context, nextContext);
|
|
791
870
|
const groupChanged = nextGroupBy !== current.groupBy;
|
|
@@ -795,11 +874,12 @@ let WorkCenterState = class WorkCenterState {
|
|
|
795
874
|
// URL-derived filters land on the header slice. Anything previously
|
|
796
875
|
// applied via the in-table column filters is dropped so the BE payload
|
|
797
876
|
// matches what the user sees on the page header.
|
|
798
|
-
const filtersFromInputs = action.inputs?.filters !== undefined;
|
|
799
877
|
const nextHeaderFilters = filtersFromInputs
|
|
800
878
|
? nextContext.runtimeFilters
|
|
801
|
-
:
|
|
802
|
-
|
|
879
|
+
: cardChanged
|
|
880
|
+
? []
|
|
881
|
+
: current.headerFilters;
|
|
882
|
+
const nextColumnFilters = filtersFromInputs || cardChanged ? [] : current.columnFilters;
|
|
803
883
|
ctx.patchState({
|
|
804
884
|
activeArea: action.area,
|
|
805
885
|
byArea: {
|
|
@@ -836,6 +916,33 @@ let WorkCenterState = class WorkCenterState {
|
|
|
836
916
|
columnFilters: action.filters,
|
|
837
917
|
});
|
|
838
918
|
}
|
|
919
|
+
selectCard(ctx, action) {
|
|
920
|
+
const state = ctx.getState();
|
|
921
|
+
const current = state.byArea[action.area];
|
|
922
|
+
if (current.context.selectedCardKey === action.selectedCardKey) {
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
925
|
+
ctx.patchState({
|
|
926
|
+
activeArea: action.area,
|
|
927
|
+
byArea: {
|
|
928
|
+
...state.byArea,
|
|
929
|
+
[action.area]: {
|
|
930
|
+
...current,
|
|
931
|
+
headerFilters: [],
|
|
932
|
+
columnFilters: [],
|
|
933
|
+
groupBy: null,
|
|
934
|
+
context: {
|
|
935
|
+
...current.context,
|
|
936
|
+
selectedCardKey: action.selectedCardKey,
|
|
937
|
+
runtimeFilters: [],
|
|
938
|
+
sort: [],
|
|
939
|
+
page: 1,
|
|
940
|
+
},
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
});
|
|
944
|
+
return ctx.dispatch(new LoadRuntime(action.area, 'menu-change'));
|
|
945
|
+
}
|
|
839
946
|
/**
|
|
840
947
|
* Grouping is a backend concern: the table only renders contiguous rows, so
|
|
841
948
|
* the grouped column is pushed down as the single `context.sort` entry and
|
|
@@ -974,6 +1081,9 @@ __decorate([
|
|
|
974
1081
|
__decorate([
|
|
975
1082
|
Action(ApplyColumnFilters)
|
|
976
1083
|
], WorkCenterState.prototype, "applyColumnFilters", null);
|
|
1084
|
+
__decorate([
|
|
1085
|
+
Action(SelectCard)
|
|
1086
|
+
], WorkCenterState.prototype, "selectCard", null);
|
|
977
1087
|
__decorate([
|
|
978
1088
|
Action(SetGroupBy)
|
|
979
1089
|
], WorkCenterState.prototype, "setGroupBy", null);
|
|
@@ -1042,7 +1152,7 @@ WorkCenterState = __decorate([
|
|
|
1042
1152
|
], WorkCenterState);
|
|
1043
1153
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.8", ngImport: i0, type: WorkCenterState, decorators: [{
|
|
1044
1154
|
type: Injectable
|
|
1045
|
-
}], propDecorators: { enterArea: [], hydrateFromContext: [], setParams: [], setLookups: [], applyHeaderFilters: [], applyColumnFilters: [], setGroupBy: [], clearAllFilters: [], loadRuntime: [] } });
|
|
1155
|
+
}], propDecorators: { enterArea: [], hydrateFromContext: [], setParams: [], setLookups: [], applyHeaderFilters: [], applyColumnFilters: [], selectCard: [], setGroupBy: [], clearAllFilters: [], loadRuntime: [] } });
|
|
1046
1156
|
|
|
1047
1157
|
class WorkCenterFacade {
|
|
1048
1158
|
store = inject(Store);
|
|
@@ -1086,11 +1196,12 @@ class WorkCenterFacade {
|
|
|
1086
1196
|
setLookups(lookups) {
|
|
1087
1197
|
return this.store.dispatch(new SetLookups(lookups));
|
|
1088
1198
|
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Switches card and drops the previous card's filters, grouping and sort —
|
|
1201
|
+
* each card has its own columns and filter schema.
|
|
1202
|
+
*/
|
|
1089
1203
|
selectCardAndLoad(area, selectedCardKey) {
|
|
1090
|
-
return this.store.dispatch(
|
|
1091
|
-
new HydrateFromContext(area, { selectedCardKey, page: 1 }),
|
|
1092
|
-
new LoadRuntime(area, 'menu-change'),
|
|
1093
|
-
]);
|
|
1204
|
+
return this.store.dispatch(new SelectCard(area, selectedCardKey));
|
|
1094
1205
|
}
|
|
1095
1206
|
applyTableLazyLoadAndLoad(area, event) {
|
|
1096
1207
|
const context = this.store.selectSnapshot(WorkCenterState.context);
|
|
@@ -3012,8 +3123,13 @@ class WorkCenterPage {
|
|
|
3012
3123
|
if (item.key === this.context().selectedCardKey) {
|
|
3013
3124
|
return;
|
|
3014
3125
|
}
|
|
3126
|
+
// The store drops the previous card's filters and grouping; the table's
|
|
3127
|
+
// own filter chips live here, so they have to be cleared alongside.
|
|
3128
|
+
this.tableFilters.set({});
|
|
3015
3129
|
this.facade.selectCardAndLoad(this.area(), item.key);
|
|
3016
3130
|
this.cardSelected.emit(item.key);
|
|
3131
|
+
this.groupChanged.emit(null);
|
|
3132
|
+
this.sortChanged.emit([]);
|
|
3017
3133
|
}
|
|
3018
3134
|
onRuntimeFiltersApplied(filters) {
|
|
3019
3135
|
const mappedFilters = filters.map((filter) => ({
|
|
@@ -3189,5 +3305,5 @@ const APP_STATES = [WorkCenterState];
|
|
|
3189
3305
|
* Generated bundle index. Do not edit.
|
|
3190
3306
|
*/
|
|
3191
3307
|
|
|
3192
|
-
export { APP_STATES, ApplyColumnFilters, ApplyHeaderFilters, ClearAllFilters, EnterArea, HydrateFromContext, LoadRuntime, SetGroupBy, SetLookups, SetParams, WORK_CENTER_EMPTY_LABEL, WORK_CENTER_LEVEL_GROUP_FIELD, WORK_CENTER_LEVEL_NAME_KEY, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterClientFormModal, WorkCenterFacade, WorkCenterItemModal, WorkCenterItemModalRoute, WorkCenterPage, WorkCenterState, decodeWorkCenterRouteContextKey, encodeWorkCenterRouteContextKey };
|
|
3308
|
+
export { APP_STATES, ApplyColumnFilters, ApplyHeaderFilters, ClearAllFilters, EnterArea, HydrateFromContext, LoadRuntime, SelectCard, SetGroupBy, SetLookups, SetParams, WORK_CENTER_EMPTY_LABEL, WORK_CENTER_GROUP_NONE, WORK_CENTER_LEVEL_GROUP_FIELD, WORK_CENTER_LEVEL_NAME_KEY, WORK_CENTER_MAX_FILTERS, WORK_CENTER_MAX_PAGE_SIZE, WORK_CENTER_MAX_SORT, WORK_CENTER_QUERY_VERSION, WorkCenterActionKey, WorkCenterClientFormModal, WorkCenterFacade, WorkCenterItemModal, WorkCenterItemModalRoute, WorkCenterPage, WorkCenterState, decodeWorkCenterRouteContextKey, encodeWorkCenterRouteContextKey };
|
|
3193
3309
|
//# sourceMappingURL=masterteam-work-center.mjs.map
|