Skip to content

Commit c2f14ba

Browse files
authored
DT-384 - improve modal component to support form input (#1162)
* improve modal component to support form input - add `hasInput` prop to modals - if true, wrap content and buttons in a form - fix keyboard nav for modals with inputs * dynamically check for input instead of using a prop * refactor modals to use `<dialog />` element and native APIs * lint * fix cy tests * fix cy test * add aria-modal="true" to modal
1 parent 01de094 commit c2f14ba

14 files changed

+248
-210
lines changed

Diff for: cypress/integration/task-queues.spec.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ describe('Task Queues Page', () => {
1919
cy.wait('@activity-task-queues-api');
2020

2121
cy.get('[data-testid="pollers-title"]').contains('Pollers');
22-
cy.get('.text-lg').contains('Task Queue: a-task-queue');
22+
cy.get('[data-testid="task-queue-name"]').contains(
23+
'Task Queue: a-task-queue',
24+
);
2325
cy.get('[data-testid=worker-row]').should('have.length', 1);
2426
cy.get('[data-testid=worker-identity]').contains(wtq.pollers[0].identity);
2527
cy.get('[data-testid=worker-last-access-time]').contains(

Diff for: cypress/integration/workflow-actions.spec.js

+21-12
Original file line numberDiff line numberDiff line change
@@ -42,63 +42,72 @@ describe('Workflow Actions', () => {
4242

4343
describe('Terminate', () => {
4444
it('works if the workflow is running and write actions are enabled', () => {
45+
const confirmBtn =
46+
'[data-testid="terminate-confirmation-modal"] [data-testid="confirm-modal-button"]';
4547
cy.get('#workflow-actions-menu-button').click();
4648
cy.get(
4749
'#workflow-actions-menu >> [data-testid="terminate-button"]',
4850
).click();
4951
cy.get('#workflow-termination-reason').type('test');
50-
cy.get('[data-testid="confirm-modal-button"').click();
52+
cy.get(confirmBtn).click();
5153

5254
cy.wait('@terminate-workflow-api');
5355
cy.waitForWorkflowAPIs();
5456

5557
cy.get('#workflow-termination-success-toast').should('exist');
56-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
58+
cy.get(confirmBtn).should('not.be.visible');
5759
});
5860
});
5961

6062
describe('Cancel', () => {
6163
it('works if the workflow is running and write actions are enabled', () => {
64+
const confirmBtn =
65+
'[data-testid="cancel-confirmation-modal"] [data-testid="confirm-modal-button"]';
6266
cy.get('#workflow-actions-primary-button').click();
63-
cy.get('[data-testid="confirm-modal-button"]').click();
67+
cy.get(confirmBtn).click();
6468

6569
cy.wait('@cancel-workflow-api');
6670
cy.waitForWorkflowAPIs();
6771
cy.get('#workflow-cancelation-success-toast').should('exist');
68-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
72+
cy.get(confirmBtn).should('not.be.visible');
6973
});
7074
});
7175

7276
describe('Signal', () => {
7377
it('works if the workflow is running and write actions are enabled', () => {
78+
const confirmBtn =
79+
'[data-testid="signal-confirmation-modal"] [data-testid="confirm-modal-button"]';
7480
cy.get('#workflow-actions-menu-button').click();
7581
cy.get('#workflow-actions-menu >> [data-testid="signal-button"]').click();
7682
cy.get('#signal-name').type('sos');
7783
cy.get('div.cm-content').type('{{}{enter}"sos":true');
78-
cy.get('[data-testid="confirm-modal-button"').click();
84+
cy.get(confirmBtn).click();
7985

8086
cy.wait('@signal-workflow-api');
8187
cy.waitForWorkflowAPIs();
8288

8389
cy.get('#workflow-signal-success-toast').should('exist');
84-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
90+
cy.get(confirmBtn).should('not.be.visible');
8591
});
8692
});
8793

8894
describe('Reset', () => {
95+
const confirmBtn =
96+
'[data-testid="reset-confirmation-modal"] [data-testid="confirm-modal-button"]';
97+
8998
it('to the first workflow task if the workflow is running, and the action is enabled', () => {
9099
cy.get('#workflow-actions-menu-button').click();
91100
cy.get('#workflow-actions-menu >> [data-testid="reset-button"]').click();
92101
cy.get('[data-testid="workflow-reset-type-select"]').click();
93102
cy.get('#reset-type-select-menu >> li[role="menuitem"]').first().click();
94103
cy.get('#reset-reason').type('test');
95-
cy.get('[data-testid="confirm-modal-button"]').click();
104+
cy.get(confirmBtn).click();
96105

97106
cy.wait('@reset-workflow-api');
98107
cy.waitForWorkflowAPIs();
99108

100109
cy.get('[data-testid="workflow-reset-alert"]').should('be.visible');
101-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
110+
cy.get(confirmBtn).should('not.be.visible');
102111
});
103112

104113
it('to the last workflow task if the workflow is running, and the action is enabled', () => {
@@ -109,13 +118,13 @@ describe('Workflow Actions', () => {
109118
'#reset-type-select-menu > div:nth-child(2) > li[role="menuitem"]',
110119
).click();
111120
cy.get('#reset-reason').type('test');
112-
cy.get('[data-testid="confirm-modal-button"]').click();
121+
cy.get(confirmBtn).click();
113122

114123
cy.wait('@reset-workflow-api');
115124
cy.waitForWorkflowAPIs();
116125

117126
cy.get('[data-testid="workflow-reset-alert"]').should('be.visible');
118-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
127+
cy.get(confirmBtn).should('not.be.visible');
119128
});
120129

121130
it('to an arbitrary workflow task if the workflow is running, and the action is enabled', () => {
@@ -127,13 +136,13 @@ describe('Workflow Actions', () => {
127136
).click();
128137
cy.get('#reset-reason').type('test');
129138
cy.get('#reset-event-id').type('1');
130-
cy.get('[data-testid="confirm-modal-button"]').click();
139+
cy.get(confirmBtn).click();
131140

132141
cy.wait('@reset-workflow-api');
133142
cy.waitForWorkflowAPIs();
134143

135144
cy.get('[data-testid="workflow-reset-alert"]').should('be.visible');
136-
cy.get('[data-testid="confirm-modal-button"').should('not.exist');
145+
cy.get(confirmBtn).should('not.be.visible');
137146
});
138147
});
139148
});

Diff for: cypress/integration/workflow-bulk-actions.spec.js

+30-16
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,12 @@ describe('Batch and Bulk Workflow Actions', () => {
3838

3939
cy.get('#select-visible-workflows').click({ force: true });
4040
cy.get('[data-testid="bulk-terminate-button"]').click();
41-
cy.get('#bulk-action-reason').type('Sarah Connor');
42-
cy.get('div.modal button.destructive').click();
41+
cy.get(
42+
'[data-testid="batch-Terminate-confirmation"] #bulk-action-reason',
43+
).type('Sarah Connor');
44+
cy.get(
45+
'[data-testid="batch-Terminate-confirmation"] button.destructive',
46+
).click();
4347
cy.get('#batch-terminate-success-toast');
4448
});
4549

@@ -49,12 +53,15 @@ describe('Batch and Bulk Workflow Actions', () => {
4953
cy.get('#select-visible-workflows').click({ force: true });
5054
cy.get('[data-testid="select-all-workflows"]').click();
5155
cy.get('[data-testid="bulk-terminate-button"]').click();
52-
cy.get('[data-testid="batch-action-workflows-query"]').should(
53-
'have.text',
54-
'ExecutionStatus="Running"',
55-
);
56-
cy.get('#bulk-action-reason').type('Sarah Connor');
57-
cy.get('div.modal button.destructive').click();
56+
cy.get(
57+
'[data-testid="batch-Terminate-confirmation"] [data-testid="batch-action-workflows-query"]',
58+
).should('have.text', 'ExecutionStatus="Running"');
59+
cy.get(
60+
'[data-testid="batch-Terminate-confirmation"] #bulk-action-reason',
61+
).type('Sarah Connor');
62+
cy.get(
63+
'[data-testid="batch-Terminate-confirmation"] button.destructive',
64+
).click();
5865
cy.get('#batch-terminate-success-toast');
5966
});
6067

@@ -63,8 +70,12 @@ describe('Batch and Bulk Workflow Actions', () => {
6370

6471
cy.get('#select-visible-workflows').click({ force: true });
6572
cy.get('[data-testid="bulk-cancel-button"]').click();
66-
cy.get('#bulk-action-reason').type('Sarah Connor');
67-
cy.get('div.modal button.destructive').click();
73+
cy.get(
74+
'[data-testid="batch-Cancel-confirmation"] #bulk-action-reason',
75+
).type('Sarah Connor');
76+
cy.get(
77+
'[data-testid="batch-Cancel-confirmation"] button.destructive',
78+
).click();
6879
cy.get('#batch-cancel-success-toast');
6980
});
7081

@@ -74,12 +85,15 @@ describe('Batch and Bulk Workflow Actions', () => {
7485
cy.get('#select-visible-workflows').click({ force: true });
7586
cy.get('[data-testid="select-all-workflows"]').click();
7687
cy.get('[data-testid="bulk-cancel-button"]').click();
77-
cy.get('[data-testid="batch-action-workflows-query"]').should(
78-
'have.text',
79-
'ExecutionStatus="Running"',
80-
);
81-
cy.get('#bulk-action-reason').type('Sarah Connor');
82-
cy.get('div.modal button.destructive').click();
88+
cy.get(
89+
'[data-testid="batch-Cancel-confirmation"] [data-testid="batch-action-workflows-query"]',
90+
).should('have.text', 'ExecutionStatus="Running"');
91+
cy.get(
92+
'[data-testid="batch-Cancel-confirmation"] #bulk-action-reason',
93+
).type('Sarah Connor');
94+
cy.get(
95+
'[data-testid="batch-Cancel-confirmation"] button.destructive',
96+
).click();
8397
cy.get('#batch-cancel-success-toast');
8498
});
8599
});

Diff for: src/lib/components/workers-list.svelte

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
</script>
1515

1616
<section class="flex flex-col gap-4">
17-
<h2 class="text-lg font-medium">
17+
<h2 class="text-lg font-medium" data-testid="task-queue-name">
1818
Task Queue: <span class="select-all font-normal">{taskQueue}</span>
1919
</h2>
2020
<Table class="mb-6 w-full min-w-[600px] table-fixed">

Diff for: src/lib/components/workflow-actions.svelte

+16-39
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@
3737
let reason = '';
3838
let signalInput = '';
3939
let signalName = '';
40-
let showTerminationConfirmation = false;
41-
let showCancellationConfirmation = false;
42-
let showSignalConfirmation = false;
43-
let showResetConfirmation = false;
40+
let cancelConfirmationModal: Modal;
41+
let terminateConfirmationModal: Modal;
42+
let resetConfirmationModal: Modal;
43+
let signalConfirmationModal: Modal;
4444
let resetType: ResetType = ResetType.FirstWorkflowTask;
4545
let resetId: string | undefined = undefined;
4646
let resetReason: string | undefined = undefined;
@@ -52,47 +52,23 @@
5252
$: terminateEnabled = workflowTerminateEnabled($page.data.settings);
5353
$: resetEnabled = workflowResetEnabled($page.data.settings);
5454
55-
const showTerminationModal = () => {
56-
showTerminationConfirmation = true;
57-
};
58-
5955
const hideTerminationModal = () => {
60-
showTerminationConfirmation = false;
6156
reason = '';
6257
};
6358
64-
const showCancellationModal = () => {
65-
showCancellationConfirmation = true;
66-
};
67-
68-
const hideCancellationModal = () => {
69-
showCancellationConfirmation = false;
70-
};
71-
72-
const showSignalModal = () => {
73-
showSignalConfirmation = true;
74-
};
75-
7659
const hideSignalModal = () => {
77-
showSignalConfirmation = false;
7860
signalInput = '';
7961
signalName = '';
8062
};
8163
82-
const showResetModal = () => {
83-
showResetConfirmation = true;
84-
};
85-
8664
const hideResetModal = () => {
87-
showResetConfirmation = false;
8865
resetType = ResetType.FirstWorkflowTask;
8966
resetId = undefined;
9067
resetReason = undefined;
9168
eventIdValid = true;
9269
};
9370
9471
const handleSuccessfulTermination = async () => {
95-
hideTerminationModal();
9672
$refresh = Date.now();
9773
toaster.push({
9874
id: 'workflow-termination-success-toast',
@@ -101,7 +77,6 @@
10177
};
10278
10379
const handleTerminationError = () => {
104-
showTerminationConfirmation = false;
10580
reason = '';
10681
toaster.push({ message: 'Cannot terminate workflow.', variant: 'error' });
10782
};
@@ -137,7 +112,6 @@
137112
message: 'Unable to cancel workflow.',
138113
});
139114
}
140-
hideCancellationModal();
141115
};
142116
143117
const handleSignalInputChange = (event: CustomEvent<string>) => {
@@ -219,14 +193,14 @@
219193
$: workflowActions = [
220194
{
221195
label: 'Reset',
222-
onClick: showResetModal,
196+
onClick: () => resetConfirmationModal.open(),
223197
testId: 'reset-button',
224198
allowed: resetEnabled && workflow?.pendingChildren?.length === 0,
225199
tooltip: resetTooltipText(),
226200
},
227201
{
228202
label: 'Send a Signal',
229-
onClick: showSignalModal,
203+
onClick: () => signalConfirmationModal.open(),
230204
testId: 'signal-button',
231205
allowed: signalEnabled,
232206
tooltip: signalEnabled
@@ -235,7 +209,7 @@
235209
},
236210
{
237211
label: 'Terminate',
238-
onClick: showTerminationModal,
212+
onClick: () => terminateConfirmationModal.open(),
239213
testId: 'terminate-button',
240214
allowed: terminateEnabled,
241215
destructive: true,
@@ -257,7 +231,7 @@
257231
position="right"
258232
disabled={actionsDisabled}
259233
primaryActionDisabled={!cancelEnabled || cancelInProgress}
260-
on:click={showCancellationModal}
234+
on:click={() => cancelConfirmationModal.open()}
261235
label="Request Cancellation"
262236
>
263237
{#each workflowActions as { onClick, destructive, label, allowed, testId, tooltip }}
@@ -277,7 +251,8 @@
277251
</SplitButton>
278252

279253
<Modal
280-
open={showResetConfirmation}
254+
data-testid="reset-confirmation-modal"
255+
bind:this={resetConfirmationModal}
281256
on:confirmModal={reset}
282257
on:cancelModal={hideResetModal}
283258
confirmDisabled={resetType === ResetType.EventId && !eventIdValid}
@@ -294,10 +269,10 @@
294269
</svelte:fragment>
295270
</Modal>
296271
<Modal
297-
open={showCancellationConfirmation}
272+
data-testid="cancel-confirmation-modal"
273+
bind:this={cancelConfirmationModal}
298274
{loading}
299275
confirmType="destructive"
300-
on:cancelModal={hideCancellationModal}
301276
on:confirmModal={cancel}
302277
>
303278
<h3 slot="title">Cancel Workflow</h3>
@@ -309,7 +284,8 @@
309284
</svelte:fragment>
310285
</Modal>
311286
<Modal
312-
open={showTerminationConfirmation}
287+
data-testid="terminate-confirmation-modal"
288+
bind:this={terminateConfirmationModal}
313289
confirmText="Terminate"
314290
confirmType="destructive"
315291
on:cancelModal={hideTerminationModal}
@@ -330,7 +306,8 @@
330306
</div>
331307
</Modal>
332308
<Modal
333-
open={showSignalConfirmation}
309+
data-testid="signal-confirmation-modal"
310+
bind:this={signalConfirmationModal}
334311
confirmText="Submit"
335312
confirmDisabled={!signalName}
336313
on:cancelModal={hideSignalModal}

0 commit comments

Comments
 (0)