Skip to content

Commit 043ee4a

Browse files
committed
feat: custom table property order
1 parent 8cc8f88 commit 043ee4a

File tree

3 files changed

+54
-30
lines changed

3 files changed

+54
-30
lines changed

packages/components-vue/src/components/form/Stages.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
<div class="scroll --vertical modal-content" :class="unwrap ? $attrs.class : ''">
1212
<form
1313
method="post"
14-
:class="stagesClasses ?? 'flx --flxColumn --flx-start-stretch --gap-30'"
14+
class="flx --flxColumn --flx-start-stretch"
15+
:class="stagesClasses ?? '--gap-30'"
1516
>
1617
<FormSimple
1718
v-for="key in formInputsKeys[activeStage]"
@@ -172,6 +173,10 @@
172173
/**
173174
* Form Stages
174175
* TODO: enable transitions conditionally
176+
* TODO: cache forms to reduce rerenders
177+
*
178+
* @see https://vuejs.org/guide/built-ins/keep-alive.html
179+
* @see https://vuejs.org/api/built-in-directives.html#v-memo
175180
*
176181
* @component
177182
*/
@@ -255,6 +260,8 @@
255260
256261
// full reset
257262
newLocalFormInputs[key] = reForm;
263+
264+
if (form.listen) emit("input-values", getValues(reForm.inputs));
258265
});
259266
260267
newLocalStages.push(keys);

packages/components-vue/src/components/select/Filter.vue

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@
2222
/>
2323
</datalist>
2424
<div v-if="supportsDatalist" class="flx --flxRow --flx-start-center --gap-5" v-bind="$attrs">
25+
<ActionLink
26+
v-if="modelValue && selectOptions.length > 1"
27+
:theme="theme"
28+
:disabled="disabled"
29+
:aria-label="t('select_restablish_field')"
30+
:title="t('select_restablish_field')"
31+
@click.prevent="resetModel"
32+
>
33+
<IconFa name="xmark" :size="20" />
34+
</ActionLink>
2535
<InputText
2636
v-model="aliasModel"
2737
:list="selectFilterName"
@@ -41,16 +51,6 @@
4151
}"
4252
class="--flx"
4353
/>
44-
<ActionLink
45-
v-if="modelValue && selectOptions.length > 1"
46-
:theme="theme"
47-
:disabled="disabled"
48-
:aria-label="t('select_restablish_field')"
49-
:title="t('select_restablish_field')"
50-
@click.prevent="resetModel"
51-
>
52-
<IconFa name="xmark" :size="20" />
53-
</ActionLink>
5454
</div>
5555
</template>
5656

packages/components-vue/src/components/table/Simple.vue

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,14 @@
372372
import { useHelpers, useOrderBy } from "../../composables/utils";
373373
import useUUID from "../../composables/uuid";
374374
375-
export interface iTableProps<Ti extends Record<string, any>> extends iUseThemeProps {
375+
type tPropertyOrderFn = (a: [string, any], b: [string, any]) => -1 | 0 | 1;
376+
377+
interface iPropertyMeta extends iSelectOption {
378+
value: string;
379+
canSort: boolean;
380+
}
381+
382+
interface iTableProps<Ti extends Record<string, any>> extends iUseThemeProps {
376383
/**
377384
* Table nodes
378385
* an array of nodes
@@ -387,6 +394,7 @@
387394
* @old columns
388395
*/
389396
properties?: iProperty<Ti>[];
397+
propertyOrder?: tPropertyOrderFn;
390398
/**
391399
* read only table
392400
* @old editable(inverse)
@@ -504,38 +512,22 @@
504512
);
505513
});
506514
507-
interface iPropertyMeta extends iSelectOption {
508-
value: string;
509-
canSort: boolean;
510-
}
511-
512515
/**
513516
* This one assumes all objects within nodes are all the same
514517
*/
515518
const propertiesMeta = computed<iPropertyMeta[]>(() => {
516519
return Object.entries(props.nodes[0])
517-
.sort(([a], [b]) => {
518-
// updatedAt, updatedBy, createdAt and createdBy to last position
519-
if (a.endsWith("At") || a.endsWith("By") || b.endsWith("At") || b.endsWith("By")) {
520-
if (a.endsWith("At") || a.endsWith("By")) return 1;
521-
522-
return -1;
523-
} else if (a > b) return 1;
524-
else if (a < b) return -1;
525-
526-
return 0;
527-
})
520+
.sort(props.propertyOrder || defaultOrderProperty)
528521
.map(([key, value]): iPropertyMeta => {
529522
const options = (props.properties || []).map(toOption);
530523
const property = toOption(options.find((p) => p.value === key) || key);
531524
const aliasKey = _.snakeCase(key);
532-
const canSort = ["string", "number", "boolean"].includes(typeof value);
533525
534526
return {
535527
...property,
536528
value: String(property.value),
537529
alias: _.capitalize(_.startCase(property.alias || tet(aliasKey))),
538-
canSort: !!props.canSort && canSort,
530+
canSort: !!props.canSort && isPlainValue(value),
539531
};
540532
})
541533
.filter((property) => property.value !== "id");
@@ -549,6 +541,31 @@
549541
return `table_${seed.replaceAll(" ", "") || randomId}`;
550542
});
551543
544+
const defaultOrderProperty: tPropertyOrderFn = ([a, aValue], [b, bValue]) => {
545+
const isDateOrAuthor = (k: string) => k.endsWith("At") || k.endsWith("By");
546+
547+
// Move dates or authors backwards
548+
if (isDateOrAuthor(a) || isDateOrAuthor(b)) {
549+
// Respect whatever order they had
550+
if (isDateOrAuthor(a) && isDateOrAuthor(b)) return 0;
551+
552+
return isDateOrAuthor(a) ? 1 : -1;
553+
}
554+
// Move strings forward
555+
else if (isPlainValue(aValue) || isPlainValue(bValue)) {
556+
// Respect whatever order they had
557+
if (isPlainValue(aValue) && isPlainValue(bValue)) return 0;
558+
559+
return isPlainValue(aValue) ? -1 : 1;
560+
}
561+
562+
// Respect whatever order they had
563+
return 0;
564+
};
565+
566+
function isPlainValue(value: any) {
567+
return ["string", "number", "boolean"].includes(typeof value);
568+
}
552569
function reFillNodes(length: number): [boolean, boolean][] {
553570
return Array.from({ length }, () => [false, !!props.childrenVisibility]);
554571
}

0 commit comments

Comments
 (0)