@devtron-labs/devtron-fe-common-lib 0.0.36-beta-1 → 0.0.37-beta-1

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",
@@ -202,6 +202,9 @@ export declare enum FilterStates {
202
202
  BLOCKED = 1,
203
203
  ERROR = 2
204
204
  }
205
+ export declare enum MaterialDataSource {
206
+ EXTERNAL = "ext"
207
+ }
205
208
  export interface CDMaterialType {
206
209
  index: number;
207
210
  id: string;
@@ -228,6 +231,31 @@ export interface CDMaterialType {
228
231
  imageReleaseTags?: ReleaseTag[];
229
232
  artifactStatus?: string;
230
233
  filterState: FilterStates;
234
+ scanToolId?: number;
235
+ appliedFiltersTimestamp?: string;
236
+ appliedFilters?: FilterConditionsListType[];
237
+ appliedFiltersState?: FilterStates;
238
+ createdTime?: string;
239
+ deployed?: boolean;
240
+ dataSource?: MaterialDataSource;
241
+ }
242
+ export declare enum CDMaterialServiceEnum {
243
+ ROLLBACK = "rollback",
244
+ CD_MATERIALS = "cd-materials"
245
+ }
246
+ export declare enum CDMaterialResourceQuery {
247
+ PENDING_APPROVAL = "PENDING_APPROVAL"
248
+ }
249
+ export declare enum CDMaterialFilterQuery {
250
+ RESOURCE = "ELIGIBLE_RESOURCES",
251
+ ALL = "ALL_RESOURCES"
252
+ }
253
+ export interface CDMaterialServiceQueryParams {
254
+ search?: string;
255
+ offset?: number;
256
+ size?: number;
257
+ resource?: CDMaterialResourceQuery;
258
+ filter?: CDMaterialFilterQuery;
231
259
  }
232
260
  export interface CommonNodeAttr {
233
261
  connectingCiPipelineId?: number;
@@ -334,15 +362,20 @@ export interface FilterConditionsListType {
334
362
  description: string;
335
363
  conditions: FilterConditionsInfo[];
336
364
  }
337
- export interface CDMaterialResponseType {
365
+ export interface CDMaterialsApprovalInfo {
338
366
  approvalUsers: string[];
339
- materials: any[];
340
367
  userApprovalConfig: UserApprovalConfigType;
341
368
  requestedUserId: number;
369
+ }
370
+ export interface CDMaterialsMetaInfo {
342
371
  tagsEditable: boolean;
343
372
  appReleaseTagNames: string[];
344
373
  hideImageTaggingHardDelete: boolean;
345
374
  resourceFilters?: FilterConditionsListType[];
375
+ totalCount: number;
376
+ }
377
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
378
+ materials: CDMaterialType[];
346
379
  }
347
380
  export interface InputDetailType {
348
381
  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,6 +431,24 @@ 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.MaterialDataSource = void 0;
435
+ (function (MaterialDataSource) {
436
+ MaterialDataSource["EXTERNAL"] = "ext";
437
+ })(exports.MaterialDataSource || (exports.MaterialDataSource = {}));
438
+ exports.CDMaterialServiceEnum = void 0;
439
+ (function (CDMaterialServiceEnum) {
440
+ CDMaterialServiceEnum["ROLLBACK"] = "rollback";
441
+ CDMaterialServiceEnum["CD_MATERIALS"] = "cd-materials";
442
+ })(exports.CDMaterialServiceEnum || (exports.CDMaterialServiceEnum = {}));
443
+ exports.CDMaterialResourceQuery = void 0;
444
+ (function (CDMaterialResourceQuery) {
445
+ CDMaterialResourceQuery["PENDING_APPROVAL"] = "PENDING_APPROVAL";
446
+ })(exports.CDMaterialResourceQuery || (exports.CDMaterialResourceQuery = {}));
447
+ exports.CDMaterialFilterQuery = void 0;
448
+ (function (CDMaterialFilterQuery) {
449
+ CDMaterialFilterQuery["RESOURCE"] = "ELIGIBLE_RESOURCES";
450
+ CDMaterialFilterQuery["ALL"] = "ALL_RESOURCES";
451
+ })(exports.CDMaterialFilterQuery || (exports.CDMaterialFilterQuery = {}));
433
452
  exports.DeploymentAppTypes = void 0;
434
453
  (function (DeploymentAppTypes) {
435
454
  DeploymentAppTypes["HELM"] = "helm";
@@ -22689,77 +22708,168 @@ function getUserRole(appName) {
22689
22708
  function setImageTags(request, pipelineId, artifactId) {
22690
22709
  return post("".concat(ROUTES.IMAGE_TAGGING, "/").concat(pipelineId, "/").concat(artifactId), request);
22691
22710
  }
22692
- // FIXME: This is only returning materials to cater the case of search in approval but it should be a common function service coming from dashboard.
22693
- var getCDMaterials = function (cdMaterialId, stageType, abortSignal, isApprovalNode, imageTag) {
22694
- 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);
22695
- return get(URL, {
22696
- signal: abortSignal,
22697
- }).then(function (response) {
22698
- var _a;
22699
- var artifacts = (_a = response.result.ci_artifacts) !== null && _a !== void 0 ? _a : [];
22700
- if (!response.result) {
22701
- return {
22702
- materials: [],
22703
- };
22711
+ var processURL = function (url, params) {
22712
+ var validParams = Object.keys(params).filter(function (key) {
22713
+ return params[key] != null;
22714
+ });
22715
+ if (!validParams.length) {
22716
+ return url;
22717
+ }
22718
+ var queryString = validParams
22719
+ .map(function (key) {
22720
+ if (Array.isArray(params[key])) {
22721
+ return "".concat(key, "=").concat(params[key].join(','));
22704
22722
  }
22705
- else {
22706
- var materials = artifacts.map(function (material, index) {
22707
- var _a;
22708
- var artifactStatusValue = '';
22709
- var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22710
- return {
22711
- index: index,
22712
- id: material.id,
22713
- deployedTime: material.deployed_time
22714
- ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22715
- : 'Not Deployed',
22716
- deployedBy: material.deployedBy,
22717
- wfrId: material.wfrId,
22718
- image: extractImage(material.image),
22719
- showChanges: false,
22720
- vulnerabilities: [],
22721
- buildTime: material.build_time || '',
22722
- tab: CDModalTab.Changes,
22723
- showSourceInfo: false,
22724
- deployed: material.deployed || false,
22725
- latest: material.latest || false,
22726
- vulnerabilitiesLoading: true,
22727
- scanned: material.scanned,
22728
- scanEnabled: material.scanEnabled,
22729
- isSelected: !material.vulnerable && filterState === exports.FilterStates.ALLOWED && index === 0,
22730
- vulnerable: material.vulnerable,
22731
- runningOnParentCd: material.runningOnParentCd,
22732
- artifactStatus: artifactStatusValue,
22733
- userApprovalMetadata: material.userApprovalMetadata,
22734
- triggeredBy: material.triggeredBy,
22735
- isVirtualEnvironment: material.isVirtualEnvironment,
22736
- imageComment: material.imageComment,
22737
- imageReleaseTags: material.imageReleaseTags,
22738
- materialInfo: material.material_info
22739
- ? material.material_info.map(function (mat) {
22740
- return {
22741
- modifiedTime: mat.modifiedTime ? moment(mat.modifiedTime).format("ddd, DD MMM YYYY, hh:mm A") : '',
22742
- commitLink: createGitCommitUrl(mat.url, mat.revision),
22743
- author: mat.author || '',
22744
- message: mat.message || '',
22745
- revision: mat.revision || '',
22746
- tag: mat.tag || '',
22747
- webhookData: mat.webhookData || '',
22748
- url: mat.url || '',
22749
- branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22750
- ? material.ciConfigureSourceValue
22751
- : mat.branch) || '',
22752
- type: material.ciConfigureSourceType || '',
22753
- };
22754
- })
22755
- : [],
22756
- filterState: filterState,
22757
- };
22758
- });
22759
- return {
22760
- materials: materials
22761
- };
22723
+ return "".concat(key, "=").concat(params[key]);
22724
+ })
22725
+ .join('&');
22726
+ return "".concat(url, "?").concat(queryString);
22727
+ };
22728
+ var cdMaterialListModal = function (artifacts, offset, artifactId, artifactStatus) {
22729
+ if (!artifacts || !artifacts.length)
22730
+ return [];
22731
+ var markFirstSelected = offset === 0;
22732
+ var startIndex = offset;
22733
+ var isImageMarked = false;
22734
+ var materials = artifacts.map(function (material, index) {
22735
+ var _a, _b, _c, _d, _e, _f;
22736
+ var artifactStatusValue = '';
22737
+ var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22738
+ if (artifactId && artifactStatus && material.id === artifactId) {
22739
+ artifactStatusValue = artifactStatus;
22762
22740
  }
22741
+ var selectImage = !isImageMarked && markFirstSelected && filterState === exports.FilterStates.ALLOWED ? !material.vulnerable : false;
22742
+ if (selectImage) {
22743
+ isImageMarked = true;
22744
+ }
22745
+ return {
22746
+ index: startIndex + index,
22747
+ id: material.id,
22748
+ deployedTime: material.deployed_time
22749
+ ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22750
+ : 'Not Deployed',
22751
+ deployedBy: material.deployedBy,
22752
+ wfrId: material.wfrId,
22753
+ tab: CDModalTab.Changes,
22754
+ image: extractImage(material.image),
22755
+ showChanges: false,
22756
+ vulnerabilities: [],
22757
+ buildTime: material.build_time || '',
22758
+ isSelected: selectImage,
22759
+ showSourceInfo: false,
22760
+ deployed: material.deployed || false,
22761
+ latest: material.latest || false,
22762
+ vulnerabilitiesLoading: true,
22763
+ scanned: material.scanned,
22764
+ scanEnabled: material.scanEnabled,
22765
+ vulnerable: material.vulnerable,
22766
+ runningOnParentCd: material.runningOnParentCd,
22767
+ artifactStatus: artifactStatusValue,
22768
+ userApprovalMetadata: material.userApprovalMetadata,
22769
+ triggeredBy: material.triggeredBy,
22770
+ isVirtualEnvironment: material.isVirtualEnvironment,
22771
+ imageComment: material.imageComment,
22772
+ imageReleaseTags: material.imageReleaseTags,
22773
+ // It is going to be null but required in type so can't remove
22774
+ lastExecution: material.lastExecution,
22775
+ materialInfo: material.material_info
22776
+ ? material.material_info.map(function (mat) {
22777
+ return {
22778
+ modifiedTime: mat.modifiedTime
22779
+ ? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
22780
+ : '',
22781
+ commitLink: createGitCommitUrl(mat.url, mat.revision),
22782
+ author: mat.author || '',
22783
+ message: mat.message || '',
22784
+ revision: mat.revision || '',
22785
+ tag: mat.tag || '',
22786
+ webhookData: mat.webhookData || '',
22787
+ url: mat.url || '',
22788
+ branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22789
+ ? material.ciConfigureSourceValue
22790
+ : mat.branch) || '',
22791
+ type: material.ciConfigureSourceType || '',
22792
+ };
22793
+ })
22794
+ : [],
22795
+ filterState: filterState,
22796
+ appliedFiltersTimestamp: (_b = material.appliedFiltersTimestamp) !== null && _b !== void 0 ? _b : '',
22797
+ appliedFilters: (_c = material.appliedFilters) !== null && _c !== void 0 ? _c : [],
22798
+ appliedFiltersState: (_d = material.appliedFiltersState) !== null && _d !== void 0 ? _d : exports.FilterStates.ALLOWED,
22799
+ createdTime: (_e = material.createdTime) !== null && _e !== void 0 ? _e : '',
22800
+ dataSource: (_f = material.data_source) !== null && _f !== void 0 ? _f : '',
22801
+ };
22802
+ });
22803
+ return materials;
22804
+ };
22805
+ var processCDMaterialsApprovalInfo = function (enableApproval, cdMaterialsResult) {
22806
+ if (!enableApproval) {
22807
+ return {
22808
+ approvalUsers: [],
22809
+ userApprovalConfig: null,
22810
+ requestedUserId: 0,
22811
+ };
22812
+ }
22813
+ return {
22814
+ approvalUsers: cdMaterialsResult.approvalUsers,
22815
+ userApprovalConfig: cdMaterialsResult.userApprovalConfig,
22816
+ requestedUserId: cdMaterialsResult.requestedUserId,
22817
+ };
22818
+ };
22819
+ var processCDMaterialsMetaInfo = function (cdMaterialsResult) {
22820
+ var _a, _b;
22821
+ if (!cdMaterialsResult) {
22822
+ return {
22823
+ tagsEditable: false,
22824
+ appReleaseTagNames: [],
22825
+ hideImageTaggingHardDelete: false,
22826
+ resourceFilters: [],
22827
+ totalCount: 0,
22828
+ };
22829
+ }
22830
+ return {
22831
+ appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
22832
+ tagsEditable: cdMaterialsResult.tagsEditable,
22833
+ hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
22834
+ resourceFilters: (_a = cdMaterialsResult.resourceFilters) !== null && _a !== void 0 ? _a : [],
22835
+ totalCount: (_b = cdMaterialsResult.totalCount) !== null && _b !== void 0 ? _b : 0,
22836
+ };
22837
+ };
22838
+ var processCDMaterialServiceResponse = function (cdMaterialsResult, stage, offset, filter) {
22839
+ if (!cdMaterialsResult) {
22840
+ return __assign(__assign({ materials: [] }, processCDMaterialsMetaInfo(cdMaterialsResult)), processCDMaterialsApprovalInfo(false, cdMaterialsResult));
22841
+ }
22842
+ var materials = cdMaterialListModal(cdMaterialsResult.ci_artifacts, offset !== null && offset !== void 0 ? offset : 0, cdMaterialsResult.latest_wf_artifact_id, cdMaterialsResult.latest_wf_artifact_status);
22843
+ var approvalInfo = processCDMaterialsApprovalInfo(stage === exports.DeploymentNodeType.CD || stage === exports.DeploymentNodeType.APPROVAL, cdMaterialsResult);
22844
+ var metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult);
22845
+ // TODO: On update of service would remove from here
22846
+ var filteredMaterials = filter && filter === exports.CDMaterialFilterQuery.RESOURCE
22847
+ ? materials.filter(function (material) {
22848
+ return material.filterState === exports.FilterStates.ALLOWED;
22849
+ })
22850
+ : materials;
22851
+ return __assign(__assign({ materials: filteredMaterials }, approvalInfo), metaInfo);
22852
+ };
22853
+ var getSanitizedQueryParams = function (queryParams) {
22854
+ queryParams.filter; var rest = __rest(queryParams, ["filter"]);
22855
+ return rest;
22856
+ };
22857
+ var genericCDMaterialsService = function (serviceType, cdMaterialID, stage, signal, queryParams) {
22858
+ if (queryParams === void 0) { queryParams = {}; }
22859
+ // TODO: On update of service would remove from here
22860
+ var manipulatedParams = getSanitizedQueryParams(queryParams);
22861
+ var URL;
22862
+ switch (serviceType) {
22863
+ case exports.CDMaterialServiceEnum.ROLLBACK:
22864
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material/rollback"), manipulatedParams);
22865
+ break;
22866
+ // Meant for handling getCDMaterialList
22867
+ default:
22868
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material"), __assign(__assign({}, manipulatedParams), { stage: stageMap[stage] }));
22869
+ break;
22870
+ }
22871
+ return get(URL, { signal: signal }).then(function (response) {
22872
+ return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter);
22763
22873
  });
22764
22874
  };
22765
22875
  function extractImage(image) {
@@ -23126,7 +23236,9 @@ var SvgIcEnter = function SvgIcEnter(props) {
23126
23236
  };
23127
23237
 
23128
23238
  var ImageTagsContainer = function (_a) {
23129
- var ciPipelineId = _a.ciPipelineId, artifactId = _a.artifactId, imageComment = _a.imageComment, imageReleaseTags = _a.imageReleaseTags, updateCurrentAppMaterial = _a.updateCurrentAppMaterial, appReleaseTagNames = _a.appReleaseTagNames, setAppReleaseTagNames = _a.setAppReleaseTagNames, tagsEditable = _a.tagsEditable, setTagsEditable = _a.setTagsEditable, toggleCardMode = _a.toggleCardMode, hideHardDelete = _a.hideHardDelete, forceReInit = _a.forceReInit, isSuperAdmin = _a.isSuperAdmin;
23239
+ var
23240
+ // Setting it to zero in case of external pipeline
23241
+ ciPipelineId = _a.ciPipelineId, artifactId = _a.artifactId, imageComment = _a.imageComment, imageReleaseTags = _a.imageReleaseTags, updateCurrentAppMaterial = _a.updateCurrentAppMaterial, appReleaseTagNames = _a.appReleaseTagNames, setAppReleaseTagNames = _a.setAppReleaseTagNames, tagsEditable = _a.tagsEditable, setTagsEditable = _a.setTagsEditable, toggleCardMode = _a.toggleCardMode, hideHardDelete = _a.hideHardDelete, forceReInit = _a.forceReInit, isSuperAdmin = _a.isSuperAdmin;
23130
23242
  var _b = __read(React.useState(imageReleaseTags ? imageReleaseTags : []), 2), initialTags = _b[0], setInitialTags = _b[1];
23131
23243
  var _c = __read(React.useState(imageComment ? imageComment.comment : ''), 2), initialDescription = _c[0], setInitialDescription = _c[1];
23132
23244
  var _d = __read(React.useState(appReleaseTagNames ? appReleaseTagNames : []), 2), existingTags = _d[0], setExistingTags = _d[1];
@@ -23140,6 +23252,7 @@ var ImageTagsContainer = function (_a) {
23140
23252
  var _m = __read(React.useState([]), 2), hardDeleteTags = _m[0], setHardDeleteTags = _m[1];
23141
23253
  var _o = __read(React.useState(''), 2), descriptionValidationMessage = _o[0], setDescriptionValidationMessage = _o[1];
23142
23254
  var _p = __read(React.useState(''), 2), textInput = _p[0], setTextInput = _p[1];
23255
+ var _q = __read(React.useState(false), 2), loading = _q[0], setLoading = _q[1];
23143
23256
  React.useEffect(function () {
23144
23257
  reInitState();
23145
23258
  }, [imageReleaseTags, imageComment, tagsEditable]);
@@ -23287,7 +23400,8 @@ var ImageTagsContainer = function (_a) {
23287
23400
  hardDeleteTags: hardDeleteTags,
23288
23401
  };
23289
23402
  // set loading state true
23290
- setImageTags(payload, ciPipelineId, artifactId)
23403
+ setLoading(true);
23404
+ setImageTags(payload, ciPipelineId !== null && ciPipelineId !== void 0 ? ciPipelineId : 0, artifactId)
23291
23405
  .then(function (res) {
23292
23406
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
23293
23407
  var tags = (_b = (_a = res.result) === null || _a === void 0 ? void 0 : _a.imageReleaseTags) === null || _b === void 0 ? void 0 : _b.map(function (tag) { return ({
@@ -23326,6 +23440,9 @@ var ImageTagsContainer = function (_a) {
23326
23440
  else {
23327
23441
  showError(err);
23328
23442
  }
23443
+ })
23444
+ .finally(function () {
23445
+ setLoading(false);
23329
23446
  });
23330
23447
  return [2 /*return*/];
23331
23448
  });
@@ -23376,10 +23493,10 @@ var ImageTagsContainer = function (_a) {
23376
23493
  }, 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) {
23377
23494
  stopPropagation(e);
23378
23495
  handleCancel();
23379
- } }, { 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) {
23496
+ }, 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) {
23380
23497
  stopPropagation(e);
23381
23498
  onClickSave();
23382
- } }, { 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) {
23499
+ }, 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) {
23383
23500
  stopPropagation(e);
23384
23501
  handleTagSoftDelete(index);
23385
23502
  }, onHardDeleteClick: function (e) {
@@ -23683,9 +23800,9 @@ exports.closeOnEscKeyPressed = closeOnEscKeyPressed;
23683
23800
  exports.copyToClipboard = copyToClipboard;
23684
23801
  exports.createGitCommitUrl = createGitCommitUrl;
23685
23802
  exports.extractImage = extractImage;
23803
+ exports.genericCDMaterialsService = genericCDMaterialsService;
23686
23804
  exports.get = get;
23687
23805
  exports.getAlphabetIcon = getAlphabetIcon;
23688
- exports.getCDMaterials = getCDMaterials;
23689
23806
  exports.getCookie = getCookie;
23690
23807
  exports.getEmptyArrayOfLength = getEmptyArrayOfLength;
23691
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.36-beta-1",
3
+ "version": "0.0.37-beta-1",
4
4
  "description": "Supporting common component library",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -2,7 +2,19 @@ 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
+ } from './Types'
6
18
 
7
19
  export const getTeamListMin = (): Promise<TeamList> => {
8
20
  // ignore active field
@@ -30,7 +42,7 @@ interface UserRole extends ResponseType {
30
42
  }
31
43
  }
32
44
 
33
- let stageMap = {
45
+ const stageMap = {
34
46
  PRECD: 'PRE',
35
47
  CD: 'DEPLOY',
36
48
  POSTCD: 'POST',
@@ -51,83 +63,216 @@ export function setImageTags(request, pipelineId: number, artifactId: number){
51
63
  return post(`${ROUTES.IMAGE_TAGGING}/${pipelineId}/${artifactId}`,request )
52
64
  }
53
65
 
54
- // FIXME: This is only returning materials to cater the case of search in approval but it should be a common function service coming from dashboard.
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: [],
66
+ const processURL = (url: string, params: object) => {
67
+ const validParams = Object.keys(params).filter((key) => {
68
+ return params[key] != null
69
+ })
70
+
71
+ if (!validParams.length) {
72
+ return url
73
+ }
74
+
75
+ const queryString = validParams
76
+ .map((key) => {
77
+ if (Array.isArray(params[key])) {
78
+ return `${key}=${params[key].join(',')}`
70
79
  }
80
+ return `${key}=${params[key]}`
81
+ })
82
+ .join('&')
83
+
84
+ return `${url}?${queryString}`
85
+ }
86
+
87
+ const cdMaterialListModal = (artifacts: any[], offset: number, artifactId?: number, artifactStatus?: string) => {
88
+ if (!artifacts || !artifacts.length) return []
89
+
90
+ const markFirstSelected = offset === 0
91
+ const startIndex = offset
92
+ let isImageMarked = false
93
+
94
+ const materials = artifacts.map((material, index) => {
95
+ let artifactStatusValue = ''
96
+ const filterState = material.filterState ?? FilterStates.ALLOWED
97
+
98
+ if (artifactId && artifactStatus && material.id === artifactId) {
99
+ artifactStatusValue = artifactStatus
71
100
  }
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
- }
101
+
102
+ const selectImage =
103
+ !isImageMarked && markFirstSelected && filterState === FilterStates.ALLOWED ? !material.vulnerable : false
104
+ if (selectImage) {
105
+ isImageMarked = true
106
+ }
107
+
108
+ return {
109
+ index: startIndex + index,
110
+ id: material.id,
111
+ deployedTime: material.deployed_time
112
+ ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
113
+ : 'Not Deployed',
114
+ deployedBy: material.deployedBy,
115
+ wfrId: material.wfrId,
116
+ tab: CDModalTab.Changes,
117
+ image: extractImage(material.image),
118
+ showChanges: false,
119
+ vulnerabilities: [],
120
+ buildTime: material.build_time || '',
121
+ isSelected: selectImage,
122
+ showSourceInfo: false,
123
+ deployed: material.deployed || false,
124
+ latest: material.latest || false,
125
+ vulnerabilitiesLoading: true,
126
+ scanned: material.scanned,
127
+ scanEnabled: material.scanEnabled,
128
+ vulnerable: material.vulnerable,
129
+ runningOnParentCd: material.runningOnParentCd,
130
+ artifactStatus: artifactStatusValue,
131
+ userApprovalMetadata: material.userApprovalMetadata,
132
+ triggeredBy: material.triggeredBy,
133
+ isVirtualEnvironment: material.isVirtualEnvironment,
134
+ imageComment: material.imageComment,
135
+ imageReleaseTags: material.imageReleaseTags,
136
+ // It is going to be null but required in type so can't remove
137
+ lastExecution: material.lastExecution,
138
+ materialInfo: material.material_info
139
+ ? material.material_info.map((mat) => {
140
+ return {
141
+ modifiedTime: mat.modifiedTime
142
+ ? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
143
+ : '',
144
+ commitLink: createGitCommitUrl(mat.url, mat.revision),
145
+ author: mat.author || '',
146
+ message: mat.message || '',
147
+ revision: mat.revision || '',
148
+ tag: mat.tag || '',
149
+ webhookData: mat.webhookData || '',
150
+ url: mat.url || '',
151
+ branch:
152
+ (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
153
+ ? material.ciConfigureSourceValue
154
+ : mat.branch) || '',
155
+ type: material.ciConfigureSourceType || '',
156
+ }
157
+ })
158
+ : [],
159
+ filterState,
160
+ appliedFiltersTimestamp: material.appliedFiltersTimestamp ?? '',
161
+ appliedFilters: material.appliedFilters ?? [],
162
+ appliedFiltersState: material.appliedFiltersState ?? FilterStates.ALLOWED,
163
+ createdTime: material.createdTime ?? '',
164
+ dataSource: material.data_source ?? '',
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 {
@@ -18,8 +18,10 @@ import { showError, stopPropagation } from './Helper'
18
18
  import { TippyCustomized } from './TippyCustomized'
19
19
  import { setImageTags } from './Common.service'
20
20
  import Tippy from '@tippyjs/react'
21
+ import { Progressing } from './Progressing'
21
22
 
22
23
  export const ImageTagsContainer = ({
24
+ // Setting it to zero in case of external pipeline
23
25
  ciPipelineId,
24
26
  artifactId,
25
27
  imageComment,
@@ -47,6 +49,7 @@ export const ImageTagsContainer = ({
47
49
  const [hardDeleteTags, setHardDeleteTags] = useState<ReleaseTag[]>([])
48
50
  const [descriptionValidationMessage, setDescriptionValidationMessage] = useState<string>('')
49
51
  const [textInput, setTextInput] = useState<string>('')
52
+ const [loading, setLoading] = useState<boolean>(false)
50
53
 
51
54
 
52
55
  useEffect(() => {
@@ -213,7 +216,8 @@ export const ImageTagsContainer = ({
213
216
  }
214
217
 
215
218
  // set loading state true
216
- setImageTags(payload, ciPipelineId, artifactId)
219
+ setLoading(true)
220
+ setImageTags(payload, ciPipelineId ?? 0, artifactId)
217
221
  .then((res) => {
218
222
  const tags = res.result?.imageReleaseTags?.map((tag) => ({
219
223
  id: tag.id,
@@ -249,6 +253,9 @@ export const ImageTagsContainer = ({
249
253
  showError(err)
250
254
  }
251
255
  })
256
+ .finally(()=>{
257
+ setLoading(false)
258
+ })
252
259
  }
253
260
 
254
261
  const renderInfoCard = (): JSX.Element => {
@@ -425,6 +432,7 @@ export const ImageTagsContainer = ({
425
432
  stopPropagation(e)
426
433
  handleCancel()
427
434
  }}
435
+ disabled={loading}
428
436
  >
429
437
  Cancel
430
438
  </button>
@@ -436,8 +444,9 @@ export const ImageTagsContainer = ({
436
444
  stopPropagation(e)
437
445
  onClickSave()
438
446
  }}
447
+ disabled={loading}
439
448
  >
440
- Save
449
+ {loading ? <Progressing /> : 'Save'}
441
450
  </button>
442
451
  </div>
443
452
  </div>
@@ -226,6 +226,10 @@ export enum FilterStates {
226
226
  ERROR = 2,
227
227
  }
228
228
 
229
+ export enum MaterialDataSource {
230
+ EXTERNAL = "ext"
231
+ }
232
+
229
233
  export interface CDMaterialType {
230
234
  index: number
231
235
  id: string
@@ -252,6 +256,36 @@ export interface CDMaterialType {
252
256
  imageReleaseTags?: ReleaseTag[]
253
257
  artifactStatus?: string
254
258
  filterState: FilterStates
259
+ // Not even coming from API but required in CDMaterials for Security which makes its own api call but stores data in CDMaterials
260
+ scanToolId?: number
261
+ appliedFiltersTimestamp?: string
262
+ appliedFilters?: FilterConditionsListType[]
263
+ appliedFiltersState?: FilterStates
264
+ createdTime?: string
265
+ deployed?: boolean
266
+ dataSource?: MaterialDataSource
267
+ }
268
+
269
+ export enum CDMaterialServiceEnum {
270
+ ROLLBACK = 'rollback',
271
+ CD_MATERIALS = 'cd-materials',
272
+ }
273
+
274
+ export enum CDMaterialResourceQuery {
275
+ PENDING_APPROVAL = 'PENDING_APPROVAL'
276
+ }
277
+
278
+ export enum CDMaterialFilterQuery {
279
+ RESOURCE = 'ELIGIBLE_RESOURCES',
280
+ ALL = 'ALL_RESOURCES'
281
+ }
282
+
283
+ export interface CDMaterialServiceQueryParams {
284
+ search?: string
285
+ offset?: number
286
+ size?: number
287
+ resource?: CDMaterialResourceQuery
288
+ filter?: CDMaterialFilterQuery
255
289
  }
256
290
 
257
291
  export interface CommonNodeAttr {
@@ -367,15 +401,22 @@ export interface FilterConditionsListType {
367
401
  conditions: FilterConditionsInfo[]
368
402
  }
369
403
 
370
- export interface CDMaterialResponseType {
404
+ export interface CDMaterialsApprovalInfo {
371
405
  approvalUsers: string[]
372
- materials: any[]
373
406
  userApprovalConfig: UserApprovalConfigType
374
407
  requestedUserId: number
408
+ }
409
+
410
+ export interface CDMaterialsMetaInfo {
375
411
  tagsEditable: boolean
376
412
  appReleaseTagNames: string[]
377
413
  hideImageTaggingHardDelete: boolean
378
414
  resourceFilters?: FilterConditionsListType[]
415
+ totalCount: number
416
+ }
417
+
418
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
419
+ materials: CDMaterialType[]
379
420
  }
380
421
 
381
422
  export interface InputDetailType {