inviton-powerduck 0.0.137 → 0.0.139
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/app/powerduck-system-resources.ts +2 -0
- package/common/dialog-utils.ts +1 -1
- package/common/external-barcode-scanner.ts +0 -1
- package/common/utils/array-extend.ts +32 -29
- package/common/utils/broswer-image-compression.ts +1 -1
- package/common/utils/language-utils.ts +3 -1
- package/components/app/vue-plugin-jsxtransform.ts +1 -1
- package/components/bootstrap-toggle/index.tsx +6 -1
- package/components/chart-js/pie-chart.tsx +1 -1
- package/components/datatable/datatable-static.tsx +5 -5
- package/components/datatable/datatable.tsx +3 -3
- package/components/datatable/ts/reorder.ts +0 -2
- package/components/dropdown/index.tsx +2 -1
- package/components/dropdown/ts/select2-multi-checkboxes.ts +29 -2
- package/components/fullcalendar/timegrid-calendar.tsx +1 -1
- package/components/image-crop/image-cropping-modal.tsx +54 -15
- package/components/image-crop/upload-and-crop.tsx +21 -13
- package/components/input/localized-info-input.tsx +9 -0
- package/components/input/localized-string-input.tsx +21 -0
- package/components/input/localized-string-textarea.tsx +16 -0
- package/components/input/localized-string-wysiwyg.tsx +16 -0
- package/components/input/translate.tsx +100 -0
- package/components/modal/modal.tsx +1 -1
- package/components/photos/photo-manager.tsx +7 -11
- package/components/share/share-modal.tsx +1 -1
- package/components/share/share.tsx +1 -1
- package/package.json +2 -1
|
@@ -50,6 +50,7 @@ export interface IPowerduckSystemResources {
|
|
|
50
50
|
quickEdit: string;
|
|
51
51
|
quickEditItemsCount: string;
|
|
52
52
|
quickEditErrorNamed: string;
|
|
53
|
+
translateFromThisLanguage: string;
|
|
53
54
|
|
|
54
55
|
languageSK: string;
|
|
55
56
|
languageEN: string;
|
|
@@ -76,6 +77,7 @@ export interface IPowerduckSystemResources {
|
|
|
76
77
|
validationErrorIpAddress: string;
|
|
77
78
|
validationErrorMacAddress: string;
|
|
78
79
|
validationErrorGeneric: string;
|
|
80
|
+
uploadImageInvalidFileType: string;
|
|
79
81
|
|
|
80
82
|
signInGoogle: string;
|
|
81
83
|
signInFacebook: string;
|
package/common/dialog-utils.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { arraySort } from './array-sort';
|
|
2
2
|
|
|
3
|
-
interface ArrayExtended<T> extends Array<T> {
|
|
3
|
+
export interface ArrayExtended<T> extends Array<T> {
|
|
4
4
|
/**
|
|
5
5
|
* Removes given items from the Array
|
|
6
6
|
*
|
|
@@ -16,6 +16,11 @@ interface ArrayExtended<T> extends Array<T> {
|
|
|
16
16
|
*/
|
|
17
17
|
insertAt: (item: T, index: number) => void;
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Clones current array into new instance
|
|
21
|
+
*/
|
|
22
|
+
clone: () => ArrayExtended<T>;
|
|
23
|
+
|
|
19
24
|
/**
|
|
20
25
|
* Sorts array by given property
|
|
21
26
|
*
|
|
@@ -75,10 +80,10 @@ interface ArrayExtended<T> extends Array<T> {
|
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
if (!(Array.prototype as any).find) {
|
|
78
|
-
(Array.prototype as any).find = function (callback) {
|
|
83
|
+
(Array.prototype as any).find = function (callback, ...args) {
|
|
79
84
|
const list = new Object(this);
|
|
80
85
|
const length = (list as any).length >>> 0;
|
|
81
|
-
const thisArg =
|
|
86
|
+
const thisArg = args[0];
|
|
82
87
|
for (let i = 0; i < length; i++) {
|
|
83
88
|
const element = list[i];
|
|
84
89
|
if (callback.call(
|
|
@@ -98,9 +103,9 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
98
103
|
arr = [];
|
|
99
104
|
}
|
|
100
105
|
|
|
101
|
-
((arr as any)).remove =
|
|
102
|
-
for (let i = 0, len =
|
|
103
|
-
const item =
|
|
106
|
+
((arr as any)).remove = (items: [], ...args): void => {
|
|
107
|
+
for (let i = 0, len = args.length; i < len; i++) {
|
|
108
|
+
const item = args[i];
|
|
104
109
|
const itemIndex = arr.indexOf(item);
|
|
105
110
|
|
|
106
111
|
if (itemIndex > -1) {
|
|
@@ -109,7 +114,11 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
109
114
|
}
|
|
110
115
|
};
|
|
111
116
|
|
|
112
|
-
((arr as any)).
|
|
117
|
+
((arr as any)).clone = function () {
|
|
118
|
+
return arrayExtend(this.slice(0));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
((arr as any)).insertAt = (item, index) => {
|
|
113
122
|
arr.splice(
|
|
114
123
|
index,
|
|
115
124
|
0,
|
|
@@ -117,7 +126,7 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
117
126
|
);
|
|
118
127
|
};
|
|
119
128
|
|
|
120
|
-
((arr as any)).contains =
|
|
129
|
+
((arr as any)).contains = (item) => {
|
|
121
130
|
if (item != null) {
|
|
122
131
|
let idProp = 'Id';
|
|
123
132
|
if (item[idProp] == null) {
|
|
@@ -137,7 +146,7 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
137
146
|
return arr.includes(item);
|
|
138
147
|
};
|
|
139
148
|
|
|
140
|
-
((arr as any)).min =
|
|
149
|
+
((arr as any)).min = <T>(callbackfn: (value: T, index: number, array: T[]) => number, defaultValue?: number): number => {
|
|
141
150
|
if (arr.length == 0) {
|
|
142
151
|
return defaultValue;
|
|
143
152
|
}
|
|
@@ -153,7 +162,7 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
153
162
|
)), Number.MAX_VALUE);
|
|
154
163
|
};
|
|
155
164
|
|
|
156
|
-
((arr as any)).max =
|
|
165
|
+
((arr as any)).max = <T>(callbackfn: (value: T, index: number, array: T[]) => number, defaultValue?: number): number => {
|
|
157
166
|
if (arr.length == 0) {
|
|
158
167
|
return defaultValue;
|
|
159
168
|
}
|
|
@@ -169,7 +178,7 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
169
178
|
)), 0);
|
|
170
179
|
};
|
|
171
180
|
|
|
172
|
-
((arr as any)).sum =
|
|
181
|
+
((arr as any)).sum = <T>(callbackfn: (value: T, index: number, array: T[]) => number, defaultValue?: number): number => {
|
|
173
182
|
if (arr.length == 0) {
|
|
174
183
|
return defaultValue;
|
|
175
184
|
}
|
|
@@ -185,28 +194,22 @@ export const arrayExtend = <T>(arr: T[]): ArrayExtended<T> => {
|
|
|
185
194
|
), 0);
|
|
186
195
|
};
|
|
187
196
|
|
|
188
|
-
((arr as any)).selectMany =
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
((arr as any)).selectMany = (callback): any => arr.reduce((
|
|
198
|
+
prevVal,
|
|
199
|
+
u,
|
|
200
|
+
i,
|
|
201
|
+
) => [
|
|
202
|
+
...prevVal,
|
|
203
|
+
...(callback(
|
|
191
204
|
u,
|
|
192
205
|
i,
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
u,
|
|
197
|
-
i,
|
|
198
|
-
arr,
|
|
199
|
-
) as any),
|
|
200
|
-
], []);
|
|
201
|
-
};
|
|
206
|
+
arr,
|
|
207
|
+
) as any),
|
|
208
|
+
], []);
|
|
202
209
|
|
|
203
|
-
((arr as any)).distinct =
|
|
204
|
-
return arr.reduce((un, u) => ({ ...un, u }), {});
|
|
205
|
-
};
|
|
210
|
+
((arr as any)).distinct = (): any => arr.reduce((un, u) => ({ ...un, u }), {});
|
|
206
211
|
|
|
207
|
-
((arr as any)).sortBy =
|
|
208
|
-
return arraySort(arr as any, propName) as any;
|
|
209
|
-
};
|
|
212
|
+
((arr as any)).sortBy = <T>(propName: string | ((item: T) => string | number)): ArrayExtended<T> => arraySort(arr as any, propName) as any;
|
|
210
213
|
|
|
211
214
|
return arr as any;
|
|
212
215
|
};
|
|
@@ -25,7 +25,7 @@ export namespace LanguageUtils {
|
|
|
25
25
|
return name;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export function getLanguageList(): Array<LanguageListItem> {
|
|
28
|
+
export function getLanguageList(sort?: boolean): Array<LanguageListItem> {
|
|
29
29
|
const retVal = <Array<LanguageListItem>>[];
|
|
30
30
|
|
|
31
31
|
const getLanguage = (langCode: Language): LanguageListItem => {
|
|
@@ -80,6 +80,7 @@ export namespace LanguageUtils {
|
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
if (sort === true) {
|
|
83
84
|
try {
|
|
84
85
|
retVal.sort((a, b) => {
|
|
85
86
|
return a.text.localeCompare(b.text);
|
|
@@ -87,6 +88,7 @@ export namespace LanguageUtils {
|
|
|
87
88
|
} catch (e) {
|
|
88
89
|
arraySort(retVal, 'text');
|
|
89
90
|
}
|
|
91
|
+
}
|
|
90
92
|
|
|
91
93
|
LanguageUtils.getLanguageList = function () {
|
|
92
94
|
return retVal;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Validation } from '@vuelidate/core';
|
|
2
2
|
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
|
|
3
3
|
import type { FormItemWrapperArgs, MarginType } from '../form/form-item-wrapper';
|
|
4
|
-
import { Prop, toNative } from 'vue-facing-decorator';
|
|
4
|
+
import { Prop, toNative, Watch } from 'vue-facing-decorator';
|
|
5
5
|
import PowerduckState from '../../app/powerduck-state';
|
|
6
6
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
7
7
|
import { isNullOrEmpty } from '../../common/utils/is-null-or-empty';
|
|
@@ -68,6 +68,11 @@ class BootstrapToggleComponent extends TsxComponent<BootstrapToggleArgs> impleme
|
|
|
68
68
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
@Watch('value')
|
|
72
|
+
onValueChanged() {
|
|
73
|
+
this.$forceUpdate();
|
|
74
|
+
}
|
|
75
|
+
|
|
71
76
|
getCaptionTrue(): string {
|
|
72
77
|
return this.captionTrue || PowerduckState.getResourceValue('yes');
|
|
73
78
|
}
|
|
@@ -84,7 +84,7 @@ class PieChartComponent extends TsxComponent<PieArgs> implements PieArgs {
|
|
|
84
84
|
this.destroyChart();
|
|
85
85
|
|
|
86
86
|
this.$nextTick(() => {
|
|
87
|
-
console.log(this.getCanvasContext() == null);
|
|
87
|
+
// console.log(this.getCanvasContext() == null);
|
|
88
88
|
|
|
89
89
|
this._chart = new Chart(this.getCanvasContext(), {
|
|
90
90
|
type: this.type || PieChartType.Doughnut,
|
|
@@ -67,16 +67,15 @@ export class DataTableStaticComponent extends TsxComponent<DataTableStaticArgs>
|
|
|
67
67
|
return this.getTable().normalizeStringForSearch(str);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
private post(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const rowArr = [...(self.rows || [])];
|
|
70
|
+
private post(_data: any): Promise<any> {
|
|
71
|
+
return new Promise((resolve) => {
|
|
72
|
+
const rowArr = [...(this.rows || [])];
|
|
74
73
|
|
|
75
74
|
resolve({
|
|
76
75
|
TotalCount: rowArr.length,
|
|
77
76
|
TotalFilteredCount: rowArr.length,
|
|
78
77
|
Rows: rowArr,
|
|
79
|
-
InitRows:
|
|
78
|
+
InitRows: this.rows,
|
|
80
79
|
});
|
|
81
80
|
});
|
|
82
81
|
}
|
|
@@ -130,4 +129,5 @@ export class DataTableStaticComponent extends TsxComponent<DataTableStaticArgs>
|
|
|
130
129
|
}
|
|
131
130
|
|
|
132
131
|
const DataTableStatic = toNative(DataTableStaticComponent);
|
|
132
|
+
export type DataTableStaticType = typeof DataTableStatic.prototype;
|
|
133
133
|
export default DataTableStatic;
|
|
@@ -294,6 +294,7 @@ export interface TableColumn {
|
|
|
294
294
|
cssClass?: string;
|
|
295
295
|
visible?: boolean;
|
|
296
296
|
sortable?: boolean;
|
|
297
|
+
searchable?: boolean;
|
|
297
298
|
filterType?: DataTableFilterItemType;
|
|
298
299
|
filterItems?: DataTableFilterItemCollection;
|
|
299
300
|
filterAllowExclusivity?: boolean;
|
|
@@ -2283,7 +2284,6 @@ class DataTableComponent extends TsxComponent<DataTableArgs> implements DataTabl
|
|
|
2283
2284
|
return '';
|
|
2284
2285
|
} else if (filterType == DataTableFilterItemType.Text || filterType == null) {
|
|
2285
2286
|
return (<TextBox updateMode="input" cssClass="dt-filter-input" wrap={false} label={null} placeholder={`${capitalize(PowerduckState.getResourceValue('search'))}...`} value={this.currentAdvancedFilterState[dtColumn.id]} changed={(e) => { this.performInputFilter(dtColumn, e); }} appendIcon={closeIcon} appendIconClicked={appendIconClicked} />);
|
|
2286
|
-
// return (<input class="dt-filter-input" placeholder={AppState.resources.search.capitalize() + "..."} onKeyup={(e) => { this.performInputFilter(dtColumn, e) }} value={this.currentAdvancedFilterState[dtColumn.id]} />)
|
|
2287
2287
|
} else if (filterType == DataTableFilterItemType.Dropdown) {
|
|
2288
2288
|
return (
|
|
2289
2289
|
<div class="dt-filter-dropdown">
|
|
@@ -2291,7 +2291,7 @@ class DataTableComponent extends TsxComponent<DataTableArgs> implements DataTabl
|
|
|
2291
2291
|
label={null}
|
|
2292
2292
|
options={dtColumn.filterItems}
|
|
2293
2293
|
wrap={false}
|
|
2294
|
-
disableSearch={
|
|
2294
|
+
disableSearch={!dtColumn.searchable}
|
|
2295
2295
|
dropdownAutoWidth={true}
|
|
2296
2296
|
multiselect={true}
|
|
2297
2297
|
multiselectMode={MultiselectMode.Checkboxes}
|
|
@@ -2492,5 +2492,5 @@ class DataTableComponent extends TsxComponent<DataTableArgs> implements DataTabl
|
|
|
2492
2492
|
})();
|
|
2493
2493
|
|
|
2494
2494
|
const DataTable = toNative(DataTableComponent);
|
|
2495
|
-
export
|
|
2495
|
+
export type DataTableType = typeof DataTable.prototype;
|
|
2496
2496
|
export default DataTable;
|
|
@@ -70,8 +70,6 @@ function handleDragging(event) {
|
|
|
70
70
|
draggingItem.style.top = `${event.pageY - mouseOffsetY}px`;
|
|
71
71
|
draggingItem.style.left = `${event.pageX - mouseOffsetX}px`;
|
|
72
72
|
|
|
73
|
-
console.log(event.pageX);
|
|
74
|
-
|
|
75
73
|
const draggingItemCoordinates = getDOMNodePosition(draggingItem);
|
|
76
74
|
const prevItem = draggingItem.previousElementSibling;
|
|
77
75
|
const nextItem = draggingItem.nextElementSibling;
|
|
@@ -970,7 +970,7 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
|
|
|
970
970
|
return $(`${builder}</span></span>`);
|
|
971
971
|
};
|
|
972
972
|
} else {
|
|
973
|
-
console.log('Skipping tagsButtons - one of required conditions not met');
|
|
973
|
+
// console.log('Skipping tagsButtons - one of required conditions not met');
|
|
974
974
|
}
|
|
975
975
|
}
|
|
976
976
|
}
|
|
@@ -1218,4 +1218,5 @@ class DropdownListComponent extends TsxComponent<DropdownListArgs> implements Dr
|
|
|
1218
1218
|
}
|
|
1219
1219
|
|
|
1220
1220
|
const DropdownList = toNative(DropdownListComponent);
|
|
1221
|
+
export type DropdownListType = typeof DropdownList.prototype;
|
|
1221
1222
|
export default DropdownList;
|
|
@@ -84,12 +84,39 @@ import { PortalUtils } from '../../../common/utils/utils';
|
|
|
84
84
|
self.$element.select2({
|
|
85
85
|
allowClear: true,
|
|
86
86
|
ajax: {
|
|
87
|
-
transport(
|
|
87
|
+
transport (
|
|
88
88
|
params,
|
|
89
89
|
success,
|
|
90
90
|
failure,
|
|
91
91
|
) {
|
|
92
|
-
|
|
92
|
+
const stripDiacritics = (text: string) => {
|
|
93
|
+
const DIACRITICS = ($ as any).fn.select2.amd.require('select2/diacritics');
|
|
94
|
+
const match = a => DIACRITICS[a] || a;
|
|
95
|
+
return text.replace(/[^\u0000-\u007E]/g, match);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const normalizeForSearch = (text: string) => {
|
|
99
|
+
if (text == null) {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return stripDiacritics(text).toUpperCase();
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
let data = self.currentData || [];
|
|
106
|
+
const searchTerm = normalizeForSearch(params.data?.term?.trim());
|
|
107
|
+
|
|
108
|
+
if (searchTerm == null || searchTerm.trim() == '') {
|
|
109
|
+
success({ results: data || [] });
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const filteredData = data.filter(item => {
|
|
114
|
+
const itemText = normalizeForSearch(item.text);
|
|
115
|
+
return itemText.includes(searchTerm);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
success({ results: filteredData || [] });
|
|
119
|
+
// success({ results: data || [] });
|
|
93
120
|
},
|
|
94
121
|
},
|
|
95
122
|
language: options.language,
|
|
@@ -329,7 +329,7 @@ class TimegridCalendarComponent extends TsxComponent<TimegridCalendarArgs> imple
|
|
|
329
329
|
resourceGroupField: 'building',
|
|
330
330
|
events: this.getEvents(),
|
|
331
331
|
eventRender: (args) => {
|
|
332
|
-
console.log('rendering');
|
|
332
|
+
// console.log('rendering');
|
|
333
333
|
args.el.classList.add('tg-has-menu');
|
|
334
334
|
args.el.setAttribute('data-uuid', args.event.extendedProps.uuid);
|
|
335
335
|
args.el.setAttribute('data-event-id', args.event.id);
|
|
@@ -99,7 +99,7 @@ class ImageCropModalComponent extends TsxComponent<ImageCropModalBindingArgs> im
|
|
|
99
99
|
const start = new Date().getTime();
|
|
100
100
|
const img = new Image();
|
|
101
101
|
img.onload = function () {
|
|
102
|
-
const waitForLoad =
|
|
102
|
+
const waitForLoad = (callback) => {
|
|
103
103
|
if (new Date().getTime() - start > 700) {
|
|
104
104
|
callback();
|
|
105
105
|
} else {
|
|
@@ -150,18 +150,6 @@ class ImageCropModalComponent extends TsxComponent<ImageCropModalBindingArgs> im
|
|
|
150
150
|
(this.$refs.imageCropModal as typeof Modal.prototype).hide();
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
-
private getImageFormat(dataUrl): string {
|
|
154
|
-
if (dataUrl.length > 100) {
|
|
155
|
-
dataUrl = dataUrl.substring(0, 100);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (dataUrl.contains('image/png')) {
|
|
159
|
-
return 'image/png';
|
|
160
|
-
} else {
|
|
161
|
-
return 'image/jpeg';
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
153
|
private handleSaveButtonClicked() {
|
|
166
154
|
this.blocked = true;
|
|
167
155
|
|
|
@@ -169,7 +157,6 @@ class ImageCropModalComponent extends TsxComponent<ImageCropModalBindingArgs> im
|
|
|
169
157
|
const canvas = this.$refs.imageCropCanvas as HTMLCanvasElement;
|
|
170
158
|
const ctx = canvas.getContext('2d');
|
|
171
159
|
const selection = this.getCurrentSelection();
|
|
172
|
-
|
|
173
160
|
image.src = this.getFileName();
|
|
174
161
|
image.onload = async () => {
|
|
175
162
|
this.drawCroppedImageOnCanvas(
|
|
@@ -196,7 +183,7 @@ class ImageCropModalComponent extends TsxComponent<ImageCropModalBindingArgs> im
|
|
|
196
183
|
this.blocked = false;
|
|
197
184
|
}, 500);
|
|
198
185
|
},
|
|
199
|
-
this.getImageFormat(image.src),
|
|
186
|
+
await this.getImageFormat(image.src),
|
|
200
187
|
0.9,
|
|
201
188
|
);
|
|
202
189
|
};
|
|
@@ -272,6 +259,58 @@ class ImageCropModalComponent extends TsxComponent<ImageCropModalBindingArgs> im
|
|
|
272
259
|
}
|
|
273
260
|
}
|
|
274
261
|
|
|
262
|
+
private async getImageFormat(url: string): Promise<string | null> {
|
|
263
|
+
const response = await fetch(url, { mode: 'cors' });
|
|
264
|
+
if (!response.ok) {
|
|
265
|
+
throw new Error('Failed to fetch image');
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const buffer = await response.arrayBuffer();
|
|
269
|
+
const bytes = new Uint8Array(buffer);
|
|
270
|
+
|
|
271
|
+
if (
|
|
272
|
+
bytes[0] === 0x89
|
|
273
|
+
&& bytes[1] === 0x50
|
|
274
|
+
&& bytes[2] === 0x4E
|
|
275
|
+
&& bytes[3] === 0x47
|
|
276
|
+
) {
|
|
277
|
+
return 'image/png';
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (
|
|
281
|
+
bytes[0] === 0xFF
|
|
282
|
+
&& bytes[1] === 0xD8
|
|
283
|
+
&& bytes[bytes.length - 2] === 0xFF
|
|
284
|
+
&& bytes[bytes.length - 1] === 0xD9
|
|
285
|
+
) {
|
|
286
|
+
return 'image/jpeg';
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (
|
|
290
|
+
bytes[0] === 0x47
|
|
291
|
+
&& bytes[1] === 0x49
|
|
292
|
+
&& bytes[2] === 0x46
|
|
293
|
+
&& bytes[3] === 0x38
|
|
294
|
+
) {
|
|
295
|
+
return 'image/gif';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (
|
|
299
|
+
bytes[0] === 0x52
|
|
300
|
+
&& bytes[1] === 0x49
|
|
301
|
+
&& bytes[2] === 0x46
|
|
302
|
+
&& bytes[3] === 0x46
|
|
303
|
+
&& bytes[8] === 0x57
|
|
304
|
+
&& bytes[9] === 0x45
|
|
305
|
+
&& bytes[10] === 0x42
|
|
306
|
+
&& bytes[11] === 0x50
|
|
307
|
+
) {
|
|
308
|
+
return 'image/webp';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
|
|
275
314
|
private getCurrentSelection(): ImageCropSelection {
|
|
276
315
|
const img = $(this.getImageElement()).first();
|
|
277
316
|
const cropHolder = $(this.$refs.imageCroppingContainer).find('.jcrop-active').first();
|
|
@@ -2,8 +2,11 @@ import type { _ButtonArgsBase, ButtonLayout, ButtonSize } from '../button/button
|
|
|
2
2
|
import type { UploadButtonFileObtainedArgs } from '../button/upload-button';
|
|
3
3
|
import type { ImageCroppedUploadArgs } from './image-cropping-modal';
|
|
4
4
|
import { Prop, toNative } from 'vue-facing-decorator';
|
|
5
|
+
import PowerduckState from '../../app/powerduck-state';
|
|
5
6
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
6
7
|
import { BrowserImageCompression } from '../../common/utils/broswer-image-compression';
|
|
8
|
+
import { formatString } from '../../common/utils/format-string';
|
|
9
|
+
import { PortalUtils } from '../../common/utils/utils';
|
|
7
10
|
import UploadButton from '../button/upload-button';
|
|
8
11
|
import LoadingIndicator from '../loading-indicator';
|
|
9
12
|
import NotificationProvider from '../ui/notification';
|
|
@@ -27,6 +30,7 @@ interface UploadImageAndCropButtonArgs extends _ButtonArgsBase {
|
|
|
27
30
|
uploadComplete: (args: any) => void;
|
|
28
31
|
autoCommit?: boolean;
|
|
29
32
|
disableCompression?: boolean;
|
|
33
|
+
allowedTypes?: string[];
|
|
30
34
|
compressionMaxSizeMb?: number;
|
|
31
35
|
isLoading?: boolean;
|
|
32
36
|
}
|
|
@@ -54,6 +58,7 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
54
58
|
@Prop() uploadComplete: (args: any) => void;
|
|
55
59
|
@Prop() autoCommit: boolean;
|
|
56
60
|
@Prop() disableCompression: boolean;
|
|
61
|
+
@Prop() allowedTypes: string[];
|
|
57
62
|
@Prop() compressionMaxSizeMb?: number;
|
|
58
63
|
isInternalLoading: boolean = false;
|
|
59
64
|
|
|
@@ -61,6 +66,11 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
61
66
|
const urlCreator = window.URL || window.webkitURL;
|
|
62
67
|
const imgUrl = urlCreator.createObjectURL(e.file);
|
|
63
68
|
|
|
69
|
+
if (this.allowedTypes?.length > 0 && !this.allowedTypes.includes(e.file.type)) {
|
|
70
|
+
NotificationProvider.showErrorMessage(formatString(PowerduckState.getResourceValue('uploadImageInvalidFileType'), PortalUtils.htmlEscape(this.allowedTypes.join(', '))));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
64
74
|
if (this.useCropper != false) {
|
|
65
75
|
(this.$refs.imgCrop as typeof ImageCropModal.prototype).show({
|
|
66
76
|
fileName: e.file.name,
|
|
@@ -78,9 +88,9 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
78
88
|
file: e.file,
|
|
79
89
|
fileName: e.file.name,
|
|
80
90
|
dataUrl: null,
|
|
81
|
-
}).then((
|
|
91
|
+
}).then(() => {
|
|
82
92
|
this.isInternalLoading = false;
|
|
83
|
-
}).catch((
|
|
93
|
+
}).catch((_err) => {
|
|
84
94
|
this.isInternalLoading = false;
|
|
85
95
|
});
|
|
86
96
|
}
|
|
@@ -91,8 +101,6 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
91
101
|
}
|
|
92
102
|
|
|
93
103
|
async getUploadPromise(args: ImageCroppedUploadArgs): Promise<any> {
|
|
94
|
-
const self = this;
|
|
95
|
-
|
|
96
104
|
if (!(this.disableCompression || args.file.type == 'image/svg+xml')) {
|
|
97
105
|
args.file = await BrowserImageCompression.compress(args.file, {
|
|
98
106
|
maxSizeMB: this.compressionMaxSizeMb,
|
|
@@ -101,8 +109,8 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
101
109
|
|
|
102
110
|
return new Promise((resolve, reject) => {
|
|
103
111
|
const formData = new FormData();
|
|
104
|
-
if (
|
|
105
|
-
const argsVal =
|
|
112
|
+
if (this.uploadArgs != null) {
|
|
113
|
+
const argsVal = this.uploadArgs(args);
|
|
106
114
|
if (argsVal != null) {
|
|
107
115
|
for (const key in argsVal) {
|
|
108
116
|
formData.append(key, argsVal[key]);
|
|
@@ -110,10 +118,10 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
110
118
|
}
|
|
111
119
|
}
|
|
112
120
|
|
|
113
|
-
if (
|
|
121
|
+
if (this.autoCommit === true) {
|
|
114
122
|
const request = new XMLHttpRequest();
|
|
115
|
-
request.open('POST',
|
|
116
|
-
request.onreadystatechange =
|
|
123
|
+
request.open('POST', this.uploadUrl);
|
|
124
|
+
request.onreadystatechange = () => {
|
|
117
125
|
if (request.readyState == 4) {
|
|
118
126
|
let response;
|
|
119
127
|
try {
|
|
@@ -123,8 +131,8 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
if (request.status == 200) {
|
|
126
|
-
if (
|
|
127
|
-
|
|
134
|
+
if (this.uploadComplete) {
|
|
135
|
+
this.uploadComplete(response);
|
|
128
136
|
}
|
|
129
137
|
|
|
130
138
|
resolve(response);
|
|
@@ -144,8 +152,8 @@ class UploadImageAndCropButtonComponent extends TsxComponent<UploadImageAndCropB
|
|
|
144
152
|
|
|
145
153
|
request.send(formData);
|
|
146
154
|
} else {
|
|
147
|
-
const argsVal =
|
|
148
|
-
|
|
155
|
+
const argsVal = this.uploadArgs(args);
|
|
156
|
+
this.uploadComplete(argsVal);
|
|
149
157
|
resolve(formData);
|
|
150
158
|
}
|
|
151
159
|
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ILocalizedText } from '../../common/localized-text';
|
|
2
2
|
import type { ValidationState } from '../../common/static-wrappers/interfaces/validation-interface';
|
|
3
|
+
import type { TranslateGetRequest, TranslateGetResponse } from './translate';
|
|
3
4
|
import { Prop, toNative } from 'vue-facing-decorator';
|
|
4
5
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
5
6
|
import { Language } from '../../common/enums/language';
|
|
@@ -19,6 +20,8 @@ interface LocalizedInfoInputArgs {
|
|
|
19
20
|
validationState?: ValidationState;
|
|
20
21
|
changed: (e: ILocalizedText) => void;
|
|
21
22
|
mandatory?: boolean;
|
|
23
|
+
translatable?: boolean;
|
|
24
|
+
translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
22
25
|
}
|
|
23
26
|
|
|
24
27
|
@Component
|
|
@@ -32,6 +35,8 @@ class LocalizedInfoInputComponent extends TsxComponent<LocalizedInfoInputArgs> i
|
|
|
32
35
|
@Prop() displayType: 'input' | 'textarea';
|
|
33
36
|
@Prop() changed: (e: ILocalizedText) => void;
|
|
34
37
|
@Prop() mandatory?: boolean;
|
|
38
|
+
@Prop({ default: false }) translatable: boolean;
|
|
39
|
+
@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
35
40
|
|
|
36
41
|
getValueForTmrLanguage(lang: Language): string {
|
|
37
42
|
return this.value[lang];
|
|
@@ -99,6 +104,8 @@ class LocalizedInfoInputComponent extends TsxComponent<LocalizedInfoInputArgs> i
|
|
|
99
104
|
changed={(e) => {
|
|
100
105
|
this.valueChanged(e);
|
|
101
106
|
}}
|
|
107
|
+
translatable={this.translatable}
|
|
108
|
+
translateApiMethod={this.translateApiMethod}
|
|
102
109
|
supportedLanguages={[
|
|
103
110
|
Language.sk,
|
|
104
111
|
Language.en,
|
|
@@ -125,6 +132,8 @@ class LocalizedInfoInputComponent extends TsxComponent<LocalizedInfoInputArgs> i
|
|
|
125
132
|
changed={(e) => {
|
|
126
133
|
this.valueChanged(e);
|
|
127
134
|
}}
|
|
135
|
+
translatable={this.translatable}
|
|
136
|
+
translateApiMethod={this.translateApiMethod}
|
|
128
137
|
supportedLanguages={[
|
|
129
138
|
Language.sk,
|
|
130
139
|
Language.en,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ILocalizedText } from '../../common/localized-text';
|
|
2
2
|
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
|
|
3
3
|
import type { FormItemWrapperArgs, HintType, MarginType } from '../form/form-item-wrapper';
|
|
4
|
+
import type { TranslateGetRequest, TranslateGetResponse } from './translate';
|
|
4
5
|
import { Prop, toNative } from 'vue-facing-decorator';
|
|
5
6
|
import PowerduckState from '../../app/powerduck-state';
|
|
6
7
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
@@ -16,6 +17,7 @@ import Modal, { ModalSize } from '../modal/modal';
|
|
|
16
17
|
import ModalBody from '../modal/modal-body';
|
|
17
18
|
import ModalFooter from '../modal/modal-footer';
|
|
18
19
|
import globalIcon from './img/global.png';
|
|
20
|
+
import Translate from './translate';
|
|
19
21
|
import './css/localized-string-input.css';
|
|
20
22
|
|
|
21
23
|
interface LocalizedStringInputArgs extends FormItemWrapperArgs {
|
|
@@ -23,6 +25,8 @@ interface LocalizedStringInputArgs extends FormItemWrapperArgs {
|
|
|
23
25
|
changed: (e: ILocalizedText) => void;
|
|
24
26
|
supportedLanguages?: Language[];
|
|
25
27
|
placeholder?: string;
|
|
28
|
+
translatable?: boolean;
|
|
29
|
+
translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
@Component
|
|
@@ -44,6 +48,8 @@ class LocalizedStringInputComponent extends TsxComponent<LocalizedStringInputArg
|
|
|
44
48
|
@Prop() hintType!: HintType;
|
|
45
49
|
@Prop() appendIcon: string;
|
|
46
50
|
@Prop() prependIcon: string;
|
|
51
|
+
@Prop({default: false}) translatable: boolean;
|
|
52
|
+
@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
47
53
|
@Prop() appendClicked: () => void;
|
|
48
54
|
@Prop() prependClicked: () => void;
|
|
49
55
|
currentValue: ILocalizedText = null;
|
|
@@ -231,6 +237,21 @@ class LocalizedStringInputComponent extends TsxComponent<LocalizedStringInputArg
|
|
|
231
237
|
<img class="lsi-icon" src={LanguageUtils.getLanguageFlagUrl(lang.flag)} />
|
|
232
238
|
</label>
|
|
233
239
|
<div class="col-md-9">
|
|
240
|
+
<div class="d-flex justify-content-end">
|
|
241
|
+
{this.translatable !== false && (
|
|
242
|
+
<Translate
|
|
243
|
+
value={this.currentValue}
|
|
244
|
+
currentLangId={lang.id}
|
|
245
|
+
langArr={LanguageUtils.getLanguageList()}
|
|
246
|
+
changeValue={(langId, value) => {
|
|
247
|
+
this.handleModalValueChange(value, { id: langId });
|
|
248
|
+
this.$forceUpdate();
|
|
249
|
+
}}
|
|
250
|
+
getActualValue={(langId, value) => value[langId]}
|
|
251
|
+
apiMethod={this.translateApiMethod}
|
|
252
|
+
/>
|
|
253
|
+
)}
|
|
254
|
+
</div>
|
|
234
255
|
<div class="form-group maxwidth-input ">
|
|
235
256
|
<input
|
|
236
257
|
type="text"
|
|
@@ -2,6 +2,7 @@ import type { Language } from '../../common/enums/language';
|
|
|
2
2
|
import type { ILocalizedText } from '../../common/localized-text';
|
|
3
3
|
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
|
|
4
4
|
import type { FormItemWrapperArgs, HintType, MarginType } from '../form/form-item-wrapper';
|
|
5
|
+
import type { TranslateGetRequest, TranslateGetResponse } from './translate';
|
|
5
6
|
import { Prop, toNative } from 'vue-facing-decorator';
|
|
6
7
|
import PowerduckState from '../../app/powerduck-state';
|
|
7
8
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
@@ -10,12 +11,15 @@ import FormItemWrapper from '../form/form-item-wrapper';
|
|
|
10
11
|
import { TabPage } from '../tabs/tab-page';
|
|
11
12
|
import Tabs, { TabsRenderMode } from '../tabs/tabs';
|
|
12
13
|
import TextArea from './textarea';
|
|
14
|
+
import Translate from './translate';
|
|
13
15
|
|
|
14
16
|
interface LocalizedStringInputArgs extends FormItemWrapperArgs {
|
|
15
17
|
value: ILocalizedText;
|
|
16
18
|
changed: (e: ILocalizedText) => void;
|
|
17
19
|
supportedLanguages?: Language[];
|
|
18
20
|
placeholder?: string;
|
|
21
|
+
translatable?: boolean;
|
|
22
|
+
translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
25
|
@Component
|
|
@@ -36,6 +40,8 @@ class LocalizedStringTextareaComponent extends TsxComponent<LocalizedStringInput
|
|
|
36
40
|
@Prop() hintType!: HintType;
|
|
37
41
|
@Prop() appendIcon: string;
|
|
38
42
|
@Prop() prependIcon: string;
|
|
43
|
+
@Prop({ default: false }) translatable: boolean;
|
|
44
|
+
@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
39
45
|
@Prop() appendClicked: () => void;
|
|
40
46
|
@Prop() prependClicked: () => void;
|
|
41
47
|
currentValue: ILocalizedText = null;
|
|
@@ -110,6 +116,16 @@ class LocalizedStringTextareaComponent extends TsxComponent<LocalizedStringInput
|
|
|
110
116
|
}}
|
|
111
117
|
rows={4}
|
|
112
118
|
/>
|
|
119
|
+
{this.translatable !== false && (
|
|
120
|
+
<Translate
|
|
121
|
+
value={this.value}
|
|
122
|
+
currentLangId={lang.id}
|
|
123
|
+
langArr={langArr}
|
|
124
|
+
changeValue={this.changeValue.bind(this)}
|
|
125
|
+
getActualValue={(langId, value) => this.getActualValue(langId, value as ILocalizedText)}
|
|
126
|
+
apiMethod={this.translateApiMethod}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
113
129
|
</TabPage>
|
|
114
130
|
))}
|
|
115
131
|
</Tabs>
|
|
@@ -2,6 +2,7 @@ import type { Language } from '../../common/enums/language';
|
|
|
2
2
|
import type { ILocalizedText } from '../../common/localized-text';
|
|
3
3
|
import type { DropdownButtonItemArgs } from '../dropdown-button/dropdown-button-item';
|
|
4
4
|
import type { FormItemWrapperArgs, MarginType } from '../form/form-item-wrapper';
|
|
5
|
+
import type { TranslateGetRequest, TranslateGetResponse } from './translate';
|
|
5
6
|
import { Prop, toNative } from 'vue-facing-decorator';
|
|
6
7
|
import PowerduckState from '../../app/powerduck-state';
|
|
7
8
|
import TsxComponent, { Component } from '../../app/vuetsx';
|
|
@@ -9,6 +10,7 @@ import { LanguageUtils } from '../../common/utils/language-utils';
|
|
|
9
10
|
import FormItemWrapper from '../form/form-item-wrapper';
|
|
10
11
|
import { TabPage } from '../tabs/tab-page';
|
|
11
12
|
import Tabs, { TabsRenderMode } from '../tabs/tabs';
|
|
13
|
+
import Translate from './translate';
|
|
12
14
|
import WysiwigEditor from './wysiwig';
|
|
13
15
|
|
|
14
16
|
interface LocalizedStringInputArgs extends FormItemWrapperArgs {
|
|
@@ -17,6 +19,8 @@ interface LocalizedStringInputArgs extends FormItemWrapperArgs {
|
|
|
17
19
|
supportedLanguages?: Language[];
|
|
18
20
|
placeholder?: string;
|
|
19
21
|
resizable?: boolean;
|
|
22
|
+
translatable?: boolean;
|
|
23
|
+
translateApiMethod?: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
@Component
|
|
@@ -39,6 +43,8 @@ class LocalizedStringWysiwigComponent extends TsxComponent<LocalizedStringInputA
|
|
|
39
43
|
@Prop() prependIcon: string;
|
|
40
44
|
@Prop() appendClicked: () => void;
|
|
41
45
|
@Prop() prependClicked: () => void;
|
|
46
|
+
@Prop({ default: false }) translatable: boolean;
|
|
47
|
+
@Prop() translateApiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
42
48
|
currentValue: ILocalizedText = null;
|
|
43
49
|
editorHeight: number = null;
|
|
44
50
|
|
|
@@ -117,6 +123,16 @@ class LocalizedStringWysiwigComponent extends TsxComponent<LocalizedStringInputA
|
|
|
117
123
|
this.changeValue(lang.id, e);
|
|
118
124
|
}}
|
|
119
125
|
/>
|
|
126
|
+
{this.translatable !== false && (
|
|
127
|
+
<Translate
|
|
128
|
+
value={this.value}
|
|
129
|
+
currentLangId={lang.id}
|
|
130
|
+
langArr={langArr}
|
|
131
|
+
changeValue={this.changeValue.bind(this)}
|
|
132
|
+
getActualValue={(langId, value) => this.getActualValue(langId, value as ILocalizedText)}
|
|
133
|
+
apiMethod={this.translateApiMethod}
|
|
134
|
+
/>
|
|
135
|
+
)}
|
|
120
136
|
</TabPage>
|
|
121
137
|
))}
|
|
122
138
|
</Tabs>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Language } from '../../common/enums/language';
|
|
2
|
+
import type { ILocalizedText } from '../../common/localized-text';
|
|
3
|
+
import type LocalizedText from '../../common/localized-text';
|
|
4
|
+
import { Prop } from 'vue-facing-decorator';
|
|
5
|
+
import PowerduckState from '../../app/powerduck-state';
|
|
6
|
+
import { TsxComponentExtendedBase } from '../../app/vuestsx-extended';
|
|
7
|
+
import { Component } from '../../app/vuetsx';
|
|
8
|
+
import { LanguageUtils } from '../../common/utils/language-utils';
|
|
9
|
+
import TextButton from '../button/text-button';
|
|
10
|
+
|
|
11
|
+
interface TranslateArgs {
|
|
12
|
+
value: ILocalizedText | LocalizedText;
|
|
13
|
+
currentLangId: Language;
|
|
14
|
+
langArr: LanguageUtils.LanguageListItem[];
|
|
15
|
+
changeValue: (langId: Language, value: string) => void;
|
|
16
|
+
getActualValue: (langId: Language, value: ILocalizedText | LocalizedText) => string;
|
|
17
|
+
apiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class TranslateGetRequest {
|
|
21
|
+
fromLang: string;
|
|
22
|
+
toLang: string[];
|
|
23
|
+
text: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export class TranslateGetResponse {
|
|
27
|
+
result: LocalizedText;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Component
|
|
31
|
+
export default class Translate extends TsxComponentExtendedBase<TranslateArgs> implements TranslateArgs {
|
|
32
|
+
@Prop() value: ILocalizedText | LocalizedText;
|
|
33
|
+
@Prop() currentLangId: Language;
|
|
34
|
+
@Prop() langArr: LanguageUtils.LanguageListItem[];
|
|
35
|
+
@Prop() apiMethod: <RQ extends TranslateGetRequest, RS extends TranslateGetResponse>(data?: RQ) => Promise<RS>;
|
|
36
|
+
@Prop() changeValue: (langId: Language, value: string) => void;
|
|
37
|
+
@Prop() getActualValue: (langId: Language, value: ILocalizedText | LocalizedText) => string;
|
|
38
|
+
translateLoading = false;
|
|
39
|
+
|
|
40
|
+
async translateValue(
|
|
41
|
+
value: string,
|
|
42
|
+
fromLang: Language,
|
|
43
|
+
langArr: LanguageUtils.LanguageListItem[],
|
|
44
|
+
) {
|
|
45
|
+
console.log('value', value);
|
|
46
|
+
this.translateLoading = true;
|
|
47
|
+
const toLang = langArr.filter(x => !this.getActualValue(x.id, this.value))?.map(x => x.id);
|
|
48
|
+
console.log('toland', toLang, langArr);
|
|
49
|
+
if (toLang.length === 0) {
|
|
50
|
+
this.translateLoading = false;
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const resp = await this.tryGetDataByArgs<TranslateGetResponse, TranslateGetRequest>({
|
|
55
|
+
blockRoot: false,
|
|
56
|
+
apiMethod: this.apiMethod,
|
|
57
|
+
requestArgs: {
|
|
58
|
+
fromLang,
|
|
59
|
+
toLang,
|
|
60
|
+
text: value,
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (resp?.result != null) {
|
|
65
|
+
for (const key in resp.result) {
|
|
66
|
+
const langCode = LanguageUtils.getLanguageEnum(key);
|
|
67
|
+
this.changeValue(langCode, resp.result[key]);
|
|
68
|
+
}
|
|
69
|
+
} else {
|
|
70
|
+
console.error('Error while getting translation');
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
this.translateLoading = false;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
render(h) {
|
|
77
|
+
return this.translateLoading
|
|
78
|
+
? (
|
|
79
|
+
<div class="d-flex flex-row gap-1 align-items-center">
|
|
80
|
+
<div class="spinner-border spinner-border-sm" role="status">
|
|
81
|
+
<span class="sr-only">Loading...</span>
|
|
82
|
+
</div>
|
|
83
|
+
<span>Translating...</span>
|
|
84
|
+
</div>
|
|
85
|
+
)
|
|
86
|
+
: (
|
|
87
|
+
<TextButton
|
|
88
|
+
icon="icon icon-translate"
|
|
89
|
+
text={PowerduckState.getResourceValue('translateFromThisLanguage')}
|
|
90
|
+
clicked={() => {
|
|
91
|
+
this.translateValue(
|
|
92
|
+
this.getActualValue(this.currentLangId, this.value),
|
|
93
|
+
this.currentLangId,
|
|
94
|
+
this.langArr,
|
|
95
|
+
);
|
|
96
|
+
}}
|
|
97
|
+
/>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -314,5 +314,5 @@ class ModalComponent extends TsxComponent<ModalArgs> implements ModalArgs {
|
|
|
314
314
|
}
|
|
315
315
|
|
|
316
316
|
const Modal = toNative(ModalComponent);
|
|
317
|
-
export
|
|
317
|
+
export type ModalType = typeof Modal.prototype;
|
|
318
318
|
export default Modal;
|
|
@@ -56,13 +56,11 @@ class PhotoManagerComponent extends TsxComponentExtended<PhotoManagerArgs> imple
|
|
|
56
56
|
return [];
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
return this.photos.map((p, i) => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
};
|
|
65
|
-
});
|
|
59
|
+
return this.photos.map((p, i) => ({
|
|
60
|
+
Id: p.id as any,
|
|
61
|
+
ImageUrl: p.fullPath, // this.getFullPath(p),
|
|
62
|
+
SortOrder: p.sortOrder,
|
|
63
|
+
}));
|
|
66
64
|
}
|
|
67
65
|
|
|
68
66
|
getFullPath(img: Photo) {
|
|
@@ -71,7 +69,7 @@ class PhotoManagerComponent extends TsxComponentExtended<PhotoManagerArgs> imple
|
|
|
71
69
|
|
|
72
70
|
parseServerResponse(resp): DropzoneGalleryItem {
|
|
73
71
|
if (resp.fileData == null) {
|
|
74
|
-
throw 'break';
|
|
72
|
+
throw new Error('break');
|
|
75
73
|
}
|
|
76
74
|
|
|
77
75
|
const retVal: PhotoManagerUberModel = resp.fileData;
|
|
@@ -90,7 +88,7 @@ class PhotoManagerComponent extends TsxComponentExtended<PhotoManagerArgs> imple
|
|
|
90
88
|
|
|
91
89
|
render(h) {
|
|
92
90
|
if (this.photos == null) {
|
|
93
|
-
throw 'Photo collection cannot be null, always has to be at least empty array';
|
|
91
|
+
throw new Error('Photo collection cannot be null, always has to be at least empty array');
|
|
94
92
|
}
|
|
95
93
|
|
|
96
94
|
this.photos.forEach((p, i) => {
|
|
@@ -132,8 +130,6 @@ class PhotoManagerComponent extends TsxComponentExtended<PhotoManagerArgs> imple
|
|
|
132
130
|
changed={(items) => {
|
|
133
131
|
const itemsClone = [...(items || [])];
|
|
134
132
|
|
|
135
|
-
console.log(items);
|
|
136
|
-
|
|
137
133
|
this.photos.splice(0, this.photos.length);
|
|
138
134
|
for (const p of itemsClone) {
|
|
139
135
|
this.photos.push({
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "inviton-powerduck",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.139",
|
|
5
5
|
"files": [
|
|
6
6
|
"app/",
|
|
7
7
|
"common/",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"jquery-minicolors": "2.1.10",
|
|
50
50
|
"jquery-resizable": "1.0.6",
|
|
51
51
|
"jspreadsheet-ce": "^4.15.0",
|
|
52
|
+
"jsuites": "5.11.0",
|
|
52
53
|
"leaflet": "^1.9.4",
|
|
53
54
|
"leaflet.markercluster": "^1.5.3",
|
|
54
55
|
"mark.js": "8.11.1",
|