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

Sync with finos/main #64

Merged
merged 6 commits into from
Oct 2, 2023
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
38 changes: 33 additions & 5 deletions vuu-ui/packages/vuu-layout/src/layout-provider/LayoutProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import {
} from "react";
import {
LayoutActionType,
LayoutChangeHandler,
LayoutChangeReason,
layoutFromJson,
LayoutJSON,
layoutReducer,
LayoutReducerAction,
layoutToJSON,
processLayoutElement,
SaveAction,
} from "../layout-reducer";
import { findTarget, getChildProp, getProp, getProps, typeOf } from "../utils";
import {
Expand All @@ -34,7 +37,31 @@ const shouldSave = (action: LayoutReducerAction) =>
"switch-tab",
].includes(action.type);

type LayoutChangeHandler = (layout: LayoutJSON, source: string) => void;
const getLayoutChangeReason = (
action: LayoutReducerAction | SaveAction
): LayoutChangeReason => {
switch (action.type) {
case "switch-tab":
// TODO how can we make this more robust, shouldn't rely on 'main-tabs'
if (action.id === "main-tabs") {
return "switch-active-layout";
} else {
return "switch-active-tab";
}
case "save":
return "save-feature-props";
case "drag-drop":
return "drag-drop-operation";
case "remove":
return "remove-component";
case "splitter-resize":
return "resize-component";
case "set-title":
return "edit-feature-title";
default:
throw Error("unknown layout action");
}
};

export interface LayoutProviderProps {
children: ReactElement;
Expand All @@ -58,7 +85,8 @@ export const LayoutProvider = (props: LayoutProviderProps): ReactElement => {
const [, forceRefresh] = useState<unknown>(null);

const serializeState = useCallback(
(source) => {
(source, layoutChangeReason: LayoutChangeReason) => {
console.log(`serialize state ${layoutChangeReason}`);
if (onLayoutChange) {
const targetContainer =
findTarget(source, withDropTarget) || state.current;
Expand All @@ -67,7 +95,7 @@ export const LayoutProvider = (props: LayoutProviderProps): ReactElement => {
? getProps(targetContainer).children[0]
: targetContainer;
const serializedModel = layoutToJSON(target);
onLayoutChange(serializedModel, "drag-root");
onLayoutChange(serializedModel, layoutChangeReason);
}
},
[onLayoutChange]
Expand All @@ -80,7 +108,7 @@ export const LayoutProvider = (props: LayoutProviderProps): ReactElement => {
state.current = nextState;
forceRefresh({});
if (!suppressSave && shouldSave(action)) {
serializeState(nextState);
serializeState(nextState, getLayoutChangeReason(action));
}
}
},
Expand All @@ -95,7 +123,7 @@ export const LayoutProvider = (props: LayoutProviderProps): ReactElement => {
break;
}
case "save": {
serializeState(state.current);
serializeState(state.current, getLayoutChangeReason(action));
break;
}
default: {
Expand Down
44 changes: 44 additions & 0 deletions vuu-ui/packages/vuu-layout/src/layout-reducer/layoutTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export type LayoutResizeAction = {
};

export type SwitchTabAction = {
id?: string;
nextIdx: number;
path: string;
type: typeof LayoutActionType.SWITCH_TAB;
Expand Down Expand Up @@ -193,3 +194,46 @@ export type DragStartAction = {
path: string;
type: typeof LayoutActionType.DRAG_START;
};

export type LayoutLevelChange =
| "switch-active-tab"
| "edit-feature-title"
| "save-feature-props"
| "resize-component"
| "remove-component"
| "drag-drop-operation";

export type ApplicationLevelChange =
| "switch-active-layout"
| "open-layout"
| "close-layout"
| "rename-layout";

export type LayoutChangeReason = LayoutLevelChange | ApplicationLevelChange;

export type LayoutChangeHandler = (
layout: LayoutJSON,
layoutChangeReason: LayoutChangeReason
) => void;

export const isApplicationLevelChange = (
layoutChangeReason: LayoutChangeReason
): layoutChangeReason is ApplicationLevelChange =>
[
"switch-active-layout",
"open-layout",
"close-layout",
"rename-layout",
].includes(layoutChangeReason);

export const isLayoutLevelChange = (
layoutChangeReason: LayoutChangeReason
): layoutChangeReason is LayoutLevelChange =>
[
"switch-active-tab",
"edit-feature-title",
"save-feature-props",
"remove-component",
"resize-component",
"drag-drop-operation",
].includes(layoutChangeReason);
2 changes: 1 addition & 1 deletion vuu-ui/packages/vuu-layout/src/stack/StackLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export const StackLayout = (props: StackProps) => {

const handleTabSelection = (nextIdx: number) => {
if (path) {
dispatch({ type: "switch-tab", path, nextIdx });
dispatch({ type: "switch-tab", id, path, nextIdx });
onTabSelectionChanged?.(nextIdx);
}
};
Expand Down
52 changes: 51 additions & 1 deletion vuu-ui/packages/vuu-layout/src/utils/pathUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { isValidElement, ReactElement } from "react";
import { LayoutModel } from "../layout-reducer";
import { LayoutJSON, LayoutModel, WithActive } from "../layout-reducer";
import { isContainer } from "../registry/ComponentRegistry";
import { getProp, getProps } from "./propUtils";
import { typeOf } from "./typeOf";
Expand Down Expand Up @@ -42,6 +42,30 @@ export const resolvePath = (source: ReactElement, path = ""): string => {
return "";
};

/**
* Similar to resolvePath but operates on a JSON
* layout structure and returns the matching JSON node.
*/
export const resolveJSONPath = (
source: LayoutJSON,
path = ""
): LayoutJSON | undefined => {
const [step1, ...steps] = path.split(".");
if (step1?.startsWith("#")) {
const node = findTargetJSONById(source, step1.slice(1), true);
if (node && steps.length) {
return resolveJSONPath(node, steps.join("."));
}
} else if (step1 === "ACTIVE_CHILD") {
const { children, props } = source;
const { active } = props as WithActive;
if (typeof active === "number" && children?.[active]) {
return children[active];
}
}
return;
};

export function followPathToParent(
source: ReactElement,
path: string
Expand Down Expand Up @@ -146,6 +170,32 @@ const findTargetById = (
}
};

const findTargetJSONById = (
source: LayoutJSON,
id: string,
throwIfNotFound = true
): LayoutJSON | undefined => {
const { children, id: idProp } = source;
if (idProp === id) {
return source;
}

if (Array.isArray(children) && children.length > 0) {
for (const child of children) {
if (child !== null && typeof child === "object") {
const target = findTargetJSONById(child, id, false);
if (target) {
return target;
}
}
}
}

if (throwIfNotFound === true) {
throw Error(`pathUtils.findTargetJSONById id #${id} not found in source`);
}
};

export function followPath(
source: LayoutModel,
path: string
Expand Down
6 changes: 5 additions & 1 deletion vuu-ui/packages/vuu-shell/src/layout-config/local-config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { LayoutJSON } from "@finos/vuu-layout/src/layout-reducer";
import { resolveJSONPath } from "@finos/vuu-layout";
import { VuuUser } from "../shell";

export const loadLocalConfig = (
Expand Down Expand Up @@ -26,7 +27,10 @@ export const saveLocalConfig = (
): Promise<undefined> =>
new Promise((resolve, reject) => {
try {
console.log(`save local config at ${saveUrl}`);
// Just for demonstration,not currently being used
const layoutJson = resolveJSONPath(data, "#main-tabs.ACTIVE_CHILD");
console.log(layoutJson);

localStorage.setItem(saveUrl, JSON.stringify(data));
resolve(undefined);
} catch {
Expand Down
10 changes: 7 additions & 3 deletions vuu-ui/packages/vuu-shell/src/shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
LayoutProvider,
LayoutProviderProps,
} from "@finos/vuu-layout";
import { LayoutJSON } from "@finos/vuu-layout/src/layout-reducer";
import {
LayoutChangeHandler,
LayoutJSON,
} from "@finos/vuu-layout/src/layout-reducer";
import { AppHeader } from "./app-header";
import { ThemeMode, ThemeProvider, useThemeAttributes } from "./theme-provider";
import { logger } from "@finos/vuu-utils";
Expand Down Expand Up @@ -85,9 +88,10 @@ export const Shell = ({
user,
});

const handleLayoutChange = useCallback(
(layout) => {
const handleLayoutChange = useCallback<LayoutChangeHandler>(
(layout, layoutChangeReason) => {
try {
console.log(`handle layout changed ${layoutChangeReason}`);
saveLayoutConfig(layout);
} catch {
error?.("Failed to save layout");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,46 @@
import { Dropdown, DropdownOpenKey } from "@finos/vuu-ui-controls";
import {
Dropdown,
DropdownOpenKey,
SelectionChangeHandler,
} from "@finos/vuu-ui-controls";
import {
isColumnTypeRenderer,
isTypeDescriptor,
registerComponent,
} from "@finos/vuu-utils";
import { TableCellProps } from "@finos/vuu-datagrid-types";
// import { dispatchCommitEvent } from "@finos/vuu-ui-controls";

import "./DropdownCell.css";
import { useCallback, useState } from "react";

const classBase = "vuuTableDropdownCell";

const openKeys: DropdownOpenKey[] = ["Enter", " "];

export const DropdownCell = ({ column, columnMap, row }: TableCellProps) => {
const { valueFormatter } = column;
const values =
isTypeDescriptor(column.type) && isColumnTypeRenderer(column.type?.renderer)
? column.type?.renderer?.values
: [];

const dataIdx = columnMap[column.name];
const value = valueFormatter(row[dataIdx]);
const [value, setValue] = useState(row[dataIdx]);

const handleSelectionChange = useCallback<SelectionChangeHandler>(
(evt, selectedItem) => {
if (selectedItem) {
setValue(selectedItem);
// dispatchCommitEvent(evt.target as HTMLElement);
}
},
[]
);

return (
<Dropdown
className={classBase}
onSelectionChange={handleSelectionChange}
openKeys={openKeys}
selected={value}
source={values}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ function applyRules(
rules: EditValidationRule[],
value: VuuRowDataItemType
): string | false | undefined {
console.log(`apply rules to ${value}`);
let result: false | string | undefined = undefined;
for (const rule of rules) {
const editRuleValidator = getEditRuleValidator(rule.name);
Expand Down Expand Up @@ -42,5 +43,6 @@ function applyRules(
}
}

console.log(result);
return result;
}
Loading