@devtron-labs/devtron-fe-common-lib 0.0.33 → 0.0.34-beta-2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import { TeamList, ResponseType, DeploymentNodeType } from './Types';
1
+ import { TeamList, ResponseType, DeploymentNodeType, CDMaterialServiceEnum, CDMaterialServiceQueryParams, CDMaterialResponseType } from './Types';
2
2
  export declare const getTeamListMin: () => Promise<TeamList>;
3
3
  interface UserRole extends ResponseType {
4
4
  result?: {
@@ -13,7 +13,7 @@ export declare const SourceTypeMap: {
13
13
  };
14
14
  export declare function getUserRole(appName?: string): Promise<UserRole>;
15
15
  export declare function setImageTags(request: any, pipelineId: number, artifactId: number): Promise<ResponseType>;
16
- export declare const getCDMaterials: (cdMaterialId: any, stageType: DeploymentNodeType, abortSignal: AbortSignal, isApprovalNode?: boolean, imageTag?: string) => Promise<any>;
16
+ export declare const genericCDMaterialsService: (serviceType: CDMaterialServiceEnum, cdMaterialID: number, stage: DeploymentNodeType, signal: AbortSignal, queryParams?: CDMaterialServiceQueryParams) => Promise<CDMaterialResponseType>;
17
17
  export declare function extractImage(image: string): string;
18
18
  export declare function createGitCommitUrl(url: string, revision: string): string;
19
19
  export {};
@@ -19,6 +19,7 @@ export declare const ROUTES: {
19
19
  PROJECT_LIST_MIN: string;
20
20
  USER_CHECK_ROLE: string;
21
21
  IMAGE_TAGGING: string;
22
+ CD_MATERIAL_GET: string;
22
23
  };
23
24
  export declare enum KEY_VALUE {
24
25
  KEY = "key",
@@ -1,6 +1,6 @@
1
1
  import React, { ReactNode, CSSProperties } from 'react';
2
2
  import { Placement } from 'tippy.js';
3
- import { ImageComment, ReleaseTag } from "./ImageTags.Types";
3
+ import { ImageComment, ReleaseTag } from './ImageTags.Types';
4
4
  export interface ResponseType {
5
5
  code: number;
6
6
  status: string;
@@ -223,6 +223,30 @@ export interface CDMaterialType {
223
223
  imageReleaseTags?: ReleaseTag[];
224
224
  artifactStatus?: string;
225
225
  filterState: FilterStates;
226
+ scanToolId?: number;
227
+ appliedFiltersTimestamp?: string;
228
+ appliedFilters?: FilterConditionsListType[];
229
+ appliedFiltersState?: FilterStates;
230
+ createdTime?: string;
231
+ deployed?: boolean;
232
+ }
233
+ export declare enum CDMaterialServiceEnum {
234
+ ROLLBACK = "rollback",
235
+ CD_MATERIALS = "cd-materials"
236
+ }
237
+ export declare enum CDMaterialResourceQuery {
238
+ PENDING_APPROVAL = "PENDING_APPROVAL"
239
+ }
240
+ export declare enum CDMaterialFilterQuery {
241
+ RESOURCE = "ELIGIBLE_RESOURCES",
242
+ ALL = "ALL_RESOURCES"
243
+ }
244
+ export interface CDMaterialServiceQueryParams {
245
+ search?: string;
246
+ offset?: number;
247
+ size?: number;
248
+ resource?: CDMaterialResourceQuery;
249
+ filter?: CDMaterialFilterQuery;
226
250
  }
227
251
  export interface CommonNodeAttr {
228
252
  connectingCiPipelineId?: number;
@@ -315,14 +339,34 @@ export interface MaterialInfo {
315
339
  url?: string;
316
340
  type?: string;
317
341
  }
318
- export interface CDMaterialResponseType {
342
+ export declare enum FilterConditionType {
343
+ PASS = 1,
344
+ FAIL = 0
345
+ }
346
+ export interface FilterConditionsInfo {
347
+ conditionType: FilterConditionType;
348
+ expression: string;
349
+ }
350
+ export interface FilterConditionsListType {
351
+ id: number;
352
+ name: string;
353
+ description: string;
354
+ conditions: FilterConditionsInfo[];
355
+ }
356
+ export interface CDMaterialsApprovalInfo {
319
357
  approvalUsers: string[];
320
- materials: any[];
321
358
  userApprovalConfig: UserApprovalConfigType;
322
359
  requestedUserId: number;
360
+ }
361
+ export interface CDMaterialsMetaInfo {
323
362
  tagsEditable: boolean;
324
363
  appReleaseTagNames: string[];
325
364
  hideImageTaggingHardDelete: boolean;
365
+ resourceFilters?: FilterConditionsListType[];
366
+ totalCount: number;
367
+ }
368
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
369
+ materials: CDMaterialType[];
326
370
  }
327
371
  export interface InputDetailType {
328
372
  label: string;
package/dist/index.js CHANGED
@@ -44,6 +44,7 @@ var ROUTES = {
44
44
  PROJECT_LIST_MIN: 'team/autocomplete',
45
45
  USER_CHECK_ROLE: 'user/check/roles',
46
46
  IMAGE_TAGGING: 'app/image-tagging',
47
+ CD_MATERIAL_GET: 'app/cd-pipeline'
47
48
  };
48
49
  exports.KEY_VALUE = void 0;
49
50
  (function (KEY_VALUE) {
@@ -430,13 +431,32 @@ exports.FilterStates = void 0;
430
431
  FilterStates[FilterStates["BLOCKED"] = 1] = "BLOCKED";
431
432
  FilterStates[FilterStates["ERROR"] = 2] = "ERROR";
432
433
  })(exports.FilterStates || (exports.FilterStates = {}));
434
+ exports.CDMaterialServiceEnum = void 0;
435
+ (function (CDMaterialServiceEnum) {
436
+ CDMaterialServiceEnum["ROLLBACK"] = "rollback";
437
+ CDMaterialServiceEnum["CD_MATERIALS"] = "cd-materials";
438
+ })(exports.CDMaterialServiceEnum || (exports.CDMaterialServiceEnum = {}));
439
+ exports.CDMaterialResourceQuery = void 0;
440
+ (function (CDMaterialResourceQuery) {
441
+ CDMaterialResourceQuery["PENDING_APPROVAL"] = "PENDING_APPROVAL";
442
+ })(exports.CDMaterialResourceQuery || (exports.CDMaterialResourceQuery = {}));
443
+ exports.CDMaterialFilterQuery = void 0;
444
+ (function (CDMaterialFilterQuery) {
445
+ CDMaterialFilterQuery["RESOURCE"] = "ELIGIBLE_RESOURCES";
446
+ CDMaterialFilterQuery["ALL"] = "ALL_RESOURCES";
447
+ })(exports.CDMaterialFilterQuery || (exports.CDMaterialFilterQuery = {}));
433
448
  exports.DeploymentAppTypes = void 0;
434
449
  (function (DeploymentAppTypes) {
435
450
  DeploymentAppTypes["HELM"] = "helm";
436
451
  DeploymentAppTypes["GITOPS"] = "argo_cd";
437
452
  DeploymentAppTypes["MANIFEST_DOWNLOAD"] = "manifest_download";
438
453
  DeploymentAppTypes["MANIFEST_PUSH"] = "manifest_push";
439
- })(exports.DeploymentAppTypes || (exports.DeploymentAppTypes = {}));
454
+ })(exports.DeploymentAppTypes || (exports.DeploymentAppTypes = {}));
455
+ exports.FilterConditionType = void 0;
456
+ (function (FilterConditionType) {
457
+ FilterConditionType[FilterConditionType["PASS"] = 1] = "PASS";
458
+ FilterConditionType[FilterConditionType["FAIL"] = 0] = "FAIL";
459
+ })(exports.FilterConditionType || (exports.FilterConditionType = {}));
440
460
 
441
461
  var responseMessages = {
442
462
  100: 'Continue',
@@ -10071,7 +10091,7 @@ function CustomInput(_a) {
10071
10091
  return (jsxRuntime.jsxs("div", __assign({ className: "flex column left top" }, { children: [jsxRuntime.jsx("label", __assign({ className: "form__label ".concat(labelClassName) }, { children: label })), jsxRuntime.jsx("input", { "data-testid": dataTestid, type: type, name: name, autoComplete: "off", className: "form__input", onChange: function (e) {
10072
10092
  e.persist();
10073
10093
  onChange(e);
10074
- }, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, value: value, disabled: disabled, tabIndex: tabIndex }), handleError(error).map(function (err) { return (jsxRuntime.jsxs("div", __assign({ className: "form__error" }, { children: [jsxRuntime.jsx(SvgIcWarning, { className: "form__icon form__icon--error" }), err] }))); })] })));
10094
+ }, onBlur: onBlur, onFocus: onFocus, placeholder: placeholder, value: value, disabled: disabled, tabIndex: tabIndex }), handleError(error).map(function (err) { return (jsxRuntime.jsxs("div", __assign({ className: "form__error" }, { children: [jsxRuntime.jsx(SvgIcWarning, { className: "form__icon form__icon--error" }), err] }), err)); })] })));
10075
10095
  }
10076
10096
  function handleUTCTime(ts, isRelativeTime) {
10077
10097
  if (isRelativeTime === void 0) { isRelativeTime = false; }
@@ -22683,77 +22703,167 @@ function getUserRole(appName) {
22683
22703
  function setImageTags(request, pipelineId, artifactId) {
22684
22704
  return post("".concat(ROUTES.IMAGE_TAGGING, "/").concat(pipelineId, "/").concat(artifactId), request);
22685
22705
  }
22686
- // TODO: Add enum for filterState as well
22687
- var getCDMaterials = function (cdMaterialId, stageType, abortSignal, isApprovalNode, imageTag) {
22688
- var URL = (!imageTag) ? "app/cd-pipeline/".concat(cdMaterialId, "/material?stage=").concat(stageMap[stageType]) : "app/cd-pipeline/".concat(cdMaterialId, "/material?stage=").concat(stageMap[stageType], "&search=").concat(imageTag);
22689
- return get(URL, {
22690
- signal: abortSignal,
22691
- }).then(function (response) {
22692
- var _a;
22693
- var artifacts = (_a = response.result.ci_artifacts) !== null && _a !== void 0 ? _a : [];
22694
- if (!response.result) {
22695
- return {
22696
- materials: [],
22697
- };
22706
+ var processURL = function (url, params) {
22707
+ var validParams = Object.keys(params).filter(function (key) {
22708
+ return params[key] != null;
22709
+ });
22710
+ if (!validParams.length) {
22711
+ return url;
22712
+ }
22713
+ var queryString = validParams
22714
+ .map(function (key) {
22715
+ if (Array.isArray(params[key])) {
22716
+ return "".concat(key, "=").concat(params[key].join(','));
22698
22717
  }
22699
- else {
22700
- var materials = artifacts.map(function (material, index) {
22701
- var _a;
22702
- var artifactStatusValue = '';
22703
- var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22704
- return {
22705
- index: index,
22706
- id: material.id,
22707
- deployedTime: material.deployed_time
22708
- ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22709
- : 'Not Deployed',
22710
- deployedBy: material.deployedBy,
22711
- wfrId: material.wfrId,
22712
- image: extractImage(material.image),
22713
- showChanges: false,
22714
- vulnerabilities: [],
22715
- buildTime: material.build_time || '',
22716
- tab: CDModalTab.Changes,
22717
- showSourceInfo: false,
22718
- deployed: material.deployed || false,
22719
- latest: material.latest || false,
22720
- vulnerabilitiesLoading: true,
22721
- scanned: material.scanned,
22722
- scanEnabled: material.scanEnabled,
22723
- isSelected: !material.vulnerable && filterState === exports.FilterStates.ALLOWED && index === 0,
22724
- vulnerable: material.vulnerable,
22725
- runningOnParentCd: material.runningOnParentCd,
22726
- artifactStatus: artifactStatusValue,
22727
- userApprovalMetadata: material.userApprovalMetadata,
22728
- triggeredBy: material.triggeredBy,
22729
- isVirtualEnvironment: material.isVirtualEnvironment,
22730
- imageComment: material.imageComment,
22731
- imageReleaseTags: material.imageReleaseTags,
22732
- materialInfo: material.material_info
22733
- ? material.material_info.map(function (mat) {
22734
- return {
22735
- modifiedTime: mat.modifiedTime ? moment(mat.modifiedTime).format("ddd, DD MMM YYYY, hh:mm A") : '',
22736
- commitLink: createGitCommitUrl(mat.url, mat.revision),
22737
- author: mat.author || '',
22738
- message: mat.message || '',
22739
- revision: mat.revision || '',
22740
- tag: mat.tag || '',
22741
- webhookData: mat.webhookData || '',
22742
- url: mat.url || '',
22743
- branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22744
- ? material.ciConfigureSourceValue
22745
- : mat.branch) || '',
22746
- type: material.ciConfigureSourceType || '',
22747
- };
22748
- })
22749
- : [],
22750
- filterState: filterState,
22751
- };
22752
- });
22753
- return {
22754
- materials: materials
22755
- };
22718
+ return "".concat(key, "=").concat(params[key]);
22719
+ })
22720
+ .join('&');
22721
+ return "".concat(url, "?").concat(queryString);
22722
+ };
22723
+ var cdMaterialListModal = function (artifacts, offset, artifactId, artifactStatus) {
22724
+ if (!artifacts || !artifacts.length)
22725
+ return [];
22726
+ var markFirstSelected = offset === 0;
22727
+ var startIndex = offset;
22728
+ var isImageMarked = false;
22729
+ var materials = artifacts.map(function (material, index) {
22730
+ var _a, _b, _c, _d, _e;
22731
+ var artifactStatusValue = '';
22732
+ var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22733
+ if (artifactId && artifactStatus && material.id === artifactId) {
22734
+ artifactStatusValue = artifactStatus;
22756
22735
  }
22736
+ var selectImage = !isImageMarked && markFirstSelected && filterState === exports.FilterStates.ALLOWED ? !material.vulnerable : false;
22737
+ if (selectImage) {
22738
+ isImageMarked = true;
22739
+ }
22740
+ return {
22741
+ index: startIndex + index,
22742
+ id: material.id,
22743
+ deployedTime: material.deployed_time
22744
+ ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22745
+ : 'Not Deployed',
22746
+ deployedBy: material.deployedBy,
22747
+ wfrId: material.wfrId,
22748
+ tab: CDModalTab.Changes,
22749
+ image: extractImage(material.image),
22750
+ showChanges: false,
22751
+ vulnerabilities: [],
22752
+ buildTime: material.build_time || '',
22753
+ isSelected: selectImage,
22754
+ showSourceInfo: false,
22755
+ deployed: material.deployed || false,
22756
+ latest: material.latest || false,
22757
+ vulnerabilitiesLoading: true,
22758
+ scanned: material.scanned,
22759
+ scanEnabled: material.scanEnabled,
22760
+ vulnerable: material.vulnerable,
22761
+ runningOnParentCd: material.runningOnParentCd,
22762
+ artifactStatus: artifactStatusValue,
22763
+ userApprovalMetadata: material.userApprovalMetadata,
22764
+ triggeredBy: material.triggeredBy,
22765
+ isVirtualEnvironment: material.isVirtualEnvironment,
22766
+ imageComment: material.imageComment,
22767
+ imageReleaseTags: material.imageReleaseTags,
22768
+ // It is going to be null but required in type so can't remove
22769
+ lastExecution: material.lastExecution,
22770
+ materialInfo: material.material_info
22771
+ ? material.material_info.map(function (mat) {
22772
+ return {
22773
+ modifiedTime: mat.modifiedTime
22774
+ ? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
22775
+ : '',
22776
+ commitLink: createGitCommitUrl(mat.url, mat.revision),
22777
+ author: mat.author || '',
22778
+ message: mat.message || '',
22779
+ revision: mat.revision || '',
22780
+ tag: mat.tag || '',
22781
+ webhookData: mat.webhookData || '',
22782
+ url: mat.url || '',
22783
+ branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22784
+ ? material.ciConfigureSourceValue
22785
+ : mat.branch) || '',
22786
+ type: material.ciConfigureSourceType || '',
22787
+ };
22788
+ })
22789
+ : [],
22790
+ filterState: filterState,
22791
+ appliedFiltersTimestamp: (_b = material.appliedFiltersTimestamp) !== null && _b !== void 0 ? _b : '',
22792
+ appliedFilters: (_c = material.appliedFilters) !== null && _c !== void 0 ? _c : [],
22793
+ appliedFiltersState: (_d = material.appliedFiltersState) !== null && _d !== void 0 ? _d : exports.FilterStates.ALLOWED,
22794
+ createdTime: (_e = material.createdTime) !== null && _e !== void 0 ? _e : '',
22795
+ };
22796
+ });
22797
+ return materials;
22798
+ };
22799
+ var processCDMaterialsApprovalInfo = function (enableApproval, cdMaterialsResult) {
22800
+ if (!enableApproval) {
22801
+ return {
22802
+ approvalUsers: [],
22803
+ userApprovalConfig: null,
22804
+ requestedUserId: 0,
22805
+ };
22806
+ }
22807
+ return {
22808
+ approvalUsers: cdMaterialsResult.approvalUsers,
22809
+ userApprovalConfig: cdMaterialsResult.userApprovalConfig,
22810
+ requestedUserId: cdMaterialsResult.requestedUserId,
22811
+ };
22812
+ };
22813
+ var processCDMaterialsMetaInfo = function (cdMaterialsResult) {
22814
+ var _a, _b;
22815
+ if (!cdMaterialsResult) {
22816
+ return {
22817
+ tagsEditable: false,
22818
+ appReleaseTagNames: [],
22819
+ hideImageTaggingHardDelete: false,
22820
+ resourceFilters: [],
22821
+ totalCount: 0,
22822
+ };
22823
+ }
22824
+ return {
22825
+ appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
22826
+ tagsEditable: cdMaterialsResult.tagsEditable,
22827
+ hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
22828
+ resourceFilters: (_a = cdMaterialsResult.resourceFilters) !== null && _a !== void 0 ? _a : [],
22829
+ totalCount: (_b = cdMaterialsResult.totalCount) !== null && _b !== void 0 ? _b : 0,
22830
+ };
22831
+ };
22832
+ var processCDMaterialServiceResponse = function (cdMaterialsResult, stage, offset, filter) {
22833
+ if (!cdMaterialsResult) {
22834
+ return __assign(__assign({ materials: [] }, processCDMaterialsMetaInfo(cdMaterialsResult)), processCDMaterialsApprovalInfo(false, cdMaterialsResult));
22835
+ }
22836
+ var materials = cdMaterialListModal(cdMaterialsResult.ci_artifacts, offset !== null && offset !== void 0 ? offset : 0, cdMaterialsResult.latest_wf_artifact_id, cdMaterialsResult.latest_wf_artifact_status);
22837
+ var approvalInfo = processCDMaterialsApprovalInfo(stage === exports.DeploymentNodeType.CD || stage === exports.DeploymentNodeType.APPROVAL, cdMaterialsResult);
22838
+ var metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult);
22839
+ // TODO: On update of service would remove from here
22840
+ var filteredMaterials = filter && filter === exports.CDMaterialFilterQuery.RESOURCE
22841
+ ? materials.filter(function (material) {
22842
+ return material.filterState === exports.FilterStates.ALLOWED;
22843
+ })
22844
+ : materials;
22845
+ return __assign(__assign({ materials: filteredMaterials }, approvalInfo), metaInfo);
22846
+ };
22847
+ var getSanitizedQueryParams = function (queryParams) {
22848
+ queryParams.filter; var rest = __rest(queryParams, ["filter"]);
22849
+ return rest;
22850
+ };
22851
+ var genericCDMaterialsService = function (serviceType, cdMaterialID, stage, signal, queryParams) {
22852
+ if (queryParams === void 0) { queryParams = {}; }
22853
+ // TODO: On update of service would remove from here
22854
+ var manipulatedParams = getSanitizedQueryParams(queryParams);
22855
+ var URL;
22856
+ switch (serviceType) {
22857
+ case exports.CDMaterialServiceEnum.ROLLBACK:
22858
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material/rollback"), manipulatedParams);
22859
+ break;
22860
+ // Meant for handling getCDMaterialList
22861
+ default:
22862
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material"), __assign(__assign({}, manipulatedParams), { stage: stageMap[stage] }));
22863
+ break;
22864
+ }
22865
+ return get(URL, { signal: signal }).then(function (response) {
22866
+ return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter);
22757
22867
  });
22758
22868
  };
22759
22869
  function extractImage(image) {
@@ -23135,6 +23245,7 @@ var ImageTagsContainer = function (_a) {
23135
23245
  var _o = __read(React.useState(false), 2), isSuperAdmin = _o[0], setSuperAdmin = _o[1];
23136
23246
  var _p = __read(React.useState(''), 2), descriptionValidationMessage = _p[0], setDescriptionValidationMessage = _p[1];
23137
23247
  var _q = __read(React.useState(''), 2), textInput = _q[0], setTextInput = _q[1];
23248
+ var _r = __read(React.useState(false), 2), loading = _r[0], setLoading = _r[1];
23138
23249
  React.useEffect(function () {
23139
23250
  initialise();
23140
23251
  }, []);
@@ -23308,6 +23419,7 @@ var ImageTagsContainer = function (_a) {
23308
23419
  hardDeleteTags: hardDeleteTags,
23309
23420
  };
23310
23421
  // set loading state true
23422
+ setLoading(true);
23311
23423
  setImageTags(payload, ciPipelineId, artifactId)
23312
23424
  .then(function (res) {
23313
23425
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
@@ -23347,6 +23459,9 @@ var ImageTagsContainer = function (_a) {
23347
23459
  else {
23348
23460
  showError(err);
23349
23461
  }
23462
+ })
23463
+ .finally(function () {
23464
+ setLoading(false);
23350
23465
  });
23351
23466
  return [2 /*return*/];
23352
23467
  });
@@ -23397,10 +23512,10 @@ var ImageTagsContainer = function (_a) {
23397
23512
  }, tagId: tag.id, softDeleteTags: softDeleteTags, isSuperAdmin: isSuperAdmin, duplicateTag: tag === null || tag === void 0 ? void 0 : tag.duplicateTag, hideHardDelete: hideHardDelete }, tag.id)); }) })), showTagsWarning && (jsxRuntime.jsxs("div", __assign({ className: "cn-7 mb-8 flex left" }, { children: [jsxRuntime.jsx(SvgIcInfoFilled, { className: "form__icon--info icon-dim-16 mr-2" }), "Tags cannot be edited/removed later"] }))), jsxRuntime.jsx("div", __assign({ className: "cn-7 mt-12" }, { children: "Comment" })), jsxRuntime.jsx("div", __assign({ className: "flex left flex-wrap dc__gap-8 w-100 mt-6 mb-12", "data-testid": "add-image-comment-text-area" }, { children: jsxRuntime.jsx("textarea", { value: newDescription, onChange: handleDescriptionChange, className: "flex left flex-wrap dc__gap-8 dc__description-textarea fs-13", style: { height: '90px !important' } }) })), descriptionValidationMessage !== '' && (jsxRuntime.jsxs("div", __assign({ className: "flex left" }, { children: [jsxRuntime.jsx(SvgIcWarning, { className: "form__icon form__icon--error" }), jsxRuntime.jsx("div", __assign({ className: "form__error" }, { children: descriptionValidationMessage }))] }))), jsxRuntime.jsxs("div", __assign({ className: "w-100 flex right mt-12" }, { children: [jsxRuntime.jsx("button", __assign({ className: "cta flex cancel h-32 lh-32-imp", type: "button", onClick: function (e) {
23398
23513
  stopPropagation(e);
23399
23514
  handleCancel();
23400
- } }, { children: "Cancel" })), jsxRuntime.jsx("button", __assign({ className: "cta flex h-32 lh-32-imp ml-12", "data-testid": "save-tags-button", type: "button", onClick: function (e) {
23515
+ }, disabled: loading }, { children: "Cancel" })), jsxRuntime.jsx("button", __assign({ className: "cta flex h-32 lh-32-imp ml-12", "data-testid": "save-tags-button", type: "button", onClick: function (e) {
23401
23516
  stopPropagation(e);
23402
23517
  onClickSave();
23403
- } }, { children: "Save" }))] }))] }))) : (jsxRuntime.jsxs("div", __assign({ className: "top br-4 bcn-0 image-tags-container flexbox" }, { children: [jsxRuntime.jsx("div", __assign({ className: "flex left image-tag-left-border w-100 mt-8 mb-8 pr-10 pl-10", "data-testid": "image-tags-container-hover" }, { children: jsxRuntime.jsxs("div", __assign({ className: 'w-100' }, { children: [initialDescription && jsxRuntime.jsx("div", __assign({ className: "mb-6 fs-13 lh-20 dc__word-break-all" }, { children: initialDescription })), jsxRuntime.jsx("div", __assign({ className: "flex-wrap flex left" }, { children: initialTags === null || initialTags === void 0 ? void 0 : initialTags.map(function (tag, index) { return (jsxRuntime.jsx(ImageTagButton, { text: tag === null || tag === void 0 ? void 0 : tag.tagName, isSoftDeleted: tag === null || tag === void 0 ? void 0 : tag.deleted, isEditing: isEditing, onSoftDeleteClick: function (e) {
23518
+ }, disabled: loading }, { children: loading ? jsxRuntime.jsx(Progressing, {}) : 'Save' }))] }))] }))) : (jsxRuntime.jsxs("div", __assign({ className: "top br-4 bcn-0 image-tags-container flexbox" }, { children: [jsxRuntime.jsx("div", __assign({ className: "flex left image-tag-left-border w-100 mt-8 mb-8 pr-10 pl-10", "data-testid": "image-tags-container-hover" }, { children: jsxRuntime.jsxs("div", __assign({ className: 'w-100' }, { children: [initialDescription && jsxRuntime.jsx("div", __assign({ className: "mb-6 fs-13 lh-20 dc__word-break-all" }, { children: initialDescription })), jsxRuntime.jsx("div", __assign({ className: "flex-wrap flex left" }, { children: initialTags === null || initialTags === void 0 ? void 0 : initialTags.map(function (tag, index) { return (jsxRuntime.jsx(ImageTagButton, { text: tag === null || tag === void 0 ? void 0 : tag.tagName, isSoftDeleted: tag === null || tag === void 0 ? void 0 : tag.deleted, isEditing: isEditing, onSoftDeleteClick: function (e) {
23404
23519
  stopPropagation(e);
23405
23520
  handleTagSoftDelete(index);
23406
23521
  }, onHardDeleteClick: function (e) {
@@ -23685,9 +23800,9 @@ exports.closeOnEscKeyPressed = closeOnEscKeyPressed;
23685
23800
  exports.copyToClipboard = copyToClipboard;
23686
23801
  exports.createGitCommitUrl = createGitCommitUrl;
23687
23802
  exports.extractImage = extractImage;
23803
+ exports.genericCDMaterialsService = genericCDMaterialsService;
23688
23804
  exports.get = get;
23689
23805
  exports.getAlphabetIcon = getAlphabetIcon;
23690
- exports.getCDMaterials = getCDMaterials;
23691
23806
  exports.getCookie = getCookie;
23692
23807
  exports.getEmptyArrayOfLength = getEmptyArrayOfLength;
23693
23808
  exports.getLoginInfo = getLoginInfo;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devtron-labs/devtron-fe-common-lib",
3
- "version": "0.0.33",
3
+ "version": "0.0.34-beta-2",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -2,7 +2,20 @@ import moment from 'moment';
2
2
  import {get, post} from './Api';
3
3
  import { ROUTES } from './Constants'
4
4
  import { sortCallback } from './Helper';
5
- import { TeamList ,ResponseType, DeploymentNodeType, CDModalTab, FilterStates } from './Types';
5
+ import {
6
+ TeamList,
7
+ ResponseType,
8
+ DeploymentNodeType,
9
+ CDModalTab,
10
+ FilterStates,
11
+ CDMaterialServiceEnum,
12
+ CDMaterialServiceQueryParams,
13
+ CDMaterialResponseType,
14
+ CDMaterialsMetaInfo,
15
+ CDMaterialsApprovalInfo,
16
+ CDMaterialFilterQuery,
17
+ CDMaterialType,
18
+ } from './Types'
6
19
 
7
20
  export const getTeamListMin = (): Promise<TeamList> => {
8
21
  // ignore active field
@@ -30,7 +43,7 @@ interface UserRole extends ResponseType {
30
43
  }
31
44
  }
32
45
 
33
- let stageMap = {
46
+ const stageMap = {
34
47
  PRECD: 'PRE',
35
48
  CD: 'DEPLOY',
36
49
  POSTCD: 'POST',
@@ -51,83 +64,215 @@ export function setImageTags(request, pipelineId: number, artifactId: number){
51
64
  return post(`${ROUTES.IMAGE_TAGGING}/${pipelineId}/${artifactId}`,request )
52
65
  }
53
66
 
54
- // TODO: Add enum for filterState as well
55
- export const getCDMaterials = (
56
- cdMaterialId,
57
- stageType: DeploymentNodeType,
58
- abortSignal: AbortSignal,
59
- isApprovalNode?: boolean,
60
- imageTag?: string): Promise<any> => {
61
- const URL = (!imageTag) ? `app/cd-pipeline/${cdMaterialId}/material?stage=${stageMap[stageType]}` : `app/cd-pipeline/${cdMaterialId}/material?stage=${stageMap[stageType]}&search=${imageTag}`
62
-
63
- return get(URL, {
64
- signal: abortSignal,
65
- }).then((response) => {
66
- let artifacts = response.result.ci_artifacts ?? []
67
- if (!response.result) {
68
- return {
69
- materials: [],
67
+ const processURL = (url: string, params: object) => {
68
+ const validParams = Object.keys(params).filter((key) => {
69
+ return params[key] != null
70
+ })
71
+
72
+ if (!validParams.length) {
73
+ return url
74
+ }
75
+
76
+ const queryString = validParams
77
+ .map((key) => {
78
+ if (Array.isArray(params[key])) {
79
+ return `${key}=${params[key].join(',')}`
70
80
  }
81
+ return `${key}=${params[key]}`
82
+ })
83
+ .join('&')
84
+
85
+ return `${url}?${queryString}`
86
+ }
87
+
88
+ const cdMaterialListModal = (artifacts: any[], offset: number, artifactId?: number, artifactStatus?: string) => {
89
+ if (!artifacts || !artifacts.length) return []
90
+
91
+ const markFirstSelected = offset === 0
92
+ const startIndex = offset
93
+ let isImageMarked = false
94
+
95
+ const materials = artifacts.map((material, index) => {
96
+ let artifactStatusValue = ''
97
+ const filterState = material.filterState ?? FilterStates.ALLOWED
98
+
99
+ if (artifactId && artifactStatus && material.id === artifactId) {
100
+ artifactStatusValue = artifactStatus
71
101
  }
72
- else {
73
- const materials = artifacts.map((material, index) => {
74
- let artifactStatusValue = ''
75
- const filterState = material.filterState ?? FilterStates.ALLOWED
76
-
77
- return {
78
- index,
79
- id: material.id,
80
- deployedTime: material.deployed_time
81
- ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
82
- : 'Not Deployed',
83
- deployedBy: material.deployedBy,
84
- wfrId: material.wfrId,
85
- image: extractImage(material.image),
86
- showChanges: false,
87
- vulnerabilities: [],
88
- buildTime: material.build_time || '',
89
- tab: CDModalTab.Changes,
90
- showSourceInfo: false,
91
- deployed: material.deployed || false,
92
- latest: material.latest || false,
93
- vulnerabilitiesLoading: true,
94
- scanned: material.scanned,
95
- scanEnabled: material.scanEnabled,
96
- isSelected: !material.vulnerable && filterState === FilterStates.ALLOWED && index === 0,
97
- vulnerable: material.vulnerable,
98
- runningOnParentCd: material.runningOnParentCd,
99
- artifactStatus: artifactStatusValue,
100
- userApprovalMetadata: material.userApprovalMetadata,
101
- triggeredBy: material.triggeredBy,
102
- isVirtualEnvironment: material.isVirtualEnvironment,
103
- imageComment: material.imageComment,
104
- imageReleaseTags: material.imageReleaseTags,
105
- materialInfo: material.material_info
106
- ? material.material_info.map((mat) => {
107
- return {
108
- modifiedTime: mat.modifiedTime ? moment(mat.modifiedTime).format("ddd, DD MMM YYYY, hh:mm A") : '',
109
- commitLink: createGitCommitUrl(mat.url, mat.revision),
110
- author: mat.author || '',
111
- message: mat.message || '',
112
- revision: mat.revision || '',
113
- tag: mat.tag || '',
114
- webhookData: mat.webhookData || '',
115
- url: mat.url || '',
116
- branch:
117
- (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
118
- ? material.ciConfigureSourceValue
119
- : mat.branch) || '',
120
- type: material.ciConfigureSourceType || '',
121
- }
122
- })
123
- : [],
124
- filterState,
125
- }
126
- })
127
- return {
128
- materials: materials
129
- }
102
+
103
+ const selectImage =
104
+ !isImageMarked && markFirstSelected && filterState === FilterStates.ALLOWED ? !material.vulnerable : false
105
+ if (selectImage) {
106
+ isImageMarked = true
107
+ }
108
+
109
+ return {
110
+ index: startIndex + index,
111
+ id: material.id,
112
+ deployedTime: material.deployed_time
113
+ ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
114
+ : 'Not Deployed',
115
+ deployedBy: material.deployedBy,
116
+ wfrId: material.wfrId,
117
+ tab: CDModalTab.Changes,
118
+ image: extractImage(material.image),
119
+ showChanges: false,
120
+ vulnerabilities: [],
121
+ buildTime: material.build_time || '',
122
+ isSelected: selectImage,
123
+ showSourceInfo: false,
124
+ deployed: material.deployed || false,
125
+ latest: material.latest || false,
126
+ vulnerabilitiesLoading: true,
127
+ scanned: material.scanned,
128
+ scanEnabled: material.scanEnabled,
129
+ vulnerable: material.vulnerable,
130
+ runningOnParentCd: material.runningOnParentCd,
131
+ artifactStatus: artifactStatusValue,
132
+ userApprovalMetadata: material.userApprovalMetadata,
133
+ triggeredBy: material.triggeredBy,
134
+ isVirtualEnvironment: material.isVirtualEnvironment,
135
+ imageComment: material.imageComment,
136
+ imageReleaseTags: material.imageReleaseTags,
137
+ // It is going to be null but required in type so can't remove
138
+ lastExecution: material.lastExecution,
139
+ materialInfo: material.material_info
140
+ ? material.material_info.map((mat) => {
141
+ return {
142
+ modifiedTime: mat.modifiedTime
143
+ ? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
144
+ : '',
145
+ commitLink: createGitCommitUrl(mat.url, mat.revision),
146
+ author: mat.author || '',
147
+ message: mat.message || '',
148
+ revision: mat.revision || '',
149
+ tag: mat.tag || '',
150
+ webhookData: mat.webhookData || '',
151
+ url: mat.url || '',
152
+ branch:
153
+ (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
154
+ ? material.ciConfigureSourceValue
155
+ : mat.branch) || '',
156
+ type: material.ciConfigureSourceType || '',
157
+ }
158
+ })
159
+ : [],
160
+ filterState,
161
+ appliedFiltersTimestamp: material.appliedFiltersTimestamp ?? '',
162
+ appliedFilters: material.appliedFilters ?? [],
163
+ appliedFiltersState: material.appliedFiltersState ?? FilterStates.ALLOWED,
164
+ createdTime: material.createdTime ?? '',
165
+ }
166
+ })
167
+ return materials
168
+ }
169
+
170
+ const processCDMaterialsApprovalInfo = (enableApproval: boolean, cdMaterialsResult): CDMaterialsApprovalInfo => {
171
+ if (!enableApproval) {
172
+ return {
173
+ approvalUsers: [],
174
+ userApprovalConfig: null,
175
+ requestedUserId: 0,
176
+ }
177
+ }
178
+
179
+ return {
180
+ approvalUsers: cdMaterialsResult.approvalUsers,
181
+ userApprovalConfig: cdMaterialsResult.userApprovalConfig,
182
+ requestedUserId: cdMaterialsResult.requestedUserId,
183
+ }
184
+ }
185
+
186
+ const processCDMaterialsMetaInfo = (cdMaterialsResult): CDMaterialsMetaInfo => {
187
+ if (!cdMaterialsResult) {
188
+ return {
189
+ tagsEditable: false,
190
+ appReleaseTagNames: [],
191
+ hideImageTaggingHardDelete: false,
192
+ resourceFilters: [],
193
+ totalCount: 0,
130
194
  }
195
+ }
196
+
197
+ return {
198
+ appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
199
+ tagsEditable: cdMaterialsResult.tagsEditable,
200
+ hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
201
+ resourceFilters: cdMaterialsResult.resourceFilters ?? [],
202
+ totalCount: cdMaterialsResult.totalCount ?? 0,
203
+ }
204
+ }
205
+
206
+ const processCDMaterialServiceResponse = (
207
+ cdMaterialsResult,
208
+ stage: DeploymentNodeType,
209
+ offset: number,
210
+ filter: CDMaterialFilterQuery,
211
+ ): CDMaterialResponseType => {
212
+ if (!cdMaterialsResult) {
213
+ return {
214
+ materials: [],
215
+ ...processCDMaterialsMetaInfo(cdMaterialsResult),
216
+ ...processCDMaterialsApprovalInfo(false, cdMaterialsResult),
217
+ }
218
+ }
219
+
220
+ const materials = cdMaterialListModal(
221
+ cdMaterialsResult.ci_artifacts,
222
+ offset ?? 0,
223
+ cdMaterialsResult.latest_wf_artifact_id,
224
+ cdMaterialsResult.latest_wf_artifact_status,
225
+ )
226
+ const approvalInfo = processCDMaterialsApprovalInfo(
227
+ stage === DeploymentNodeType.CD || stage === DeploymentNodeType.APPROVAL,
228
+ cdMaterialsResult,
229
+ )
230
+ const metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult)
231
+
232
+ // TODO: On update of service would remove from here
233
+ const filteredMaterials =
234
+ filter && filter === CDMaterialFilterQuery.RESOURCE
235
+ ? materials.filter((material) => {
236
+ return material.filterState === FilterStates.ALLOWED
237
+ })
238
+ : materials
239
+
240
+ return {
241
+ materials: filteredMaterials,
242
+ ...approvalInfo,
243
+ ...metaInfo,
244
+ }
245
+ }
246
+
247
+ const getSanitizedQueryParams = (queryParams: CDMaterialServiceQueryParams): CDMaterialServiceQueryParams => {
248
+ const { filter, ...rest } = queryParams
249
+ return rest
250
+ }
251
+
252
+ export const genericCDMaterialsService = (
253
+ serviceType: CDMaterialServiceEnum,
254
+ cdMaterialID: number,
255
+ stage: DeploymentNodeType,
256
+ signal: AbortSignal,
257
+ queryParams: CDMaterialServiceQueryParams = {},
258
+ ): Promise<CDMaterialResponseType> => {
259
+ // TODO: On update of service would remove from here
260
+ const manipulatedParams = getSanitizedQueryParams(queryParams)
261
+
262
+ let URL
263
+ switch (serviceType) {
264
+ case CDMaterialServiceEnum.ROLLBACK:
265
+ URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material/rollback`, manipulatedParams)
266
+ break
267
+
268
+ // Meant for handling getCDMaterialList
269
+ default:
270
+ URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material`, { ...manipulatedParams, stage: stageMap[stage] })
271
+ break
272
+ }
273
+
274
+ return get(URL, { signal }).then((response) => {
275
+ return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter)
131
276
  })
132
277
  }
133
278
 
@@ -24,6 +24,7 @@ export const ROUTES = {
24
24
  PROJECT_LIST_MIN: 'team/autocomplete',
25
25
  USER_CHECK_ROLE: 'user/check/roles',
26
26
  IMAGE_TAGGING:'app/image-tagging',
27
+ CD_MATERIAL_GET: 'app/cd-pipeline'
27
28
  }
28
29
 
29
30
  export enum KEY_VALUE {
@@ -326,7 +326,7 @@ export function CustomInput({
326
326
  tabIndex={tabIndex}
327
327
  />
328
328
  {handleError(error).map((err) => (
329
- <div className="form__error">
329
+ <div className="form__error" key={err}>
330
330
  <FormError className="form__icon form__icon--error" />
331
331
  {err}
332
332
  </div>
@@ -18,6 +18,7 @@ import { showError, stopPropagation } from './Helper'
18
18
  import { TippyCustomized } from './TippyCustomized'
19
19
  import { setImageTags, getUserRole } from './Common.service'
20
20
  import Tippy from '@tippyjs/react'
21
+ import { Progressing } from './Progressing'
21
22
 
22
23
  export const ImageTagsContainer = ({
23
24
  ciPipelineId,
@@ -47,6 +48,7 @@ export const ImageTagsContainer = ({
47
48
  const [isSuperAdmin, setSuperAdmin] = useState<boolean>(false)
48
49
  const [descriptionValidationMessage, setDescriptionValidationMessage] = useState<string>('')
49
50
  const [textInput, setTextInput] = useState<string>('')
51
+ const [loading, setLoading] = useState<boolean>(false)
50
52
 
51
53
  useEffect(() => {
52
54
  initialise()
@@ -226,6 +228,7 @@ export const ImageTagsContainer = ({
226
228
  }
227
229
 
228
230
  // set loading state true
231
+ setLoading(true)
229
232
  setImageTags(payload, ciPipelineId, artifactId)
230
233
  .then((res) => {
231
234
  const tags = res.result?.imageReleaseTags?.map((tag) => ({
@@ -262,6 +265,9 @@ export const ImageTagsContainer = ({
262
265
  showError(err)
263
266
  }
264
267
  })
268
+ .finally(()=>{
269
+ setLoading(false)
270
+ })
265
271
  }
266
272
 
267
273
  const renderInfoCard = (): JSX.Element => {
@@ -438,6 +444,7 @@ export const ImageTagsContainer = ({
438
444
  stopPropagation(e)
439
445
  handleCancel()
440
446
  }}
447
+ disabled={loading}
441
448
  >
442
449
  Cancel
443
450
  </button>
@@ -449,8 +456,9 @@ export const ImageTagsContainer = ({
449
456
  stopPropagation(e)
450
457
  onClickSave()
451
458
  }}
459
+ disabled={loading}
452
460
  >
453
- Save
461
+ {loading ? <Progressing /> : 'Save'}
454
462
  </button>
455
463
  </div>
456
464
  </div>
@@ -1,6 +1,6 @@
1
1
  import React, { ReactNode, CSSProperties } from 'react'
2
2
  import { Placement } from 'tippy.js'
3
- import { ImageComment, ReleaseTag } from "./ImageTags.Types";
3
+ import { ImageComment, ReleaseTag } from './ImageTags.Types'
4
4
  export interface ResponseType {
5
5
  code: number
6
6
  status: string
@@ -218,7 +218,7 @@ export interface UserApprovalMetadataType {
218
218
  export enum FilterStates {
219
219
  ALLOWED = 0,
220
220
  BLOCKED = 1,
221
- ERROR = 2
221
+ ERROR = 2,
222
222
  }
223
223
 
224
224
  export interface CDMaterialType {
@@ -246,7 +246,36 @@ export interface CDMaterialType {
246
246
  imageComment?: ImageComment
247
247
  imageReleaseTags?: ReleaseTag[]
248
248
  artifactStatus?: string
249
- filterState: FilterStates;
249
+ filterState: FilterStates
250
+ // Not even coming from API but required in CDMaterials for Security which makes its own api call but stores data in CDMaterials
251
+ scanToolId?: number
252
+ appliedFiltersTimestamp?: string
253
+ appliedFilters?: FilterConditionsListType[]
254
+ appliedFiltersState?: FilterStates
255
+ createdTime?: string
256
+ deployed?: boolean
257
+ }
258
+
259
+ export enum CDMaterialServiceEnum {
260
+ ROLLBACK = 'rollback',
261
+ CD_MATERIALS = 'cd-materials',
262
+ }
263
+
264
+ export enum CDMaterialResourceQuery {
265
+ PENDING_APPROVAL = 'PENDING_APPROVAL'
266
+ }
267
+
268
+ export enum CDMaterialFilterQuery {
269
+ RESOURCE = 'ELIGIBLE_RESOURCES',
270
+ ALL = 'ALL_RESOURCES'
271
+ }
272
+
273
+ export interface CDMaterialServiceQueryParams {
274
+ search?: string
275
+ offset?: number
276
+ size?: number
277
+ resource?: CDMaterialResourceQuery
278
+ filter?: CDMaterialFilterQuery
250
279
  }
251
280
 
252
281
  export interface CommonNodeAttr {
@@ -304,7 +333,7 @@ export interface CommonNodeAttr {
304
333
  deploymentAppType?: DeploymentAppTypes
305
334
  isCITriggerBlocked?: boolean
306
335
  ciBlockState?: {
307
- action: any,
336
+ action: any
308
337
  metadataField: string
309
338
  }
310
339
  appReleaseTagNames?: string[]
@@ -315,7 +344,7 @@ export enum DeploymentAppTypes {
315
344
  HELM = 'helm',
316
345
  GITOPS = 'argo_cd',
317
346
  MANIFEST_DOWNLOAD = 'manifest_download',
318
- MANIFEST_PUSH='manifest_push'
347
+ MANIFEST_PUSH = 'manifest_push',
319
348
  }
320
349
 
321
350
  export interface VulnerabilityType {
@@ -345,16 +374,40 @@ export interface MaterialInfo {
345
374
  type?: string
346
375
  }
347
376
 
348
- export interface CDMaterialResponseType {
377
+ export enum FilterConditionType {
378
+ PASS = 1,
379
+ FAIL = 0,
380
+ }
381
+
382
+ export interface FilterConditionsInfo {
383
+ conditionType: FilterConditionType
384
+ expression: string
385
+ }
386
+
387
+ export interface FilterConditionsListType {
388
+ id: number
389
+ name: string
390
+ description: string
391
+ conditions: FilterConditionsInfo[]
392
+ }
393
+
394
+ export interface CDMaterialsApprovalInfo {
349
395
  approvalUsers: string[]
350
- materials: any[]
351
396
  userApprovalConfig: UserApprovalConfigType
352
397
  requestedUserId: number
398
+ }
399
+
400
+ export interface CDMaterialsMetaInfo {
353
401
  tagsEditable: boolean
354
402
  appReleaseTagNames: string[]
355
403
  hideImageTaggingHardDelete: boolean
404
+ resourceFilters?: FilterConditionsListType[]
405
+ totalCount: number
356
406
  }
357
407
 
408
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
409
+ materials: CDMaterialType[]
410
+ }
358
411
 
359
412
  export interface InputDetailType {
360
413
  label: string
@@ -404,7 +457,6 @@ export interface AsyncState<T> {
404
457
  dependencies: any[]
405
458
  }
406
459
 
407
-
408
460
  export interface AsyncOptions {
409
461
  resetOnChange: boolean
410
462
  }