Skip to content

Commit

Permalink
Merge pull request #1547 from finos/fix-vuu-tables
Browse files Browse the repository at this point in the history
fix useVuuTables, same table name different modules
  • Loading branch information
heswell authored Nov 23, 2024
2 parents 76ba8d8 + fd47589 commit 49341c9
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 68 deletions.
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

0 comments on commit 49341c9

Please sign in to comment.