@c8y/ngx-components 1018.0.147 → 1018.0.152
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.
- package/core/common/date.pipe.d.ts +2 -2
- package/core/common/stringify-object.pipe.d.ts +2 -1
- package/core/range-display/range-display.component.d.ts +19 -1
- package/ecosystem/application-properties/update-application-modal/update-application-modal.component.d.ts +0 -2
- package/ecosystem/packages/deploy-application/deploy-application.component.d.ts +7 -6
- package/ecosystem/shared/ecosystem.constants.d.ts +3 -1
- package/ecosystem/shared/ecosystem.model.d.ts +3 -1
- package/ecosystem/shared/ecosystem.service.d.ts +11 -5
- package/esm2020/core/common/date.pipe.mjs +12 -7
- package/esm2020/core/common/stringify-object.pipe.mjs +11 -8
- package/esm2020/core/range-display/range-display.component.mjs +87 -4
- package/esm2020/ecosystem/application-properties/application-properties.component.mjs +6 -4
- package/esm2020/ecosystem/application-properties/update-application-modal/update-application-modal.component.mjs +11 -22
- package/esm2020/ecosystem/applications/install-from-package/install-from-package.component.mjs +2 -2
- package/esm2020/ecosystem/packages/deploy-application/deploy-application.component.mjs +28 -85
- package/esm2020/ecosystem/shared/ecosystem.constants.mjs +5 -3
- package/esm2020/ecosystem/shared/ecosystem.model.mjs +3 -1
- package/esm2020/ecosystem/shared/ecosystem.service.mjs +121 -24
- package/fesm2015/c8y-ngx-components-ecosystem-shared.mjs +139 -27
- package/fesm2015/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
- package/fesm2015/c8y-ngx-components-ecosystem.mjs +110 -179
- package/fesm2015/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2015/c8y-ngx-components.mjs +105 -15
- package/fesm2015/c8y-ngx-components.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components-ecosystem-shared.mjs +126 -25
- package/fesm2020/c8y-ngx-components-ecosystem-shared.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components-ecosystem.mjs +110 -176
- package/fesm2020/c8y-ngx-components-ecosystem.mjs.map +1 -1
- package/fesm2020/c8y-ngx-components.mjs +103 -15
- package/fesm2020/c8y-ngx-components.mjs.map +1 -1
- package/locales/locales.pot +15 -3
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import { gettext, PackageType, Status, DropAreaComponent, C8yStepper, CoreModule
|
|
|
6
6
|
import * as i3 from '@c8y/client';
|
|
7
7
|
import { ApplicationAvailability, ApplicationType } from '@c8y/client';
|
|
8
8
|
import { saveAs } from 'file-saver';
|
|
9
|
-
import { groupBy, uniqBy, get, pick, kebabCase, cloneDeep } from 'lodash-es';
|
|
9
|
+
import { groupBy, uniqBy, get, pick, omit, isUndefined, kebabCase, cloneDeep } from 'lodash-es';
|
|
10
10
|
import { BehaviorSubject, defer, merge, combineLatest } from 'rxjs';
|
|
11
11
|
import { map, shareReplay, debounceTime, take, distinctUntilKeyChanged, tap, filter, switchMap } from 'rxjs/operators';
|
|
12
12
|
import { gt, coerce } from 'semver';
|
|
@@ -37,6 +37,7 @@ var ERROR_TYPE;
|
|
|
37
37
|
(function (ERROR_TYPE) {
|
|
38
38
|
ERROR_TYPE["TYPE_VALIDATION"] = "TYPE_VALIDATION";
|
|
39
39
|
ERROR_TYPE["ALREADY_SUBSCRIBED"] = "ALREADY_SUBSCRIBED";
|
|
40
|
+
ERROR_TYPE["ALREADY_EXIST"] = "ALREADY_EXIST";
|
|
40
41
|
ERROR_TYPE["INTERNAL_ERROR"] = "INTERNAL_ERROR";
|
|
41
42
|
ERROR_TYPE["NO_MANIFEST_FILE"] = "NO_MANIFEST_FILE";
|
|
42
43
|
ERROR_TYPE["INVALID_PACKAGE"] = "INVALID_PACKAGE";
|
|
@@ -44,6 +45,7 @@ var ERROR_TYPE;
|
|
|
44
45
|
ERROR_TYPE["MICROSERVICE_NAME_TOO_LONG"] = "MICROSERVICE_NAME_TOO_LONG";
|
|
45
46
|
ERROR_TYPE["APPLICATION_CREATION_FAILED"] = "APPLICATION_CREATION_FAILED";
|
|
46
47
|
ERROR_TYPE["KEY_OR_CONTEXT_PATH_MISMATCH"] = "KEY_OR_CONTEXT_PATH_MISMATCH";
|
|
48
|
+
ERROR_TYPE["VERSION_NOT_FOUND"] = "VERSION_NOT_FOUND";
|
|
47
49
|
})(ERROR_TYPE || (ERROR_TYPE = {}));
|
|
48
50
|
const PRODUCT_EXPERIENCE = {
|
|
49
51
|
APPLICATIONS: {
|
|
@@ -96,6 +98,7 @@ const PRODUCT_EXPERIENCE = {
|
|
|
96
98
|
};
|
|
97
99
|
|
|
98
100
|
const ERROR_MESSAGES = {
|
|
101
|
+
[ERROR_TYPE.ALREADY_EXIST]: gettext('Could not deploy the application, as the application with the same name, context-path or key exist already.'),
|
|
99
102
|
[ERROR_TYPE.TYPE_VALIDATION]: gettext('Wrong file format. Expected a *.zip file with a valid manifest.'),
|
|
100
103
|
[ERROR_TYPE.ALREADY_SUBSCRIBED]: gettext('Could not subscribe to the microservice because another application with the same context path is already subscribed.'),
|
|
101
104
|
[ERROR_TYPE.NO_MANIFEST_FILE]: gettext('Could not find a manifest.'),
|
|
@@ -104,7 +107,8 @@ const ERROR_MESSAGES = {
|
|
|
104
107
|
[ERROR_TYPE.INTERNAL_ERROR]: gettext('An internal error occurred, try to upload again.'),
|
|
105
108
|
[ERROR_TYPE.MICROSERVICE_NAME_TOO_LONG]: gettext('Microservice name "{{ name }}" must not be longer than {{ maxChars }} characters.'),
|
|
106
109
|
[ERROR_TYPE.APPLICATION_CREATION_FAILED]: gettext('Application creation failed.'),
|
|
107
|
-
[ERROR_TYPE.KEY_OR_CONTEXT_PATH_MISMATCH]: gettext('The contextPath or key of the uploaded archive do not match with the existing
|
|
110
|
+
[ERROR_TYPE.KEY_OR_CONTEXT_PATH_MISMATCH]: gettext('The "contextPath`KEEP_ORIGINAL`" or "key`KEEP_ORIGINAL`" of the uploaded archive do not match with the existing application.'),
|
|
111
|
+
[ERROR_TYPE.VERSION_NOT_FOUND]: gettext('The selected version was not found on the server.')
|
|
108
112
|
};
|
|
109
113
|
const APP_STATE = {
|
|
110
114
|
SUBSCRIBED: {
|
|
@@ -159,7 +163,7 @@ const PACKAGE_TYPE_LABELS = {
|
|
|
159
163
|
};
|
|
160
164
|
const packageProperties = [
|
|
161
165
|
{
|
|
162
|
-
label: gettext('
|
|
166
|
+
label: gettext('Latest version'),
|
|
163
167
|
key: 'version'
|
|
164
168
|
},
|
|
165
169
|
{
|
|
@@ -334,6 +338,18 @@ class EcosystemService {
|
|
|
334
338
|
});
|
|
335
339
|
}
|
|
336
340
|
getPackageApplications(customFilter = {}) {
|
|
341
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
342
|
+
const filterCallback = app => this.isPackage(app);
|
|
343
|
+
return this.getApplicationsFiltered(customFilter, filterCallback);
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
getHostedAndPackageApplications(customFilter = {}) {
|
|
347
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
348
|
+
const filterCallback = app => this.isPackage(app) || this.isApplication(app);
|
|
349
|
+
return this.getApplicationsFiltered(customFilter, filterCallback);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
getApplicationsFiltered(customFilter = {}, filterCallback = (app) => !!app) {
|
|
337
353
|
return __awaiter(this, void 0, void 0, function* () {
|
|
338
354
|
const filter = Object.assign({}, customFilter);
|
|
339
355
|
const sharedFilter = Object.assign({
|
|
@@ -345,7 +361,7 @@ class EcosystemService {
|
|
|
345
361
|
this.getApplications(filter),
|
|
346
362
|
this.applicationService.list(sharedFilter)
|
|
347
363
|
]);
|
|
348
|
-
const webApps = [...apps, ...shared].filter(
|
|
364
|
+
const webApps = [...apps, ...shared].filter(filterCallback);
|
|
349
365
|
// an app could be subscribed to a tenant, but also have it's availability set to SHARED, in that case it would occur twice.
|
|
350
366
|
const uniqWebApps = uniqBy(webApps, (app) => app.id);
|
|
351
367
|
return uniqWebApps.sort((a, b) => a.name.localeCompare(b.name));
|
|
@@ -431,20 +447,6 @@ class EcosystemService {
|
|
|
431
447
|
availability });
|
|
432
448
|
return config;
|
|
433
449
|
}
|
|
434
|
-
updateAppManifest(application, sourcePackage) {
|
|
435
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
436
|
-
const { id } = application;
|
|
437
|
-
const cleanedApp = this.removeAppProperties(application);
|
|
438
|
-
if (!cleanedApp.manifest) {
|
|
439
|
-
cleanedApp.manifest = {};
|
|
440
|
-
}
|
|
441
|
-
cleanedApp.manifest.isPackage = false;
|
|
442
|
-
cleanedApp.manifest.source = sourcePackage.id;
|
|
443
|
-
return yield this.applicationService
|
|
444
|
-
.binary(id)
|
|
445
|
-
.updateFiles([{ path: CUMULOCITY_JSON, contents: JSON.stringify(cleanedApp) }]);
|
|
446
|
-
});
|
|
447
|
-
}
|
|
448
450
|
listArchives(appId) {
|
|
449
451
|
return __awaiter(this, void 0, void 0, function* () {
|
|
450
452
|
const filter = {
|
|
@@ -678,6 +680,85 @@ class EcosystemService {
|
|
|
678
680
|
}
|
|
679
681
|
});
|
|
680
682
|
}
|
|
683
|
+
deployApp(selectedPackage, formGroupValue, model) {
|
|
684
|
+
var _a;
|
|
685
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
686
|
+
// Create new app config
|
|
687
|
+
const config = this.createConfig(selectedPackage, formGroupValue);
|
|
688
|
+
const requestedVersion = model.selected.version;
|
|
689
|
+
let cleanManifest;
|
|
690
|
+
try {
|
|
691
|
+
const manifest = yield this.applicationService.getAppManifest(selectedPackage, requestedVersion);
|
|
692
|
+
cleanManifest = omit(manifest, ['name', 'contextPath', 'key']);
|
|
693
|
+
}
|
|
694
|
+
catch (ex) {
|
|
695
|
+
throw new EcosystemError(ERROR_TYPE.VERSION_NOT_FOUND);
|
|
696
|
+
}
|
|
697
|
+
config.isSetup = true;
|
|
698
|
+
config.manifest = cleanManifest;
|
|
699
|
+
config.availability = ApplicationAvailability.PRIVATE;
|
|
700
|
+
config.manifest.isPackage = false;
|
|
701
|
+
config.manifest.source = selectedPackage.id;
|
|
702
|
+
config.manifest.package = 'blueprint';
|
|
703
|
+
// because of a issue with SHARED availability we always should check again
|
|
704
|
+
// if the app not exist already
|
|
705
|
+
const allExistingApps = yield this.getHostedAndPackageApplications();
|
|
706
|
+
const doesAppKeyOrContextPathExist = this.checkIfAppNameKeyPathExists(allExistingApps, config);
|
|
707
|
+
if (doesAppKeyOrContextPathExist) {
|
|
708
|
+
throw new EcosystemError(ERROR_TYPE.ALREADY_EXIST);
|
|
709
|
+
}
|
|
710
|
+
// Create new app
|
|
711
|
+
const newApp = (yield this.applicationService.create(config)).data;
|
|
712
|
+
try {
|
|
713
|
+
// Binary upload can fail if SHARED package
|
|
714
|
+
// in this case, catch error and fall back to
|
|
715
|
+
// clone API.
|
|
716
|
+
yield this.uploadBinaryFromOtherPackage(selectedPackage, newApp, model.selected.binaryId, requestedVersion);
|
|
717
|
+
}
|
|
718
|
+
catch (error) {
|
|
719
|
+
if (((_a = error === null || error === void 0 ? void 0 : error.res) === null || _a === void 0 ? void 0 : _a.status) === 404) {
|
|
720
|
+
yield this.fallbackToClone(newApp, selectedPackage, requestedVersion);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
return newApp;
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
fallbackToClone(application, selectedPackage, requestedVersion) {
|
|
727
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
728
|
+
let wasSuccess = true;
|
|
729
|
+
let clonedPkg;
|
|
730
|
+
try {
|
|
731
|
+
clonedPkg = (yield this.applicationService.clone(selectedPackage, requestedVersion)).data;
|
|
732
|
+
yield this.uploadBinaryFromOtherPackage(selectedPackage, application, clonedPkg.activeVersionId, requestedVersion, clonedPkg);
|
|
733
|
+
}
|
|
734
|
+
catch (error) {
|
|
735
|
+
this.alertError(error);
|
|
736
|
+
wasSuccess = false;
|
|
737
|
+
}
|
|
738
|
+
finally {
|
|
739
|
+
yield this.deleteApp(clonedPkg, true);
|
|
740
|
+
}
|
|
741
|
+
return wasSuccess;
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
uploadBinaryFromOtherPackage(selectedPackage, applicationToUploadBinaryTo, binaryId, requestedVersion, useBinariesFrom) {
|
|
745
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
746
|
+
const { data: binaryDetails } = yield this.inventoryService.detail(binaryId);
|
|
747
|
+
// Get binary from specific package version
|
|
748
|
+
const binary = yield this.getBinary(useBinariesFrom || selectedPackage, {
|
|
749
|
+
id: binaryId
|
|
750
|
+
});
|
|
751
|
+
// Create zip
|
|
752
|
+
const fileBinary = new Blob([binary], { type: binaryDetails.contentType });
|
|
753
|
+
const file = new File([fileBinary], binaryDetails.name, {
|
|
754
|
+
type: binaryDetails.contentType
|
|
755
|
+
});
|
|
756
|
+
// Upload binary to new app
|
|
757
|
+
yield this.uploadArchiveToApp(file, applicationToUploadBinaryTo);
|
|
758
|
+
// update the app manifest
|
|
759
|
+
yield this.updateAppManifest(applicationToUploadBinaryTo, selectedPackage, requestedVersion);
|
|
760
|
+
});
|
|
761
|
+
}
|
|
681
762
|
getAppState(app) {
|
|
682
763
|
if (!this.isOwner(app)) {
|
|
683
764
|
return APP_STATE.SUBSCRIBED;
|
|
@@ -776,6 +857,45 @@ class EcosystemService {
|
|
|
776
857
|
}
|
|
777
858
|
});
|
|
778
859
|
}
|
|
860
|
+
filterContainString(name, filterTerm) {
|
|
861
|
+
const term = filterTerm.toLowerCase().trim();
|
|
862
|
+
return name && name.toLowerCase().indexOf(term) > -1;
|
|
863
|
+
}
|
|
864
|
+
updateAppManifest(application, selectedPackage, requestedVersion) {
|
|
865
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
866
|
+
const { id } = application;
|
|
867
|
+
const cleanedApp = this.removeAppProperties(application);
|
|
868
|
+
let manifest = selectedPackage.manifest || {};
|
|
869
|
+
if (requestedVersion) {
|
|
870
|
+
try {
|
|
871
|
+
const versionedAppManifest = yield this.applicationService.getAppManifest(selectedPackage, requestedVersion);
|
|
872
|
+
manifest = versionedAppManifest;
|
|
873
|
+
}
|
|
874
|
+
catch (ex) {
|
|
875
|
+
throw new EcosystemError(ERROR_TYPE.VERSION_NOT_FOUND);
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
cleanedApp.manifest = manifest;
|
|
879
|
+
cleanedApp.manifest.isPackage = false;
|
|
880
|
+
cleanedApp.manifest.source = selectedPackage.id;
|
|
881
|
+
return yield this.applicationService
|
|
882
|
+
.binary(id)
|
|
883
|
+
.updateFiles([{ path: CUMULOCITY_JSON, contents: JSON.stringify(cleanedApp) }]);
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
checkIfAppNameKeyPathExists(existingApps, app, retryNo) {
|
|
887
|
+
if (isUndefined(retryNo)) {
|
|
888
|
+
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
889
|
+
existingApp.key === app.key ||
|
|
890
|
+
existingApp.contextPath === app.contextPath);
|
|
891
|
+
}
|
|
892
|
+
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
893
|
+
existingApp.key === app.key ||
|
|
894
|
+
existingApp.contextPath === app.contextPath ||
|
|
895
|
+
existingApp.name === [app.name, retryNo].join('-') ||
|
|
896
|
+
existingApp.key === [app.key, retryNo].join('-') ||
|
|
897
|
+
existingApp.contextPath === [app.contextPath, retryNo].join('-'));
|
|
898
|
+
}
|
|
779
899
|
getAppKey(appModel, name) {
|
|
780
900
|
let key = appModel === null || appModel === void 0 ? void 0 : appModel.key;
|
|
781
901
|
if (!key) {
|
|
@@ -812,17 +932,9 @@ class EcosystemService {
|
|
|
812
932
|
}
|
|
813
933
|
return baseName;
|
|
814
934
|
}
|
|
815
|
-
checkIfAppNameKeyPathExists(existingApps, app, retryNo) {
|
|
816
|
-
return existingApps.find(existingApp => existingApp.name === app.name ||
|
|
817
|
-
existingApp.key === app.key ||
|
|
818
|
-
existingApp.contextPath === app.contextPath ||
|
|
819
|
-
existingApp.name === [app.name, retryNo].join('-') ||
|
|
820
|
-
existingApp.key === [app.key, retryNo].join('-') ||
|
|
821
|
-
existingApp.contextPath === [app.contextPath, retryNo].join('-'));
|
|
822
|
-
}
|
|
823
935
|
removeAppProperties(app) {
|
|
824
936
|
const tempApp = cloneDeep(app);
|
|
825
|
-
const propertiesToRemove = ['id', 'owner', 'activeVersionId', 'self'];
|
|
937
|
+
const propertiesToRemove = ['id', 'owner', 'activeVersionId', 'self', 'type'];
|
|
826
938
|
propertiesToRemove.forEach(prop => delete tempApp[prop]);
|
|
827
939
|
return tempApp;
|
|
828
940
|
}
|