@devtron-labs/devtron-fe-common-lib 0.0.39 → 0.0.40

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,21 @@ 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
+ canApproverDeploy: boolean;
377
+ }
378
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
379
+ materials: CDMaterialType[];
346
380
  }
347
381
  export interface InputDetailType {
348
382
  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";
@@ -22697,77 +22716,170 @@ function getUserRole(appName) {
22697
22716
  function setImageTags(request, pipelineId, artifactId) {
22698
22717
  return post("".concat(ROUTES.IMAGE_TAGGING, "/").concat(pipelineId, "/").concat(artifactId), request);
22699
22718
  }
22700
- // 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.
22701
- var getCDMaterials = function (cdMaterialId, stageType, abortSignal, isApprovalNode, imageTag) {
22702
- 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);
22703
- return get(URL, {
22704
- signal: abortSignal,
22705
- }).then(function (response) {
22706
- var _a;
22707
- var artifacts = (_a = response.result.ci_artifacts) !== null && _a !== void 0 ? _a : [];
22708
- if (!response.result) {
22709
- return {
22710
- materials: [],
22711
- };
22719
+ var processURL = function (url, params) {
22720
+ var validParams = Object.keys(params).filter(function (key) {
22721
+ return params[key] != null;
22722
+ });
22723
+ if (!validParams.length) {
22724
+ return url;
22725
+ }
22726
+ var queryString = validParams
22727
+ .map(function (key) {
22728
+ if (Array.isArray(params[key])) {
22729
+ return "".concat(key, "=").concat(params[key].join(','));
22712
22730
  }
22713
- else {
22714
- var materials = artifacts.map(function (material, index) {
22715
- var _a;
22716
- var artifactStatusValue = '';
22717
- var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22718
- return {
22719
- index: index,
22720
- id: material.id,
22721
- deployedTime: material.deployed_time
22722
- ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22723
- : 'Not Deployed',
22724
- deployedBy: material.deployedBy,
22725
- wfrId: material.wfrId,
22726
- image: extractImage(material.image),
22727
- showChanges: false,
22728
- vulnerabilities: [],
22729
- buildTime: material.build_time || '',
22730
- tab: CDModalTab.Changes,
22731
- showSourceInfo: false,
22732
- deployed: material.deployed || false,
22733
- latest: material.latest || false,
22734
- vulnerabilitiesLoading: true,
22735
- scanned: material.scanned,
22736
- scanEnabled: material.scanEnabled,
22737
- isSelected: !material.vulnerable && filterState === exports.FilterStates.ALLOWED && index === 0,
22738
- vulnerable: material.vulnerable,
22739
- runningOnParentCd: material.runningOnParentCd,
22740
- artifactStatus: artifactStatusValue,
22741
- userApprovalMetadata: material.userApprovalMetadata,
22742
- triggeredBy: material.triggeredBy,
22743
- isVirtualEnvironment: material.isVirtualEnvironment,
22744
- imageComment: material.imageComment,
22745
- imageReleaseTags: material.imageReleaseTags,
22746
- materialInfo: material.material_info
22747
- ? material.material_info.map(function (mat) {
22748
- return {
22749
- modifiedTime: mat.modifiedTime ? moment(mat.modifiedTime).format("ddd, DD MMM YYYY, hh:mm A") : '',
22750
- commitLink: createGitCommitUrl(mat.url, mat.revision),
22751
- author: mat.author || '',
22752
- message: mat.message || '',
22753
- revision: mat.revision || '',
22754
- tag: mat.tag || '',
22755
- webhookData: mat.webhookData || '',
22756
- url: mat.url || '',
22757
- branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22758
- ? material.ciConfigureSourceValue
22759
- : mat.branch) || '',
22760
- type: material.ciConfigureSourceType || '',
22761
- };
22762
- })
22763
- : [],
22764
- filterState: filterState,
22765
- };
22766
- });
22767
- return {
22768
- materials: materials
22769
- };
22731
+ return "".concat(key, "=").concat(params[key]);
22732
+ })
22733
+ .join('&');
22734
+ return "".concat(url, "?").concat(queryString);
22735
+ };
22736
+ var cdMaterialListModal = function (artifacts, offset, artifactId, artifactStatus) {
22737
+ if (!artifacts || !artifacts.length)
22738
+ return [];
22739
+ var markFirstSelected = offset === 0;
22740
+ var startIndex = offset;
22741
+ var isImageMarked = false;
22742
+ var materials = artifacts.map(function (material, index) {
22743
+ var _a, _b, _c, _d, _e, _f;
22744
+ var artifactStatusValue = '';
22745
+ var filterState = (_a = material.filterState) !== null && _a !== void 0 ? _a : exports.FilterStates.ALLOWED;
22746
+ if (artifactId && artifactStatus && material.id === artifactId) {
22747
+ artifactStatusValue = artifactStatus;
22770
22748
  }
22749
+ var selectImage = !isImageMarked && markFirstSelected && filterState === exports.FilterStates.ALLOWED ? !material.vulnerable : false;
22750
+ if (selectImage) {
22751
+ isImageMarked = true;
22752
+ }
22753
+ return {
22754
+ index: startIndex + index,
22755
+ id: material.id,
22756
+ deployedTime: material.deployed_time
22757
+ ? moment(material.deployed_time).format('ddd, DD MMM YYYY, hh:mm A')
22758
+ : 'Not Deployed',
22759
+ deployedBy: material.deployedBy,
22760
+ wfrId: material.wfrId,
22761
+ tab: CDModalTab.Changes,
22762
+ image: extractImage(material.image),
22763
+ showChanges: false,
22764
+ vulnerabilities: [],
22765
+ buildTime: material.build_time || '',
22766
+ isSelected: selectImage,
22767
+ showSourceInfo: false,
22768
+ deployed: material.deployed || false,
22769
+ latest: material.latest || false,
22770
+ vulnerabilitiesLoading: true,
22771
+ scanned: material.scanned,
22772
+ scanEnabled: material.scanEnabled,
22773
+ vulnerable: material.vulnerable,
22774
+ runningOnParentCd: material.runningOnParentCd,
22775
+ artifactStatus: artifactStatusValue,
22776
+ userApprovalMetadata: material.userApprovalMetadata,
22777
+ triggeredBy: material.triggeredBy,
22778
+ isVirtualEnvironment: material.isVirtualEnvironment,
22779
+ imageComment: material.imageComment,
22780
+ imageReleaseTags: material.imageReleaseTags,
22781
+ // It is going to be null but required in type so can't remove
22782
+ lastExecution: material.lastExecution,
22783
+ materialInfo: material.material_info
22784
+ ? material.material_info.map(function (mat) {
22785
+ return {
22786
+ modifiedTime: mat.modifiedTime
22787
+ ? moment(mat.modifiedTime).format('ddd, DD MMM YYYY, hh:mm A')
22788
+ : '',
22789
+ commitLink: createGitCommitUrl(mat.url, mat.revision),
22790
+ author: mat.author || '',
22791
+ message: mat.message || '',
22792
+ revision: mat.revision || '',
22793
+ tag: mat.tag || '',
22794
+ webhookData: mat.webhookData || '',
22795
+ url: mat.url || '',
22796
+ branch: (material.ciConfigureSourceType === SourceTypeMap.WEBHOOK
22797
+ ? material.ciConfigureSourceValue
22798
+ : mat.branch) || '',
22799
+ type: material.ciConfigureSourceType || '',
22800
+ };
22801
+ })
22802
+ : [],
22803
+ filterState: filterState,
22804
+ appliedFiltersTimestamp: (_b = material.appliedFiltersTimestamp) !== null && _b !== void 0 ? _b : '',
22805
+ appliedFilters: (_c = material.appliedFilters) !== null && _c !== void 0 ? _c : [],
22806
+ appliedFiltersState: (_d = material.appliedFiltersState) !== null && _d !== void 0 ? _d : exports.FilterStates.ALLOWED,
22807
+ createdTime: (_e = material.createdTime) !== null && _e !== void 0 ? _e : '',
22808
+ dataSource: (_f = material.data_source) !== null && _f !== void 0 ? _f : '',
22809
+ };
22810
+ });
22811
+ return materials;
22812
+ };
22813
+ var processCDMaterialsApprovalInfo = function (enableApproval, cdMaterialsResult) {
22814
+ if (!enableApproval) {
22815
+ return {
22816
+ approvalUsers: [],
22817
+ userApprovalConfig: null,
22818
+ requestedUserId: 0,
22819
+ };
22820
+ }
22821
+ return {
22822
+ approvalUsers: cdMaterialsResult.approvalUsers,
22823
+ userApprovalConfig: cdMaterialsResult.userApprovalConfig,
22824
+ requestedUserId: cdMaterialsResult.requestedUserId,
22825
+ };
22826
+ };
22827
+ var processCDMaterialsMetaInfo = function (cdMaterialsResult) {
22828
+ var _a, _b, _c, _d;
22829
+ if (!cdMaterialsResult) {
22830
+ return {
22831
+ tagsEditable: false,
22832
+ appReleaseTagNames: [],
22833
+ hideImageTaggingHardDelete: false,
22834
+ resourceFilters: [],
22835
+ totalCount: 0,
22836
+ canApproverDeploy: (_a = cdMaterialsResult.canApproverDeploy) !== null && _a !== void 0 ? _a : false,
22837
+ };
22838
+ }
22839
+ return {
22840
+ appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
22841
+ tagsEditable: cdMaterialsResult.tagsEditable,
22842
+ hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
22843
+ resourceFilters: (_b = cdMaterialsResult.resourceFilters) !== null && _b !== void 0 ? _b : [],
22844
+ totalCount: (_c = cdMaterialsResult.totalCount) !== null && _c !== void 0 ? _c : 0,
22845
+ canApproverDeploy: (_d = cdMaterialsResult.canApproverDeploy) !== null && _d !== void 0 ? _d : false,
22846
+ };
22847
+ };
22848
+ var processCDMaterialServiceResponse = function (cdMaterialsResult, stage, offset, filter) {
22849
+ if (!cdMaterialsResult) {
22850
+ return __assign(__assign({ materials: [] }, processCDMaterialsMetaInfo(cdMaterialsResult)), processCDMaterialsApprovalInfo(false, cdMaterialsResult));
22851
+ }
22852
+ var materials = cdMaterialListModal(cdMaterialsResult.ci_artifacts, offset !== null && offset !== void 0 ? offset : 0, cdMaterialsResult.latest_wf_artifact_id, cdMaterialsResult.latest_wf_artifact_status);
22853
+ var approvalInfo = processCDMaterialsApprovalInfo(stage === exports.DeploymentNodeType.CD || stage === exports.DeploymentNodeType.APPROVAL, cdMaterialsResult);
22854
+ var metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult);
22855
+ // TODO: On update of service would remove from here
22856
+ var filteredMaterials = filter && filter === exports.CDMaterialFilterQuery.RESOURCE
22857
+ ? materials.filter(function (material) {
22858
+ return material.filterState === exports.FilterStates.ALLOWED;
22859
+ })
22860
+ : materials;
22861
+ return __assign(__assign({ materials: filteredMaterials }, approvalInfo), metaInfo);
22862
+ };
22863
+ var getSanitizedQueryParams = function (queryParams) {
22864
+ queryParams.filter; var rest = __rest(queryParams, ["filter"]);
22865
+ return rest;
22866
+ };
22867
+ var genericCDMaterialsService = function (serviceType, cdMaterialID, stage, signal, queryParams) {
22868
+ if (queryParams === void 0) { queryParams = {}; }
22869
+ // TODO: On update of service would remove from here
22870
+ var manipulatedParams = getSanitizedQueryParams(queryParams);
22871
+ var URL;
22872
+ switch (serviceType) {
22873
+ case exports.CDMaterialServiceEnum.ROLLBACK:
22874
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material/rollback"), manipulatedParams);
22875
+ break;
22876
+ // Meant for handling getCDMaterialList
22877
+ default:
22878
+ URL = processURL("".concat(ROUTES.CD_MATERIAL_GET, "/").concat(cdMaterialID, "/material"), __assign(__assign({}, manipulatedParams), { stage: stageMap[stage] }));
22879
+ break;
22880
+ }
22881
+ return get(URL, { signal: signal }).then(function (response) {
22882
+ return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter);
22771
22883
  });
22772
22884
  };
22773
22885
  function extractImage(image) {
@@ -23134,7 +23246,9 @@ var SvgIcEnter = function SvgIcEnter(props) {
23134
23246
  };
23135
23247
 
23136
23248
  var ImageTagsContainer = function (_a) {
23137
- 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;
23249
+ var
23250
+ // Setting it to zero in case of external pipeline
23251
+ 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;
23138
23252
  var _b = __read(React.useState(imageReleaseTags ? imageReleaseTags : []), 2), initialTags = _b[0], setInitialTags = _b[1];
23139
23253
  var _c = __read(React.useState(imageComment ? imageComment.comment : ''), 2), initialDescription = _c[0], setInitialDescription = _c[1];
23140
23254
  var _d = __read(React.useState(appReleaseTagNames ? appReleaseTagNames : []), 2), existingTags = _d[0], setExistingTags = _d[1];
@@ -23148,6 +23262,7 @@ var ImageTagsContainer = function (_a) {
23148
23262
  var _m = __read(React.useState([]), 2), hardDeleteTags = _m[0], setHardDeleteTags = _m[1];
23149
23263
  var _o = __read(React.useState(''), 2), descriptionValidationMessage = _o[0], setDescriptionValidationMessage = _o[1];
23150
23264
  var _p = __read(React.useState(''), 2), textInput = _p[0], setTextInput = _p[1];
23265
+ var _q = __read(React.useState(false), 2), loading = _q[0], setLoading = _q[1];
23151
23266
  React.useEffect(function () {
23152
23267
  reInitState();
23153
23268
  }, [imageReleaseTags, imageComment, tagsEditable]);
@@ -23295,7 +23410,8 @@ var ImageTagsContainer = function (_a) {
23295
23410
  hardDeleteTags: hardDeleteTags,
23296
23411
  };
23297
23412
  // set loading state true
23298
- setImageTags(payload, ciPipelineId, artifactId)
23413
+ setLoading(true);
23414
+ setImageTags(payload, ciPipelineId !== null && ciPipelineId !== void 0 ? ciPipelineId : 0, artifactId)
23299
23415
  .then(function (res) {
23300
23416
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
23301
23417
  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 ({
@@ -23334,6 +23450,9 @@ var ImageTagsContainer = function (_a) {
23334
23450
  else {
23335
23451
  showError(err);
23336
23452
  }
23453
+ })
23454
+ .finally(function () {
23455
+ setLoading(false);
23337
23456
  });
23338
23457
  return [2 /*return*/];
23339
23458
  });
@@ -23384,10 +23503,10 @@ var ImageTagsContainer = function (_a) {
23384
23503
  }, 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) {
23385
23504
  stopPropagation(e);
23386
23505
  handleCancel();
23387
- } }, { 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) {
23506
+ }, 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) {
23388
23507
  stopPropagation(e);
23389
23508
  onClickSave();
23390
- } }, { 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) {
23509
+ }, 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) {
23391
23510
  stopPropagation(e);
23392
23511
  handleTagSoftDelete(index);
23393
23512
  }, onHardDeleteClick: function (e) {
@@ -23801,9 +23920,9 @@ exports.closeOnEscKeyPressed = closeOnEscKeyPressed;
23801
23920
  exports.copyToClipboard = copyToClipboard;
23802
23921
  exports.createGitCommitUrl = createGitCommitUrl;
23803
23922
  exports.extractImage = extractImage;
23923
+ exports.genericCDMaterialsService = genericCDMaterialsService;
23804
23924
  exports.get = get;
23805
23925
  exports.getAlphabetIcon = getAlphabetIcon;
23806
- exports.getCDMaterials = getCDMaterials;
23807
23926
  exports.getCookie = getCookie;
23808
23927
  exports.getEmptyArrayOfLength = getEmptyArrayOfLength;
23809
23928
  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.39",
3
+ "version": "0.0.40",
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,218 @@ 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,
194
+ canApproverDeploy: cdMaterialsResult.canApproverDeploy ?? false,
130
195
  }
196
+ }
197
+
198
+ return {
199
+ appReleaseTagNames: cdMaterialsResult.appReleaseTagNames,
200
+ tagsEditable: cdMaterialsResult.tagsEditable,
201
+ hideImageTaggingHardDelete: cdMaterialsResult.hideImageTaggingHardDelete,
202
+ resourceFilters: cdMaterialsResult.resourceFilters ?? [],
203
+ totalCount: cdMaterialsResult.totalCount ?? 0,
204
+ canApproverDeploy: cdMaterialsResult.canApproverDeploy ?? false,
205
+ }
206
+ }
207
+
208
+ const processCDMaterialServiceResponse = (
209
+ cdMaterialsResult,
210
+ stage: DeploymentNodeType,
211
+ offset: number,
212
+ filter: CDMaterialFilterQuery,
213
+ ): CDMaterialResponseType => {
214
+ if (!cdMaterialsResult) {
215
+ return {
216
+ materials: [],
217
+ ...processCDMaterialsMetaInfo(cdMaterialsResult),
218
+ ...processCDMaterialsApprovalInfo(false, cdMaterialsResult),
219
+ }
220
+ }
221
+
222
+ const materials = cdMaterialListModal(
223
+ cdMaterialsResult.ci_artifacts,
224
+ offset ?? 0,
225
+ cdMaterialsResult.latest_wf_artifact_id,
226
+ cdMaterialsResult.latest_wf_artifact_status,
227
+ )
228
+ const approvalInfo = processCDMaterialsApprovalInfo(
229
+ stage === DeploymentNodeType.CD || stage === DeploymentNodeType.APPROVAL,
230
+ cdMaterialsResult,
231
+ )
232
+ const metaInfo = processCDMaterialsMetaInfo(cdMaterialsResult)
233
+
234
+ // TODO: On update of service would remove from here
235
+ const filteredMaterials =
236
+ filter && filter === CDMaterialFilterQuery.RESOURCE
237
+ ? materials.filter((material) => {
238
+ return material.filterState === FilterStates.ALLOWED
239
+ })
240
+ : materials
241
+
242
+ return {
243
+ materials: filteredMaterials,
244
+ ...approvalInfo,
245
+ ...metaInfo,
246
+ }
247
+ }
248
+
249
+ const getSanitizedQueryParams = (queryParams: CDMaterialServiceQueryParams): CDMaterialServiceQueryParams => {
250
+ const { filter, ...rest } = queryParams
251
+ return rest
252
+ }
253
+
254
+ export const genericCDMaterialsService = (
255
+ serviceType: CDMaterialServiceEnum,
256
+ cdMaterialID: number,
257
+ stage: DeploymentNodeType,
258
+ signal: AbortSignal,
259
+ queryParams: CDMaterialServiceQueryParams = {},
260
+ ): Promise<CDMaterialResponseType> => {
261
+ // TODO: On update of service would remove from here
262
+ const manipulatedParams = getSanitizedQueryParams(queryParams)
263
+
264
+ let URL
265
+ switch (serviceType) {
266
+ case CDMaterialServiceEnum.ROLLBACK:
267
+ URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material/rollback`, manipulatedParams)
268
+ break
269
+
270
+ // Meant for handling getCDMaterialList
271
+ default:
272
+ URL = processURL(`${ROUTES.CD_MATERIAL_GET}/${cdMaterialID}/material`, { ...manipulatedParams, stage: stageMap[stage] })
273
+ break
274
+ }
275
+
276
+ return get(URL, { signal }).then((response) => {
277
+ return processCDMaterialServiceResponse(response.result, stage, queryParams.offset, queryParams.filter)
131
278
  })
132
279
  }
133
280
 
@@ -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,23 @@ 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
+ canApproverDeploy: boolean
417
+ }
418
+
419
+ export interface CDMaterialResponseType extends CDMaterialsMetaInfo, CDMaterialsApprovalInfo {
420
+ materials: CDMaterialType[]
379
421
  }
380
422
 
381
423
  export interface InputDetailType {