Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix useVuuTables, same table name different modules #1547

Merged
merged 1 commit into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 7 additions & 8 deletions vuu-ui/packages/vuu-data-react/src/hooks/useVuuTables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { useDataSource } from "@finos/vuu-utils";
import { useCallback, useEffect, useState } from "react";

export const useVuuTables = () => {
const [tables, setTables] = useState<Map<string, TableSchema> | undefined>();
const [tableSchemas, setTableSchemas] = useState<TableSchema[] | undefined>();

const { getServerAPI } = useDataSource();

const buildTables = useCallback((schemas: TableSchema[]) => {
const vuuTables = new Map<string, TableSchema>();
schemas.forEach((schema) => {
vuuTables.set(schema.table.table, schema);
const { module, table } = schema.table;
vuuTables.set(`${module}:${table}`, schema);
});
return vuuTables;
}, []);
Expand All @@ -20,12 +21,10 @@ export const useVuuTables = () => {
try {
const server = await getServerAPI();
const { tables } = await server.getTableList();
const tableSchemas = buildTables(
await Promise.all(
tables.map((vuuTable) => server.getTableSchema(vuuTable)),
),
const tableSchemas = await Promise.all(
tables.map((vuuTable) => server.getTableSchema(vuuTable)),
);
setTables(tableSchemas);
setTableSchemas(tableSchemas);
} catch (err) {
console.warn(
`useVuuTables: error fetching table metadata ${String(err)}`,
Expand All @@ -36,5 +35,5 @@ export const useVuuTables = () => {
fetchTableMetadata();
}, [buildTables, getServerAPI]);

return tables;
return tableSchemas;
};
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,16 @@ export const FeatureAndLayoutProvider = ({
staticFeatures,
systemLayouts,
}: FeatureAndLayoutProviderProps): ReactElement => {
const vuuTables = useVuuTables();
const tableSchemas = useVuuTables();
const { dynamicFeatures, tableFeatures } = useMemo<{
dynamicFeatures: DynamicFeatureProps[];
tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[];
}>(
() =>
vuuTables
? getCustomAndTableFeatures(dynamicFeaturesProp, vuuTables)
tableSchemas
? getCustomAndTableFeatures(dynamicFeaturesProp, tableSchemas)
: NO_FEATURES_VUU,
[dynamicFeaturesProp, vuuTables],
[dynamicFeaturesProp, tableSchemas],
);

return (
Expand Down
84 changes: 46 additions & 38 deletions vuu-ui/packages/vuu-utils/src/feature-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ export interface StaticFeatureDescriptor {
}

const isStaticFeature = (
feature: unknown
feature: unknown,
): feature is StaticFeatureDescriptor =>
feature !== null && typeof feature === "object" && "type" in feature;

export const isStaticFeatures = (
features: unknown
features: unknown,
): features is StaticFeatureDescriptor[] =>
Array.isArray(features) && features.every(isStaticFeature);

Expand All @@ -82,7 +82,7 @@ export function featureFromJson({ type }: { type: string }): ReactElement {
const componentType = type.match(/^[a-z]/) ? type : getLayoutComponent(type);
if (componentType === undefined) {
throw Error(
`layoutUtils unable to create feature component from JSON, unknown type ${type}`
`layoutUtils unable to create feature component from JSON, unknown type ${type}`,
);
}
return React.createElement(componentType);
Expand All @@ -100,23 +100,27 @@ export const isCustomFeature = (feature: DynamicFeatureDescriptor) =>

export const isWildcardSchema = (schema?: "*" | VuuTable): schema is "*" =>
schema === "*";
export const isTableSchema = (schema?: "*" | VuuTable): schema is VuuTable =>
typeof schema === "object" &&
typeof schema.module === "string" &&
typeof schema.table === "string";
export const isVuuTable = (vuuTable?: "*" | VuuTable): vuuTable is VuuTable =>
typeof vuuTable === "object" &&
typeof vuuTable.module === "string" &&
typeof vuuTable.table === "string";

export interface FeaturePropsWithFilterTableFeature
extends Omit<DynamicFeatureProps, "ComponentProps"> {
ComponentProps: FilterTableFeatureProps;
}

export const hasFilterTableFeatureProps = (
props: DynamicFeatureProps
props: DynamicFeatureProps,
): props is FeaturePropsWithFilterTableFeature =>
typeof props.ComponentProps === "object" &&
props.ComponentProps !== null &&
"tableSchema" in props.ComponentProps;

export const isSameTable = (t1: VuuTable, t2: VuuTable) => {
t1.module === t2.module && t1.table == t2.table;
};

// Sort TableScheas by module
export const byModule = (schema1: TableSchema, schema2: TableSchema) => {
const m1 = schema1.table.module.toLowerCase();
Expand All @@ -142,19 +146,19 @@ export type GetFeaturePaths = (params: {

export const getFilterTableFeatures = (
schemas: TableSchema[],
getFeaturePath: GetFeaturePaths
getFeaturePath: GetFeaturePaths,
) =>
schemas
.sort(byModule)
.map<DynamicFeatureProps<FilterTableFeatureProps>>((schema) => ({
...getFeaturePath({ env, fileName: "FilterTable" }),
ComponentProps: {
tableSchema: schema
tableSchema: schema,
},
ViewProps: {
allowRename: true
allowRename: true,
},
title: `${schema.table.module} ${schema.table.table}`
title: `${schema.table.module} ${schema.table.table}`,
}));

export type Component = {
Expand All @@ -164,11 +168,11 @@ export type Component = {

export const assertComponentRegistered = (
componentName: string,
component: unknown
component: unknown,
) => {
if (typeof component !== "function") {
console.warn(
`${componentName} module not loaded, will be unabale to deserialize from layout JSON`
`${componentName} module not loaded, will be unabale to deserialize from layout JSON`,
);
}
};
Expand All @@ -181,14 +185,14 @@ export const assertComponentsRegistered = (componentList: Component[]) => {

export const getCustomAndTableFeatures = (
dynamicFeatures: DynamicFeatureDescriptor[],
vuuTables: Map<string, TableSchema>
tableSchemas: TableSchema[],
): {
dynamicFeatures: DynamicFeatureProps[];
tableFeatures: DynamicFeatureProps<FilterTableFeatureProps>[];
} => {
const [customFeatureConfig, tableFeaturesConfig] = partition(
dynamicFeatures,
isCustomFeature
isCustomFeature,
);

const customFeatures: DynamicFeatureProps[] = [];
Expand All @@ -199,32 +203,34 @@ export const getCustomAndTableFeatures = (
viewProps,
...feature
} of tableFeaturesConfig) {
const { schema } = featureProps;
if (isWildcardSchema(schema) && vuuTables) {
for (const tableSchema of vuuTables.values()) {
const { schema: vuuTable } = featureProps;
if (isWildcardSchema(vuuTable) && tableSchemas) {
for (const tableSchema of tableSchemas) {
tableFeatures.push({
...feature,
ComponentProps: {
tableSchema
tableSchema,
},
title: `${tableSchema.table.module} ${wordify(
tableSchema.table.table
tableSchema.table.table,
)}`,
ViewProps: {
...viewProps,
allowRename: true
}
allowRename: true,
},
});
}
} else if (isTableSchema(schema) && vuuTables) {
const tableSchema = vuuTables.get(schema.table);
} else if (isVuuTable(vuuTable) && tableSchemas) {
const tableSchema = tableSchemas.find((tableSchema) =>
isSameTable(vuuTable, tableSchema.table),
);
if (tableSchema) {
tableFeatures.push({
...feature,
ComponentProps: {
tableSchema
tableSchema,
},
ViewProps: viewProps
ViewProps: viewProps,
});
}
}
Expand All @@ -235,29 +241,31 @@ export const getCustomAndTableFeatures = (
viewProps,
...feature
} of customFeatureConfig) {
const { schema, schemas } = featureProps;
if (isTableSchema(schema) && vuuTables) {
const tableSchema = vuuTables.get(schema.table);
const { schema: vuuTable, schemas } = featureProps;
if (isVuuTable(vuuTable) && tableSchemas) {
const tableSchema = tableSchemas.find((tableSchema) =>
isSameTable(vuuTable, tableSchema.table),
);
customFeatures.push({
...feature,
ComponentProps: {
tableSchema
tableSchema,
},
ViewProps: viewProps
ViewProps: viewProps,
});
} else if (Array.isArray(schemas) && vuuTables) {
} else if (Array.isArray(schemas) && tableSchemas) {
customFeatures.push({
...feature,
ComponentProps: schemas.reduce<Record<string, TableSchema>>(
(map, schema) => {
map[`${schema.table}Schema`] = vuuTables.get(
schema.table
(map, vuuTable) => {
map[`${vuuTable.table}Schema`] = tableSchemas.find((tableSchema) =>
isSameTable(vuuTable, tableSchema.table),
) as TableSchema;
return map;
},
{}
{},
),
ViewProps: viewProps
ViewProps: viewProps,
});
} else {
customFeatures.push(feature);
Expand Down
13 changes: 8 additions & 5 deletions vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { RpcResponseHandler } from "@finos/vuu-data-types";
import { useDialog } from "@finos/vuu-popups";
import { VuuTable } from "@finos/vuu-protocol-types";
import { Feature } from "@finos/vuu-shell";
import { isActionMessage } from "@finos/vuu-utils";
import { isActionMessage, isSameTable } from "@finos/vuu-utils";
import { useCallback } from "react";

const withTable = (action: unknown): action is { table: VuuTable } =>
Expand All @@ -12,7 +12,7 @@ const withTable = (action: unknown): action is { table: VuuTable } =>
const vuuFilterTableFeatureUrl = "../feature-filter-table/index.js";

export const useRpcResponseHandler = () => {
const tables = useVuuTables();
const tableSchemas = useVuuTables();
const { setDialogState } = useDialog();

const handleRpcResponse = useCallback<RpcResponseHandler>(
Expand All @@ -26,10 +26,13 @@ export const useRpcResponseHandler = () => {
) {
if (
withTable(rpcResponse.action) &&
tables &&
tableSchemas &&
rpcResponse.action.table
) {
const schema = tables.get(rpcResponse.action.table.table);
const { table } = rpcResponse.action;
const schema = tableSchemas.find((tableSchema) =>
isSameTable(tableSchema.table, table),
);
if (schema) {
// If we already have this table open in this viewport, ignore
setDialogState({
Expand All @@ -49,7 +52,7 @@ export const useRpcResponseHandler = () => {
}
return false;
},
[setDialogState, tables],
[setDialogState, tableSchemas],
);

return {
Expand Down
32 changes: 19 additions & 13 deletions vuu-ui/showcase/src/examples/VUU/Vuu.examples.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { List, ListItem } from "@finos/vuu-ui-controls";
import { useVuuTables } from "@finos/vuu-data-react";
import { useVuuTables, VuuDataSourceProvider } from "@finos/vuu-data-react";
import { useAutoLoginToVuuServer } from "../utils";

let displaySequence = 1;

export const VuuTables = () => {
const tables = useVuuTables();
const VuuTablesTemplate = () => {
const tableSchemas = useVuuTables();

useAutoLoginToVuuServer({ authenticate: false });

useAutoLoginToVuuServer();
return (
<VuuDataSourceProvider>
<List width={200}>
{tableSchemas?.map(({ table: { module, table } }, i) => (
<ListItem key={i}>{`[${module}] ${table}`}</ListItem>
)) ?? null}
</List>
</VuuDataSourceProvider>
);
};

export const VuuTables = () => {
return (
<List width={200}>
{tables
? Array.from(tables.entries()).map(([tableName, schema]) => (
<ListItem
key={tableName}
>{`[${schema.table.module}] ${schema.table.table}`}</ListItem>
))
: null}
</List>
<VuuDataSourceProvider>
<VuuTablesTemplate />
</VuuDataSourceProvider>
);
};

Expand Down
Loading