@sumaris-net/ngx-components 18.8.4 → 18.8.6
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/esm2022/src/app/shared/image/gallery/image-gallery.component.mjs +10 -5
- package/esm2022/src/app/shared/image/gallery/testing/gallery.testing.mjs +1 -1
- package/esm2022/src/app/shared/image/image.model.mjs +1 -1
- package/esm2022/src/app/shared/image/image.service.mjs +10 -9
- package/fesm2022/sumaris-net.ngx-components.mjs +19 -13
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/app/shared/image/gallery/image-gallery.component.d.ts +4 -2
- package/src/app/shared/image/image.model.d.ts +1 -0
- package/src/app/shared/image/image.service.d.ts +5 -4
- package/src/assets/manifest.json +1 -1
|
@@ -17,19 +17,15 @@ export class ImageService extends StartableService {
|
|
|
17
17
|
settings;
|
|
18
18
|
translate;
|
|
19
19
|
popoverController;
|
|
20
|
-
actionSheetController;
|
|
21
20
|
environment;
|
|
22
21
|
defaultMaxHeight = 1024;
|
|
23
22
|
defaultMaxWidth = 1024;
|
|
24
|
-
constructor(platform, settings, translate, popoverController,
|
|
25
|
-
// protected camera: Camera,
|
|
26
|
-
actionSheetController, environment) {
|
|
23
|
+
constructor(platform, settings, translate, popoverController, environment) {
|
|
27
24
|
super(platform);
|
|
28
25
|
this.platform = platform;
|
|
29
26
|
this.settings = settings;
|
|
30
27
|
this.translate = translate;
|
|
31
28
|
this.popoverController = popoverController;
|
|
32
|
-
this.actionSheetController = actionSheetController;
|
|
33
29
|
this.environment = environment;
|
|
34
30
|
this._debug = !environment.production;
|
|
35
31
|
if (this._debug)
|
|
@@ -63,9 +59,14 @@ export class ImageService extends StartableService {
|
|
|
63
59
|
});
|
|
64
60
|
if (!data)
|
|
65
61
|
return undefined;
|
|
62
|
+
// DEBUG
|
|
63
|
+
if (this._debug && data.exif) {
|
|
64
|
+
console.debug(`[image-service] Image added, with exif:`, data.exif);
|
|
65
|
+
}
|
|
66
66
|
return [
|
|
67
67
|
{
|
|
68
68
|
dataUrl: data.dataUrl,
|
|
69
|
+
exif: data.exif,
|
|
69
70
|
},
|
|
70
71
|
];
|
|
71
72
|
}
|
|
@@ -77,7 +78,7 @@ export class ImageService extends StartableService {
|
|
|
77
78
|
/* -- protected functions -- */
|
|
78
79
|
async addUploadedImages(event, opts) {
|
|
79
80
|
const { data } = await FilesUtils.showUploadPopover(this.popoverController, event, {
|
|
80
|
-
uniqueFile: true,
|
|
81
|
+
uniqueFile: opts?.multiple !== true,
|
|
81
82
|
fileExtension: '.png, .jpg',
|
|
82
83
|
instantUpload: true,
|
|
83
84
|
uploadFn: (file) => ImagesUtils.readAsDataURL(file, {
|
|
@@ -92,16 +93,16 @@ export class ImageService extends StartableService {
|
|
|
92
93
|
.map((file) => file.response.body) // Get response body = data as base64
|
|
93
94
|
.map((dataUrl) => ({ dataUrl }));
|
|
94
95
|
}
|
|
95
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, deps: [{ token: i1.PlatformService }, { token: i2.LocalSettingsService }, { token: i3.TranslateService }, { token: i4.PopoverController }, { token:
|
|
96
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, deps: [{ token: i1.PlatformService }, { token: i2.LocalSettingsService }, { token: i3.TranslateService }, { token: i4.PopoverController }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
96
97
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, providedIn: 'root' });
|
|
97
98
|
}
|
|
98
99
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, decorators: [{
|
|
99
100
|
type: Injectable,
|
|
100
101
|
args: [{ providedIn: 'root' }]
|
|
101
|
-
}], ctorParameters: () => [{ type: i1.PlatformService }, { type: i2.LocalSettingsService }, { type: i3.TranslateService }, { type: i4.PopoverController }, { type:
|
|
102
|
+
}], ctorParameters: () => [{ type: i1.PlatformService }, { type: i2.LocalSettingsService }, { type: i3.TranslateService }, { type: i4.PopoverController }, { type: i5.Environment, decorators: [{
|
|
102
103
|
type: Inject,
|
|
103
104
|
args: [ENVIRONMENT]
|
|
104
105
|
}, {
|
|
105
106
|
type: Optional
|
|
106
107
|
}] }] });
|
|
107
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
108
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1hZ2Uuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvc2hhcmVkL2ltYWdlL2ltYWdlLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBSTdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBRSxXQUFXLEVBQWUsTUFBTSx5Q0FBeUMsQ0FBQztBQUduRixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDaEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ25ELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFHNUMsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzVDLE9BQU8sRUFBRSxNQUFNLEVBQUUsZ0JBQWdCLEVBQWdCLE1BQU0sbUJBQW1CLENBQUM7Ozs7Ozs7QUFHM0UsTUFBTSxPQUFPLFlBQWEsU0FBUSxnQkFBZ0I7SUFLcEM7SUFDQTtJQUNBO0lBQ0E7SUFDaUM7SUFSckMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0lBQ3hCLGVBQWUsR0FBRyxJQUFJLENBQUM7SUFFL0IsWUFDWSxRQUF5QixFQUN6QixRQUE4QixFQUM5QixTQUEyQixFQUMzQixpQkFBb0MsRUFDSCxXQUF5QjtRQUVwRSxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7UUFOTixhQUFRLEdBQVIsUUFBUSxDQUFpQjtRQUN6QixhQUFRLEdBQVIsUUFBUSxDQUFzQjtRQUM5QixjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQUMzQixzQkFBaUIsR0FBakIsaUJBQWlCLENBQW1CO1FBQ0gsZ0JBQVcsR0FBWCxXQUFXLENBQWM7UUFHcEUsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLFdBQVcsQ0FBQyxVQUFVLENBQUM7UUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTTtZQUFFLE9BQU8sQ0FBQyxLQUFLLENBQUMsMEJBQTBCLENBQUMsQ0FBQztJQUM3RCxDQUFDO0lBRVMsS0FBSyxDQUFDLFNBQVM7UUFDdkIsSUFBSSxDQUFDO1lBQ0gsTUFBTSxNQUFNLEdBQUcsU0FBUyxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JELE9BQU8sQ0FBQyxJQUFJLENBQUMsZ0NBQWdDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixPQUFPLENBQUMsS0FBSyxDQUFDLDhCQUE4QixHQUFHLENBQUMsR0FBRyxFQUFFLE9BQU8sSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3hFLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQUcsQ0FDUCxLQUFhLEVBQ2IsSUFBcUc7UUFFckcsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQUUsTUFBTSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFFdEMsa0NBQWtDO1FBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDL0IsT0FBTyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQzdDLENBQUM7UUFFRCxPQUFPLENBQUMsSUFBSSxDQUFDLGlDQUFpQyxDQUFDLENBQUM7UUFFaEQsSUFBSSxDQUFDO1lBQ0gsTUFBTSxJQUFJLEdBQUcsTUFBTSxNQUFNLENBQUMsUUFBUSxDQUFDO2dCQUNqQyxNQUFNLEVBQUUsSUFBSSxDQUFDLGdCQUFnQjtnQkFDN0IsS0FBSyxFQUFFLElBQUksQ0FBQyxlQUFlO2dCQUMzQixpQkFBaUIsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxtQkFBbUIsQ0FBQztnQkFDOUQsa0JBQWtCLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMseUJBQXlCLENBQUM7Z0JBQ3JFLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxPQUFPO2dCQUNwQyxHQUFHLElBQUk7YUFDUixDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsSUFBSTtnQkFBRSxPQUFPLFNBQVMsQ0FBQztZQUU1QixRQUFRO1lBQ1IsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztnQkFDN0IsT0FBTyxDQUFDLEtBQUssQ0FBQyx5Q0FBeUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdEUsQ0FBQztZQUVELE9BQU87Z0JBQ0U7b0JBQ0wsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO29CQUNyQixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUk7aUJBQ2hCO2FBQ0YsQ0FBQztRQUNKLENBQUM7UUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2IsT0FBTyxDQUFDLElBQUksQ0FBQyw2Q0FBNkMsR0FBRyxFQUFFLE9BQU8sSUFBSSxHQUFHLE9BQU8sR0FBRyxFQUFFLGFBQWEsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQ2hILE9BQU8sU0FBUyxDQUFDO1FBQ25CLENBQUM7SUFDSCxDQUFDO0lBRUQsK0JBQStCO0lBRXJCLEtBQUssQ0FBQyxpQkFBaUIsQ0FDL0IsS0FBYSxFQUNiLElBQXNGO1FBRXRGLE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLFVBQVUsQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLEVBQUUsS0FBSyxFQUFFO1lBQ2pGLFVBQVUsRUFBRSxJQUFJLEVBQUUsUUFBUSxLQUFLLElBQUk7WUFDbkMsYUFBYSxFQUFFLFlBQVk7WUFDM0IsYUFBYSxFQUFFLElBQUk7WUFDbkIsUUFBUSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FDakIsV0FBVyxDQUFDLGFBQWEsQ0FBQyxJQUFJLEVBQUU7Z0JBQzlCLFFBQVEsRUFBRSxJQUFJLENBQUMsZUFBZTtnQkFDOUIsU0FBUyxFQUFFLElBQUksQ0FBQyxnQkFBZ0I7Z0JBQ2hDLEdBQUcsSUFBSTthQUNSLENBQUM7U0FDTCxDQUFDLENBQUM7UUFFSCxJQUFJLFlBQVksQ0FBQyxJQUFJLENBQUM7WUFBRSxPQUFPLENBQUMsMEJBQTBCO1FBQzFELE9BQU8sQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO2FBQ2hCLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxxQ0FBcUM7YUFDdkUsR0FBRyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxDQUFPLEVBQUUsT0FBTyxFQUFFLENBQUEsQ0FBQyxDQUFDO0lBQzFDLENBQUM7d0dBeEZVLFlBQVksc0pBU2IsV0FBVzs0R0FUVixZQUFZLGNBREMsTUFBTTs7NEZBQ25CLFlBQVk7a0JBRHhCLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkFVN0IsTUFBTTsyQkFBQyxXQUFXOzswQkFBRyxRQUFRIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0LCBJbmplY3RhYmxlLCBPcHRpb25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgUG9wb3ZlckNvbnRyb2xsZXIgfSBmcm9tICdAaW9uaWMvYW5ndWxhcic7XG5cbmltcG9ydCB7IFRyYW5zbGF0ZVNlcnZpY2UgfSBmcm9tICdAbmd4LXRyYW5zbGF0ZS9jb3JlJztcbmltcG9ydCB7IFN0YXJ0YWJsZVNlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9zdGFydGFibGUtc2VydmljZS5jbGFzcyc7XG5pbXBvcnQgeyBFTlZJUk9OTUVOVCwgRW52aXJvbm1lbnQgfSBmcm9tICcuLi8uLi8uLi9lbnZpcm9ubWVudHMvZW52aXJvbm1lbnQuY2xhc3MnO1xuaW1wb3J0IHsgUGxhdGZvcm1TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29yZS9zZXJ2aWNlcy9wbGF0Zm9ybS5zZXJ2aWNlJztcbmltcG9ydCB7IExvY2FsU2V0dGluZ3NTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vY29yZS9zZXJ2aWNlcy9sb2NhbC1zZXR0aW5ncy5zZXJ2aWNlJztcbmltcG9ydCB7IEZpbGVzVXRpbHMgfSBmcm9tICcuLi9maWxlL2ZpbGUudXRpbHMnO1xuaW1wb3J0IHsgSW1hZ2VzVXRpbHMgfSBmcm9tICcuLi9maWxlL2ltYWdlcy51dGlscyc7XG5pbXBvcnQgeyBpc0VtcHR5QXJyYXkgfSBmcm9tICcuLi9mdW5jdGlvbnMnO1xuXG5pbXBvcnQgeyBJbWFnZSB9IGZyb20gJy4vaW1hZ2UubW9kZWwnO1xuaW1wb3J0IHsgQ2FwYWNpdG9yIH0gZnJvbSAnQGNhcGFjaXRvci9jb3JlJztcbmltcG9ydCB7IENhbWVyYSwgQ2FtZXJhUmVzdWx0VHlwZSwgSW1hZ2VPcHRpb25zIH0gZnJvbSAnQGNhcGFjaXRvci9jYW1lcmEnO1xuXG5ASW5qZWN0YWJsZSh7IHByb3ZpZGVkSW46ICdyb290JyB9KVxuZXhwb3J0IGNsYXNzIEltYWdlU2VydmljZSBleHRlbmRzIFN0YXJ0YWJsZVNlcnZpY2Uge1xuICBwcml2YXRlIGRlZmF1bHRNYXhIZWlnaHQgPSAxMDI0O1xuICBwcml2YXRlIGRlZmF1bHRNYXhXaWR0aCA9IDEwMjQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIHBsYXRmb3JtOiBQbGF0Zm9ybVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIHNldHRpbmdzOiBMb2NhbFNldHRpbmdzU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgdHJhbnNsYXRlOiBUcmFuc2xhdGVTZXJ2aWNlLFxuICAgIHByb3RlY3RlZCBwb3BvdmVyQ29udHJvbGxlcjogUG9wb3ZlckNvbnRyb2xsZXIsXG4gICAgQEluamVjdChFTlZJUk9OTUVOVCkgQE9wdGlvbmFsKCkgcHJvdGVjdGVkIGVudmlyb25tZW50PzogRW52aXJvbm1lbnRcbiAgKSB7XG4gICAgc3VwZXIocGxhdGZvcm0pO1xuICAgIHRoaXMuX2RlYnVnID0gIWVudmlyb25tZW50LnByb2R1Y3Rpb247XG4gICAgaWYgKHRoaXMuX2RlYnVnKSBjb25zb2xlLmRlYnVnKGBbaW1hZ2VdIENyZWF0aW5nIHNlcnZpY2VgKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBhc3luYyBuZ09uU3RhcnQoKTogUHJvbWlzZTxhbnk+IHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgY2FtZXJhID0gQ2FwYWNpdG9yLmlzUGx1Z2luQXZhaWxhYmxlKCdDYW1lcmEnKTtcbiAgICAgIGNvbnNvbGUuaW5mbyhgW2ltYWdlXSBTdGFydGluZy4uLiB7Y2FtZXJhOiAke2NhbWVyYX19YCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdDYW5ub3QgY2hlY2sgQ2FtZXJhIHBsdWdpbjogJyArIChlcnI/Lm1lc3NhZ2UgfHwgZXJyKSk7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgYWRkKFxuICAgIGV2ZW50PzogRXZlbnQsXG4gICAgb3B0cz86IHsgbWF4SGVpZ2h0PzogbnVtYmVyOyBtYXdXaWR0aD86IG51bWJlcjsgcXVhbGl0eT86IG51bWJlcjsgbXVsdGlwbGU/OiBib29sZWFuIH0gJiBJbWFnZU9wdGlvbnNcbiAgKTogUHJvbWlzZTxJbWFnZVtdIHwgdW5kZWZpbmVkPiB7XG4gICAgaWYgKCF0aGlzLnN0YXJ0ZWQpIGF3YWl0IHRoaXMucmVhZHkoKTtcblxuICAgIC8vIElmIGRlc2t0b3A6IG9wZW4gdXBsb2FkIHBvcG92ZXJcbiAgICBpZiAoIXRoaXMucGxhdGZvcm0uaXNDb3Jkb3ZhKCkpIHtcbiAgICAgIHJldHVybiB0aGlzLmFkZFVwbG9hZGVkSW1hZ2VzKGV2ZW50LCBvcHRzKTtcbiAgICB9XG5cbiAgICBjb25zb2xlLmluZm8oYFtpbWFnZS1zZXJ2aWNlXSBBZGRpbmcgaW1hZ2UuLi5gKTtcblxuICAgIHRyeSB7XG4gICAgICBjb25zdCBkYXRhID0gYXdhaXQgQ2FtZXJhLmdldFBob3RvKHtcbiAgICAgICAgaGVpZ2h0OiB0aGlzLmRlZmF1bHRNYXhIZWlnaHQsXG4gICAgICAgIHdpZHRoOiB0aGlzLmRlZmF1bHRNYXhXaWR0aCxcbiAgICAgICAgcHJvbXB0TGFiZWxDYW5jZWw6IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ0NPTU1PTi5CVE5fQ0FOQ0VMJyksXG4gICAgICAgIHByb21wdExhYmVsUGljdHVyZTogdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnSU1BR0UuQlROX0NBTUVSQV9TT1VSQ0UnKSxcbiAgICAgICAgcmVzdWx0VHlwZTogQ2FtZXJhUmVzdWx0VHlwZS5EYXRhVXJsLFxuICAgICAgICAuLi5vcHRzLFxuICAgICAgfSk7XG4gICAgICBpZiAoIWRhdGEpIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgICAgIC8vIERFQlVHXG4gICAgICBpZiAodGhpcy5fZGVidWcgJiYgZGF0YS5leGlmKSB7XG4gICAgICAgIGNvbnNvbGUuZGVidWcoYFtpbWFnZS1zZXJ2aWNlXSBJbWFnZSBhZGRlZCwgd2l0aCBleGlmOmAsIGRhdGEuZXhpZik7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbXG4gICAgICAgIDxJbWFnZT57XG4gICAgICAgICAgZGF0YVVybDogZGF0YS5kYXRhVXJsLFxuICAgICAgICAgIGV4aWY6IGRhdGEuZXhpZixcbiAgICAgICAgfSxcbiAgICAgIF07XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmluZm8oYFtpbWFnZS1zZXJ2aWNlXSBFcnJvciB3aGlsZSBhZGRpbmcgaW1hZ2U6ICR7ZXJyPy5tZXNzYWdlIHx8IGVycn0gLT4gJHtlcnI/Lm9yaWdpbmFsU3RhY2sgfHwgJyd9YCk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIC8qIC0tIHByb3RlY3RlZCBmdW5jdGlvbnMgLS0gKi9cblxuICBwcm90ZWN0ZWQgYXN5bmMgYWRkVXBsb2FkZWRJbWFnZXMoXG4gICAgZXZlbnQ/OiBFdmVudCxcbiAgICBvcHRzPzogeyBtYXhIZWlnaHQ/OiBudW1iZXI7IG1hd1dpZHRoPzogbnVtYmVyOyBxdWFsaXR5PzogbnVtYmVyOyBtdWx0aXBsZT86IGJvb2xlYW4gfVxuICApOiBQcm9taXNlPEltYWdlW10gfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCB7IGRhdGEgfSA9IGF3YWl0IEZpbGVzVXRpbHMuc2hvd1VwbG9hZFBvcG92ZXIodGhpcy5wb3BvdmVyQ29udHJvbGxlciwgZXZlbnQsIHtcbiAgICAgIHVuaXF1ZUZpbGU6IG9wdHM/Lm11bHRpcGxlICE9PSB0cnVlLFxuICAgICAgZmlsZUV4dGVuc2lvbjogJy5wbmcsIC5qcGcnLFxuICAgICAgaW5zdGFudFVwbG9hZDogdHJ1ZSxcbiAgICAgIHVwbG9hZEZuOiAoZmlsZSkgPT5cbiAgICAgICAgSW1hZ2VzVXRpbHMucmVhZEFzRGF0YVVSTChmaWxlLCB7XG4gICAgICAgICAgbWF4V2lkdGg6IHRoaXMuZGVmYXVsdE1heFdpZHRoLFxuICAgICAgICAgIG1heEhlaWdodDogdGhpcy5kZWZhdWx0TWF4SGVpZ2h0LFxuICAgICAgICAgIC4uLm9wdHMsXG4gICAgICAgIH0pLFxuICAgIH0pO1xuXG4gICAgaWYgKGlzRW1wdHlBcnJheShkYXRhKSkgcmV0dXJuOyAvLyBObyBmaWxlcyB1cGxvYWRlZDogc2tpcFxuICAgIHJldHVybiAoZGF0YSB8fCBbXSlcbiAgICAgIC5tYXAoKGZpbGUpID0+IGZpbGUucmVzcG9uc2UuYm9keSkgLy8gR2V0IHJlc3BvbnNlIGJvZHkgPSBkYXRhIGFzIGJhc2U2NFxuICAgICAgLm1hcCgoZGF0YVVybCkgPT4gPEltYWdlPnsgZGF0YVVybCB9KTtcbiAgfVxufVxuIl19
|
|
@@ -25830,19 +25830,15 @@ class ImageService extends StartableService {
|
|
|
25830
25830
|
settings;
|
|
25831
25831
|
translate;
|
|
25832
25832
|
popoverController;
|
|
25833
|
-
actionSheetController;
|
|
25834
25833
|
environment;
|
|
25835
25834
|
defaultMaxHeight = 1024;
|
|
25836
25835
|
defaultMaxWidth = 1024;
|
|
25837
|
-
constructor(platform, settings, translate, popoverController,
|
|
25838
|
-
// protected camera: Camera,
|
|
25839
|
-
actionSheetController, environment) {
|
|
25836
|
+
constructor(platform, settings, translate, popoverController, environment) {
|
|
25840
25837
|
super(platform);
|
|
25841
25838
|
this.platform = platform;
|
|
25842
25839
|
this.settings = settings;
|
|
25843
25840
|
this.translate = translate;
|
|
25844
25841
|
this.popoverController = popoverController;
|
|
25845
|
-
this.actionSheetController = actionSheetController;
|
|
25846
25842
|
this.environment = environment;
|
|
25847
25843
|
this._debug = !environment.production;
|
|
25848
25844
|
if (this._debug)
|
|
@@ -25876,9 +25872,14 @@ class ImageService extends StartableService {
|
|
|
25876
25872
|
});
|
|
25877
25873
|
if (!data)
|
|
25878
25874
|
return undefined;
|
|
25875
|
+
// DEBUG
|
|
25876
|
+
if (this._debug && data.exif) {
|
|
25877
|
+
console.debug(`[image-service] Image added, with exif:`, data.exif);
|
|
25878
|
+
}
|
|
25879
25879
|
return [
|
|
25880
25880
|
{
|
|
25881
25881
|
dataUrl: data.dataUrl,
|
|
25882
|
+
exif: data.exif,
|
|
25882
25883
|
},
|
|
25883
25884
|
];
|
|
25884
25885
|
}
|
|
@@ -25890,7 +25891,7 @@ class ImageService extends StartableService {
|
|
|
25890
25891
|
/* -- protected functions -- */
|
|
25891
25892
|
async addUploadedImages(event, opts) {
|
|
25892
25893
|
const { data } = await FilesUtils.showUploadPopover(this.popoverController, event, {
|
|
25893
|
-
uniqueFile: true,
|
|
25894
|
+
uniqueFile: opts?.multiple !== true,
|
|
25894
25895
|
fileExtension: '.png, .jpg',
|
|
25895
25896
|
instantUpload: true,
|
|
25896
25897
|
uploadFn: (file) => ImagesUtils.readAsDataURL(file, {
|
|
@@ -25905,13 +25906,13 @@ class ImageService extends StartableService {
|
|
|
25905
25906
|
.map((file) => file.response.body) // Get response body = data as base64
|
|
25906
25907
|
.map((dataUrl) => ({ dataUrl }));
|
|
25907
25908
|
}
|
|
25908
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, deps: [{ token: PlatformService }, { token: LocalSettingsService }, { token: i1$1.TranslateService }, { token: i2$1.PopoverController }, { token:
|
|
25909
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, deps: [{ token: PlatformService }, { token: LocalSettingsService }, { token: i1$1.TranslateService }, { token: i2$1.PopoverController }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
25909
25910
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, providedIn: 'root' });
|
|
25910
25911
|
}
|
|
25911
25912
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ImageService, decorators: [{
|
|
25912
25913
|
type: Injectable,
|
|
25913
25914
|
args: [{ providedIn: 'root' }]
|
|
25914
|
-
}], ctorParameters: () => [{ type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: i2$1.PopoverController }, { type:
|
|
25915
|
+
}], ctorParameters: () => [{ type: PlatformService }, { type: LocalSettingsService }, { type: i1$1.TranslateService }, { type: i2$1.PopoverController }, { type: Environment, decorators: [{
|
|
25915
25916
|
type: Inject,
|
|
25916
25917
|
args: [ENVIRONMENT]
|
|
25917
25918
|
}, {
|
|
@@ -25956,6 +25957,7 @@ class AppImageGalleryComponent {
|
|
|
25956
25957
|
showTitle = true;
|
|
25957
25958
|
showAddTextButton = false;
|
|
25958
25959
|
showAddCardButton = true;
|
|
25960
|
+
showCardToolbar = true;
|
|
25959
25961
|
addButtonColor = 'tertiary';
|
|
25960
25962
|
addButtonText = 'COMMON.BTN_ADD';
|
|
25961
25963
|
cardTemplate;
|
|
@@ -26007,6 +26009,7 @@ class AppImageGalleryComponent {
|
|
|
26007
26009
|
this.mode = this.mode ?? (this.mobile ? 'list' : 'mosaic');
|
|
26008
26010
|
this._colSize = GalleryModeColSize[this.mode];
|
|
26009
26011
|
this.showToolbar = toBoolean(this.showToolbar, !this.mobile);
|
|
26012
|
+
this.showCardToolbar = toBoolean(this.showCardToolbar, !this.mobile);
|
|
26010
26013
|
this.showAddCardButton = toBoolean(this.showAddCardButton, this.mobile);
|
|
26011
26014
|
this.showFabButton = toBoolean(this.showFabButton, this.mobile && !this.showAddCardButton);
|
|
26012
26015
|
// Get modal presenting element (iOS only)
|
|
@@ -26084,7 +26087,7 @@ class AppImageGalleryComponent {
|
|
|
26084
26087
|
event?.preventDefault();
|
|
26085
26088
|
event?.stopPropagation();
|
|
26086
26089
|
event?.stopImmediatePropagation();
|
|
26087
|
-
this.
|
|
26090
|
+
this.focusCardToolbar(cardToolbar);
|
|
26088
26091
|
const titleControl = new FormControl(row.currentData.title, Validators.compose([Validators.required, Validators.maxLength(255)]));
|
|
26089
26092
|
this._titleForm = new FormGroup({ title: titleControl });
|
|
26090
26093
|
this._titleAutofocus = this.mobile && this.enabled && !this.readOnly;
|
|
@@ -26100,7 +26103,7 @@ class AppImageGalleryComponent {
|
|
|
26100
26103
|
// Hide the toolbar, because the focus have been given to the event's origin (the edit button)
|
|
26101
26104
|
setTimeout(() => this.hideCardToolbar(cardToolbar), 750);
|
|
26102
26105
|
}
|
|
26103
|
-
|
|
26106
|
+
focusCardToolbar(cardToolbar) {
|
|
26104
26107
|
const el = cardToolbar['el'];
|
|
26105
26108
|
el.classList.add('focused');
|
|
26106
26109
|
}
|
|
@@ -26253,11 +26256,11 @@ class AppImageGalleryComponent {
|
|
|
26253
26256
|
this.cd.markForCheck();
|
|
26254
26257
|
}
|
|
26255
26258
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppImageGalleryComponent, deps: [{ token: ImageService }, { token: i2$1.Platform }, { token: i2$1.AlertController }, { token: i1$1.TranslateService }, { token: i0.ChangeDetectorRef }, { token: ENVIRONMENT, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
26256
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: ["debug", "debug", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], mobile: ["mobile", "mobile", booleanAttribute], mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: ["showToolbar", "showToolbar", booleanAttribute], showFabButton: ["showFabButton", "showFabButton", booleanAttribute], showTitle: ["showTitle", "showTitle", booleanAttribute], showAddTextButton: ["showAddTextButton", "showAddTextButton", booleanAttribute], showAddCardButton: ["showAddCardButton", "showAddCardButton", booleanAttribute], addButtonColor: "addButtonColor", addButtonText: "addButtonText", cardTemplate: "cardTemplate", imageSizes: "imageSizes", imageSizeQueryParam: "imageSizeQueryParam", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows", onAfterEditRow: "onAfterEditRow", click: "click" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }, { propertyName: "swiperRef", first: true, predicate: ["modalSwiper"], descendants: true }], ngImport: i0, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: image, mode: mode }\"></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\" *ngIf=\"image.title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n <button\n mat-button\n *ngIf=\"showTitle\"\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"addButtonText\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>ion-img{min-height:100%;max-height:var(--img-max-height);transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"], dependencies: [{ kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2$1.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonModal, selector: "ion-modal" }, { kind: "component", type: i2$1.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2$1.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i1$5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i12$1.RxFor, selector: "[rxFor][rxForOf]", inputs: ["rxForOf", "rxForTemplate", "rxForStrategy", "rxForParent", "rxForPatchZone", "rxForTrackBy", "rxForRenderCallback"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: AppendQueryParamsPipePipe, name: "appendQueryParams" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
26259
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: { cardColor: "cardColor", debug: ["debug", "debug", booleanAttribute], disabled: ["disabled", "disabled", booleanAttribute], readOnly: ["readOnly", "readOnly", booleanAttribute], mobile: ["mobile", "mobile", booleanAttribute], mode: "mode", confirmBeforeDelete: "confirmBeforeDelete", showToolbar: ["showToolbar", "showToolbar", booleanAttribute], showFabButton: ["showFabButton", "showFabButton", booleanAttribute], showTitle: ["showTitle", "showTitle", booleanAttribute], showAddTextButton: ["showAddTextButton", "showAddTextButton", booleanAttribute], showAddCardButton: ["showAddCardButton", "showAddCardButton", booleanAttribute], showCardToolbar: ["showCardToolbar", "showCardToolbar", booleanAttribute], addButtonColor: "addButtonColor", addButtonText: "addButtonText", cardTemplate: "cardTemplate", imageSizes: "imageSizes", imageSizeQueryParam: "imageSizeQueryParam", dataSource: "dataSource" }, outputs: { onBeforeDeleteRows: "onBeforeDeleteRows", onAfterAddRows: "onAfterAddRows", onAfterEditRow: "onAfterEditRow", click: "click" }, viewQueries: [{ propertyName: "zoomModal", first: true, predicate: ["zoomModal"], descendants: true }, { propertyName: "titlePopover", first: true, predicate: ["titlePopover"], descendants: true }, { propertyName: "swiperRef", first: true, predicate: ["modalSwiper"], descendants: true }], ngImport: i0, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: image, mode: mode }\"></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"addButtonText\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>ion-img{min-height:100%;max-height:var(--img-max-height);transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"], dependencies: [{ kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i2$1.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: i2$1.IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i2$1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i2$1.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i2$1.IonImg, selector: "ion-img", inputs: ["alt", "src"] }, { kind: "component", type: i2$1.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonSegment, selector: "ion-segment", inputs: ["color", "disabled", "mode", "scrollable", "selectOnFocus", "swipeGesture", "value"] }, { kind: "component", type: i2$1.IonSegmentButton, selector: "ion-segment-button", inputs: ["disabled", "layout", "mode", "type", "value"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonModal, selector: "ion-modal" }, { kind: "component", type: i2$1.IonPopover, selector: "ion-popover" }, { kind: "directive", type: i2$1.SelectValueAccessor, selector: "ion-select, ion-radio-group, ion-segment, ion-datetime" }, { kind: "directive", type: i1$3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i3.MatLabel, selector: "mat-label" }, { kind: "directive", type: i4.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i6$1.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i9.MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "component", type: i9.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "directive", type: i1$5.CdkTrapFocus, selector: "[cdkTrapFocus]", inputs: ["cdkTrapFocus", "cdkTrapFocusAutoCapture"], exportAs: ["cdkTrapFocus"] }, { kind: "directive", type: i1$1.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "directive", type: i12$1.RxFor, selector: "[rxFor][rxForOf]", inputs: ["rxForOf", "rxForTemplate", "rxForStrategy", "rxForParent", "rxForPatchZone", "rxForTrackBy", "rxForRenderCallback"] }, { kind: "pipe", type: i1$1.TranslatePipe, name: "translate" }, { kind: "pipe", type: PropertyGetPipe, name: "propertyGet" }, { kind: "pipe", type: ArrayLengthPipe, name: "isArrayLength" }, { kind: "pipe", type: IsNotNilOrBlankPipe, name: "isNotNilOrBlank" }, { kind: "pipe", type: AppendQueryParamsPipePipe, name: "appendQueryParams" }], animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
26257
26260
|
}
|
|
26258
26261
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AppImageGalleryComponent, decorators: [{
|
|
26259
26262
|
type: Component,
|
|
26260
|
-
args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: image, mode: mode }\"></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n <ion-toolbar color=\"transparent\" class=\"title\" *ngIf=\"image.title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n\n <!-- action toolbar (desktop only) shown when hover image -->\n <ion-toolbar #cardToolbar *ngIf=\"!mobile && !readOnly\" color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n <button\n mat-button\n *ngIf=\"showTitle\"\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"showCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"addButtonText\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>ion-img{min-height:100%;max-height:var(--img-max-height);transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"] }]
|
|
26263
|
+
args: [{ selector: 'app-image-gallery', animations: [fadeInAnimation, fadeInOutAnimation], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ion-toolbar color=\"light\" *ngIf=\"showToolbar\">\n <!-- Add -->\n <button\n mat-icon-button\n *ngIf=\"!readOnly && !mobile && enabled\"\n [title]=\"'COMMON.BTN_ADD' | translate\"\n (click)=\"add()\"\n >\n <mat-icon>add</mat-icon>\n </button>\n\n <ion-buttons slot=\"end\">\n <!-- Toggle view mode -->\n <ion-segment (ionChange)=\"toggleViewMode($event)\" color=\"accent\" [value]=\"_colSize\">\n <ion-segment-button [value]=\"4\">\n <mat-icon>view_module</mat-icon>\n </ion-segment-button>\n <ion-segment-button [value]=\"12\">\n <mat-icon>view_list</mat-icon>\n </ion-segment-button>\n </ion-segment>\n </ion-buttons>\n</ion-toolbar>\n\n<div class=\"gallery-container ion-padding-bottom {{ this.mode }}\">\n <div *ngIf=\"mobile && zoomActive\" class=\"backdrop\" [style.opacity]=\"zoomScale\"></div>\n\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <ion-col *rxFor=\"let row of _data$; index as index; trackBy: trackByFn\" [size]=\"_colSize\">\n @let image = row | propertyGet: 'currentData';\n @if (cardTemplate) {\n <ng-container *ngTemplateOutlet=\"cardTemplate; context: { $implicit: image, mode: mode }\"></ng-container>\n } @else {\n <ion-card\n #card\n class=\"image-card\"\n [class.zoom-hover]=\"!mobile\"\n [color]=\"cardColor\"\n (click)=\"clickRow(row, index)\"\n tappable\n @fadeInAnimation\n >\n <figure class=\"card-thumbnail\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams()\" />\n } @else {\n <ion-img [src]=\"image.dataUrl\" />\n }\n </figure>\n\n <!-- toolbar for title (when not hover) -->\n @if (showTitle && image.title) {\n <ion-toolbar color=\"transparent\" class=\"title\">\n <ion-label class=\"card-title\">{{ image.title }}</ion-label>\n </ion-toolbar>\n }\n\n <!-- action toolbar shown when hover image -->\n @if (!readOnly && !mobile && showCardToolbar) {\n <ion-toolbar #cardToolbar color=\"light\" class=\"buttons\">\n <!-- edit title button -->\n @if (showTitle) {\n <button\n mat-button\n slot=\"start\"\n [disabled]=\"disabled\"\n (click)=\"editTitle($event, row, cardToolbar)\"\n (focusin)=\"focusCardToolbar(cardToolbar)\"\n >\n <mat-icon>edit</mat-icon>\n <mat-label>\n <span *ngIf=\"row.currentData.title | isNotNilOrBlank; else editLabel\" translate>\n IMAGE.GALLERY.BTN_EDIT_TITLE\n </span>\n <ng-template #editLabel>\n <span translate>IMAGE.GALLERY.BTN_ADD_TITLE</span>\n </ng-template>\n </mat-label>\n </button>\n }\n\n <div class=\"flex-spacer\"></div>\n\n <!-- delete button -->\n <button\n mat-icon-button\n slot=\"end\"\n class=\"ion-float-end\"\n [title]=\"'COMMON.BTN_DELETE' | translate\"\n [disabled]=\"disabled\"\n (click)=\"delete($event, row)\"\n >\n <mat-icon>delete</mat-icon>\n </button>\n </ion-toolbar>\n }\n </ion-card>\n }\n </ion-col>\n\n <!-- add button -->\n @if ((showAddTextButton || showAddCardButton) && !readOnly) {\n <ion-col [size]=\"_colSize\" @fadeInAnimation>\n @if (showAddTextButton) {\n <ion-button (click)=\"add($event)\" [disabled]=\"disabled\" [color]=\"addButtonColor\">\n <mat-label translate>{{ addButtonText }}</mat-label>\n <ion-icon slot=\"end\" name=\"camera\"></ion-icon>\n </ion-button>\n } @else if (showAddCardButton) {\n <ion-card\n class=\"image-card-button\"\n color=\"light\"\n (click)=\"add($event)\"\n [disabled]=\"disabled\"\n [title]=\"addButtonText\"\n tappable\n >\n <ion-card-content>\n <div class=\"icon-container\">\n <ion-icon name=\"camera\" [color]=\"addButtonColor\"></ion-icon>\n <ion-icon name=\"add\" [color]=\"addButtonColor\" class=\"icon-secondary\"></ion-icon>\n </div>\n </ion-card-content>\n </ion-card>\n }\n </ion-col>\n }\n </ion-row>\n </ion-grid>\n</div>\n\n<!-- FAB button: add -->\n<ion-fab\n slot=\"fixed\"\n vertical=\"bottom\"\n horizontal=\"end\"\n *ngIf=\"showFabButton && !readOnly\"\n [class.cdk-visually-hidden]=\"disabled\"\n @fadeInOutAnimation\n>\n <ion-fab-button color=\"tertiary\" (click)=\"add($event)\">\n <ion-icon name=\"camera\"></ion-icon>\n <ion-icon name=\"add\" class=\"icon-secondary\" style=\"left: 33px; top: 9px; font-size: 20px\"></ion-icon>\n </ion-fab-button>\n</ion-fab>\n\n<!-- Zoom modal -->\n<ion-modal #zoomModal class=\"stack-modal zoom-modal\" [class.modal-fullscreen]=\"mobile\" [class.modal-large]=\"!mobile\">\n <ng-template>\n <ion-content class=\"ion-no-padding ion-no-margin\">\n @let count = rows?.length || 0;\n <!-- Counter -->\n <div class=\"top-left\">\n <ion-label color=\"light\">{{ activeSlideIndex + 1 }} / {{ count }}</ion-label>\n </div>\n\n <!-- zoom button -->\n <div class=\"top-right\">\n @if (!mobile) {\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, true)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"add\"></ion-icon>\n </ion-fab-button>\n <ion-fab-button size=\"small\" (click)=\"zoom(modalSwiper, false)\" color=\"light\">\n <ion-icon name=\"search\"></ion-icon>\n <ion-icon class=\"icon-secondary\" name=\"remove\"></ion-icon>\n </ion-fab-button>\n }\n </div>\n\n <!-- navigation side buttons next/back -->\n <ng-container *ngIf=\"!mobile && (rows | isArrayLength: { greaterThan: 1 })\">\n <div class=\"side-buttons prev\" (click)=\"slidePrev(modalSwiper)\">\n <ion-icon name=\"chevron-back\"></ion-icon>\n </div>\n <div class=\"side-buttons next\" (click)=\"slideNext(modalSwiper)\">\n <ion-icon name=\"chevron-forward\"></ion-icon>\n </div>\n </ng-container>\n\n <!-- image slides -->\n <swiper-container\n #modalSwiper\n [modules]=\"swiperModules\"\n [zoom]=\"true\"\n (swiperslidechange)=\"onSlideChange(modalSwiper)\"\n (swiperinit)=\"initModalSlides(modalSwiper)\"\n >\n @for (row of rows; track row.id; let last = $last) {\n <swiper-slide>\n @let image = row | propertyGet: 'currentData';\n <div class=\"swiper-zoom-container\">\n @if (image.url) {\n <ion-img [src]=\"image.url | appendQueryParams: getImageSizeQueryParams('modal')\" />\n } @else {\n <img [src]=\"image.dataUrl\" [alt]=\"image.title\" />\n }\n </div>\n </swiper-slide>\n }\n </swiper-container>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar color=\"light\">\n <ion-row>\n <ion-col size=\"4\" class=\"ion-text-start\">\n <ion-button\n *ngIf=\"!readOnly\"\n (click)=\"deleteFromModal($event, modalSwiper)\"\n [disabled]=\"disabled\"\n fill=\"clear\"\n color=\"danger\"\n >\n <mat-icon slot=\"start\">delete</mat-icon>\n {{ 'COMMON.BTN_DELETE' | translate }}\n </ion-button>\n </ion-col>\n <ion-col size=\"4\"></ion-col>\n <ion-col size=\"4\" class=\"ion-text-end\">\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\" fill=\"clear\" *ngIf=\"mobile; else desktop\">\n <ion-icon slot=\"start\" name=\"close\"></ion-icon>\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n <ng-template #desktop>\n <ion-button (click)=\"zoomModal.dismiss()\" color=\"tertiary\">\n {{ 'COMMON.BTN_CLOSE' | translate }}\n </ion-button>\n </ng-template>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-modal>\n\n<ion-popover #titlePopover>\n <ng-template>\n <ion-content class=\"ion-padding\" cdkTrapFocus [cdkTrapFocusAutoCapture]=\"true\">\n <form [formGroup]=\"_titleForm\">\n <mat-form-field floatLabel=\"auto\">\n <mat-label translate>IMAGE.GALLERY.TITLE</mat-label>\n <input\n matInput\n formControlName=\"title\"\n [readonly]=\"disabled\"\n [appAutofocus]=\"_titleAutofocus\"\n (keydown.control.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n />\n </mat-form-field>\n </form>\n </ion-content>\n\n <ion-footer>\n <ion-toolbar>\n <ion-row class=\"ion-no-padding\" nowrap>\n <ion-col></ion-col>\n\n <ion-col size=\"auto\">\n <ion-button fill=\"clear\" color=\"dark\" (click)=\"titlePopover.dismiss(null, 'CANCEL')\">\n <ion-label translate>COMMON.BTN_CANCEL</ion-label>\n </ion-button>\n <ion-button\n [fill]=\"disabled ? 'clear' : 'solid'\"\n (click)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n (keyup.enter)=\"titlePopover.dismiss(_titleForm.controls.title.value)\"\n color=\"tertiary\"\n [disabled]=\"disabled\"\n [title]=\"'COMMON.BTN_VALIDATE_WITH_SHORTCUT_HELP' | translate\"\n >\n <ion-label translate>COMMON.BTN_VALIDATE</ion-label>\n </ion-button>\n </ion-col>\n </ion-row>\n </ion-toolbar>\n </ion-footer>\n </ng-template>\n</ion-popover>\n", styles: [":host{--image-margin-inline: 10px}mat-toolbar,.mat-toolbar-single-row{padding:0;height:42px}ion-card{margin-left:unset;margin-right:unset;margin-inline:var(--image-margin-inline, 10px)}.image-slide{overflow:visible}.image-card{height:calc(100% - 23px);background-color:var(--ion-color-base);z-index:9;--img-scale: 1}.image-card .card-thumbnail{position:relative;overflow:hidden;display:flex;justify-content:center;align-items:center;margin:0;padding:0;width:100%;height:100%}.image-card .card-thumbnail>ion-img{min-height:100%;max-height:var(--img-max-height);transition:scale .2s ease-in-out;scale:var(--img-scale)}.image-card .card-thumbnail>ion-img img{max-height:var(--img-max-height)}.image-card.zoom-hover:hover{--img-scale: 1.2}.image-card ion-toolbar{--top-offset: calc(-1 * var(--ion-toolbar-height));position:absolute}.image-card ion-toolbar.title{--padding-start: 16px;--padding-end: 16px;--ion-color-base: rgba(0, 0, 0, .45) !important;position:absolute;top:calc(100% + var(--top-offset));transition:opacity .2s ease-in-out}.image-card ion-toolbar.title ion-label{color:#fff}.image-card ion-toolbar.buttons{--padding-start: 4px;--padding-end: 4px;--ion-color-base: var(--ion-color-light) !important;position:absolute;top:100%;transition:transform .2s ease-in-out}.image-card:hover ion-toolbar.buttons,.image-card ion-toolbar.buttons.focused{transform:translateY(var(--top-offset))}.image-card-button{height:calc(100% - var(--image-margin-inline, 0px) * 2 - 3px);transition:.2s ease-in-out;max-width:250px}.image-card-button ion-card-content{height:100%}.image-card-button .icon-container{height:auto;position:relative;top:calc(50% - 75px);display:flex;align-items:center;justify-content:center}.image-card-button ion-icon:first-of-type{font-size:150px;height:150px;position:relative;top:0}.image-card-button ion-icon.icon-secondary{font-size:50px;position:absolute;top:0;left:max(min(50% + 25px,100% - 50px),0px)}.image-card-button ion-button{float:right}.image-card-button:hover{--ion-color-base: var(--ion-color-shade) !important}.image-card-button:hover ion-icon{--ion-color-base: var(--ion-color-shade) !important}.backdrop{height:100vh;width:100vw;background:#000;position:absolute;z-index:10}.zoom-modal{-webkit-user-select:none;user-select:none}.zoom-modal .top-left{z-index:14;position:absolute;display:inline-grid;left:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .top-right{z-index:14;position:absolute;display:inline-grid;right:var(--ion-padding-start, 8px);top:var(--ion-padding-start, 8px)}.zoom-modal .side-buttons{--side-buttons-width: 120px;--side-buttons-margin: calc(var(--side-buttons-width) / 3);z-index:13;position:absolute;top:0;bottom:0;width:var(--side-buttons-width)}.zoom-modal .side-buttons ion-icon{top:50%;color:#fff;font-size:2.5rem;position:absolute;opacity:0;transition-duration:.15s;transition-timing-function:ease-in}.zoom-modal .side-buttons:hover{cursor:pointer}.zoom-modal .side-buttons:hover ion-icon{opacity:1}.zoom-modal .side-buttons.prev{left:0}.zoom-modal .side-buttons.prev ion-icon{left:var(--side-buttons-margin)}.zoom-modal .side-buttons.next{right:0}.zoom-modal .side-buttons.next ion-icon{right:var(--side-buttons-margin)}.zoom-modal swiper-container{height:100%;background:#000}.zoom-modal ion-fab-button .icon-secondary{top:11px;left:6px;height:14px}\n"] }]
|
|
26261
26264
|
}], ctorParameters: () => [{ type: ImageService }, { type: i2$1.Platform }, { type: i2$1.AlertController }, { type: i1$1.TranslateService }, { type: i0.ChangeDetectorRef }, { type: Environment, decorators: [{
|
|
26262
26265
|
type: Optional
|
|
26263
26266
|
}, {
|
|
@@ -26296,6 +26299,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
26296
26299
|
}], showAddCardButton: [{
|
|
26297
26300
|
type: Input,
|
|
26298
26301
|
args: [{ transform: booleanAttribute }]
|
|
26302
|
+
}], showCardToolbar: [{
|
|
26303
|
+
type: Input,
|
|
26304
|
+
args: [{ transform: booleanAttribute }]
|
|
26299
26305
|
}], addButtonColor: [{
|
|
26300
26306
|
type: Input
|
|
26301
26307
|
}], addButtonText: [{
|
|
@@ -45975,7 +45981,7 @@ class GalleryTestPage {
|
|
|
45975
45981
|
this.dataSource.save();
|
|
45976
45982
|
}
|
|
45977
45983
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GalleryTestPage, deps: [{ token: ImageAttachmentService }], target: i0.ɵɵFactoryTarget.Component });
|
|
45978
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GalleryTestPage, selector: "app-gallery-test-page", providers: [{ provide: ImageAttachmentService, useClass: ImageAttachmentService }], ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Image gallery</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n <!-- DEBUG -->\n <app-debug title=\"Galley\">\n <ion-grid>\n <ion-row>\n <ion-col>gallery.count: {{ gallery.rows?.length }}</ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <app-image-gallery\n #gallery\n [dataSource]=\"dataSource\"\n (onAfterAddRows)=\"save()\"\n (onAfterEditRow)=\"save()\"\n ></app-image-gallery>\n</ion-content>\n", dependencies: [{ kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonBackButton, selector: "ion-back-button" }, { kind: "component", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: ["cardColor", "debug", "disabled", "readOnly", "mobile", "mode", "confirmBeforeDelete", "showToolbar", "showFabButton", "showTitle", "showAddTextButton", "showAddCardButton", "addButtonColor", "addButtonText", "cardTemplate", "imageSizes", "imageSizeQueryParam", "dataSource"], outputs: ["onBeforeDeleteRows", "onAfterAddRows", "onAfterEditRow", "click"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }] });
|
|
45984
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: GalleryTestPage, selector: "app-gallery-test-page", providers: [{ provide: ImageAttachmentService, useClass: ImageAttachmentService }], ngImport: i0, template: "<ion-header>\n <ion-toolbar color=\"primary\">\n <ion-buttons slot=\"start\">\n <ion-back-button></ion-back-button>\n </ion-buttons>\n\n <ion-title>Image gallery</ion-title>\n </ion-toolbar>\n</ion-header>\n\n<ion-content>\n <!-- DEBUG -->\n <app-debug title=\"Galley\">\n <ion-grid>\n <ion-row>\n <ion-col>gallery.count: {{ gallery.rows?.length }}</ion-col>\n </ion-row>\n </ion-grid>\n </app-debug>\n\n <app-image-gallery\n #gallery\n [dataSource]=\"dataSource\"\n (onAfterAddRows)=\"save()\"\n (onAfterEditRow)=\"save()\"\n ></app-image-gallery>\n</ion-content>\n", dependencies: [{ kind: "component", type: i2$1.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i2$1.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i2$1.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i2$1.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i2$1.IonHeader, selector: "ion-header", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i2$1.IonRow, selector: "ion-row" }, { kind: "component", type: i2$1.IonTitle, selector: "ion-title", inputs: ["color", "size"] }, { kind: "component", type: i2$1.IonToolbar, selector: "ion-toolbar", inputs: ["color", "mode"] }, { kind: "component", type: i2$1.IonBackButton, selector: "ion-back-button" }, { kind: "component", type: AppImageGalleryComponent, selector: "app-image-gallery", inputs: ["cardColor", "debug", "disabled", "readOnly", "mobile", "mode", "confirmBeforeDelete", "showToolbar", "showFabButton", "showTitle", "showAddTextButton", "showAddCardButton", "showCardToolbar", "addButtonColor", "addButtonText", "cardTemplate", "imageSizes", "imageSizeQueryParam", "dataSource"], outputs: ["onBeforeDeleteRows", "onAfterAddRows", "onAfterEditRow", "click"] }, { kind: "component", type: DebugComponent, selector: "app-debug", inputs: ["titlePrefix", "title", "enable", "expanded"] }] });
|
|
45979
45985
|
}
|
|
45980
45986
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: GalleryTestPage, decorators: [{
|
|
45981
45987
|
type: Component,
|