1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: AGPL-3.0
5 import { Dispatch } from 'redux';
6 import { dialogActions } from 'store/dialog/dialog-actions';
7 import { RootState } from 'store/store';
8 import { ResourceKind, extractUuidKind } from 'models/resource';
9 import { getResource } from 'store/resources/resources';
10 import { GroupContentsResourcePrefix } from 'services/groups-service/groups-service';
11 import { snackbarActions, SnackbarKind } from 'store/snackbar/snackbar-actions';
12 import { ContainerRequestResource } from 'models/container-request';
13 import { CollectionResource } from 'models/collection';
14 import { ProjectResource } from 'models/project';
15 import { ServiceRepository } from 'services/services';
16 import { FilterBuilder } from 'services/api/filter-builder';
17 import { ListResults } from 'services/common-service/common-service';
18 import { RepositoryResource } from 'models/repositories';
19 import { SshKeyResource } from 'models/ssh-key';
20 import { VirtualMachinesResource } from 'models/virtual-machines';
21 import { UserResource } from 'models/user';
22 import { LinkResource } from 'models/link';
23 import { WorkflowResource } from 'models/workflow';
24 import { KeepServiceResource } from 'models/keep-services';
25 import { ApiClientAuthorization } from 'models/api-client-authorization';
26 import React from 'react';
28 export const ADVANCED_TAB_DIALOG = 'advancedTabDialog';
30 export interface AdvancedTabDialogData {
32 apiResponse: JSX.Element;
33 metadata: ListResults<LinkResource> | string;
34 user: UserResource | string;
36 pythonExample: string;
38 cliGetExample: string;
39 cliUpdateHeader: string;
40 cliUpdateExample: string;
46 COLLECTION = 'collection',
47 STORAGE_CLASSES_CONFIRMED = 'storage_classes_confirmed'
51 CONTAINER_REQUEST = 'container_request',
52 OUTPUT_NAME = 'output_name'
57 DELETE_AT = 'delete_at'
61 REPOSITORY = 'repository',
62 CREATED_AT = 'created_at'
66 SSH_KEY = 'authorized_key',
67 CREATED_AT = 'created_at'
70 enum VirtualMachineData {
71 VIRTUAL_MACHINE = 'virtual_machine',
72 CREATED_AT = 'created_at'
76 REPOSITORIES = 'repositories',
77 AUTORIZED_KEYS = 'authorized_keys',
78 VIRTUAL_MACHINES = 'virtual_machines',
79 KEEP_SERVICES = 'keep_services',
81 API_CLIENT_AUTHORIZATIONS = 'api_client_authorizations',
85 enum KeepServiceData {
86 KEEP_SERVICE = 'keep_services',
87 CREATED_AT = 'created_at'
95 enum ApiClientAuthorizationsData {
96 API_CLIENT_AUTHORIZATION = 'api_client_authorization',
97 EXPIRES_AT = 'expires_at'
102 PROPERTIES = 'properties'
106 WORKFLOW = 'workflow',
107 CREATED_AT = 'created_at'
110 type AdvanceResourceKind = CollectionData | ProcessData | ProjectData | RepositoryData | SshKeyData | VirtualMachineData | KeepServiceData | ApiClientAuthorizationsData | UserData | LinkData | WorkflowData;
111 type AdvanceResourcePrefix = GroupContentsResourcePrefix | ResourcePrefix;
112 type AdvanceResponseData = ContainerRequestResource | ProjectResource | CollectionResource | RepositoryResource | SshKeyResource | VirtualMachinesResource | KeepServiceResource | ApiClientAuthorization | UserResource | LinkResource | WorkflowResource | undefined;
114 export const openAdvancedTabDialog = (uuid: string) =>
115 async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
116 const kind = extractUuidKind(uuid);
118 case ResourceKind.COLLECTION:
119 const { data: dataCollection, metadata: metaCollection, user: userCollection } = await dispatch<any>(getDataForAdvancedTab(uuid));
120 const advanceDataCollection = advancedTabData({
122 metadata: metaCollection,
123 user: userCollection,
124 apiResponseKind: collectionApiResponse,
125 data: dataCollection,
126 resourceKind: CollectionData.COLLECTION,
127 resourcePrefix: GroupContentsResourcePrefix.COLLECTION,
128 resourceKindProperty: CollectionData.STORAGE_CLASSES_CONFIRMED,
129 property: dataCollection.storageClassesConfirmed
131 dispatch<any>(initAdvancedTabDialog(advanceDataCollection));
133 case ResourceKind.PROCESS:
134 const { data: dataProcess, metadata: metaProcess, user: userProcess } = await dispatch<any>(getDataForAdvancedTab(uuid));
135 const advancedDataProcess = advancedTabData({
137 metadata: metaProcess,
139 apiResponseKind: containerRequestApiResponse,
141 resourceKind: ProcessData.CONTAINER_REQUEST,
142 resourcePrefix: GroupContentsResourcePrefix.PROCESS,
143 resourceKindProperty: ProcessData.OUTPUT_NAME,
144 property: dataProcess.outputName
146 dispatch<any>(initAdvancedTabDialog(advancedDataProcess));
148 case ResourceKind.PROJECT:
149 const { data: dataProject, metadata: metaProject, user: userProject } = await dispatch<any>(getDataForAdvancedTab(uuid));
150 const advanceDataProject = advancedTabData({
152 metadata: metaProject,
154 apiResponseKind: groupRequestApiResponse,
156 resourceKind: ProjectData.GROUP,
157 resourcePrefix: GroupContentsResourcePrefix.PROJECT,
158 resourceKindProperty: ProjectData.DELETE_AT,
159 property: dataProject.deleteAt
161 dispatch<any>(initAdvancedTabDialog(advanceDataProject));
163 case ResourceKind.REPOSITORY:
164 const dataRepository = getState().repositories.items.find(it => it.uuid === uuid);
165 const advanceDataRepository = advancedTabData({
169 apiResponseKind: repositoryApiResponse,
170 data: dataRepository,
171 resourceKind: RepositoryData.REPOSITORY,
172 resourcePrefix: ResourcePrefix.REPOSITORIES,
173 resourceKindProperty: RepositoryData.CREATED_AT,
174 property: dataRepository!.createdAt
176 dispatch<any>(initAdvancedTabDialog(advanceDataRepository));
178 case ResourceKind.SSH_KEY:
179 const dataSshKey = getState().auth.sshKeys.find(it => it.uuid === uuid);
180 const advanceDataSshKey = advancedTabData({
184 apiResponseKind: sshKeyApiResponse,
186 resourceKind: SshKeyData.SSH_KEY,
187 resourcePrefix: ResourcePrefix.AUTORIZED_KEYS,
188 resourceKindProperty: SshKeyData.CREATED_AT,
189 property: dataSshKey!.createdAt
191 dispatch<any>(initAdvancedTabDialog(advanceDataSshKey));
193 case ResourceKind.VIRTUAL_MACHINE:
194 const dataVirtualMachine = getState().virtualMachines.virtualMachines.items.find(it => it.uuid === uuid);
195 const advanceDataVirtualMachine = advancedTabData({
199 apiResponseKind: virtualMachineApiResponse,
200 data: dataVirtualMachine,
201 resourceKind: VirtualMachineData.VIRTUAL_MACHINE,
202 resourcePrefix: ResourcePrefix.VIRTUAL_MACHINES,
203 resourceKindProperty: VirtualMachineData.CREATED_AT,
204 property: dataVirtualMachine.createdAt
206 dispatch<any>(initAdvancedTabDialog(advanceDataVirtualMachine));
208 case ResourceKind.KEEP_SERVICE:
209 const dataKeepService = getState().keepServices.find(it => it.uuid === uuid);
210 const advanceDataKeepService = advancedTabData({
214 apiResponseKind: keepServiceApiResponse,
215 data: dataKeepService,
216 resourceKind: KeepServiceData.KEEP_SERVICE,
217 resourcePrefix: ResourcePrefix.KEEP_SERVICES,
218 resourceKindProperty: KeepServiceData.CREATED_AT,
219 property: dataKeepService!.createdAt
221 dispatch<any>(initAdvancedTabDialog(advanceDataKeepService));
223 case ResourceKind.USER:
224 const { resources } = getState();
225 const data = getResource<UserResource>(uuid)(resources);
226 const metadata = await services.linkService.list({
227 filters: new FilterBuilder()
228 .addEqual('head_uuid', uuid)
231 const advanceDataUser = advancedTabData({
235 apiResponseKind: userApiResponse,
237 resourceKind: UserData.USER,
238 resourcePrefix: ResourcePrefix.USERS,
239 resourceKindProperty: UserData.USERNAME,
240 property: data!.username
242 dispatch<any>(initAdvancedTabDialog(advanceDataUser));
244 case ResourceKind.API_CLIENT_AUTHORIZATION:
245 const apiClientAuthorizationResources = getState().resources;
246 const dataApiClientAuthorization = getResource<ApiClientAuthorization>(uuid)(apiClientAuthorizationResources);
247 const advanceDataApiClientAuthorization = advancedTabData({
251 apiResponseKind: apiClientAuthorizationApiResponse,
252 data: dataApiClientAuthorization,
253 resourceKind: ApiClientAuthorizationsData.API_CLIENT_AUTHORIZATION,
254 resourcePrefix: ResourcePrefix.API_CLIENT_AUTHORIZATIONS,
255 resourceKindProperty: ApiClientAuthorizationsData.EXPIRES_AT,
256 property: dataApiClientAuthorization!.createdAt
258 dispatch<any>(initAdvancedTabDialog(advanceDataApiClientAuthorization));
260 case ResourceKind.LINK:
261 const linkResources = getState().resources;
262 const dataLink = getResource<LinkResource>(uuid)(linkResources);
263 const advanceDataLink = advancedTabData({
267 apiResponseKind: linkApiResponse,
269 resourceKind: LinkData.LINK,
270 resourcePrefix: ResourcePrefix.LINKS,
271 resourceKindProperty: LinkData.PROPERTIES,
272 property: dataLink!.properties
274 dispatch<any>(initAdvancedTabDialog(advanceDataLink));
276 case ResourceKind.WORKFLOW:
277 const wfResources = getState().resources;
278 const dataWf = getResource<WorkflowResource>(uuid)(wfResources);
279 const advanceDataWf = advancedTabData({
283 apiResponseKind: wfApiResponse,
285 resourceKind: WorkflowData.WORKFLOW,
286 resourcePrefix: GroupContentsResourcePrefix.WORKFLOW,
287 resourceKindProperty: WorkflowData.CREATED_AT,
288 property: dataWf!.createdAt
290 dispatch<any>(initAdvancedTabDialog(advanceDataWf));
294 dispatch(snackbarActions.OPEN_SNACKBAR({ message: "Could not open advanced tab for this resource.", hideDuration: 2000, kind: SnackbarKind.ERROR }));
298 const getDataForAdvancedTab = (uuid: string) =>
299 async (dispatch: Dispatch<any>, getState: () => RootState, services: ServiceRepository) => {
300 const { resources } = getState();
301 const data = getResource<any>(uuid)(resources);
302 const metadata = await services.linkService.list({
303 filters: new FilterBuilder()
304 .addEqual('head_uuid', uuid)
308 return { data, metadata };
311 const initAdvancedTabDialog = (data: AdvancedTabDialogData) => dialogActions.OPEN_DIALOG({ id: ADVANCED_TAB_DIALOG, data });
313 interface AdvancedTabData {
315 metadata: ListResults<LinkResource> | string;
316 user: UserResource | string;
317 apiResponseKind: (apiResponse) => JSX.Element;
318 data: AdvanceResponseData;
319 resourceKind: AdvanceResourceKind;
320 resourcePrefix: AdvanceResourcePrefix;
321 resourceKindProperty: AdvanceResourceKind;
325 const advancedTabData = ({ uuid, user, metadata, apiResponseKind, data, resourceKind, resourcePrefix, resourceKindProperty, property }: AdvancedTabData) => {
330 apiResponse: apiResponseKind(data),
331 pythonHeader: pythonHeader(resourceKind),
332 pythonExample: pythonExample(uuid, resourcePrefix),
333 cliGetHeader: cliGetHeader(resourceKind),
334 cliGetExample: cliGetExample(uuid, resourceKind),
335 cliUpdateHeader: cliUpdateHeader(resourceKind, resourceKindProperty),
336 cliUpdateExample: cliUpdateExample(uuid, resourceKind, property, resourceKindProperty),
337 curlHeader: curlHeader(resourceKind, resourceKindProperty),
338 curlExample: curlExample(uuid, resourcePrefix, property, resourceKind, resourceKindProperty),
342 const pythonHeader = (resourceKind: string) =>
343 `An example python command to get a ${resourceKind} using its uuid:`;
345 const pythonExample = (uuid: string, resourcePrefix: string) => {
346 const pythonExample = `import arvados
348 x = arvados.api().${resourcePrefix}().get(uuid='${uuid}').execute()`;
350 return pythonExample;
353 const cliGetHeader = (resourceKind: string) =>
354 `An example arv command to get a ${resourceKind} using its uuid:`;
356 const cliGetExample = (uuid: string, resourceKind: string) => {
357 const cliGetExample = `arv ${resourceKind} get \\
360 return cliGetExample;
363 const cliUpdateHeader = (resourceKind: string, resourceName: string) =>
364 `An example arv command to update the "${resourceName}" attribute for the current ${resourceKind}:`;
366 const cliUpdateExample = (uuid: string, resourceKind: string, resource: string | string[], resourceName: string) => {
367 const CLIUpdateCollectionExample = `arv ${resourceKind} update \\
369 --${resourceKind} '{"${resourceName}":${JSON.stringify(resource)}}'`;
371 return CLIUpdateCollectionExample;
374 const curlHeader = (resourceKind: string, resource: string) =>
375 `An example curl command to update the "${resource}" attribute for the current ${resourceKind}:`;
377 const curlExample = (uuid: string, resourcePrefix: string, resource: string | string[], resourceKind: string, resourceName: string) => {
378 const curlExample = `curl -X PUT \\
379 -H "Authorization: OAuth2 $ARVADOS_API_TOKEN" \\
380 --data-urlencode ${resourceKind}@/dev/stdin \\
381 https://$ARVADOS_API_HOST/arvados/v1/${resourcePrefix}/${uuid} \\
384 "${resourceName}": ${JSON.stringify(resource, null, 4)}
391 const stringify = (item: string | null | number | boolean) =>
392 JSON.stringify(item) || 'null';
394 const stringifyObject = (item: any) =>
395 JSON.stringify(item, null, 2) || 'null';
397 const containerRequestApiResponse = (apiResponse: ContainerRequestResource): JSX.Element => {
398 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, state, requestingContainerUuid, containerUuid,
399 containerCountMax, mounts, runtimeConstraints, containerImage, environment, cwd, command, outputPath, priority, expiresAt, filters, containerCount,
400 useExisting, schedulingParameters, outputUuid, logUuid, outputName, outputTtl } = apiResponse;
403 "owner_uuid": "${ownerUuid}",
404 "created_at": "${createdAt}",
405 "modified_at": ${stringify(modifiedAt)},
406 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
407 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
408 "name": ${stringify(name)},
409 "description": ${stringify(description)},
410 "properties": ${stringifyObject(properties)},
411 "state": ${stringify(state)},
412 "requesting_container_uuid": ${stringify(requestingContainerUuid)},
413 "container_uuid": ${stringify(containerUuid)},
414 "container_count_max": ${stringify(containerCountMax)},
415 "mounts": ${stringifyObject(mounts)},
416 "runtime_constraints": ${stringifyObject(runtimeConstraints)},
417 "container_image": ${stringify(containerImage)},
418 "environment": ${stringifyObject(environment)},
419 "cwd": ${stringify(cwd)},
420 "command": ${stringifyObject(command)},
421 "output_path": ${stringify(outputPath)},
422 "priority": ${stringify(priority)},
423 "expires_at": ${stringify(expiresAt)},
424 "filters": ${stringify(filters)},
425 "container_count": ${stringify(containerCount)},
426 "use_existing": ${stringify(useExisting)},
427 "scheduling_parameters": ${stringifyObject(schedulingParameters)},
428 "output_uuid": ${stringify(outputUuid)},
429 "log_uuid": ${stringify(logUuid)},
430 "output_name": ${stringify(outputName)},
431 "output_ttl": ${stringify(outputTtl)}`;
433 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
436 const collectionApiResponse = (apiResponse: CollectionResource): JSX.Element => {
437 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, description, properties, portableDataHash, replicationDesired,
438 replicationConfirmedAt, replicationConfirmed, deleteAt, trashAt, isTrashed, storageClassesDesired,
439 storageClassesConfirmed, storageClassesConfirmedAt, currentVersionUuid, version, preserveVersion, fileCount, fileSizeTotal } = apiResponse;
442 "owner_uuid": "${ownerUuid}",
443 "created_at": "${createdAt}",
444 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
445 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
446 "modified_at": ${stringify(modifiedAt)},
447 "portable_data_hash": ${stringify(portableDataHash)},
448 "replication_desired": ${stringify(replicationDesired)},
449 "replication_confirmed_at": ${stringify(replicationConfirmedAt)},
450 "replication_confirmed": ${stringify(replicationConfirmed)},
451 "name": ${stringify(name)},
452 "description": ${stringify(description)},
453 "properties": ${stringifyObject(properties)},
454 "delete_at": ${stringify(deleteAt)},
455 "trash_at": ${stringify(trashAt)},
456 "is_trashed": ${stringify(isTrashed)},
457 "storage_classes_desired": ${JSON.stringify(storageClassesDesired, null, 2)},
458 "storage_classes_confirmed": ${JSON.stringify(storageClassesConfirmed, null, 2)},
459 "storage_classes_confirmed_at": ${stringify(storageClassesConfirmedAt)},
460 "current_version_uuid": ${stringify(currentVersionUuid)},
461 "version": ${version},
462 "preserve_version": ${preserveVersion},
463 "file_count": ${fileCount},
464 "file_size_total": ${fileSizeTotal}`;
466 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
469 const groupRequestApiResponse = (apiResponse: ProjectResource): JSX.Element => {
470 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name,
471 description, groupClass, trashAt, isTrashed, deleteAt, properties,
472 canWrite, canManage } = apiResponse;
475 "owner_uuid": "${ownerUuid}",
476 "created_at": "${createdAt}",
477 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
478 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
479 "modified_at": ${stringify(modifiedAt)},
480 "name": ${stringify(name)},
481 "description": ${stringify(description)},
482 "group_class": ${stringify(groupClass)},
483 "trash_at": ${stringify(trashAt)},
484 "is_trashed": ${stringify(isTrashed)},
485 "delete_at": ${stringify(deleteAt)},
486 "properties": ${stringifyObject(properties)},
487 "can_write": ${stringify(canWrite)},
488 "can_manage": ${stringify(canManage)}`;
490 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
493 const repositoryApiResponse = (apiResponse: RepositoryResource): JSX.Element => {
494 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, cloneUrls } = apiResponse;
497 "owner_uuid": "${ownerUuid}",
498 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
499 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
500 "modified_at": ${stringify(modifiedAt)},
501 "name": ${stringify(name)},
502 "created_at": "${createdAt}",
503 "clone_urls": ${stringifyObject(cloneUrls)}`;
505 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
508 const sshKeyApiResponse = (apiResponse: SshKeyResource): JSX.Element => {
509 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, name, authorizedUserUuid, expiresAt } = apiResponse;
512 "owner_uuid": "${ownerUuid}",
513 "authorized_user_uuid": "${authorizedUserUuid}",
514 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
515 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
516 "modified_at": ${stringify(modifiedAt)},
517 "name": ${stringify(name)},
518 "created_at": "${createdAt}",
519 "expires_at": "${expiresAt}"`;
520 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
523 const virtualMachineApiResponse = (apiResponse: VirtualMachinesResource): JSX.Element => {
524 const { uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, hostname } = apiResponse;
526 "hostname": ${stringify(hostname)},
528 "owner_uuid": "${ownerUuid}",
529 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
530 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
531 "modified_at": ${stringify(modifiedAt)},
532 "modified_at": ${stringify(modifiedAt)},
533 "created_at": "${createdAt}"`;
535 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
538 const keepServiceApiResponse = (apiResponse: KeepServiceResource): JSX.Element => {
540 uuid, readOnly, serviceHost, servicePort, serviceSslFlag, serviceType,
541 ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid
545 "owner_uuid": "${ownerUuid}",
546 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
547 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
548 "modified_at": ${stringify(modifiedAt)},
549 "service_host": "${serviceHost}",
550 "service_port": "${servicePort}",
551 "service_ssl_flag": "${stringify(serviceSslFlag)}",
552 "service_type": "${serviceType}",
553 "created_at": "${createdAt}",
554 "read_only": "${stringify(readOnly)}"`;
556 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
559 const userApiResponse = (apiResponse: UserResource): JSX.Element => {
561 uuid, ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid,
562 email, firstName, lastName, username, isActive, isAdmin, prefs,
566 "owner_uuid": "${ownerUuid}",
567 "created_at": "${createdAt}",
568 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
569 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
570 "modified_at": ${stringify(modifiedAt)},
572 "first_name": "${firstName}",
573 "last_name": "${stringify(lastName)}",
574 "username": "${username}",
575 "is_active": "${isActive},
576 "is_admin": "${isAdmin},
577 "prefs": "${stringifyObject(prefs)},
578 "username": "${username}"`;
580 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
583 const apiClientAuthorizationApiResponse = (apiResponse: ApiClientAuthorization): JSX.Element => {
585 uuid, ownerUuid, apiToken, apiClientId, userId, createdByIpAddress, lastUsedByIpAddress,
586 lastUsedAt, expiresAt, scopes, updatedAt, createdAt
590 "owner_uuid": "${ownerUuid}",
591 "api_token": "${stringify(apiToken)}",
592 "api_client_id": "${stringify(apiClientId)}",
593 "created_by_ip_address": "${stringify(createdByIpAddress)}",
594 "last_used_by_ip_address": "${stringify(lastUsedByIpAddress)}",
595 "last_used_at": "${stringify(lastUsedAt)}",
596 "expires_at": "${stringify(expiresAt)}",
597 "created_at": "${stringify(createdAt)}",
598 "updated_at": "${stringify(updatedAt)}",
599 "scopes": "${JSON.stringify(scopes, null, 2)}"`;
601 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
604 const linkApiResponse = (apiResponse: LinkResource): JSX.Element => {
606 uuid, name, headUuid, properties, headKind, tailUuid, tailKind, linkClass,
607 ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid
612 "head_uuid": "${headUuid}",
613 "head_kind": "${headKind}",
614 "tail_uuid": "${tailUuid}",
615 "tail_kind": "${tailKind}",
616 "link_class": "${linkClass}",
617 "owner_uuid": "${ownerUuid}",
618 "created_at": "${stringify(createdAt)}",
619 "modified_at": ${stringify(modifiedAt)},
620 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
621 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)},
622 "properties": "${JSON.stringify(properties, null, 2)}"`;
624 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;
628 const wfApiResponse = (apiResponse: WorkflowResource): JSX.Element => {
631 ownerUuid, createdAt, modifiedAt, modifiedByClientUuid, modifiedByUserUuid, description
636 "owner_uuid": "${ownerUuid}",
637 "created_at": "${stringify(createdAt)}",
638 "modified_at": ${stringify(modifiedAt)},
639 "modified_by_client_uuid": ${stringify(modifiedByClientUuid)},
640 "modified_by_user_uuid": ${stringify(modifiedByUserUuid)}
641 "description": ${stringify(description)}`;
643 return <span style={{ marginLeft: '-15px' }}>{'{'} {response} {'\n'} <span style={{ marginLeft: '-15px' }}>{'}'}</span></span>;