Skip to content

Commit

Permalink
feat(dynamic): mixin in list
Browse files Browse the repository at this point in the history
  • Loading branch information
maksimzinchuk committed Oct 9, 2024
1 parent f65a4b4 commit c6d954d
Show file tree
Hide file tree
Showing 22 changed files with 108 additions and 58 deletions.
2 changes: 1 addition & 1 deletion framework/core/composables/useMenuService/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function useMenuServiceFn(): MenuService {

menuItems.value = constructedMenu.value
.map(
(x, index): MenuItem => ({
(x): MenuItem => ({
...x,
title: computed(() => t(x.title as string)),
id: _.snakeCase(t(x.title as string)),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@
</template>

<script lang="ts" setup>
import { inject, ref } from "vue";
import { ref } from "vue";
import { AppDescriptor } from "../../../../../core/api/platform";
import { Sidebar } from "./../../../sidebar";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ const useBladeNavigationSingleton = createSharedComposable(() => {
(instance !== null && inject<BladeNavigationPlugin>("bladeNavigationPlugin")) || bladeNavigationInstance;
const router = navigationInstance?.router;

const { parseUrl, parseWorkspaceUrl, getURLQuery, routes } = utils(router);
const { parseUrl, parseWorkspaceUrl, getURLQuery } = utils(router);

watch(
() => route.path,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { mergeProps, h } from "vue";
import { mergeProps } from "vue";
import { Content, InternalNotificationOptions, NotificationOptions } from "../types";
import { useContainer } from "../composables";

Expand Down
2 changes: 1 addition & 1 deletion framework/shared/components/sidebar/sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface Emits {
defineEmits<Emits>();
const props = withDefaults(defineProps<Props>(), {
withDefaults(defineProps<Props>(), {
position: "right",
render: "always",
});
Expand Down
1 change: 1 addition & 0 deletions framework/shared/components/sign-in/useExternalProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const useExternalProvider = (): IUseExternalProvider => {
return searchParams.get("returnUrl") || searchParams.get("ReturnUrl");
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
async function externalSignIn(authenticationType: string, oidcUrl: string) {
try {
const origin = window.location.origin;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useI18n } from "vue-i18n";
import { Component, ExtractPropTypes, computed, h, onMounted, ref, unref, watch } from "vue";
import { Component, ExtractPropTypes, computed, h, onMounted, ref, unref } from "vue";
import componentProps from "./props";
import { StatusSchema } from "../../types";
import { StatusField } from "../factories";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MultivalueSchema } from "../../..";
import { SchemaBaseArgTypes } from "./common/args";
import { template, templateWithVisibilityToggle } from "./common/templates";
import page from "./pages/DynamicRender";
import { computed, defineComponent, reactive, ref, watch } from "vue";
import { reactive, ref } from "vue";
import { VcIcon } from "../../../../../../ui/components/atoms/vc-icon";

const customTemplateComponent = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ export const WithAsyncOptions: StoryFn<SelectSchema> = (args) => ({
mockedProperty: null,
},
scope: {
mockedOptionsArray: async (keyword?: string, skip = 0, ids?: string[]) =>
mockedOptionsArray: async () =>
new Promise((resolve) => {
setTimeout(() => {
resolve({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ComputedRef, MaybeRef, Ref, computed, ref, watch } from "vue";
import { ComputedRef, MaybeRef, computed, ref, watch } from "vue";
import * as _ from "lodash-es";
import { useForm, useIsFormDirty, useIsFormValid } from "vee-validate";
import { useForm, useIsFormValid } from "vee-validate";
import { useAsync, useLoading } from "../../../../../core/composables";
import type { ItemId, IValidationState, UseDetails } from "../types";
import { createUnrefFn } from "@vueuse/core";
Expand Down Expand Up @@ -31,12 +31,12 @@ export const useDetailsFactory = <Item extends { id?: string }>(factoryParams: U
}
});

const { loading: manageLoading, action: saveChanges } = useAsync<Item, Item | undefined>(async (item) => {
const { loading: manageLoading, action: saveChanges } = useAsync<Item, Item | undefined>(async (itemToSave) => {
if (validationState.value.valid) {
const res = await factoryParams.saveChanges?.(item as Item);
const res = await factoryParams.saveChanges?.(itemToSave as Item);
isModified.value = false;

const id = item?.id ?? res?.id;
const id = itemToSave?.id ?? res?.id;

if (id) {
await load({ id });
Expand Down
14 changes: 12 additions & 2 deletions framework/shared/modules/dynamic/helpers/override.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const handleOverrides = (overrides: OverridesSchema, schemaCopy: { [key:

const upsertHelper = (overrides: OverridesSchema, schemaCopy: { [key: string]: DynamicSchema }) => {
return Object.entries(schemaCopy).reduce(
(obj, [name, schema]) => {
(obj, [, schema]) => {
const clonedSchema = _.cloneDeep(schema);
overrides.upsert
?.filter((x) => clonedSchema.settings.id === x.id)
Expand Down Expand Up @@ -66,7 +66,17 @@ const upsertHelper = (overrides: OverridesSchema, schemaCopy: { [key: string]: D
_.set(clonedSchema, currentPath, args.value);
}
});
obj[name] = clonedSchema;

const newId = clonedSchema.settings.id;

if (newId !== schema.settings.id) {
obj[newId] = clonedSchema;

obj[schema.settings.id] = schema;
} else {
obj[schema.settings.id] = clonedSchema;
}

return obj;
},
{} as Record<string, DynamicSchema>,
Expand Down
31 changes: 24 additions & 7 deletions framework/shared/modules/dynamic/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ const register = (
component: BladeInstanceConstructor as BladeInstanceConstructor,
name: bladeName,
model: json,
composables: args.composables,
composables: { ...args.composables },
};

registeredModules[bladeName] = newModule;
Expand Down Expand Up @@ -214,11 +214,15 @@ export function createDynamicAppModule(args: {
): void;
} {
let schemaCopy: { [key: string]: DynamicSchema } = {};
let composablesCopy: { [key: string]: (...args: any[]) => any } = args.composables ?? {};

if (args.schema && Object.keys(args.schema).length > 0) {
schemaCopy = _.cloneDeep({ ...args.schema });
// Save schemas in the global registry
Object.assign(registeredSchemas, schemaCopy);
Object.entries(args.schema).forEach(([, schema]) => {
if (schema.settings && schema.settings.id) {
schemaCopy[schema.settings.id] = _.cloneDeep(schema);
registeredSchemas[schema.settings.id] = schemaCopy[schema.settings.id];
}
});
} else {
// Use registered schemas if new ones are not provided
schemaCopy = _.cloneDeep({ ...registeredSchemas });
Expand Down Expand Up @@ -246,13 +250,26 @@ export function createDynamicAppModule(args: {
};

const moduleUid = _.uniqueId("module_");
Object.entries(schemaCopy).forEach(([key, JsonSchema], index) => {
Object.entries(schemaCopy).forEach(([, JsonSchema], index) => {
const bladeId = JsonSchema.settings.id;
const mixin = args.mixin?.[JsonSchema.settings.id];

if (args.overrides) {
const idsOnOverridesUnique = [...new Set(args.overrides?.upsert?.map((x) => x.id))];

composablesCopy = {
...composablesCopy,
...Object.values(registeredModules).find((module) => {
return idsOnOverridesUnique.includes(module.name);
})?.composables,
};
}

const registerArgs = {
app,
component: bladePages[JsonSchema.settings.component as keyof typeof bladePages] as BladeInstanceConstructor,
composables: { ...args.composables },
mixin: args.mixin?.[JsonSchema.settings.id] ? args.mixin[JsonSchema.settings.id] : undefined,
composables: { ...composablesCopy },
mixin,
json: JsonSchema,
options,
moduleUid,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,10 @@ import {
ConcreteComponent,
toRefs,
provide,
toRef,
type VNode,
} from "vue";
import { DynamicDetailsSchema, FormContentSchema, SettingsSchema } from "../types";
import { reactiveComputed, refDefault, toReactive, useMounted, useTemplateRefsList } from "@vueuse/core";
import { reactiveComputed, toReactive, useMounted, useTemplateRefsList } from "@vueuse/core";
import {
DetailsBladeContext,
DetailsBaseBladeScope,
Expand All @@ -96,7 +95,6 @@ import {
usePopup,
useBladeNavigation,
CoreBladeExposed,
DetailsBladeExposed,
} from "../../../index";
import SchemaRender from "../components/SchemaRender";
import { VcSelect, VcImage } from "../../../../ui/components";
Expand Down
36 changes: 32 additions & 4 deletions framework/shared/modules/dynamic/pages/dynamic-blade-list.vue
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,8 @@ import { useFunctions, useNotifications } from "../../../../core/composables";
import { IActionBuilderResult, ITableColumns } from "../../../../core/types";
import { useToolbarReducer } from "../composables/useToolbarReducer";
import { notification, useBladeNavigation, usePopup } from "../../../components";
import { ITableConfig, ListBaseBladeScope, ListBladeContext, UseList } from "../factories/types";
import { ListBaseBladeScope, ListBladeContext, UseList } from "../factories/types";
import { IParentCallArgs } from "../../../index";
import * as _ from "lodash-es";
import { reactiveComputed, toReactive, useMounted } from "@vueuse/core";
import { safeIn } from "../helpers/safeIn";
Expand All @@ -190,6 +189,7 @@ export interface Props {
model?: DynamicGridSchema;
composables?: Record<string, (...args: any[]) => Record<string, any>>;
isWidgetView?: boolean;
mixinFn?: ((...args: any[]) => any)[];
}
export interface Emits {
Expand Down Expand Up @@ -223,6 +223,7 @@ const selectedItemId = shallowRef();
const sort = shallowRef();
const selectedIds = shallowRef<string[]>([]);
const itemsProxy = ref<Record<string, any>[]>();
const isMixinReady = ref(false);
const { moduleNotifications, markAsRead } = useNotifications(settings.value?.pushNotificationType);
const { setNavigationQuery, getNavigationQuery } = useBladeNavigation();
Expand Down Expand Up @@ -266,7 +267,8 @@ if (typeof props.composables?.[props.model?.settings?.composable ?? ""] === "und
throw new Error(`Composable ( ${props.model?.settings?.composable} ) is not defined`);
}
const { load, remove, items, loading, pagination, query, scope } = props.composables
// eslint-disable-next-line prefer-const
let { load, remove, items, loading, pagination, query, scope } = props.composables
? (props.composables?.[props.model?.settings?.composable ?? ""]({
emit,
props,
Expand All @@ -283,6 +285,32 @@ const { load, remove, items, loading, pagination, query, scope } = props.composa
scope: undefined,
} as unknown as UseList<Record<string, any>[], Record<string, any>, ListBaseBladeScope>);
if (props.mixinFn?.length) {
console.log("props.mixinFn", props.mixinFn);
const mixinResults = props.mixinFn?.map((mixin) => mixin({ loading, items, scope, load, remove, query }));
const mergedResults = mixinResults.reduce((acc, result) => {
return {
...acc,
...result,
};
}, {});
console.log("mergedResults", mergedResults);
loading = mergedResults.loading ?? loading;
items = mergedResults.items ?? items;
scope = mergedResults.scope ?? scope;
load = mergedResults.load ?? load;
remove = mergedResults.remove ?? remove;
query = mergedResults.query ?? query;
// console.log('query', query, mergedResults.query)
isMixinReady.value = true;
} else {
isMixinReady.value = true;
}
const isBladeEditable = computed(() =>
"disabled" in toValue(scope || {}) ? !toValue(toValue(scope || {})?.disabled) : false,
);
Expand Down Expand Up @@ -410,7 +438,7 @@ const toolbarComputed =
[];
onBeforeMount(async () => {
if (props.composables)
if (props.composables && isMixinReady.value)
await load({
sort: sort.value,
...query.value,
Expand Down
4 changes: 1 addition & 3 deletions framework/shared/modules/dynamic/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@ import {
VcMultivalue,
VcRating,
VcStatus,
VcVideo,
VcPagination,
} from "./../../../../ui/components";
import { IActionBuilderResult, ITableColumns, IValidationRules, MenuItemConfig } from "../../../../core/types";
import { ITableColumns, IValidationRules, MenuItemConfig } from "../../../../core/types";
import type { ComponentProps } from "./../../../utilities/vueUtils";
import VcInputCurrency from "../../../../ui/components/molecules/vc-input-currency/vc-input-currency.vue";
import { UnwrapRef } from "vue";

export type KeysOfUnion<T> = T extends T ? keyof T : never;

Expand Down
3 changes: 1 addition & 2 deletions framework/ui/components/atoms/vc-card/vc-card.stories.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import type { Meta, StoryFn, StoryObj } from "@storybook/vue3";
import type { Meta, StoryFn } from "@storybook/vue3";
import { VcCard } from ".";
import { VcInput, VcCol, VcButton } from "./../../";
import { h } from "vue";

const VARIANT = ["default", "success", "danger"];

Expand Down
8 changes: 4 additions & 4 deletions framework/ui/components/molecules/vc-input/vc-input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -511,10 +511,10 @@ function emitValue(val: string | number | Date | null) {
emitValueFn = () => {
if (mutatedModel.value !== val) {
let value;
if (props.type === "number" && val !== null) {
value = parseFloat(val as string);
} else if (props.type === "integer" && val !== null) {
value = Math.trunc(parseInt(val as string));
if (props.type === "number" && val !== null && val !== undefined) {
value = val !== "" ? parseFloat(val as string) : null;
} else if (props.type === "integer" && val !== null && val !== undefined) {
value = val !== "" ? Math.trunc(parseInt(val as string)) : null;
} else {
value = val;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export const AsyncOptions: StoryFn<typeof VcSelect> = (args) => ({
components: { VcSelect } as Record<keyof typeof VcSelect, unknown>,
setup() {
const val = ref();
const getItems = async (keyword?: string, skip = 0, ids?: string[]) =>
const getItems = async () =>
new Promise((resolve) => {
setTimeout(() => {
resolve({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Meta, StoryFn } from "@storybook/vue3";
import { VcBlade } from "./";
import { onMounted, ref } from "vue";
import { ref } from "vue";

export default {
title: "organisms/VcBlade",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ export interface Emits {
(event: "search:change", value: string): void;
}
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
defineProps<Props>();
defineEmits<Emits>();
</script>

<style lang="scss">
Expand Down
1 change: 0 additions & 1 deletion framework/ui/components/organisms/vc-table/vc-table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,6 @@ const slots = useSlots();
// template refs
const reorderRef = ref<HTMLElement | null>();
const tableRef = ref<HTMLElement | null>();
const searchInput = ref<HTMLElement | null>();

// event listeners
let columnResizeListener: ((...args: any[]) => any) | null = null;
Expand Down
Loading

0 comments on commit c6d954d

Please sign in to comment.