Skip to content

Commit ea3d271

Browse files
preetriti1Priti Sambandam
and
Priti Sambandam
authored
feat(templates): Adding connection create UI in list grid (#5022)
Co-authored-by: Priti Sambandam <[email protected]>
1 parent 81cc703 commit ea3d271

File tree

10 files changed

+219
-94
lines changed

10 files changed

+219
-94
lines changed

Localize/lang/strings.json

+4
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@
599599
"MnThTq": "Insert function",
600600
"MsCHhQ": "Timed Out",
601601
"MtWzvX": "Enter a positive integer between {min} and {max}",
602+
"N+qRUv": "Fill out the fields below to create a connection for {connectorName}",
602603
"N0pS6Y": "Target schema",
603604
"N2CF0J": "Required. The key name of the form data values to return.",
604605
"N4dEVo": "Headers",
@@ -1542,6 +1543,7 @@
15421543
"_MnThTq.comment": "Message to insert function",
15431544
"_MsCHhQ.comment": "The status message to show in monitoring view.",
15441545
"_MtWzvX.comment": "descriptio of maximum waiting runs setting",
1546+
"_N+qRUv.comment": "Message to show in title for connection creation",
15451547
"_N0pS6Y.comment": "Target schema",
15461548
"_N2CF0J.comment": "Required string parameter to be used as key for triggerFormDataMultiValues function",
15471549
"_N4dEVo.comment": "Display name for headers in outputs",
@@ -2509,6 +2511,7 @@
25092511
"_yF2R//.comment": "Label for description of custom substring Function",
25102512
"_yKOsmK.comment": "Label for description of custom sort Function",
25112513
"_yNtBUV.comment": "Warning message for when input node type does not match one of the function node input's allowed types",
2514+
"_yQ6+nV.comment": "Link to create a connection",
25122515
"_yRDuqj.comment": "Button text to add all advanced parameters",
25132516
"_yVFIAQ.comment": "Time zone value ",
25142517
"_yVh9kr.comment": "Hour of the day",
@@ -3173,6 +3176,7 @@
31733176
"yF2R//": "Returns a subset of characters from a string.",
31743177
"yKOsmK": "Returns an array sorted in ascending order",
31753178
"yNtBUV": "Warning: input node type does not match one of the allowed types for this input.",
3179+
"yQ6+nV": "Connect",
31763180
"yRDuqj": "Show all",
31773181
"yVFIAQ": "(UTC-01:00) Cabo Verde Is.",
31783182
"yVh9kr": "8",

apps/Standalone/src/designer/app/AzureLogicAppsDesigner/Utilities/Workflow.ts

+47-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { ConnectionsData, ParametersData } from '../Models/Workflow';
1+
import type { ConnectionAndAppSetting, ConnectionsData, ParametersData } from '../Models/Workflow';
22
import type { ConnectionReferences } from '@microsoft/logic-apps-designer';
33

44
export class WorkflowUtility {
@@ -122,3 +122,49 @@ function replaceIfFoundAndVerifyJson(stringifiedJson: string, searchValue: strin
122122
return undefined;
123123
}
124124
}
125+
126+
export async function addConnectionData(
127+
connectionAndSetting: ConnectionAndAppSetting,
128+
connectionsData: ConnectionsData,
129+
settings: any
130+
): Promise<void> {
131+
addConnectionInJson(connectionAndSetting, connectionsData ?? {});
132+
addOrUpdateAppSettings(connectionAndSetting.settings, settings?.properties ?? {});
133+
}
134+
135+
function addConnectionInJson(connectionAndSetting: ConnectionAndAppSetting, connectionsJson: ConnectionsData): void {
136+
const { connectionData, connectionKey, pathLocation } = connectionAndSetting;
137+
138+
let pathToSetConnectionsData: any = connectionsJson;
139+
140+
for (const path of pathLocation) {
141+
if (!pathToSetConnectionsData[path]) {
142+
pathToSetConnectionsData[path] = {};
143+
}
144+
145+
pathToSetConnectionsData = pathToSetConnectionsData[path];
146+
}
147+
148+
if (pathToSetConnectionsData && pathToSetConnectionsData[connectionKey]) {
149+
// TODO: To show this in a notification of info bar on the blade.
150+
// const message = 'ConnectionKeyAlreadyExist - Connection key \'{0}\' already exists.'.format(connectionKey);
151+
return;
152+
}
153+
154+
pathToSetConnectionsData[connectionKey] = connectionData;
155+
}
156+
157+
function addOrUpdateAppSettings(settings: Record<string, string>, originalSettings: Record<string, string>): Record<string, string> {
158+
const settingsToAdd = Object.keys(settings);
159+
160+
for (const settingKey of settingsToAdd) {
161+
if (originalSettings[settingKey]) {
162+
// TODO: To show this in a notification of info bar on the blade that key will be overriden.
163+
}
164+
165+
// eslint-disable-next-line no-param-reassign
166+
originalSettings[settingKey] = settings[settingKey];
167+
}
168+
169+
return originalSettings;
170+
}

apps/Standalone/src/designer/app/AzureLogicAppsDesigner/laDesigner.tsx

+4-42
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import {
2424
useWorkflowApp,
2525
} from './Services/WorkflowAndArtifacts';
2626
import { ArmParser } from './Utilities/ArmParser';
27-
import { WorkflowUtility } from './Utilities/Workflow';
27+
import { WorkflowUtility, addConnectionData } from './Utilities/Workflow';
2828
import { Chatbot, chatbotPanelWidth } from '@microsoft/logic-apps-chatbot';
2929
import {
3030
BaseApiManagementService,
@@ -123,9 +123,8 @@ const DesignerEditor = () => {
123123
[originalConnectionsData, parameters, settingsData?.properties]
124124
);
125125

126-
const addConnectionData = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
127-
addConnectionInJson(connectionAndSetting, connectionsData ?? {});
128-
addOrUpdateAppSettings(connectionAndSetting.settings, settingsData?.properties ?? {});
126+
const addConnectionDataInternal = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
127+
addConnectionData(connectionAndSetting, connectionsData ?? {}, settingsData ?? {});
129128
};
130129

131130
const getConnectionConfiguration = async (connectionId: string): Promise<any> => {
@@ -168,7 +167,7 @@ const DesignerEditor = () => {
168167
equals(workflow?.kind, 'stateful'),
169168
connectionsData ?? {},
170169
workflowAppData as WorkflowApp,
171-
addConnectionData,
170+
addConnectionDataInternal,
172171
getConnectionConfiguration,
173172
tenantId,
174173
objectId,
@@ -716,43 +715,6 @@ const getDesignerServices = (
716715
};
717716
};
718717

719-
const addConnectionInJson = (connectionAndSetting: ConnectionAndAppSetting, connectionsJson: ConnectionsData): void => {
720-
const { connectionData, connectionKey, pathLocation } = connectionAndSetting;
721-
722-
let pathToSetConnectionsData: any = connectionsJson;
723-
724-
for (const path of pathLocation) {
725-
if (!pathToSetConnectionsData[path]) {
726-
pathToSetConnectionsData[path] = {};
727-
}
728-
729-
pathToSetConnectionsData = pathToSetConnectionsData[path];
730-
}
731-
732-
if (pathToSetConnectionsData && pathToSetConnectionsData[connectionKey]) {
733-
// TODO: To show this in a notification of info bar on the blade.
734-
// const message = 'ConnectionKeyAlreadyExist - Connection key \'{0}\' already exists.'.format(connectionKey);
735-
return;
736-
}
737-
738-
pathToSetConnectionsData[connectionKey] = connectionData;
739-
};
740-
741-
const addOrUpdateAppSettings = (settings: Record<string, string>, originalSettings: Record<string, string>): Record<string, string> => {
742-
const settingsToAdd = Object.keys(settings);
743-
744-
for (const settingKey of settingsToAdd) {
745-
if (originalSettings[settingKey]) {
746-
// TODO: To show this in a notification of info bar on the blade that key will be overriden.
747-
}
748-
749-
// eslint-disable-next-line no-param-reassign
750-
originalSettings[settingKey] = settings[settingKey];
751-
}
752-
753-
return originalSettings;
754-
};
755-
756718
const hasNewKeys = (original: Record<string, any> = {}, updated: Record<string, any> = {}) => {
757719
return !Object.keys(updated).some((key) => !Object.keys(original).includes(key));
758720
};

apps/Standalone/src/templates/app/TemplatesStandaloneDesigner.tsx

+10-3
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import {
1414
useCurrentTenantId,
1515
useWorkflowApp,
1616
} from '../../designer/app/AzureLogicAppsDesigner/Services/WorkflowAndArtifacts';
17-
import type { ConnectionsData } from '../../designer/app/AzureLogicAppsDesigner/Models/Workflow';
17+
import type { ConnectionAndAppSetting, ConnectionsData } from '../../designer/app/AzureLogicAppsDesigner/Models/Workflow';
1818
import type { WorkflowApp } from '../../designer/app/AzureLogicAppsDesigner/Models/WorkflowApp';
1919
import { ArmParser } from '../../designer/app/AzureLogicAppsDesigner/Utilities/ArmParser';
2020
import { StandaloneOAuthService } from '../../designer/app/AzureLogicAppsDesigner/Services/OAuthService';
21-
import { WorkflowUtility } from '../../designer/app/AzureLogicAppsDesigner/Utilities/Workflow';
21+
import { WorkflowUtility, addConnectionData } from '../../designer/app/AzureLogicAppsDesigner/Utilities/Workflow';
2222
import { HttpClient } from '../../designer/app/AzureLogicAppsDesigner/Services/HttpClient';
2323
// import { useNavigate } from 'react-router-dom';
2424
// import type { Template, LogicAppsV2 } from '@microsoft/logic-apps-shared';
@@ -154,8 +154,13 @@ export const TemplatesStandaloneDesigner = () => {
154154
}
155155
};
156156

157+
const addConnectionDataInternal = async (connectionAndSetting: ConnectionAndAppSetting): Promise<void> => {
158+
addConnectionData(connectionAndSetting, connectionsData ?? {}, settingsData ?? {});
159+
};
160+
157161
const services = useMemo(
158-
() => getServices(connectionsData ?? {}, workflowAppData as WorkflowApp, tenantId, objectId, canonicalLocation),
162+
() =>
163+
getServices(connectionsData ?? {}, workflowAppData as WorkflowApp, addConnectionDataInternal, tenantId, objectId, canonicalLocation),
159164
// eslint-disable-next-line react-hooks/exhaustive-deps
160165
[connectionsData, settingsData, workflowAppData, tenantId, canonicalLocation]
161166
);
@@ -190,6 +195,7 @@ const httpClient = new HttpClient();
190195
const getServices = (
191196
connectionsData: ConnectionsData,
192197
workflowApp: WorkflowApp | undefined,
198+
addConnection: (data: ConnectionAndAppSetting) => Promise<void>,
193199
tenantId: string | undefined,
194200
objectId: string | undefined,
195201
location: string
@@ -215,6 +221,7 @@ const getServices = (
215221
},
216222
workflowAppDetails: { appName, identity: workflowApp?.identity as any },
217223
readConnections: () => Promise.resolve(connectionsData),
224+
writeConnection: addConnection as any,
218225
});
219226
const gatewayService = new BaseGatewayService({
220227
baseUrl: armUrl,

libs/designer/src/lib/core/state/templates/templateSlice.ts

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import {
1212
type LogicAppsV2,
1313
type Template,
1414
InitWorkflowService,
15+
type ILoggerService,
16+
DevLogger,
17+
InitLoggerService,
1518
} from '@microsoft/logic-apps-shared';
1619
import type { PayloadAction } from '@reduxjs/toolkit';
1720
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
@@ -64,11 +67,21 @@ export const initializeTemplateServices = createAsyncThunk(
6467
functionService,
6568
appServiceService,
6669
connectionParameterEditorService,
70+
loggerService,
6771
}: TemplateServiceOptions) => {
6872
InitConnectionService(connectionService);
6973
InitOAuthService(oAuthService);
7074
InitWorkflowService(workflowService);
7175

76+
const loggerServices: ILoggerService[] = [];
77+
if (loggerService) {
78+
loggerServices.push(loggerService);
79+
}
80+
if (process.env.NODE_ENV !== 'production') {
81+
loggerServices.push(new DevLogger());
82+
}
83+
InitLoggerService(loggerServices);
84+
7285
if (gatewayService) {
7386
InitGatewayService(gatewayService);
7487
}

libs/designer/src/lib/ui/panel/connectionsPanel/createConnection/createConnection.tsx

+13-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import LegacyManagedIdentityDropdown from './formInputs/legacyManagedIdentityPic
77
import LegacyMultiAuth, { LegacyMultiAuthOptions } from './formInputs/legacyMultiAuth';
88
import type { ConnectionParameterProps } from './formInputs/universalConnectionParameter';
99
import { UniversalConnectionParameter } from './formInputs/universalConnectionParameter';
10-
import type { IDropdownOption } from '@fluentui/react';
10+
import { css, type IDropdownOption } from '@fluentui/react';
1111
import { Body1Strong, Button, Divider, MessageBar, MessageBarActions, MessageBarBody } from '@fluentui/react-components';
1212
import {
1313
ConnectionParameterEditorService,
@@ -47,10 +47,12 @@ import TenantPicker from './formInputs/tenantPicker';
4747
type ParamType = ConnectionParameter | ConnectionParameterSetParameter;
4848

4949
export interface CreateConnectionProps {
50+
classes?: Record<string, string>;
5051
nodeIds?: string[];
5152
iconUri?: string;
5253
connector: Connector;
5354
connectionParameterSets?: ConnectionParameterSets;
55+
description?: string;
5456
identity?: ManagedIdentity;
5557
isLoading?: boolean;
5658
createConnectionCallback?: (
@@ -78,11 +80,13 @@ export interface CreateConnectionProps {
7880

7981
export const CreateConnection = (props: CreateConnectionProps) => {
8082
const {
83+
classes,
8184
nodeIds = [],
8285
showActionBar = true,
8386
iconUri = '',
8487
connector,
8588
connectionParameterSets: _connectionParameterSets,
89+
description,
8690
identity,
8791
isLoading = false,
8892
createConnectionCallback,
@@ -573,13 +577,17 @@ export const CreateConnection = (props: CreateConnectionProps) => {
573577
// RENDER
574578

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

580-
<Body1Strong>{componentDescription}</Body1Strong>
584+
<Body1Strong>{description ?? componentDescription}</Body1Strong>
581585

582-
<div className="msla-create-connection-container">
586+
<div
587+
className={
588+
classes?.['content'] ? css('msla-create-connection-container', classes?.['content']) : 'msla-create-connection-container'
589+
}
590+
>
583591
{/* Error Bar */}
584592
{errorMessage && (
585593
<MessageBar intent={'error'} style={{ width: '100%' }}>

libs/designer/src/lib/ui/panel/connectionsPanel/createConnection/createConnectionWrapper.tsx

+12-1
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,24 @@ export interface CreatedConnectionPayload {
108108
}
109109

110110
export const CreateConnectionInternal = (props: {
111+
classes?: Record<string, string>;
111112
connectorId: string;
112113
operationType: string;
113114
existingReferences: string[];
114115
hideCancelButton: boolean;
115116
showActionBar: boolean;
116117
updateConnectionInState: (payload: CreatedConnectionPayload) => void;
117118
onConnectionCreated: (connection: Connection) => void;
119+
onConnectionCancelled?: () => void;
120+
description?: string;
118121
nodeIds?: string[];
119122
assistedConnectionProps?: AssistedConnectionProps;
120123
connectionMetadata?: ConnectionMetadata;
121124
}) => {
122125
const {
126+
classes,
123127
connectorId,
128+
description,
124129
operationType,
125130
assistedConnectionProps,
126131
existingReferences,
@@ -130,6 +135,7 @@ export const CreateConnectionInternal = (props: {
130135
showActionBar,
131136
updateConnectionInState,
132137
onConnectionCreated,
138+
onConnectionCancelled,
133139
} = props;
134140
const dispatch = useDispatch<AppDispatch>();
135141

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

319325
const cancelCallback = useCallback(() => {
320326
dispatch(setIsCreatingConnection(false));
321-
}, [dispatch]);
327+
if (onConnectionCancelled) {
328+
onConnectionCancelled();
329+
}
330+
}, [dispatch, onConnectionCancelled]);
322331

323332
const loadingText = intl.formatMessage({
324333
defaultMessage: 'Loading connection data...',
@@ -339,12 +348,14 @@ export const CreateConnectionInternal = (props: {
339348
nodeIds={nodeIds}
340349
iconUri={iconUri}
341350
showActionBar={showActionBar}
351+
classes={classes}
342352
connector={connector}
343353
connectionParameterSets={getSupportedParameterSets(
344354
connector.properties.connectionParameterSets,
345355
operationType,
346356
connector.properties.capabilities
347357
)}
358+
description={description}
348359
identity={identity}
349360
createConnectionCallback={createConnectionCallback}
350361
isLoading={isCreating}

0 commit comments

Comments
 (0)