@michalrakus/x-react-web-lib 1.18.0 → 1.20.0
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/XEditor.d.ts +3 -0
- package/XEditor.js +5 -0
- package/XEditorBase.d.ts +3 -0
- package/XEditorBase.js +5 -0
- package/XExportRowsDialog.d.ts +1 -1
- package/XExportRowsDialog.js +1 -1
- package/XHtmlRenderer.d.ts +3 -0
- package/XHtmlRenderer.js +5 -0
- package/XLazyDataTable.d.ts +1 -1
- package/XLazyDataTable.js +1 -1
- package/XMultilineRenderer.d.ts +3 -0
- package/XMultilineRenderer.js +5 -0
- package/gulpfile.js +7 -2
- package/lib/administration/XBrowseMetaBrowse.d.ts +1 -1
- package/lib/administration/XBrowseMetaBrowse.js +1 -1
- package/lib/administration/XUserBrowse.d.ts +1 -1
- package/lib/administration/XUserBrowse.js +1 -1
- package/lib/components/XAutoComplete.d.ts +11 -9
- package/lib/components/XAutoComplete.js +7 -78
- package/lib/components/XAutoCompleteBase.d.ts +42 -7
- package/lib/components/XAutoCompleteBase.js +342 -45
- package/lib/components/XAutoCompleteDT.d.ts +14 -8
- package/lib/components/XAutoCompleteDT.js +3 -69
- package/lib/components/XEditBrowse.js +1 -1
- package/lib/components/XEditor.d.ts +15 -0
- package/lib/components/XEditor.js +64 -0
- package/lib/components/XEditorBase.d.ts +9 -0
- package/lib/components/XEditorBase.js +91 -0
- package/lib/components/XFormBase.d.ts +1 -0
- package/lib/components/XFormBase.js +19 -4
- package/lib/components/XFormDataTable2.js +1 -1
- package/lib/components/XInputTextareaBase.js +3 -4
- package/lib/components/{XExportRowsDialog.d.ts → XLazyDataTable/XExportRowsDialog.d.ts} +1 -1
- package/lib/components/{XExportRowsDialog.js → XLazyDataTable/XExportRowsDialog.js} +5 -5
- package/lib/components/XLazyDataTable/XHtmlRenderer.d.ts +7 -0
- package/lib/components/XLazyDataTable/XHtmlRenderer.js +78 -0
- package/lib/components/{XLazyDataTable.d.ts → XLazyDataTable/XLazyDataTable.d.ts} +20 -8
- package/lib/components/{XLazyDataTable.js → XLazyDataTable/XLazyDataTable.js} +62 -36
- package/lib/components/XLazyDataTable/XMultilineRenderer.d.ts +8 -0
- package/lib/components/XLazyDataTable/XMultilineRenderer.js +80 -0
- package/lib/components/XLazyDataTable/XMultilineSwitch.d.ts +7 -0
- package/lib/components/XLazyDataTable/XMultilineSwitch.js +20 -0
- package/lib/components/XSearchBrowseParams.d.ts +2 -2
- package/lib/components/XSearchButton.js +2 -2
- package/lib/components/XSearchButtonDT.js +2 -2
- package/lib/components/XUtils.d.ts +4 -0
- package/lib/components/XUtils.js +51 -11
- package/lib/components/XUtilsMetadata.d.ts +1 -1
- package/lib/serverApi/FindParam.d.ts +12 -2
- package/lib/serverApi/FindParam.js +3 -2
- package/lib/serverApi/XUtilsCommon.d.ts +2 -0
- package/lib/serverApi/XUtilsCommon.js +37 -1
- package/lib/serverApi/XUtilsMetadataCommon.d.ts +1 -0
- package/lib/serverApi/XUtilsMetadataCommon.js +16 -0
- package/lib/serverApi/x-lib-api.d.ts +6 -0
- package/lib/serverApi/x-lib-api.js +3 -0
- package/package.json +2 -1
|
@@ -48,6 +48,42 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
48
48
|
__setModuleDefault(result, mod);
|
|
49
49
|
return result;
|
|
50
50
|
};
|
|
51
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
52
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
53
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
54
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
55
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
56
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
57
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
58
|
+
});
|
|
59
|
+
};
|
|
60
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
61
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
62
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
63
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
64
|
+
function step(op) {
|
|
65
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
66
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
67
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
68
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
69
|
+
switch (op[0]) {
|
|
70
|
+
case 0: case 1: t = op; break;
|
|
71
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
72
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
73
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
74
|
+
default:
|
|
75
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
76
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
77
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
78
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
79
|
+
if (t[2]) _.ops.pop();
|
|
80
|
+
_.trys.pop(); continue;
|
|
81
|
+
}
|
|
82
|
+
op = body.call(thisArg, _);
|
|
83
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
84
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
85
|
+
}
|
|
86
|
+
};
|
|
51
87
|
var __read = (this && this.__read) || function (o, n) {
|
|
52
88
|
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
53
89
|
if (!m) return o;
|
|
@@ -73,6 +109,17 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
73
109
|
}
|
|
74
110
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
75
111
|
};
|
|
112
|
+
var __values = (this && this.__values) || function(o) {
|
|
113
|
+
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
114
|
+
if (m) return m.call(o);
|
|
115
|
+
if (o && typeof o.length === "number") return {
|
|
116
|
+
next: function () {
|
|
117
|
+
if (o && i >= o.length) o = void 0;
|
|
118
|
+
return { value: o && o[i++], done: !o };
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
122
|
+
};
|
|
76
123
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
77
124
|
exports.XAutoCompleteBase = void 0;
|
|
78
125
|
var react_1 = __importStar(require("react"));
|
|
@@ -81,6 +128,7 @@ var splitbutton_1 = require("primereact/splitbutton");
|
|
|
81
128
|
var dialog_1 = require("primereact/dialog");
|
|
82
129
|
var XUtils_1 = require("./XUtils");
|
|
83
130
|
var button_1 = require("primereact/button");
|
|
131
|
+
var XUtilsCommon_1 = require("../serverApi/XUtilsCommon");
|
|
84
132
|
var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
85
133
|
__extends(XAutoCompleteBase, _super);
|
|
86
134
|
function XAutoCompleteBase(props) {
|
|
@@ -90,63 +138,228 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
90
138
|
inputChanged: false,
|
|
91
139
|
inputValueState: undefined,
|
|
92
140
|
notValid: false,
|
|
141
|
+
suggestions: undefined,
|
|
93
142
|
filteredSuggestions: undefined,
|
|
94
143
|
formDialogOpened: false,
|
|
95
144
|
searchDialogOpened: false
|
|
96
145
|
};
|
|
97
|
-
_this.
|
|
146
|
+
_this.suggestionsLoadedForOSS = false;
|
|
147
|
+
_this.wasOnChangeCalled = false;
|
|
98
148
|
_this.completeMethod = _this.completeMethod.bind(_this);
|
|
99
149
|
_this.onChange = _this.onChange.bind(_this);
|
|
100
150
|
_this.onSelect = _this.onSelect.bind(_this);
|
|
101
151
|
_this.onBlur = _this.onBlur.bind(_this);
|
|
152
|
+
_this.itemTemplate = _this.itemTemplate.bind(_this);
|
|
153
|
+
_this.itemTemplateString = _this.itemTemplateString.bind(_this);
|
|
154
|
+
_this.computeDefaultDisplayValue = _this.computeDefaultDisplayValue.bind(_this);
|
|
102
155
|
_this.formDialogOnSaveOrCancel = _this.formDialogOnSaveOrCancel.bind(_this);
|
|
103
156
|
_this.formDialogOnHide = _this.formDialogOnHide.bind(_this);
|
|
104
157
|
_this.searchDialogOnChoose = _this.searchDialogOnChoose.bind(_this);
|
|
105
158
|
_this.searchDialogOnHide = _this.searchDialogOnHide.bind(_this);
|
|
106
159
|
return _this;
|
|
107
160
|
}
|
|
161
|
+
XAutoCompleteBase.prototype.getXSuggestionsLoadType = function () {
|
|
162
|
+
var suggestionsLoadType;
|
|
163
|
+
if (this.props.suggestions) {
|
|
164
|
+
suggestionsLoadType = "suggestions";
|
|
165
|
+
}
|
|
166
|
+
else if (!this.props.suggestionsLoad) {
|
|
167
|
+
suggestionsLoadType = "onSearchStart"; // default
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
suggestionsLoadType = this.props.suggestionsLoad;
|
|
171
|
+
}
|
|
172
|
+
return suggestionsLoadType;
|
|
173
|
+
};
|
|
174
|
+
// helper
|
|
175
|
+
XAutoCompleteBase.prototype.getFields = function () {
|
|
176
|
+
return Array.isArray(this.props.field) ? this.props.field : [this.props.field];
|
|
177
|
+
};
|
|
178
|
+
XAutoCompleteBase.prototype.getFirstField = function () {
|
|
179
|
+
return this.getFields()[0];
|
|
180
|
+
};
|
|
108
181
|
XAutoCompleteBase.prototype.componentDidMount = function () {
|
|
182
|
+
if (this.getXSuggestionsLoadType() === "eager") {
|
|
183
|
+
this.loadSuggestions();
|
|
184
|
+
}
|
|
109
185
|
if (this.props.setFocusOnCreate) {
|
|
110
186
|
this.setFocusToInput();
|
|
111
187
|
}
|
|
112
188
|
};
|
|
113
|
-
XAutoCompleteBase.prototype.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
// specialna null polozka (prazdny objekt) - test dame az za test fieldValue na undefined - koli performance
|
|
124
|
-
if (fieldValue === undefined && Object.keys(suggestion).length === 0) {
|
|
125
|
-
return false;
|
|
189
|
+
XAutoCompleteBase.prototype.loadSuggestions = function () {
|
|
190
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
191
|
+
var suggestions;
|
|
192
|
+
return __generator(this, function (_a) {
|
|
193
|
+
switch (_a.label) {
|
|
194
|
+
case 0: return [4 /*yield*/, this.fetchSuggestions()];
|
|
195
|
+
case 1:
|
|
196
|
+
suggestions = _a.sent();
|
|
197
|
+
this.setState({ suggestions: suggestions });
|
|
198
|
+
return [2 /*return*/];
|
|
126
199
|
}
|
|
127
|
-
// bolo:
|
|
128
|
-
//return XUtils.normalizeString(fieldValue).startsWith(queryNormalized);
|
|
129
|
-
return XUtils_1.XUtils.normalizeString(fieldValue).indexOf(queryNormalized_1) !== -1;
|
|
130
200
|
});
|
|
131
|
-
}
|
|
132
|
-
this.setState({ filteredSuggestions: filteredSuggestions });
|
|
201
|
+
});
|
|
133
202
|
};
|
|
134
|
-
XAutoCompleteBase.prototype.
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (!this.wasSearchStartCalled) {
|
|
140
|
-
this.props.onSearchStart();
|
|
141
|
-
this.wasSearchStartCalled = true; // ak user dalej typuje, nechceme znova nacitavat suggestions
|
|
142
|
-
}
|
|
203
|
+
XAutoCompleteBase.prototype.fetchSuggestions = function () {
|
|
204
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
205
|
+
return __generator(this, function (_a) {
|
|
206
|
+
if (!this.props.suggestionsQuery) {
|
|
207
|
+
throw "XAutoCompleteBase.loadSuggestions: unexpected error - prop suggestionsQuery is undefined";
|
|
143
208
|
}
|
|
209
|
+
return [2 /*return*/, XUtils_1.XUtils.fetchRows(this.props.suggestionsQuery.entity, XUtils_1.XUtils.evalFilter(this.props.suggestionsQuery.filter), this.getSortField(), this.props.suggestionsQuery.fields)];
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
XAutoCompleteBase.prototype.getSortField = function () {
|
|
214
|
+
var sortField = this.props.suggestionsQuery.sortField;
|
|
215
|
+
if (!sortField) {
|
|
216
|
+
// len pri ne-lazy pouzivame ako default sort prvy displayField
|
|
217
|
+
// pri lazy to spomaluje selecty v pripade ze klauzula LIMIT vyrazne obmedzi vysledny zoznam suggestions
|
|
218
|
+
// pri lazy zosortujeme na frontende v XAutoCompleteBase
|
|
219
|
+
if (this.getXSuggestionsLoadType() !== "lazy") {
|
|
220
|
+
sortField = this.getFirstField();
|
|
144
221
|
}
|
|
222
|
+
}
|
|
223
|
+
return sortField;
|
|
224
|
+
};
|
|
225
|
+
XAutoCompleteBase.prototype.completeMethod = function (event) {
|
|
226
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
227
|
+
var filteredSuggestions, xSuggestionsLoadType, suggestions, queryNormalized, queryNormalizedList_1, filter, suggestionsRequest, findResult;
|
|
228
|
+
var _this = this;
|
|
229
|
+
return __generator(this, function (_a) {
|
|
230
|
+
switch (_a.label) {
|
|
231
|
+
case 0:
|
|
232
|
+
xSuggestionsLoadType = this.getXSuggestionsLoadType();
|
|
233
|
+
if (!(xSuggestionsLoadType !== "lazy")) return [3 /*break*/, 8];
|
|
234
|
+
suggestions = void 0;
|
|
235
|
+
if (!(xSuggestionsLoadType === "suggestions")) return [3 /*break*/, 1];
|
|
236
|
+
suggestions = this.props.suggestions;
|
|
237
|
+
return [3 /*break*/, 7];
|
|
238
|
+
case 1:
|
|
239
|
+
if (!(xSuggestionsLoadType === "eager")) return [3 /*break*/, 2];
|
|
240
|
+
suggestions = this.state.suggestions;
|
|
241
|
+
return [3 /*break*/, 7];
|
|
242
|
+
case 2:
|
|
243
|
+
if (!(xSuggestionsLoadType === "onSearchStart")) return [3 /*break*/, 6];
|
|
244
|
+
if (!!this.suggestionsLoadedForOSS) return [3 /*break*/, 4];
|
|
245
|
+
return [4 /*yield*/, this.fetchSuggestions()];
|
|
246
|
+
case 3:
|
|
247
|
+
suggestions = _a.sent();
|
|
248
|
+
// ulozime si
|
|
249
|
+
this.setState({ suggestions: suggestions });
|
|
250
|
+
this.suggestionsLoadedForOSS = true; // ak user dalej typuje, nechceme znova nacitavat suggestions
|
|
251
|
+
return [3 /*break*/, 5];
|
|
252
|
+
case 4:
|
|
253
|
+
// uz mame nacitane
|
|
254
|
+
suggestions = this.state.suggestions;
|
|
255
|
+
_a.label = 5;
|
|
256
|
+
case 5: return [3 /*break*/, 7];
|
|
257
|
+
case 6: throw 'Unexpected error - unknown xSuggestionsLoadType';
|
|
258
|
+
case 7:
|
|
259
|
+
if (!event.query.trim().length) {
|
|
260
|
+
// input je prazdny - volanie sem nastane ak user otvori dropdown cez dropdown button
|
|
261
|
+
filteredSuggestions = __spreadArray([], __read(suggestions), false);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
queryNormalized = XUtils_1.XUtils.normalizeString(event.query);
|
|
265
|
+
if (this.props.splitQueryValue) {
|
|
266
|
+
queryNormalizedList_1 = queryNormalized.split(' ').filter(function (value) { return value !== ''; }); // nechceme pripadne prazdne retazce ''
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
queryNormalizedList_1 = [queryNormalized]; // nesplitujeme
|
|
270
|
+
}
|
|
271
|
+
filteredSuggestions = suggestions.filter(function (suggestion) {
|
|
272
|
+
var e_1, _a;
|
|
273
|
+
var fieldValue = _this.itemTemplateString(suggestion);
|
|
274
|
+
// specialna null polozka (prazdny objekt) - test dame az za test fieldValue na undefined - koli performance
|
|
275
|
+
if (fieldValue === undefined && Object.keys(suggestion).length === 0) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
var fieldValueNormalized = XUtils_1.XUtils.normalizeString(fieldValue);
|
|
279
|
+
// all partial query values must match
|
|
280
|
+
var match = true;
|
|
281
|
+
try {
|
|
282
|
+
for (var queryNormalizedList_2 = __values(queryNormalizedList_1), queryNormalizedList_2_1 = queryNormalizedList_2.next(); !queryNormalizedList_2_1.done; queryNormalizedList_2_1 = queryNormalizedList_2.next()) {
|
|
283
|
+
var queryItemNormalized = queryNormalizedList_2_1.value;
|
|
284
|
+
// look for substring
|
|
285
|
+
if (fieldValueNormalized.indexOf(queryItemNormalized) === -1) {
|
|
286
|
+
match = false;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
292
|
+
finally {
|
|
293
|
+
try {
|
|
294
|
+
if (queryNormalizedList_2_1 && !queryNormalizedList_2_1.done && (_a = queryNormalizedList_2.return)) _a.call(queryNormalizedList_2);
|
|
295
|
+
}
|
|
296
|
+
finally { if (e_1) throw e_1.error; }
|
|
297
|
+
}
|
|
298
|
+
return match;
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
return [3 /*break*/, 10];
|
|
302
|
+
case 8:
|
|
303
|
+
// ************* lazy ***************
|
|
304
|
+
// na backendev SELECT-e pouzijeme klauzulu LIMIT <maxRows + 1>
|
|
305
|
+
// ak najdeme menej ako <maxRows + 1> zaznamov tak vieme ze sme nasli vsetky
|
|
306
|
+
// ak najdeme presne <maxRows + 1> zaznamov, tak na konci zobrazime uzivatelovi specialnu polozku "..."
|
|
307
|
+
// ktora ho upozorni ze existuju aj dalsie zaznamy splnujuce podmienku
|
|
308
|
+
// pikoska - ak je query je velmi siroke (select by bez LIMIT <maxRows + 1> vratil mnoho zaznamov),
|
|
309
|
+
// tak je takyto select velmi lacny (niekolko ms) - staci totiz najst prvych napr. 20 zaznamov splnujucich podmienku, t.j. netreba robit full-table scan
|
|
310
|
+
// to ale plati len v pripade ze nepouzijeme ORDER BY - pri pouziti ORDER BY urobi full-table scan (vyfiltruje) a nasledne zosortuje
|
|
311
|
+
// toto sa da obist specialnym selectom:
|
|
312
|
+
// select t.* from (select t0.* from table t0 order by t0.<attr1>) t where <full-text-condition> limit 20
|
|
313
|
+
// (najprv zosortuje a az potom filtruje prvych 20 zaznamov - predpoklad je ze nad t0.<attr1> mame index aby rychlo sortoval)
|
|
314
|
+
// tento specialny select mozme v buducnosti dorobit (na backende) ak chceme podporovat (rychle) sortovanie v DB pre autocomplete
|
|
315
|
+
if (!this.props.suggestionsQuery) {
|
|
316
|
+
throw "XAutoCompleteBase.loadSuggestions: unexpected error - prop suggestionsQuery is undefined";
|
|
317
|
+
}
|
|
318
|
+
filter = XUtils_1.XUtils.evalFilter(this.props.suggestionsQuery.filter);
|
|
319
|
+
suggestionsRequest = {
|
|
320
|
+
maxRows: this.props.lazyLoadMaxRows + 1,
|
|
321
|
+
fullTextSearch: { fields: this.getFields(), value: event.query.trim(), splitValue: this.props.splitQueryValue, matchMode: "contains" },
|
|
322
|
+
entity: this.props.suggestionsQuery.entity,
|
|
323
|
+
filterItems: XUtils_1.XUtils.createCustomFilterItems(filter),
|
|
324
|
+
multiSortMeta: XUtils_1.XUtils.createMultiSortMeta(this.getSortField()),
|
|
325
|
+
fields: this.props.suggestionsQuery.fields
|
|
326
|
+
};
|
|
327
|
+
return [4 /*yield*/, XUtils_1.XUtils.fetchOne('x-lazy-auto-complete-suggestions', suggestionsRequest)];
|
|
328
|
+
case 9:
|
|
329
|
+
findResult = _a.sent();
|
|
330
|
+
filteredSuggestions = findResult.rowList;
|
|
331
|
+
// ak sme nesortovali v DB (co je draha operacia) tak zosortujeme teraz
|
|
332
|
+
// (itemTemplateString sa vola duplicitne ale pre tych cca 20 zaznamov je to ok)
|
|
333
|
+
if (this.props.suggestionsQuery.sortField === undefined) {
|
|
334
|
+
filteredSuggestions = XUtils_1.XUtils.arraySort(filteredSuggestions, this.itemTemplateString);
|
|
335
|
+
}
|
|
336
|
+
// ak mame o 1 zaznam viac ako je lazyLoadMaxRows, zmenime posledny zaznam na ...
|
|
337
|
+
// TODO - lepsie by bolo posledny zaznam vyhodit a popisok ... zobrazit do footer-a (odpadnu problemy z pripadnou selekciou pseudozaznamu ...)
|
|
338
|
+
if (filteredSuggestions.length > this.props.lazyLoadMaxRows) {
|
|
339
|
+
filteredSuggestions[filteredSuggestions.length - 1] = XAutoCompleteBase.valueMoreSuggestions; // zatial priamo string
|
|
340
|
+
}
|
|
341
|
+
_a.label = 10;
|
|
342
|
+
case 10:
|
|
343
|
+
this.setState({ filteredSuggestions: filteredSuggestions });
|
|
344
|
+
return [2 /*return*/];
|
|
345
|
+
}
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
};
|
|
349
|
+
XAutoCompleteBase.prototype.onChange = function (e) {
|
|
350
|
+
if (typeof e.value === 'string' && !XAutoCompleteBase.isMoreSuggestions(e.value)) {
|
|
145
351
|
this.setState({ inputChanged: true, inputValueState: e.value });
|
|
352
|
+
this.wasOnChangeCalled = false; // reset na default hodnotu
|
|
146
353
|
}
|
|
147
354
|
};
|
|
148
355
|
XAutoCompleteBase.prototype.onSelect = function (e) {
|
|
149
|
-
this.setObjectValue
|
|
356
|
+
// nevolame this.setObjectValue ak uz bol zavolany z onBlur
|
|
357
|
+
if (!this.wasOnChangeCalled) {
|
|
358
|
+
// nedovolime vybrat specialny zaznam ...
|
|
359
|
+
if (!XAutoCompleteBase.isMoreSuggestions(e.value)) {
|
|
360
|
+
this.setObjectValue(e.value, XUtils_1.OperationType.None);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
150
363
|
};
|
|
151
364
|
XAutoCompleteBase.prototype.onBlur = function (e) {
|
|
152
365
|
// optimalizacia - testujeme len ak inputChanged === true
|
|
@@ -159,6 +372,11 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
159
372
|
var filteredSuggestions = this.state.filteredSuggestions;
|
|
160
373
|
if (filteredSuggestions && filteredSuggestions.length === 1) {
|
|
161
374
|
this.setObjectValue(filteredSuggestions[0], XUtils_1.OperationType.None);
|
|
375
|
+
// ak bol tento this.setObjectValue vyvolany klikom do suggestions dropdown-u,
|
|
376
|
+
// tak bude este nasledne zavolany onSelect a tam chceme zamedzit volaniu this.setObjectValue,
|
|
377
|
+
// preto nastavujeme tento priznak
|
|
378
|
+
// priznak vratime naspet na false ak uzivatel zacne cokolvek robit s autocomplete (zacne don typovat alebo klikne na dropdown)
|
|
379
|
+
this.wasOnChangeCalled = true;
|
|
162
380
|
}
|
|
163
381
|
else {
|
|
164
382
|
// tu by sme mohli skusit vyratat vysledok pre filteredSuggestions este raz, mozno este vypocet filteredSuggestions nedobehol
|
|
@@ -190,8 +408,9 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
190
408
|
}
|
|
191
409
|
}
|
|
192
410
|
}
|
|
193
|
-
// odchadzame z inputu, zresetujeme priznak - ak zacne user pracovat s autocomplete-om, nacitaju sa suggestions z DB (ak mame
|
|
194
|
-
|
|
411
|
+
// odchadzame z inputu, zresetujeme priznak - ak zacne user pracovat s autocomplete-om, nacitaju sa suggestions z DB (ak mame suggestionsLoad = onSearchStart)
|
|
412
|
+
// suggestions chceme nacitat, lebo user moze zmenit iny atribut ktory ovplyvnuje filter autocomplete-u -> chceme novy zoznam suggestions
|
|
413
|
+
this.suggestionsLoadedForOSS = false;
|
|
195
414
|
};
|
|
196
415
|
XAutoCompleteBase.prototype.createErrorMessage = function () {
|
|
197
416
|
return "Value \"".concat(this.state.inputValueState, "\" was not found among valid values.");
|
|
@@ -231,6 +450,14 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
231
450
|
if (object !== null) {
|
|
232
451
|
// ak bol save, treba tento novy object pouzit
|
|
233
452
|
this.setObjectValue(object, objectChange);
|
|
453
|
+
// ak pouzivame zoznam this.state.suggestions, tak ho rereadneme
|
|
454
|
+
// poznamka: ak pouzivame this.props.suggestions z parenta, tak si musi zoznam rereadnut parent!
|
|
455
|
+
if (objectChange !== XUtils_1.OperationType.None) {
|
|
456
|
+
// zmenil sa zaznam dobrovolnika v DB
|
|
457
|
+
// zatial len refreshneme z DB
|
|
458
|
+
// ak by bol reqest pomaly, mozme pri inserte (nove id) / update (existujuce id) upravit zoznam a usetrime tym request do DB
|
|
459
|
+
this.loadSuggestions();
|
|
460
|
+
}
|
|
234
461
|
// treba upravit this.state.filteredSuggestions? setli sme novy objekt, panel so suggestions by mal byt zavrety - TODO - overit
|
|
235
462
|
}
|
|
236
463
|
else {
|
|
@@ -270,7 +497,7 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
270
497
|
_this.formDialogInitValuesForInsert = {};
|
|
271
498
|
// ak mame nevalidnu hodnotu, tak ju predplnime (snaha o user friendly)
|
|
272
499
|
if (_this.state.inputChanged) {
|
|
273
|
-
_this.formDialogInitValuesForInsert[_this.
|
|
500
|
+
_this.formDialogInitValuesForInsert[_this.getFirstField()] = _this.state.inputValueState;
|
|
274
501
|
}
|
|
275
502
|
_this.setState({ formDialogOpened: true });
|
|
276
503
|
}
|
|
@@ -329,15 +556,9 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
329
556
|
});
|
|
330
557
|
};
|
|
331
558
|
XAutoCompleteBase.prototype.onOpenDropdown = function (e) {
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
// otvori dropdown (search je metoda popisana v API, volanie sme skopcili zo zdrojakov primereact)
|
|
338
|
-
//this.autoCompleteRef.current.search(e, '', 'dropdown');
|
|
339
|
-
this.openDropdown(e);
|
|
340
|
-
}
|
|
559
|
+
this.openDropdown(e);
|
|
560
|
+
this.suggestionsLoadedForOSS = false; // user mohol vyplnit nieco co meni filter a ide znova pracovat s autocomplete, nacitame suggestions znova (suggestionsLoad = onSearchStart)
|
|
561
|
+
this.wasOnChangeCalled = false; // reset na default hodnotu
|
|
341
562
|
};
|
|
342
563
|
XAutoCompleteBase.prototype.openDropdown = function (e) {
|
|
343
564
|
// otvori dropdown (search je metoda popisana v API, volanie sme skopcili zo zdrojakov primereact)
|
|
@@ -358,19 +579,88 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
358
579
|
if (!this.state.inputChanged) {
|
|
359
580
|
// poznamka: ak object === null tak treba do inputu zapisovat prazdny retazec, ak by sme pouzili null, neprejavila by sa zmena v modeli na null
|
|
360
581
|
var object = this.props.value;
|
|
361
|
-
inputValue = (object !== null) ? object : ""; // TODO - je "" ok?
|
|
582
|
+
inputValue = (object !== null) ? this.computeItemTemplate(object, -1, true) : ""; // TODO - je "" ok?
|
|
362
583
|
}
|
|
363
584
|
else {
|
|
364
585
|
inputValue = this.state.inputValueState;
|
|
365
586
|
}
|
|
366
587
|
return inputValue;
|
|
367
588
|
};
|
|
589
|
+
XAutoCompleteBase.prototype.itemTemplate = function (suggestion, index) {
|
|
590
|
+
return this.computeItemTemplate(suggestion, index, false);
|
|
591
|
+
};
|
|
592
|
+
// pouziva sa na vytvorenie hodnoty do inputu (vyselectovany zaznam) a tiez na pripadne sortovanie a filtrovanie na frontende (ak nepouzivame lazy nacitavanie)
|
|
593
|
+
XAutoCompleteBase.prototype.itemTemplateString = function (suggestion) {
|
|
594
|
+
var itemValue = this.computeItemTemplate(suggestion, -1, true);
|
|
595
|
+
if (typeof itemValue !== "string") {
|
|
596
|
+
throw "XAutoCompleteBase: function of the property itemTemplate created non-string value for suggestion. Please create string value if parameter createStringValue = true.";
|
|
597
|
+
}
|
|
598
|
+
return itemValue;
|
|
599
|
+
};
|
|
600
|
+
XAutoCompleteBase.prototype.computeItemTemplate = function (suggestion, index, createStringValue) {
|
|
601
|
+
var itemTemplate;
|
|
602
|
+
// osetrenie specialnej polozky ... dame sem, nech sa to nemusi inde riesit
|
|
603
|
+
if (XAutoCompleteBase.isMoreSuggestions(suggestion)) {
|
|
604
|
+
itemTemplate = suggestion;
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
if (this.props.itemTemplate) {
|
|
608
|
+
itemTemplate = this.props.itemTemplate(suggestion, index, createStringValue, this.computeDefaultDisplayValue);
|
|
609
|
+
}
|
|
610
|
+
else {
|
|
611
|
+
itemTemplate = this.computeDefaultDisplayValue(suggestion);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
return itemTemplate;
|
|
615
|
+
};
|
|
616
|
+
XAutoCompleteBase.prototype.computeDefaultDisplayValue = function (suggestion) {
|
|
617
|
+
var e_2, _a;
|
|
618
|
+
var displayValue = "";
|
|
619
|
+
if (XAutoCompleteBase.isMoreSuggestions(suggestion)) {
|
|
620
|
+
displayValue = suggestion;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
try {
|
|
624
|
+
for (var _b = __values(this.getFields()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
625
|
+
var field = _c.value;
|
|
626
|
+
// TODO - konverzie na spravny typ/string
|
|
627
|
+
var _d = __read(XUtilsCommon_1.XUtilsCommon.getPrefixAndField(field), 2), prefix = _d[0], fieldOnly = _d[1];
|
|
628
|
+
var value = XUtilsCommon_1.XUtilsCommon.getValueByPath(suggestion, fieldOnly);
|
|
629
|
+
if (value !== null && value !== undefined) {
|
|
630
|
+
var valueStr = value.toString(); // TODO - spravnu konverziu
|
|
631
|
+
if (valueStr !== "") {
|
|
632
|
+
if (displayValue !== "") {
|
|
633
|
+
displayValue += " ";
|
|
634
|
+
}
|
|
635
|
+
if (prefix) {
|
|
636
|
+
displayValue += prefix;
|
|
637
|
+
}
|
|
638
|
+
displayValue += valueStr;
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
644
|
+
finally {
|
|
645
|
+
try {
|
|
646
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
647
|
+
}
|
|
648
|
+
finally { if (e_2) throw e_2.error; }
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return displayValue;
|
|
652
|
+
};
|
|
653
|
+
// vrati true ak sa jedna o specialny typ XAutoCompleteBase.valueMoreSuggestions
|
|
654
|
+
XAutoCompleteBase.isMoreSuggestions = function (suggestion) {
|
|
655
|
+
return typeof suggestion === "string" && suggestion === XAutoCompleteBase.valueMoreSuggestions;
|
|
656
|
+
};
|
|
368
657
|
// takto cez metodku, mozno sa metodka vola len ked sa otvori dialog a usetrime nieco...
|
|
369
658
|
XAutoCompleteBase.prototype.createSearchBrowseParams = function () {
|
|
659
|
+
var _a;
|
|
370
660
|
return {
|
|
371
661
|
onChoose: this.searchDialogOnChoose,
|
|
372
|
-
displayFieldFilter: (this.state.inputChanged ? { field: this.
|
|
373
|
-
|
|
662
|
+
displayFieldFilter: (this.state.inputChanged ? { field: this.getFirstField(), constraint: { value: this.state.inputValueState, matchMode: "contains" } } : undefined),
|
|
663
|
+
customFilter: (_a = this.props.suggestionsQuery) === null || _a === void 0 ? void 0 : _a.filter
|
|
374
664
|
};
|
|
375
665
|
};
|
|
376
666
|
XAutoCompleteBase.prototype.render = function () {
|
|
@@ -421,7 +711,7 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
421
711
|
// <DobrovolnikForm id={this.formDialogObjectId} object={this.formDialogInitValuesForInsert} onSaveOrCancel={this.formDialogOnSaveOrCancel}/>
|
|
422
712
|
// formgroup-inline lepi SplitButton na autocomplete a zarovna jeho vysku
|
|
423
713
|
return (react_1.default.createElement("div", { className: "x-auto-complete-base", style: { width: this.props.width } },
|
|
424
|
-
react_1.default.createElement(autocomplete_1.AutoComplete, __assign({ value: inputValue, suggestions: this.state.filteredSuggestions, completeMethod: this.completeMethod,
|
|
714
|
+
react_1.default.createElement(autocomplete_1.AutoComplete, __assign({ value: inputValue, suggestions: this.state.filteredSuggestions, completeMethod: this.completeMethod, itemTemplate: this.itemTemplate, onChange: this.onChange, onSelect: this.onSelect, onBlur: this.onBlur, minLength: this.props.minLength, scrollHeight: this.props.scrollHeight, ref: this.autoCompleteRef, readOnly: readOnly, disabled: readOnly }, XUtils_1.XUtils.createErrorProps(error), { inputClassName: this.props.inputClassName })),
|
|
425
715
|
dropdownButton,
|
|
426
716
|
this.props.valueForm != undefined ?
|
|
427
717
|
react_1.default.createElement(dialog_1.Dialog, { visible: this.state.formDialogOpened, onHide: this.formDialogOnHide, header: this.formDialogObjectId ? 'Modification' : 'New row' }, react_1.default.cloneElement(this.props.valueForm, {
|
|
@@ -432,6 +722,13 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
432
722
|
react_1.default.createElement(dialog_1.Dialog, { visible: this.state.searchDialogOpened, onHide: this.searchDialogOnHide }, react_1.default.cloneElement(this.props.searchBrowse, { searchBrowseParams: this.createSearchBrowseParams() } /*, props.searchBrowse.children*/))
|
|
433
723
|
: undefined));
|
|
434
724
|
};
|
|
725
|
+
XAutoCompleteBase.valueMoreSuggestions = "...";
|
|
726
|
+
XAutoCompleteBase.defaultProps = {
|
|
727
|
+
lazyLoadMaxRows: 10,
|
|
728
|
+
splitQueryValue: true,
|
|
729
|
+
minLength: 1,
|
|
730
|
+
scrollHeight: '15rem' // primereact has 200px
|
|
731
|
+
};
|
|
435
732
|
return XAutoCompleteBase;
|
|
436
733
|
}(react_1.Component));
|
|
437
734
|
exports.XAutoCompleteBase = XAutoCompleteBase;
|
|
@@ -1,26 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
import React from "react";
|
|
2
2
|
import { XFormComponentDT, XFormComponentDTProps } from "./XFormComponentDT";
|
|
3
3
|
import { XAssoc } from "../serverApi/XEntityMetadata";
|
|
4
4
|
import { OperationType } from "./XUtils";
|
|
5
5
|
import { XError } from "./XErrors";
|
|
6
|
+
import { XSuggestionsLoadProp } from "./XAutoCompleteBase";
|
|
6
7
|
import { XTableFieldFilterProp } from "./XFormDataTable2";
|
|
8
|
+
import { DataTableSortMeta } from "primereact/datatable";
|
|
7
9
|
export interface XAutoCompleteDTProps extends XFormComponentDTProps {
|
|
8
10
|
assocField: string;
|
|
9
|
-
displayField: string;
|
|
11
|
+
displayField: string | string[];
|
|
12
|
+
itemTemplate?: (suggestion: any, index: number, createStringValue: boolean, defaultValue: (suggestion: any) => string) => React.ReactNode;
|
|
10
13
|
searchBrowse?: JSX.Element;
|
|
11
14
|
assocForm?: JSX.Element;
|
|
12
|
-
filter?: XTableFieldFilterProp;
|
|
13
15
|
suggestions?: any[];
|
|
16
|
+
suggestionsLoad?: XSuggestionsLoadProp;
|
|
17
|
+
lazyLoadMaxRows?: number;
|
|
18
|
+
splitQueryValue?: boolean;
|
|
19
|
+
minLength?: number;
|
|
20
|
+
filter?: XTableFieldFilterProp;
|
|
21
|
+
sortField?: string | DataTableSortMeta[];
|
|
22
|
+
fields?: string[];
|
|
23
|
+
scrollHeight?: string;
|
|
24
|
+
inputClassName?: string;
|
|
14
25
|
}
|
|
15
26
|
export declare class XAutoCompleteDT extends XFormComponentDT<XAutoCompleteDTProps> {
|
|
16
27
|
protected xAssoc: XAssoc;
|
|
17
28
|
protected errorInBase: string | undefined;
|
|
18
|
-
state: {
|
|
19
|
-
suggestions: any[];
|
|
20
|
-
};
|
|
21
29
|
constructor(props: XAutoCompleteDTProps);
|
|
22
|
-
componentDidMount(): void;
|
|
23
|
-
readAndSetSuggestions(): Promise<void>;
|
|
24
30
|
getField(): string;
|
|
25
31
|
isNotNull(): boolean;
|
|
26
32
|
getValue(): any | null;
|