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

feat(templates): Adding connection create UI in list grid #5022

Merged
merged 1 commit into from
Jun 25, 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
4 changes: 4 additions & 0 deletions Localize/lang/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,7 @@
"MnThTq": "Insert function",
"MsCHhQ": "Timed Out",
"MtWzvX": "Enter a positive integer between {min} and {max}",
"N+qRUv": "Fill out the fields below to create a connection for {connectorName}",
"N0pS6Y": "Target schema",
"N2CF0J": "Required. The key name of the form data values to return.",
"N4dEVo": "Headers",
Expand Down Expand Up @@ -1544,6 +1545,7 @@
"_MnThTq.comment": "Message to insert function",
"_MsCHhQ.comment": "The status message to show in monitoring view.",
"_MtWzvX.comment": "descriptio of maximum waiting runs setting",
"_N+qRUv.comment": "Message to show in title for connection creation",
"_N0pS6Y.comment": "Target schema",
"_N2CF0J.comment": "Required string parameter to be used as key for triggerFormDataMultiValues function",
"_N4dEVo.comment": "Display name for headers in outputs",
Expand Down Expand Up @@ -2510,6 +2512,7 @@
"_yF2R//.comment": "Label for description of custom substring Function",
"_yKOsmK.comment": "Label for description of custom sort Function",
"_yNtBUV.comment": "Warning message for when input node type does not match one of the function node input's allowed types",
"_yQ6+nV.comment": "Link to create a connection",
"_yRDuqj.comment": "Button text to add all advanced parameters",
"_yVFIAQ.comment": "Time zone value ",
"_yVh9kr.comment": "Hour of the day",
Expand Down Expand Up @@ -3170,6 +3173,7 @@
"yF2R//": "Returns a subset of characters from a string.",
"yKOsmK": "Returns an array sorted in ascending order",
"yNtBUV": "Warning: input node type does not match one of the allowed types for this input.",
"yQ6+nV": "Connect",
"yRDuqj": "Show all",
"yVFIAQ": "(UTC-01:00) Cabo Verde Is.",
"yVh9kr": "8",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ConnectionsData, ParametersData } from '../Models/Workflow';
import type { ConnectionAndAppSetting, ConnectionsData, ParametersData } from '../Models/Workflow';
import type { ConnectionReferences } from '@microsoft/logic-apps-designer';

export class WorkflowUtility {
Expand Down Expand Up @@ -122,3 +122,49 @@ function replaceIfFoundAndVerifyJson(stringifiedJson: string, searchValue: strin
return undefined;
}
}

export async function addConnectionData(
connectionAndSetting: ConnectionAndAppSetting,
connectionsData: ConnectionsData,
settings: any
): Promise<void> {
addConnectionInJson(connectionAndSetting, connectionsData ?? {});
addOrUpdateAppSettings(connectionAndSetting.settings, settings?.properties ?? {});
}

function addConnectionInJson(connectionAndSetting: ConnectionAndAppSetting, connectionsJson: ConnectionsData): void {
const { connectionData, connectionKey, pathLocation } = connectionAndSetting;

let pathToSetConnectionsData: any = connectionsJson;

for (const path of pathLocation) {
if (!pathToSetConnectionsData[path]) {
pathToSetConnectionsData[path] = {};
}

pathToSetConnectionsData = pathToSetConnectionsData[path];
}

if (pathToSetConnectionsData && pathToSetConnectionsData[connectionKey]) {
// TODO: To show this in a notification of info bar on the blade.
// const message = 'ConnectionKeyAlreadyExist - Connection key \'{0}\' already exists.'.format(connectionKey);
return;
}

pathToSetConnectionsData[connectionKey] = connectionData;
}

function addOrUpdateAppSettings(settings: Record<string, string>, originalSettings: Record<string, string>): Record<string, string> {
const settingsToAdd = Object.keys(settings);

for (const settingKey of settingsToAdd) {
if (originalSettings[settingKey]) {
// TODO: To show this in a notification of info bar on the blade that key will be overriden.
}

// eslint-disable-next-line no-param-reassign
originalSettings[settingKey] = settings[settingKey];
}

return originalSettings;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
useWorkflowApp,
} from './Services/WorkflowAndArtifacts';
import { ArmParser } from './Utilities/ArmParser';
import { WorkflowUtility } from './Utilities/Workflow';
import { WorkflowUtility, addConnectionData } from './Utilities/Workflow';
import { Chatbot, chatbotPanelWidth } from '@microsoft/logic-apps-chatbot';
import {
BaseApiManagementService,
Expand Down Expand Up @@ -123,9 +123,8 @@ const DesignerEditor = () => {
[originalConnectionsData, parameters, settingsData?.properties]
);

const addConnectionData = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
addConnectionInJson(connectionAndSetting, connectionsData ?? {});
addOrUpdateAppSettings(connectionAndSetting.settings, settingsData?.properties ?? {});
const addConnectionDataInternal = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
addConnectionData(connectionAndSetting, connectionsData ?? {}, settingsData ?? {});
};

const getConnectionConfiguration = async (connectionId: string): Promise<any> => {
Expand Down Expand Up @@ -168,7 +167,7 @@ const DesignerEditor = () => {
equals(workflow?.kind, 'stateful'),
connectionsData ?? {},
workflowAppData as WorkflowApp,
addConnectionData,
addConnectionDataInternal,
getConnectionConfiguration,
tenantId,
objectId,
Expand Down Expand Up @@ -716,43 +715,6 @@ const getDesignerServices = (
};
};

const addConnectionInJson = (connectionAndSetting: ConnectionAndAppSetting, connectionsJson: ConnectionsData): void => {
const { connectionData, connectionKey, pathLocation } = connectionAndSetting;

let pathToSetConnectionsData: any = connectionsJson;

for (const path of pathLocation) {
if (!pathToSetConnectionsData[path]) {
pathToSetConnectionsData[path] = {};
}

pathToSetConnectionsData = pathToSetConnectionsData[path];
}

if (pathToSetConnectionsData && pathToSetConnectionsData[connectionKey]) {
// TODO: To show this in a notification of info bar on the blade.
// const message = 'ConnectionKeyAlreadyExist - Connection key \'{0}\' already exists.'.format(connectionKey);
return;
}

pathToSetConnectionsData[connectionKey] = connectionData;
};

const addOrUpdateAppSettings = (settings: Record<string, string>, originalSettings: Record<string, string>): Record<string, string> => {
const settingsToAdd = Object.keys(settings);

for (const settingKey of settingsToAdd) {
if (originalSettings[settingKey]) {
// TODO: To show this in a notification of info bar on the blade that key will be overriden.
}

// eslint-disable-next-line no-param-reassign
originalSettings[settingKey] = settings[settingKey];
}

return originalSettings;
};

const hasNewKeys = (original: Record<string, any> = {}, updated: Record<string, any> = {}) => {
return !Object.keys(updated).some((key) => !Object.keys(original).includes(key));
};
Expand Down
13 changes: 10 additions & 3 deletions apps/Standalone/src/templates/app/TemplatesStandaloneDesigner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import {
useCurrentTenantId,
useWorkflowApp,
} from '../../designer/app/AzureLogicAppsDesigner/Services/WorkflowAndArtifacts';
import type { ConnectionsData } from '../../designer/app/AzureLogicAppsDesigner/Models/Workflow';
import type { ConnectionAndAppSetting, ConnectionsData } from '../../designer/app/AzureLogicAppsDesigner/Models/Workflow';
import type { WorkflowApp } from '../../designer/app/AzureLogicAppsDesigner/Models/WorkflowApp';
import { ArmParser } from '../../designer/app/AzureLogicAppsDesigner/Utilities/ArmParser';
import { StandaloneOAuthService } from '../../designer/app/AzureLogicAppsDesigner/Services/OAuthService';
import { WorkflowUtility } from '../../designer/app/AzureLogicAppsDesigner/Utilities/Workflow';
import { WorkflowUtility, addConnectionData } from '../../designer/app/AzureLogicAppsDesigner/Utilities/Workflow';
import { HttpClient } from '../../designer/app/AzureLogicAppsDesigner/Services/HttpClient';
// import { useNavigate } from 'react-router-dom';
// import type { Template, LogicAppsV2 } from '@microsoft/logic-apps-shared';
Expand Down Expand Up @@ -154,8 +154,13 @@ export const TemplatesStandaloneDesigner = () => {
}
};

const addConnectionDataInternal = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
addConnectionData(connectionAndSetting, connectionsData ?? {}, settingsData ?? {});
};

const services = useMemo(
() => getServices(connectionsData ?? {}, workflowAppData as WorkflowApp, tenantId, objectId, canonicalLocation),
() =>
getServices(connectionsData ?? {}, workflowAppData as WorkflowApp, addConnectionDataInternal, tenantId, objectId, canonicalLocation),
// eslint-disable-next-line react-hooks/exhaustive-deps
[connectionsData, settingsData, workflowAppData, tenantId, canonicalLocation]
);
Expand Down Expand Up @@ -190,6 +195,7 @@ const httpClient = new HttpClient();
const getServices = (
connectionsData: ConnectionsData,
workflowApp: WorkflowApp | undefined,
addConnection: (data: ConnectionAndAppSetting) => Promise<void>,
tenantId: string | undefined,
objectId: string | undefined,
location: string
Expand All @@ -215,6 +221,7 @@ const getServices = (
},
workflowAppDetails: { appName, identity: workflowApp?.identity as any },
readConnections: () => Promise.resolve(connectionsData),
writeConnection: addConnection as any,
});
const gatewayService = new BaseGatewayService({
baseUrl: armUrl,
Expand Down
13 changes: 13 additions & 0 deletions libs/designer/src/lib/core/state/templates/templateSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
type LogicAppsV2,
type Template,
InitWorkflowService,
type ILoggerService,
DevLogger,
InitLoggerService,
} from '@microsoft/logic-apps-shared';
import type { PayloadAction } from '@reduxjs/toolkit';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
Expand Down Expand Up @@ -64,11 +67,21 @@ export const initializeTemplateServices = createAsyncThunk(
functionService,
appServiceService,
connectionParameterEditorService,
loggerService,
}: TemplateServiceOptions) => {
InitConnectionService(connectionService);
InitOAuthService(oAuthService);
InitWorkflowService(workflowService);

const loggerServices: ILoggerService[] = [];
if (loggerService) {
loggerServices.push(loggerService);
}
if (process.env.NODE_ENV !== 'production') {
loggerServices.push(new DevLogger());
}
InitLoggerService(loggerServices);

if (gatewayService) {
InitGatewayService(gatewayService);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import LegacyManagedIdentityDropdown from './formInputs/legacyManagedIdentityPic
import LegacyMultiAuth, { LegacyMultiAuthOptions } from './formInputs/legacyMultiAuth';
import type { ConnectionParameterProps } from './formInputs/universalConnectionParameter';
import { UniversalConnectionParameter } from './formInputs/universalConnectionParameter';
import type { IDropdownOption } from '@fluentui/react';
import { css, type IDropdownOption } from '@fluentui/react';
import { Body1Strong, Button, Divider, MessageBar, MessageBarActions, MessageBarBody } from '@fluentui/react-components';
import {
ConnectionParameterEditorService,
Expand Down Expand Up @@ -47,10 +47,12 @@ import TenantPicker from './formInputs/tenantPicker';
type ParamType = ConnectionParameter | ConnectionParameterSetParameter;

export interface CreateConnectionProps {
classes?: Record<string, string>;
nodeIds?: string[];
iconUri?: string;
connector: Connector;
connectionParameterSets?: ConnectionParameterSets;
description?: string;
identity?: ManagedIdentity;
isLoading?: boolean;
createConnectionCallback?: (
Expand Down Expand Up @@ -78,11 +80,13 @@ export interface CreateConnectionProps {

export const CreateConnection = (props: CreateConnectionProps) => {
const {
classes,
nodeIds = [],
showActionBar = true,
iconUri = '',
connector,
connectionParameterSets: _connectionParameterSets,
description,
identity,
isLoading = false,
createConnectionCallback,
Expand Down Expand Up @@ -573,13 +577,17 @@ export const CreateConnection = (props: CreateConnectionProps) => {
// RENDER

return (
<div className="msla-edit-connection-container">
<div className={classes?.['root'] ? css('msla-edit-connection-container', classes?.['root']) : 'msla-edit-connection-container'}>
{showActionBar ? <ActionList nodeIds={nodeIds} iconUri={iconUri} /> : null}
<Divider />
{showActionBar ? <Divider /> : null}

<Body1Strong>{componentDescription}</Body1Strong>
<Body1Strong>{description ?? componentDescription}</Body1Strong>

<div className="msla-create-connection-container">
<div
className={
classes?.['content'] ? css('msla-create-connection-container', classes?.['content']) : 'msla-create-connection-container'
}
>
{/* Error Bar */}
{errorMessage && (
<MessageBar intent={'error'} style={{ width: '100%' }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,24 @@ export interface CreatedConnectionPayload {
}

export const CreateConnectionInternal = (props: {
classes?: Record<string, string>;
connectorId: string;
operationType: string;
existingReferences: string[];
hideCancelButton: boolean;
showActionBar: boolean;
updateConnectionInState: (payload: CreatedConnectionPayload) => void;
onConnectionCreated: (connection: Connection) => void;
onConnectionCancelled?: () => void;
description?: string;
nodeIds?: string[];
assistedConnectionProps?: AssistedConnectionProps;
connectionMetadata?: ConnectionMetadata;
}) => {
const {
classes,
connectorId,
description,
operationType,
assistedConnectionProps,
existingReferences,
Expand All @@ -130,6 +135,7 @@ export const CreateConnectionInternal = (props: {
showActionBar,
updateConnectionInState,
onConnectionCreated,
onConnectionCancelled,
} = props;
const dispatch = useDispatch<AppDispatch>();

Expand Down Expand Up @@ -318,7 +324,10 @@ export const CreateConnectionInternal = (props: {

const cancelCallback = useCallback(() => {
dispatch(setIsCreatingConnection(false));
}, [dispatch]);
if (onConnectionCancelled) {
onConnectionCancelled();
}
}, [dispatch, onConnectionCancelled]);

const loadingText = intl.formatMessage({
defaultMessage: 'Loading connection data...',
Expand All @@ -339,12 +348,14 @@ export const CreateConnectionInternal = (props: {
nodeIds={nodeIds}
iconUri={iconUri}
showActionBar={showActionBar}
classes={classes}
connector={connector}
connectionParameterSets={getSupportedParameterSets(
connector.properties.connectionParameterSets,
operationType,
connector.properties.capabilities
)}
description={description}
identity={identity}
createConnectionCallback={createConnectionCallback}
isLoading={isCreating}
Expand Down
Loading
Loading