Skip to content

Commit 58cc22a

Browse files
authored
Merge pull request #6088 from Shopify/07-10-update_results_ui_for_copy_import
Update results UI for copy + import
2 parents 2ec8a8c + eeb4859 commit 58cc22a

File tree

11 files changed

+237
-44
lines changed

11 files changed

+237
-44
lines changed

packages/store/src/prompts/copy_result.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ describe('renderCopyResult', () => {
5757
renderCopyResult(sourceShop, targetShop, mockOperation)
5858

5959
expect(renderOperationResult).toHaveBeenCalledWith(
60-
['Copy operation from', {info: 'source-shop.myshopify.com'}, 'to', {info: 'target-shop.myshopify.com'}],
60+
[{subdued: 'From:'}, 'source-shop.myshopify.com', {subdued: '\nTo: '}, 'target-shop.myshopify.com'],
6161
mockOperation,
62+
targetShop,
6263
)
6364
})
6465
})

packages/store/src/prompts/copy_result.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ export function renderCopyResult(
88
targetShop: Shop,
99
copyOperation: BulkDataOperationByIdResponse,
1010
): void {
11-
const msg: Token[] = [`Copy operation from`, {info: sourceShop.domain}, `to`, {info: targetShop.domain}]
12-
renderOperationResult(msg, copyOperation)
11+
const msg: Token[] = [{subdued: 'From:'}, sourceShop.domain, {subdued: '\nTo: '}, targetShop.domain]
12+
renderOperationResult(msg, copyOperation, targetShop)
1313
}

packages/store/src/prompts/export_results.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('renderExportResult', () => {
2626
bulkData: {
2727
operation: {
2828
id: 'bulk-op-1',
29-
operationType: 'EXPORT',
29+
operationType: 'STORE_EXPORT',
3030
status: 'COMPLETED',
3131
sourceStore: {
3232
id: '1',
@@ -75,7 +75,7 @@ describe('renderExportResult', () => {
7575
bulkData: {
7676
operation: {
7777
id: 'bulk-op-1',
78-
operationType: 'EXPORT',
78+
operationType: 'STORE_EXPORT',
7979
status: 'COMPLETED',
8080
sourceStore: {
8181
id: '1',
@@ -119,7 +119,7 @@ describe('renderExportResult', () => {
119119
bulkData: {
120120
operation: {
121121
id: 'bulk-op-1',
122-
operationType: 'EXPORT',
122+
operationType: 'STORE_EXPORT',
123123
status: 'COMPLETED',
124124
sourceStore: {
125125
id: '1',

packages/store/src/prompts/import_result.test.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ describe('renderImportResult', () => {
2525
bulkData: {
2626
operation: {
2727
id: 'bulk-op-1',
28-
operationType: 'IMPORT',
28+
operationType: 'STORE_IMPORT',
2929
status: 'COMPLETED',
3030
sourceStore: {
3131
id: '1',
@@ -42,11 +42,13 @@ describe('renderImportResult', () => {
4242
}
4343

4444
test('calls renderOperationResult with correct base message', () => {
45-
renderImportResult(targetShop, mockOperation)
45+
const filePath = 'input.sqlite'
46+
renderImportResult(filePath, targetShop, mockOperation)
4647

4748
expect(renderOperationResult).toHaveBeenCalledWith(
48-
['Import operation to', {info: 'target-shop.myshopify.com'}],
49+
[{subdued: 'From:'}, 'input.sqlite', {subdued: '\nTo: '}, 'target-shop.myshopify.com'],
4950
mockOperation,
51+
targetShop,
5052
)
5153
})
5254
})

packages/store/src/prompts/import_result.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ import {BulkDataOperationByIdResponse} from '../apis/organizations/types.js'
33
import {Shop} from '../apis/destinations/index.js'
44
import {Token} from '@shopify/cli-kit/node/ui'
55

6-
export function renderImportResult(targetShop: Shop, importOperation: BulkDataOperationByIdResponse): void {
7-
const msg: Token[] = [`Import operation to`, {info: targetShop.domain}]
8-
renderOperationResult(msg, importOperation)
6+
export function renderImportResult(
7+
filePath: string,
8+
targetShop: Shop,
9+
importOperation: BulkDataOperationByIdResponse,
10+
): void {
11+
const msg: Token[] = [{subdued: 'From:'}, filePath, {subdued: '\nTo: '}, targetShop.domain]
12+
renderOperationResult(msg, importOperation, targetShop)
913
}

packages/store/src/prompts/operation_result.test.ts

Lines changed: 189 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ describe('renderOperationResult', () => {
4646
renderOperationResult([...baseMsg], operation)
4747

4848
expect(renderSuccess).toHaveBeenCalledWith({
49-
body: ['Base message', 'complete. '],
49+
headline: 'Copy completed',
50+
body: ['Base message'],
51+
nextSteps: undefined,
5052
})
5153
expect(renderWarning).not.toHaveBeenCalled()
5254
})
@@ -90,11 +92,9 @@ describe('renderOperationResult', () => {
9092
renderOperationResult([...baseMsg], operation)
9193

9294
expect(renderSuccess).toHaveBeenCalledWith({
93-
body: [
94-
'Base message',
95-
'complete. ',
96-
{link: {label: 'Results file can be downloaded for more details', url: 'https://example.com/results'}},
97-
],
95+
headline: 'Copy completed',
96+
body: ['Base message'],
97+
nextSteps: [['Download', {link: {label: 'result data', url: 'https://example.com/results'}}]],
9898
})
9999
expect(renderWarning).not.toHaveBeenCalled()
100100
})
@@ -137,7 +137,9 @@ describe('renderOperationResult', () => {
137137
renderOperationResult([...baseMsg], operation)
138138

139139
expect(renderWarning).toHaveBeenCalledWith({
140-
body: ['Base message', 'completed with', {error: 'errors. '}],
140+
headline: 'Copy completed with errors',
141+
body: ['Base message'],
142+
nextSteps: undefined,
141143
})
142144
expect(renderSuccess).not.toHaveBeenCalled()
143145
})
@@ -181,13 +183,187 @@ describe('renderOperationResult', () => {
181183
renderOperationResult([...baseMsg], operation)
182184

183185
expect(renderWarning).toHaveBeenCalledWith({
184-
body: [
185-
'Base message',
186-
'completed with',
187-
{error: 'errors. '},
188-
{link: {label: 'Results file can be downloaded for more details', url: 'https://example.com/results'}},
189-
],
186+
headline: 'Copy completed with errors',
187+
body: ['Base message'],
188+
nextSteps: [['Download', {link: {label: 'result data', url: 'https://example.com/results'}}]],
190189
})
191190
expect(renderSuccess).not.toHaveBeenCalled()
192191
})
192+
193+
test('renders success with target store link for STORE_COPY operation', () => {
194+
const targetShop = {
195+
id: '2',
196+
domain: 'target-shop.myshopify.com',
197+
name: 'Target Shop',
198+
status: 'ACTIVE',
199+
webUrl: 'https://target-shop.myshopify.com',
200+
handle: 'target-shop',
201+
publicId: 'pub2',
202+
shortName: 'target',
203+
organizationId: 'org1',
204+
}
205+
206+
const operation: BulkDataOperationByIdResponse = {
207+
organization: {
208+
name: 'Test Organization',
209+
bulkData: {
210+
operation: {
211+
id: 'bulk-op-1',
212+
operationType: 'STORE_COPY',
213+
status: 'COMPLETED',
214+
sourceStore: {
215+
id: '1',
216+
name: 'Source Store',
217+
},
218+
targetStore: {
219+
id: '2',
220+
name: 'Target Store',
221+
},
222+
storeOperations: [
223+
{
224+
id: 'op1',
225+
store: {
226+
id: '1',
227+
name: 'Store 1',
228+
},
229+
remoteOperationType: 'EXPORT',
230+
remoteOperationStatus: 'COMPLETED',
231+
totalObjectCount: 100,
232+
completedObjectCount: 100,
233+
url: 'https://example.com/results',
234+
},
235+
],
236+
},
237+
},
238+
},
239+
}
240+
241+
renderOperationResult([...baseMsg], operation, targetShop)
242+
243+
expect(renderSuccess).toHaveBeenCalledWith({
244+
headline: 'Copy completed',
245+
body: ['Base message'],
246+
nextSteps: [
247+
['View', {link: {label: 'target shop', url: 'https://target-shop.myshopify.com'}}],
248+
['Download', {link: {label: 'result data', url: 'https://example.com/results'}}],
249+
],
250+
})
251+
})
252+
253+
test('renders success with target store link for STORE_IMPORT operation', () => {
254+
const targetShop = {
255+
id: '2',
256+
domain: 'target-shop.myshopify.com',
257+
name: 'Target Shop',
258+
status: 'ACTIVE',
259+
webUrl: 'https://target-shop.myshopify.com',
260+
handle: 'target-shop',
261+
publicId: 'pub2',
262+
shortName: 'target',
263+
organizationId: 'org1',
264+
}
265+
266+
const operation: BulkDataOperationByIdResponse = {
267+
organization: {
268+
name: 'Test Organization',
269+
bulkData: {
270+
operation: {
271+
id: 'bulk-op-1',
272+
operationType: 'STORE_IMPORT',
273+
status: 'COMPLETED',
274+
sourceStore: {
275+
id: '2',
276+
name: 'Target Store',
277+
},
278+
targetStore: {
279+
id: '2',
280+
name: 'Target Store',
281+
},
282+
storeOperations: [
283+
{
284+
id: 'op1',
285+
store: {
286+
id: '2',
287+
name: 'Target Store',
288+
},
289+
remoteOperationType: 'IMPORT',
290+
remoteOperationStatus: 'COMPLETED',
291+
totalObjectCount: 100,
292+
completedObjectCount: 100,
293+
url: 'https://example.com/results',
294+
},
295+
],
296+
},
297+
},
298+
},
299+
}
300+
301+
renderOperationResult([...baseMsg], operation, targetShop)
302+
303+
expect(renderSuccess).toHaveBeenCalledWith({
304+
headline: 'Copy completed',
305+
body: ['Base message'],
306+
nextSteps: [
307+
['View', {link: {label: 'target shop', url: 'https://target-shop.myshopify.com'}}],
308+
['Download', {link: {label: 'result data', url: 'https://example.com/results'}}],
309+
],
310+
})
311+
})
312+
313+
test('does not render target store link for STORE_EXPORT operation', () => {
314+
const targetShop = {
315+
id: '1',
316+
domain: 'source-shop.myshopify.com',
317+
name: 'Source Shop',
318+
status: 'ACTIVE',
319+
webUrl: 'https://source-shop.myshopify.com',
320+
handle: 'source-shop',
321+
publicId: 'pub1',
322+
shortName: 'source',
323+
organizationId: 'org1',
324+
}
325+
326+
const operation: BulkDataOperationByIdResponse = {
327+
organization: {
328+
name: 'Test Organization',
329+
bulkData: {
330+
operation: {
331+
id: 'bulk-op-1',
332+
operationType: 'STORE_EXPORT',
333+
status: 'COMPLETED',
334+
sourceStore: {
335+
id: '1',
336+
name: 'Source Store',
337+
},
338+
targetStore: {
339+
id: '1',
340+
name: 'Source Store',
341+
},
342+
storeOperations: [
343+
{
344+
id: 'op1',
345+
store: {
346+
id: '1',
347+
name: 'Source Store',
348+
},
349+
remoteOperationType: 'EXPORT',
350+
remoteOperationStatus: 'COMPLETED',
351+
totalObjectCount: 100,
352+
completedObjectCount: 100,
353+
url: 'https://example.com/results',
354+
},
355+
],
356+
},
357+
},
358+
},
359+
}
360+
361+
renderOperationResult([...baseMsg], operation, targetShop)
362+
363+
expect(renderSuccess).toHaveBeenCalledWith({
364+
headline: 'Copy completed',
365+
body: ['Base message'],
366+
nextSteps: [['Download', {link: {label: 'result data', url: 'https://example.com/results'}}]],
367+
})
368+
})
193369
})
Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,39 @@
11
import {BulkDataOperationByIdResponse} from '../apis/organizations/types.js'
2-
import {renderSuccess, renderWarning, Token} from '@shopify/cli-kit/node/ui'
2+
import {Shop} from '../apis/destinations/index.js'
3+
import {renderSuccess, renderWarning, InlineToken, Token, TokenItem} from '@shopify/cli-kit/node/ui'
34

4-
export function renderOperationResult(baseMsg: Token[], operation: BulkDataOperationByIdResponse): void {
5+
export function renderOperationResult(
6+
baseMsg: Token[],
7+
operation: BulkDataOperationByIdResponse,
8+
targetShop?: Shop,
9+
): void {
510
const storeOperations = operation.organization.bulkData.operation.storeOperations
611
const hasErrors = storeOperations.some((op) => op.remoteOperationStatus === 'FAILED')
712
const url = storeOperations[0]?.url
13+
const operationType = operation.organization.bulkData.operation.operationType
14+
15+
const nextSteps: TokenItem<InlineToken>[] = []
16+
17+
if (targetShop && (operationType === 'STORE_COPY' || operationType === 'STORE_IMPORT')) {
18+
const targetStoreUrl = `https://${targetShop.domain}`
19+
nextSteps.push(['View', {link: {label: 'target shop', url: targetStoreUrl}}])
20+
}
21+
22+
if (url) {
23+
nextSteps.push(['Download', {link: {label: 'result data', url}}])
24+
}
825

926
if (hasErrors) {
10-
baseMsg.push(`completed with`)
11-
baseMsg.push({error: `errors. `})
12-
if (url) {
13-
const link = {link: {label: 'Results file can be downloaded for more details', url}}
14-
baseMsg.push(link)
15-
}
1627
renderWarning({
28+
headline: 'Copy completed with errors',
1729
body: baseMsg,
30+
nextSteps: nextSteps.length > 0 ? nextSteps : undefined,
1831
})
1932
} else {
20-
baseMsg.push('complete. ')
21-
if (url) {
22-
const link = {link: {label: 'Results file can be downloaded for more details', url}}
23-
baseMsg.push(link)
24-
}
2533
renderSuccess({
34+
headline: 'Copy completed',
2635
body: baseMsg,
36+
nextSteps: nextSteps.length > 0 ? nextSteps : undefined,
2737
})
2838
}
2939
}

packages/store/src/services/store/mock/mock-api-client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export class MockApiClient implements ApiClientInterface {
4242
success: true,
4343
operation: {
4444
id: 'mock-export-operation-id',
45-
operationType: 'EXPORT',
45+
operationType: 'STORE_EXPORT',
4646
status: 'IN_PROGRESS',
4747
},
4848
userErrors: [],
@@ -64,7 +64,7 @@ export class MockApiClient implements ApiClientInterface {
6464
success: true,
6565
operation: {
6666
id: 'mock-import-operation-id',
67-
operationType: 'IMPORT',
67+
operationType: 'STORE_IMPORT',
6868
status: 'IN_PROGRESS',
6969
},
7070
userErrors: [],

0 commit comments

Comments
 (0)