Skip to content

Commit

Permalink
feat(Template): Set up Standalone with Submodule Connection + Models (#…
Browse files Browse the repository at this point in the history
…4748)

* copied over templates for standalone

* added templates library

* changed templates lib to align with templates

* added working UI of dev toolbox to templates

* display serialized template json

* added templates designer under libs

* display template connections with button

* used arm token to load logic app portal data

* Added submodule for LogicAppsTemplates library

* restructured templates standalone

* moved templates to designer library

* removed templates library

* restructured designer library templates state

* added the submodule to /sample folder & added data provider wrapper

* added submodule properly & added loading manifestNames

* added working maniests system loaded from github

* cleanup

* removed unused mocks

* changed namespace of template model to Template

* removed unusd workspace

* Revert "removed unusd workspace"

This reverts commit 8810321.

* removed unused workspace only

* fixed errors

* resolved unimported imports

* reflected NIT to keep the file clean

---------

Co-authored-by: Travis Harris <travisharris@microsoft.com>
  • Loading branch information
Elaina-Lee and hartra344 committed May 1, 2024
1 parent ebad1be commit 6c7ffba
Show file tree
Hide file tree
Showing 24 changed files with 2,030 additions and 3,040 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
@@ -0,0 +1,3 @@
[submodule "libs/designer/src/lib/core/templates/samples"]
path = libs/designer/src/lib/core/templates/samples
url = https://github.com/Azure/LogicAppsTemplates
12 changes: 0 additions & 12 deletions Localize/lang/strings.json
@@ -1,7 +1,6 @@
{
"++ZVe/": "Testing",
"+0H8Or": "Warning: input node type does not match the schema node's type",
"+0ua83": "Parameters",
"+0yxlR": "Function display",
"+3rROX": "Protected",
"+FcXe9": "Faulted",
Expand Down Expand Up @@ -858,7 +857,6 @@
"Xnn0uj": "Request",
"XqamWZ": "Delete",
"XsktQ/": "Limit Logic Apps to not include workflow metadata headers in the response.",
"XtVOMn": "Something went wrong",
"XtuP5e": "Math functions",
"Xv5CGN": "(UTC-05:00) Indiana (East)",
"Xx/naD": "Required. The name of the action whose body outputs you want.",
Expand Down Expand Up @@ -915,11 +913,9 @@
"Zi9gQK": "Add new item",
"ZihyUf": "Close",
"ZkjTbp": "Learn more about dynamic content.",
"ZvAp7m": "Save",
"ZyDq4/": "Show a different suggestion",
"_++ZVe/.comment": "Title for testing section",
"_+0H8Or.comment": "Warning message for when input node type does not match schema node type",
"_+0ua83.comment": "Button text for parameters",
"_+0yxlR.comment": "Label for the function display radio group",
"_+3rROX.comment": "Label in the chatbot header stating that the users information is protected in this chatbot",
"_+FcXe9.comment": "The status message to show in monitoring view.",
Expand Down Expand Up @@ -1776,7 +1772,6 @@
"_Xnn0uj.comment": "Header text for request",
"_XqamWZ.comment": "Label of Delete Token Button",
"_XsktQ/.comment": "description of workflow headers on response setting",
"_XtVOMn.comment": "Something went wrong text",
"_XtuP5e.comment": "Label for math functions",
"_Xv5CGN.comment": "Time zone value ",
"_Xx/naD.comment": "Required string parameter to determine action's body output wanted",
Expand Down Expand Up @@ -1833,7 +1828,6 @@
"_Zi9gQK.comment": "Label to add item to property editor",
"_ZihyUf.comment": "Label for the close button in the chatbot header",
"_ZkjTbp.comment": "Text for dynamic content link",
"_ZvAp7m.comment": "Button text for save",
"_ZyDq4/.comment": "Text for the show different suggestion flow button",
"_a7j3gS.comment": "Required number parameter to divide in mod function",
"_aAXnqw.comment": "Required number of occurrences to get nthIndexOf function with",
Expand Down Expand Up @@ -1952,7 +1946,6 @@
"_fElufw.comment": "Select an API Management resource",
"_fKYuwf.comment": "Placeholder description for a newly inserted File parameter",
"_fVG5aD.comment": "Time zone value ",
"_fZJWBR.comment": "Loading designer text",
"_faUrud.comment": "Message to show under the loading icon when loading connection parameters",
"_fg/34o.comment": "Label for logical functions",
"_fifSPb.comment": "Time zone value ",
Expand Down Expand Up @@ -2188,7 +2181,6 @@
"_oWGaw9.comment": "Click to view less token options.",
"_oZMhX/.comment": "Text of Tooltip to expand",
"_odQ554.comment": "Response body for test map API",
"_ohOaXj.comment": "Button text for errors",
"_onXUu0.comment": "Text to tell users to click to add comments",
"_osKNnl.comment": "Error validation message for doubles",
"_ox2Ou7.comment": "Placeholder for empty collapsed dictionary",
Expand Down Expand Up @@ -2272,7 +2264,6 @@
"_sEqLTV.comment": "An accessability label that describes the testing tab",
"_sFbnCs.comment": "Time zone value ",
"_sFwHQc.comment": "aria label description for cancel button",
"_sOnphB.comment": "Button text for resubmit",
"_sQ2vRs.comment": "add a case to switch statement",
"_sRpETS.comment": "Warning message for when custom value does not match schema node type",
"_sVQe34.comment": "The description for the test tab parameters.",
Expand Down Expand Up @@ -2592,7 +2583,6 @@
"fElufw": "Select an API Management resource",
"fKYuwf": "Please select file or image",
"fVG5aD": "(UTC-05:00) Haiti",
"fZJWBR": "Loading designer",
"faUrud": "Loading connection data...",
"fg/34o": "Logical functions",
"fifSPb": "(UTC-03:30) Newfoundland",
Expand Down Expand Up @@ -2828,7 +2818,6 @@
"oWGaw9": "See Less",
"oZMhX/": "Expand",
"odQ554": "Response body",
"ohOaXj": "Errors",
"onXUu0": "Add a note",
"osKNnl": "Enter a valid Double number.",
"ox2Ou7": "Enter a valid JSON",
Expand Down Expand Up @@ -2912,7 +2901,6 @@
"sEqLTV": "Testing Tab",
"sFbnCs": "(UTC-05:00) Chetumal",
"sFwHQc": "Cancel creating a connection",
"sOnphB": "Resubmit",
"sQ2vRs": "Add Case",
"sRpETS": "Warning: custom value does not match the schema node's type",
"sVQe34": "Provide parameters to test the output.",
Expand Down
11 changes: 11 additions & 0 deletions apps/Standalone/src/App.tsx
Expand Up @@ -3,8 +3,10 @@ import { Provider } from 'react-redux';
import { DesignerWrapper } from './designer/app/DesignerShell/designer';
import { store as designerStore } from './designer/state/store';
import { store as dataMapperStore } from './dataMapperV1/state/Store';
import { store as templateStore } from './templates/state/Store';
import { DataMapperStandaloneDesignerV1 } from './dataMapperV1/app/DataMapperStandaloneDesignerV1';
import { DataMapperStandaloneDesignerV2 } from './dataMapperV1/app/DataMapperStandaloneDesignerV2';
import { TemplatesStandaloneDesigner } from './templates/app/TemplatesStandaloneDesigner';

export const App = () => {
return (
Expand All @@ -13,6 +15,7 @@ export const App = () => {
<Route path="/" element={<DesignerStandalone />} />
<Route path="/datamapperv1" element={<DataMapperV1 />} />
<Route path="/datamapperv2" element={<DataMapperV2 />} />
<Route path="/templates" element={<TemplatesStandalone />} />
{/* Using path="*"" means "match anything", so this route
acts like a catch-all for URLs that we don't have explicit
routes for. */}
Expand Down Expand Up @@ -44,3 +47,11 @@ const DataMapperV2 = () => {
</Provider>
);
};

const TemplatesStandalone = () => {
return (
<Provider store={templateStore}>
<TemplatesStandaloneDesigner />
</Provider>
);
};
29 changes: 29 additions & 0 deletions apps/Standalone/src/templates/app/TemplatesStandaloneDesigner.tsx
@@ -0,0 +1,29 @@
import type { ReactNode } from 'react';
import { ReactQueryProvider, TemplatesDataProvider } from '@microsoft/logic-apps-designer';
import { loadToken } from '../../environments/environment';
import { DevToolbox } from '../components/DevToolbox';
import type { RootState } from '../state/Store';
import { TemplatesDesigner, TemplatesDesignerProvider } from '@microsoft/logic-apps-designer';
import { useQuery } from '@tanstack/react-query';
import { useSelector } from 'react-redux';

const LoadWhenArmTokenIsLoaded = ({ children }: { children: ReactNode }) => {
const { isLoading } = useQuery(['armToken'], loadToken);
return isLoading ? null : <>{children}</>;
};
export const TemplatesStandaloneDesigner = () => {
const theme = useSelector((state: RootState) => state.workflowLoader.theme);

return (
<ReactQueryProvider>
<LoadWhenArmTokenIsLoaded>
<DevToolbox />
<TemplatesDesignerProvider locale="en-US" theme={theme}>
<TemplatesDataProvider>
<TemplatesDesigner />
</TemplatesDataProvider>
</TemplatesDesignerProvider>
</LoadWhenArmTokenIsLoaded>
</ReactQueryProvider>
);
};
98 changes: 98 additions & 0 deletions apps/Standalone/src/templates/components/DevToolbox.tsx
@@ -0,0 +1,98 @@
import type { AppDispatch, RootState } from '../state/Store';
import type { IDropdownOption } from '@fluentui/react';
import { Dropdown, Stack, StackItem } from '@fluentui/react';
import { Accordion, AccordionHeader, AccordionItem, AccordionPanel, Tooltip, tokens } from '@fluentui/react-components';
import { Theme as ThemeType } from '@microsoft/logic-apps-shared';
import { useCallback, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { AzureStandardLogicAppSelector } from '../../designer/app/AzureLogicAppsDesigner/LogicAppSelectionSetting/AzureStandardLogicAppSelector';
import { AzureConsumptionLogicAppSelector } from '../../designer/app/AzureLogicAppsDesigner/LogicAppSelectionSetting/AzureConsumptionLogicAppSelector';
import { useIsConsumption } from '../../designer/state/workflowLoadingSelectors';
import { ThemeProvider } from '@fluentui/react';
import { FluentProvider, webDarkTheme, webLightTheme } from '@fluentui/react-components';
import { AzureThemeDark } from '@fluentui/azure-themes/lib/azure/AzureThemeDark';
import { AzureThemeLight } from '@fluentui/azure-themes/lib/azure/AzureThemeLight';
import { workflowLoaderSlice } from '../state/WorkflowLoader';

const themeDropdownOptions = [
{ key: ThemeType.Light, text: 'Light' },
{ key: ThemeType.Dark, text: 'Dark' },
];

export const DevToolbox = () => {
const dispatch = useDispatch<AppDispatch>();

const { theme } = useSelector((state: RootState) => state.workflowLoader);

const [isTooltipVisible, setIsTooltipVisible] = useState<boolean>(false);
const isLightMode = theme === ThemeType.Light;

const changeThemeCB = useCallback(
(_: unknown, item: IDropdownOption | undefined) => {
dispatch(workflowLoaderSlice.actions.changeTheme((item?.key as ThemeType) ?? ''));
},
[dispatch]
);

const isConsumption = useIsConsumption();

return (
<ThemeProvider theme={isLightMode ? AzureThemeLight : AzureThemeDark}>
<FluentProvider theme={isLightMode ? webLightTheme : webDarkTheme}>
<div style={{ marginBottom: '8px', backgroundColor: tokens.colorNeutralBackground2, padding: 4 }}>
<Accordion defaultOpenItems={'1'} collapsible style={{ position: 'relative' }}>
<Tooltip
content="Clippy says hello!"
relationship="label"
positioning="below-start"
withArrow
showDelay={100}
hideDelay={500}
onVisibleChange={(_e, data) => setIsTooltipVisible(data.visible)}
>
<div
style={{
position: 'absolute',
top: 8,
right: 12,
padding: 4,
backgroundColor: tokens.colorNeutralBackground4,
borderRadius: tokens.borderRadiusMedium,
zIndex: 10,
cursor: 'pointer',
}}
>
<span role="img" aria-label="Clippy!" style={{ fontSize: 20 }}>
📎
</span>{' '}
Tooltip tester! It&apos;s {isTooltipVisible ? 'visible' : 'hidden'}
</div>
</Tooltip>

<AccordionItem value="1">
<AccordionHeader>Dev Toolbox</AccordionHeader>
<AccordionPanel>
<Stack horizontal tokens={{ childrenGap: '12px' }} wrap>
<StackItem key={'themeDropDown'} style={{ width: '250px' }}>
<Dropdown
label="Theme"
selectedKey={theme}
onChange={changeThemeCB}
placeholder="Select a theme"
options={themeDropdownOptions}
style={{ marginBottom: '12px' }}
/>
</StackItem>

<StackItem style={{ width: '100%' }}>
{isConsumption ? <AzureConsumptionLogicAppSelector /> : <AzureStandardLogicAppSelector />}
</StackItem>
</Stack>
</AccordionPanel>
</AccordionItem>
</Accordion>
</div>
</FluentProvider>
</ThemeProvider>
);
};
11 changes: 11 additions & 0 deletions apps/Standalone/src/templates/state/Store.ts
@@ -0,0 +1,11 @@
import { workflowLoaderSlice } from './WorkflowLoader';
import { configureStore } from '@reduxjs/toolkit';

export const store = configureStore({
reducer: {
workflowLoader: workflowLoaderSlice.reducer, // Aligning with Designer WorkflowLoader to utilize AppSelectors
},
});

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
58 changes: 58 additions & 0 deletions apps/Standalone/src/templates/state/WorkflowLoader.ts
@@ -0,0 +1,58 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import type { PayloadAction } from '@reduxjs/toolkit';
import { createSlice } from '@reduxjs/toolkit';
import { Theme as ThemeType } from '@microsoft/logic-apps-shared';

export interface WorkflowLoadingState {
resourcePath?: string;
appId?: string;
workflowName?: string;
runId?: string;
isConsumption: boolean;
theme: ThemeType;
}

const initialState: WorkflowLoadingState = {
appId: undefined,
isConsumption: false,
theme: ThemeType.Light,
};

export const workflowLoaderSlice = createSlice({
name: 'workflowLoader',
initialState,
reducers: {
setAppid: (state, action: PayloadAction<string>) => {
state.appId = action.payload;
},
setWorkflowName: (state, action: PayloadAction<string>) => {
state.workflowName = action.payload;
},
changeRunId: (state, action: PayloadAction<string>) => {
state.runId = action.payload;
},
setResourcePath: (state, action: PayloadAction<string>) => {
state.resourcePath = action.payload;
},
clearWorkflowDetails: (state) => {
state.appId = undefined;
state.workflowName = undefined;
state.runId = undefined;
state.resourcePath = '';
},
setConsumption: (state, action: PayloadAction<boolean>) => {
state.isConsumption = action.payload;
state.appId = undefined;
state.workflowName = undefined;
state.resourcePath = '';
},
changeTheme: (state, action: PayloadAction<ThemeType>) => {
state.theme = action.payload;
},
},
});

export const { setResourcePath, setAppid, setWorkflowName, clearWorkflowDetails, setConsumption, changeRunId } =
workflowLoaderSlice.actions;

export default workflowLoaderSlice.reducer;
6 changes: 5 additions & 1 deletion e2e/designer/serialization.spec.ts
Expand Up @@ -18,7 +18,11 @@ test.describe(
assert: { type: 'json' },
});

expect({ connectionReferences: mock.default.connectionReferences, parameters: mock.default.parameters, definition: mock.default.definition }).toEqual(serialized as any);
expect({
connectionReferences: mock.default.connectionReferences,
parameters: mock.default.parameters,
definition: mock.default.definition,
}).toEqual(serialized as any);
});

test('Should serialize the workflow after deserializing it and match with a switch statement', async ({ page }) => {
Expand Down
3 changes: 3 additions & 0 deletions libs/designer/src/lib/core/index.ts
Expand Up @@ -4,6 +4,7 @@ export * from './ProviderWrappedContext';
export { getReactQueryClient } from './ReactQueryProvider';
export type { RootState, AppDispatch } from './store';
export { store } from './store';
export { templateStore } from './state/templates/store';
export {
useConnectionMapping,
useConnectionRefs,
Expand Down Expand Up @@ -50,6 +51,8 @@ export {
} from './state/panel/panelSelectors';
export { initializeServices } from './state/designerOptions/designerOptionsSlice';
export { resetWorkflowState, resetNodesLoadStatus } from './state/global';
export { TemplatesDataProvider } from './templates/TemplatesDataProvider';
export { TemplatesDesignerProvider } from './templates/TemplatesDesignerProvider';
export {
validateParameter,
getCustomCodeFilesWithData,
Expand Down

0 comments on commit 6c7ffba

Please sign in to comment.