@michalrakus/x-react-web-lib 1.17.0 → 1.19.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/lib/components/XAutoComplete.d.ts +9 -9
- package/lib/components/XAutoComplete.js +7 -78
- package/lib/components/XAutoCompleteBase.d.ts +39 -7
- package/lib/components/XAutoCompleteBase.js +351 -64
- package/lib/components/XAutoCompleteDT.d.ts +10 -6
- package/lib/components/XAutoCompleteDT.js +3 -69
- package/lib/components/XCalendar.d.ts +1 -2
- package/lib/components/XCalendar.js +79 -10
- package/lib/components/XFormBase.js +5 -1
- package/lib/components/XFormComponent.js +9 -6
- package/lib/components/XFormDataTable2.d.ts +15 -1
- package/lib/components/XFormDataTable2.js +24 -4
- package/lib/components/XFormRowCol/XFormCol.d.ts +1 -0
- package/lib/components/XFormRowCol/XFormCol.js +1 -1
- package/lib/components/XFormRowCol/XFormInlineRow.d.ts +1 -0
- package/lib/components/XFormRowCol/XFormInlineRow.js +1 -1
- package/lib/components/XFormRowCol/XFormRow.d.ts +1 -0
- package/lib/components/XFormRowCol/XFormRow.js +1 -1
- package/lib/components/XFormRowCol/XFormRowCol.d.ts +1 -0
- package/lib/components/XFormRowCol/XFormRowCol.js +1 -1
- package/lib/components/XInputDate.d.ts +0 -1
- package/lib/components/XInputDate.js +4 -18
- package/lib/components/XInputDateDT.d.ts +9 -10
- package/lib/components/XInputDateDT.js +35 -39
- package/lib/components/XInputDecimal.js +1 -1
- package/lib/components/XInputTextarea.js +1 -1
- package/lib/components/XInputTextareaDT.d.ts +12 -0
- package/lib/components/XInputTextareaDT.js +44 -0
- package/lib/components/XLazyDataTable.d.ts +4 -2
- package/lib/components/XLazyDataTable.js +17 -4
- 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.js +1 -1
- package/lib/serverApi/FindParam.d.ts +12 -2
- package/lib/serverApi/FindParam.js +3 -2
- package/lib/serverApi/XUtilsCommon.d.ts +5 -0
- package/lib/serverApi/XUtilsCommon.js +43 -0
- package/lib/serverApi/XUtilsConversions.d.ts +1 -0
- package/lib/serverApi/XUtilsConversions.js +63 -5
- package/package.json +1 -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,226 @@ 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.computeDisplayValue = _this.computeDisplayValue.bind(_this);
|
|
102
154
|
_this.formDialogOnSaveOrCancel = _this.formDialogOnSaveOrCancel.bind(_this);
|
|
103
155
|
_this.formDialogOnHide = _this.formDialogOnHide.bind(_this);
|
|
104
156
|
_this.searchDialogOnChoose = _this.searchDialogOnChoose.bind(_this);
|
|
105
157
|
_this.searchDialogOnHide = _this.searchDialogOnHide.bind(_this);
|
|
106
158
|
return _this;
|
|
107
159
|
}
|
|
160
|
+
XAutoCompleteBase.prototype.getXSuggestionsLoadType = function () {
|
|
161
|
+
var suggestionsLoadType;
|
|
162
|
+
if (this.props.suggestions) {
|
|
163
|
+
suggestionsLoadType = "suggestions";
|
|
164
|
+
}
|
|
165
|
+
else if (!this.props.suggestionsLoad) {
|
|
166
|
+
suggestionsLoadType = "onSearchStart"; // default
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
suggestionsLoadType = this.props.suggestionsLoad;
|
|
170
|
+
}
|
|
171
|
+
return suggestionsLoadType;
|
|
172
|
+
};
|
|
173
|
+
// helper
|
|
174
|
+
XAutoCompleteBase.prototype.getFields = function () {
|
|
175
|
+
return Array.isArray(this.props.field) ? this.props.field : [this.props.field];
|
|
176
|
+
};
|
|
177
|
+
XAutoCompleteBase.prototype.getFirstField = function () {
|
|
178
|
+
return this.getFields()[0];
|
|
179
|
+
};
|
|
108
180
|
XAutoCompleteBase.prototype.componentDidMount = function () {
|
|
181
|
+
if (this.getXSuggestionsLoadType() === "eager") {
|
|
182
|
+
this.loadSuggestions();
|
|
183
|
+
}
|
|
109
184
|
if (this.props.setFocusOnCreate) {
|
|
110
185
|
this.setFocusToInput();
|
|
111
186
|
}
|
|
112
187
|
};
|
|
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;
|
|
188
|
+
XAutoCompleteBase.prototype.loadSuggestions = function () {
|
|
189
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
190
|
+
var suggestions;
|
|
191
|
+
return __generator(this, function (_a) {
|
|
192
|
+
switch (_a.label) {
|
|
193
|
+
case 0: return [4 /*yield*/, this.fetchSuggestions()];
|
|
194
|
+
case 1:
|
|
195
|
+
suggestions = _a.sent();
|
|
196
|
+
this.setState({ suggestions: suggestions });
|
|
197
|
+
return [2 /*return*/];
|
|
126
198
|
}
|
|
127
|
-
// bolo:
|
|
128
|
-
//return XUtils.normalizeString(fieldValue).startsWith(queryNormalized);
|
|
129
|
-
return XUtils_1.XUtils.normalizeString(fieldValue).indexOf(queryNormalized_1) !== -1;
|
|
130
199
|
});
|
|
131
|
-
}
|
|
132
|
-
this.setState({ filteredSuggestions: filteredSuggestions });
|
|
200
|
+
});
|
|
133
201
|
};
|
|
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
|
-
}
|
|
202
|
+
XAutoCompleteBase.prototype.fetchSuggestions = function () {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
204
|
+
return __generator(this, function (_a) {
|
|
205
|
+
if (!this.props.suggestionsQuery) {
|
|
206
|
+
throw "XAutoCompleteBase.loadSuggestions: unexpected error - prop suggestionsQuery is undefined";
|
|
143
207
|
}
|
|
208
|
+
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)];
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
XAutoCompleteBase.prototype.getSortField = function () {
|
|
213
|
+
var sortField = this.props.suggestionsQuery.sortField;
|
|
214
|
+
if (!sortField) {
|
|
215
|
+
// len pri ne-lazy pouzivame ako default sort prvy displayField
|
|
216
|
+
// pri lazy to spomaluje selecty v pripade ze klauzula LIMIT vyrazne obmedzi vysledny zoznam suggestions
|
|
217
|
+
// pri lazy zosortujeme na frontende v XAutoCompleteBase
|
|
218
|
+
if (this.getXSuggestionsLoadType() !== "lazy") {
|
|
219
|
+
sortField = this.getFirstField();
|
|
144
220
|
}
|
|
221
|
+
}
|
|
222
|
+
return sortField;
|
|
223
|
+
};
|
|
224
|
+
XAutoCompleteBase.prototype.completeMethod = function (event) {
|
|
225
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
226
|
+
var filteredSuggestions, xSuggestionsLoadType, suggestions, queryNormalized, queryNormalizedList_1, filter, suggestionsRequest, findResult;
|
|
227
|
+
var _this = this;
|
|
228
|
+
return __generator(this, function (_a) {
|
|
229
|
+
switch (_a.label) {
|
|
230
|
+
case 0:
|
|
231
|
+
xSuggestionsLoadType = this.getXSuggestionsLoadType();
|
|
232
|
+
if (!(xSuggestionsLoadType !== "lazy")) return [3 /*break*/, 8];
|
|
233
|
+
suggestions = void 0;
|
|
234
|
+
if (!(xSuggestionsLoadType === "suggestions")) return [3 /*break*/, 1];
|
|
235
|
+
suggestions = this.props.suggestions;
|
|
236
|
+
return [3 /*break*/, 7];
|
|
237
|
+
case 1:
|
|
238
|
+
if (!(xSuggestionsLoadType === "eager")) return [3 /*break*/, 2];
|
|
239
|
+
suggestions = this.state.suggestions;
|
|
240
|
+
return [3 /*break*/, 7];
|
|
241
|
+
case 2:
|
|
242
|
+
if (!(xSuggestionsLoadType === "onSearchStart")) return [3 /*break*/, 6];
|
|
243
|
+
if (!!this.suggestionsLoadedForOSS) return [3 /*break*/, 4];
|
|
244
|
+
return [4 /*yield*/, this.fetchSuggestions()];
|
|
245
|
+
case 3:
|
|
246
|
+
suggestions = _a.sent();
|
|
247
|
+
// ulozime si
|
|
248
|
+
this.setState({ suggestions: suggestions });
|
|
249
|
+
this.suggestionsLoadedForOSS = true; // ak user dalej typuje, nechceme znova nacitavat suggestions
|
|
250
|
+
return [3 /*break*/, 5];
|
|
251
|
+
case 4:
|
|
252
|
+
// uz mame nacitane
|
|
253
|
+
suggestions = this.state.suggestions;
|
|
254
|
+
_a.label = 5;
|
|
255
|
+
case 5: return [3 /*break*/, 7];
|
|
256
|
+
case 6: throw 'Unexpected error - unknown xSuggestionsLoadType';
|
|
257
|
+
case 7:
|
|
258
|
+
if (!event.query.trim().length) {
|
|
259
|
+
// input je prazdny - volanie sem nastane ak user otvori dropdown cez dropdown button
|
|
260
|
+
filteredSuggestions = __spreadArray([], __read(suggestions), false);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
queryNormalized = XUtils_1.XUtils.normalizeString(event.query);
|
|
264
|
+
if (this.props.splitQueryValue) {
|
|
265
|
+
queryNormalizedList_1 = queryNormalized.split(' ').filter(function (value) { return value !== ''; }); // nechceme pripadne prazdne retazce ''
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
queryNormalizedList_1 = [queryNormalized]; // nesplitujeme
|
|
269
|
+
}
|
|
270
|
+
filteredSuggestions = suggestions.filter(function (suggestion) {
|
|
271
|
+
var e_1, _a;
|
|
272
|
+
var fieldValue = _this.computeDisplayValue(suggestion);
|
|
273
|
+
// specialna null polozka (prazdny objekt) - test dame az za test fieldValue na undefined - koli performance
|
|
274
|
+
if (fieldValue === undefined && Object.keys(suggestion).length === 0) {
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
var fieldValueNormalized = XUtils_1.XUtils.normalizeString(fieldValue);
|
|
278
|
+
// all partial query values must match
|
|
279
|
+
var match = true;
|
|
280
|
+
try {
|
|
281
|
+
for (var queryNormalizedList_2 = __values(queryNormalizedList_1), queryNormalizedList_2_1 = queryNormalizedList_2.next(); !queryNormalizedList_2_1.done; queryNormalizedList_2_1 = queryNormalizedList_2.next()) {
|
|
282
|
+
var queryItemNormalized = queryNormalizedList_2_1.value;
|
|
283
|
+
// look for substring
|
|
284
|
+
if (fieldValueNormalized.indexOf(queryItemNormalized) === -1) {
|
|
285
|
+
match = false;
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
291
|
+
finally {
|
|
292
|
+
try {
|
|
293
|
+
if (queryNormalizedList_2_1 && !queryNormalizedList_2_1.done && (_a = queryNormalizedList_2.return)) _a.call(queryNormalizedList_2);
|
|
294
|
+
}
|
|
295
|
+
finally { if (e_1) throw e_1.error; }
|
|
296
|
+
}
|
|
297
|
+
return match;
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
return [3 /*break*/, 10];
|
|
301
|
+
case 8:
|
|
302
|
+
// ************* lazy ***************
|
|
303
|
+
// na backendev SELECT-e pouzijeme klauzulu LIMIT <maxRows + 1>
|
|
304
|
+
// ak najdeme menej ako <maxRows + 1> zaznamov tak vieme ze sme nasli vsetky
|
|
305
|
+
// ak najdeme presne <maxRows + 1> zaznamov, tak na konci zobrazime uzivatelovi specialnu polozku "..."
|
|
306
|
+
// ktora ho upozorni ze existuju aj dalsie zaznamy splnujuce podmienku
|
|
307
|
+
// pikoska - ak je query je velmi siroke (select by bez LIMIT <maxRows + 1> vratil mnoho zaznamov),
|
|
308
|
+
// tak je takyto select velmi lacny (niekolko ms) - staci totiz najst prvych napr. 20 zaznamov splnujucich podmienku, t.j. netreba robit full-table scan
|
|
309
|
+
// to ale plati len v pripade ze nepouzijeme ORDER BY - pri pouziti ORDER BY urobi full-table scan (vyfiltruje) a nasledne zosortuje
|
|
310
|
+
// toto sa da obist specialnym selectom:
|
|
311
|
+
// select t.* from (select t0.* from table t0 order by t0.<attr1>) t where <full-text-condition> limit 20
|
|
312
|
+
// (najprv zosortuje a az potom filtruje prvych 20 zaznamov - predpoklad je ze nad t0.<attr1> mame index aby rychlo sortoval)
|
|
313
|
+
// tento specialny select mozme v buducnosti dorobit (na backende) ak chceme podporovat (rychle) sortovanie v DB pre autocomplete
|
|
314
|
+
if (!this.props.suggestionsQuery) {
|
|
315
|
+
throw "XAutoCompleteBase.loadSuggestions: unexpected error - prop suggestionsQuery is undefined";
|
|
316
|
+
}
|
|
317
|
+
filter = XUtils_1.XUtils.evalFilter(this.props.suggestionsQuery.filter);
|
|
318
|
+
suggestionsRequest = {
|
|
319
|
+
maxRows: this.props.lazyLoadMaxRows + 1,
|
|
320
|
+
fullTextSearch: { fields: this.getFields(), value: event.query.trim(), splitValue: this.props.splitQueryValue, matchMode: "contains" },
|
|
321
|
+
entity: this.props.suggestionsQuery.entity,
|
|
322
|
+
filterItems: XUtils_1.XUtils.createCustomFilterItems(filter),
|
|
323
|
+
multiSortMeta: XUtils_1.XUtils.createMultiSortMeta(this.getSortField()),
|
|
324
|
+
fields: this.props.suggestionsQuery.fields
|
|
325
|
+
};
|
|
326
|
+
return [4 /*yield*/, XUtils_1.XUtils.fetchOne('x-lazy-auto-complete-suggestions', suggestionsRequest)];
|
|
327
|
+
case 9:
|
|
328
|
+
findResult = _a.sent();
|
|
329
|
+
filteredSuggestions = findResult.rowList;
|
|
330
|
+
// ak sme nesortovali v DB (co je draha operacia) tak zosortujeme teraz
|
|
331
|
+
// (computeDisplayValue sa vola duplicitne ale pre tych cca 20 zaznamov je to ok)
|
|
332
|
+
if (this.props.suggestionsQuery.sortField === undefined) {
|
|
333
|
+
filteredSuggestions = XUtils_1.XUtils.arraySort(filteredSuggestions, this.computeDisplayValue);
|
|
334
|
+
}
|
|
335
|
+
// ak mame o 1 zaznam viac ako je lazyLoadMaxRows, zmenime posledny zaznam na ...
|
|
336
|
+
if (filteredSuggestions.length > this.props.lazyLoadMaxRows) {
|
|
337
|
+
filteredSuggestions[filteredSuggestions.length - 1] = XAutoCompleteBase.valueMoreSuggestions; // zatial priamo string
|
|
338
|
+
}
|
|
339
|
+
_a.label = 10;
|
|
340
|
+
case 10:
|
|
341
|
+
this.setState({ filteredSuggestions: filteredSuggestions });
|
|
342
|
+
return [2 /*return*/];
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
};
|
|
347
|
+
XAutoCompleteBase.prototype.onChange = function (e) {
|
|
348
|
+
if (typeof e.value === 'string' && !XAutoCompleteBase.isMoreSuggestions(e.value)) {
|
|
145
349
|
this.setState({ inputChanged: true, inputValueState: e.value });
|
|
350
|
+
this.wasOnChangeCalled = false; // reset na default hodnotu
|
|
146
351
|
}
|
|
147
352
|
};
|
|
148
353
|
XAutoCompleteBase.prototype.onSelect = function (e) {
|
|
149
|
-
this.setObjectValue
|
|
354
|
+
// nevolame this.setObjectValue ak uz bol zavolany z onBlur
|
|
355
|
+
if (!this.wasOnChangeCalled) {
|
|
356
|
+
// nedovolime vybrat specialny zaznam ...
|
|
357
|
+
if (!XAutoCompleteBase.isMoreSuggestions(e.value)) {
|
|
358
|
+
this.setObjectValue(e.value, XUtils_1.OperationType.None);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
150
361
|
};
|
|
151
362
|
XAutoCompleteBase.prototype.onBlur = function (e) {
|
|
152
363
|
// optimalizacia - testujeme len ak inputChanged === true
|
|
@@ -159,6 +370,11 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
159
370
|
var filteredSuggestions = this.state.filteredSuggestions;
|
|
160
371
|
if (filteredSuggestions && filteredSuggestions.length === 1) {
|
|
161
372
|
this.setObjectValue(filteredSuggestions[0], XUtils_1.OperationType.None);
|
|
373
|
+
// ak bol tento this.setObjectValue vyvolany klikom do suggestions dropdown-u,
|
|
374
|
+
// tak bude este nasledne zavolany onSelect a tam chceme zamedzit volaniu this.setObjectValue,
|
|
375
|
+
// preto nastavujeme tento priznak
|
|
376
|
+
// priznak vratime naspet na false ak uzivatel zacne cokolvek robit s autocomplete (zacne don typovat alebo klikne na dropdown)
|
|
377
|
+
this.wasOnChangeCalled = true;
|
|
162
378
|
}
|
|
163
379
|
else {
|
|
164
380
|
// tu by sme mohli skusit vyratat vysledok pre filteredSuggestions este raz, mozno este vypocet filteredSuggestions nedobehol
|
|
@@ -190,8 +406,9 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
190
406
|
}
|
|
191
407
|
}
|
|
192
408
|
}
|
|
193
|
-
// odchadzame z inputu, zresetujeme priznak - ak zacne user pracovat s autocomplete-om, nacitaju sa suggestions z DB (ak mame
|
|
194
|
-
|
|
409
|
+
// odchadzame z inputu, zresetujeme priznak - ak zacne user pracovat s autocomplete-om, nacitaju sa suggestions z DB (ak mame suggestionsLoad = onSearchStart)
|
|
410
|
+
// suggestions chceme nacitat, lebo user moze zmenit iny atribut ktory ovplyvnuje filter autocomplete-u -> chceme novy zoznam suggestions
|
|
411
|
+
this.suggestionsLoadedForOSS = false;
|
|
195
412
|
};
|
|
196
413
|
XAutoCompleteBase.prototype.createErrorMessage = function () {
|
|
197
414
|
return "Value \"".concat(this.state.inputValueState, "\" was not found among valid values.");
|
|
@@ -231,6 +448,14 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
231
448
|
if (object !== null) {
|
|
232
449
|
// ak bol save, treba tento novy object pouzit
|
|
233
450
|
this.setObjectValue(object, objectChange);
|
|
451
|
+
// ak pouzivame zoznam this.state.suggestions, tak ho rereadneme
|
|
452
|
+
// poznamka: ak pouzivame this.props.suggestions z parenta, tak si musi zoznam rereadnut parent!
|
|
453
|
+
if (objectChange !== XUtils_1.OperationType.None) {
|
|
454
|
+
// zmenil sa zaznam dobrovolnika v DB
|
|
455
|
+
// zatial len refreshneme z DB
|
|
456
|
+
// ak by bol reqest pomaly, mozme pri inserte (nove id) / update (existujuce id) upravit zoznam a usetrime tym request do DB
|
|
457
|
+
this.loadSuggestions();
|
|
458
|
+
}
|
|
234
459
|
// treba upravit this.state.filteredSuggestions? setli sme novy objekt, panel so suggestions by mal byt zavrety - TODO - overit
|
|
235
460
|
}
|
|
236
461
|
else {
|
|
@@ -270,7 +495,7 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
270
495
|
_this.formDialogInitValuesForInsert = {};
|
|
271
496
|
// ak mame nevalidnu hodnotu, tak ju predplnime (snaha o user friendly)
|
|
272
497
|
if (_this.state.inputChanged) {
|
|
273
|
-
_this.formDialogInitValuesForInsert[_this.
|
|
498
|
+
_this.formDialogInitValuesForInsert[_this.getFirstField()] = _this.state.inputValueState;
|
|
274
499
|
}
|
|
275
500
|
_this.setState({ formDialogOpened: true });
|
|
276
501
|
}
|
|
@@ -287,13 +512,7 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
287
512
|
alert('Please select some row.');
|
|
288
513
|
}
|
|
289
514
|
else {
|
|
290
|
-
|
|
291
|
-
if (_this.props.idField === undefined) {
|
|
292
|
-
throw "XAutoCompleteBase: property valueForm is defined but property idField is also needed for form editation.";
|
|
293
|
-
}
|
|
294
|
-
_this.formDialogObjectId = _this.props.value[_this.props.idField];
|
|
295
|
-
_this.formDialogInitValuesForInsert = undefined;
|
|
296
|
-
_this.setState({ formDialogOpened: true });
|
|
515
|
+
_this.onEditAssocValue();
|
|
297
516
|
}
|
|
298
517
|
}
|
|
299
518
|
}
|
|
@@ -335,39 +554,87 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
335
554
|
});
|
|
336
555
|
};
|
|
337
556
|
XAutoCompleteBase.prototype.onOpenDropdown = function (e) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
// otvori dropdown (search je metoda popisana v API, volanie sme skopcili zo zdrojakov primereact)
|
|
344
|
-
//this.autoCompleteRef.current.search(e, '', 'dropdown');
|
|
345
|
-
this.openDropdown(e);
|
|
346
|
-
}
|
|
557
|
+
this.openDropdown(e);
|
|
558
|
+
this.suggestionsLoadedForOSS = false; // user mohol vyplnit nieco co meni filter a ide znova pracovat s autocomplete, nacitame suggestions znova (suggestionsLoad = onSearchStart)
|
|
559
|
+
this.wasOnChangeCalled = false; // reset na default hodnotu
|
|
347
560
|
};
|
|
348
561
|
XAutoCompleteBase.prototype.openDropdown = function (e) {
|
|
349
562
|
// otvori dropdown (search je metoda popisana v API, volanie sme skopcili zo zdrojakov primereact)
|
|
350
563
|
this.autoCompleteRef.current.search(e, '', 'dropdown');
|
|
351
564
|
};
|
|
565
|
+
XAutoCompleteBase.prototype.onEditAssocValue = function () {
|
|
566
|
+
// otvorime dialog na update
|
|
567
|
+
if (this.props.idField === undefined) {
|
|
568
|
+
throw "XAutoCompleteBase: property valueForm is defined but property idField is also needed for form editation.";
|
|
569
|
+
}
|
|
570
|
+
this.formDialogObjectId = this.props.value[this.props.idField];
|
|
571
|
+
this.formDialogInitValuesForInsert = undefined;
|
|
572
|
+
this.setState({ formDialogOpened: true });
|
|
573
|
+
};
|
|
352
574
|
// vracia objekt (ak inputChanged === false) alebo string (ak inputChanged === true)
|
|
353
575
|
XAutoCompleteBase.prototype.computeInputValue = function () {
|
|
354
576
|
var inputValue;
|
|
355
577
|
if (!this.state.inputChanged) {
|
|
356
578
|
// poznamka: ak object === null tak treba do inputu zapisovat prazdny retazec, ak by sme pouzili null, neprejavila by sa zmena v modeli na null
|
|
357
579
|
var object = this.props.value;
|
|
358
|
-
inputValue = (object !== null) ? object : ""; // TODO - je "" ok?
|
|
580
|
+
inputValue = (object !== null) ? this.computeDisplayValue(object) : ""; // TODO - je "" ok?
|
|
359
581
|
}
|
|
360
582
|
else {
|
|
361
583
|
inputValue = this.state.inputValueState;
|
|
362
584
|
}
|
|
363
585
|
return inputValue;
|
|
364
586
|
};
|
|
587
|
+
XAutoCompleteBase.prototype.itemTemplate = function (suggestion, index) {
|
|
588
|
+
return this.computeDisplayValue(suggestion);
|
|
589
|
+
};
|
|
590
|
+
XAutoCompleteBase.prototype.computeDisplayValue = function (suggestion) {
|
|
591
|
+
var e_2, _a;
|
|
592
|
+
var displayValue = "";
|
|
593
|
+
if (XAutoCompleteBase.isMoreSuggestions(suggestion)) {
|
|
594
|
+
displayValue = suggestion;
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
try {
|
|
598
|
+
for (var _b = __values(this.getFields()), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
599
|
+
var field = _c.value;
|
|
600
|
+
// TODO - konverzie na spravny typ/string
|
|
601
|
+
var _d = __read(XUtilsCommon_1.XUtilsCommon.getPrefixAndField(field), 2), prefix = _d[0], fieldOnly = _d[1];
|
|
602
|
+
var value = XUtilsCommon_1.XUtilsCommon.getValueByPath(suggestion, fieldOnly);
|
|
603
|
+
if (value !== null && value !== undefined) {
|
|
604
|
+
var valueStr = value.toString(); // TODO - spravnu konverziu
|
|
605
|
+
if (valueStr !== "") {
|
|
606
|
+
if (displayValue !== "") {
|
|
607
|
+
displayValue += " ";
|
|
608
|
+
}
|
|
609
|
+
if (prefix) {
|
|
610
|
+
displayValue += prefix;
|
|
611
|
+
}
|
|
612
|
+
displayValue += valueStr;
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
618
|
+
finally {
|
|
619
|
+
try {
|
|
620
|
+
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
621
|
+
}
|
|
622
|
+
finally { if (e_2) throw e_2.error; }
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
return displayValue;
|
|
626
|
+
};
|
|
627
|
+
// vrati true ak sa jedna o specialny typ XAutoCompleteBase.valueMoreSuggestions
|
|
628
|
+
XAutoCompleteBase.isMoreSuggestions = function (suggestion) {
|
|
629
|
+
return typeof suggestion === "string" && suggestion === XAutoCompleteBase.valueMoreSuggestions;
|
|
630
|
+
};
|
|
365
631
|
// takto cez metodku, mozno sa metodka vola len ked sa otvori dialog a usetrime nieco...
|
|
366
632
|
XAutoCompleteBase.prototype.createSearchBrowseParams = function () {
|
|
633
|
+
var _a;
|
|
367
634
|
return {
|
|
368
635
|
onChoose: this.searchDialogOnChoose,
|
|
369
|
-
displayFieldFilter: (this.state.inputChanged ? { field: this.
|
|
370
|
-
|
|
636
|
+
displayFieldFilter: (this.state.inputChanged ? { field: this.getFirstField(), constraint: { value: this.state.inputValueState, matchMode: "contains" } } : undefined),
|
|
637
|
+
customFilter: (_a = this.props.suggestionsQuery) === null || _a === void 0 ? void 0 : _a.filter
|
|
371
638
|
};
|
|
372
639
|
};
|
|
373
640
|
XAutoCompleteBase.prototype.render = function () {
|
|
@@ -375,21 +642,34 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
375
642
|
var _a;
|
|
376
643
|
var readOnly = (_a = this.props.readOnly) !== null && _a !== void 0 ? _a : false;
|
|
377
644
|
var dropdownButton;
|
|
378
|
-
if (
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
this.
|
|
645
|
+
if (!readOnly) {
|
|
646
|
+
if (this.props.searchBrowse || this.props.valueForm) {
|
|
647
|
+
// mame searchBrowse alebo CRUD operacie, potrebujeme SplitButton
|
|
648
|
+
var splitButtonItems = [];
|
|
649
|
+
if (this.props.valueForm) {
|
|
650
|
+
this.createInsertUpdateItems(splitButtonItems);
|
|
651
|
+
}
|
|
652
|
+
if (this.props.searchBrowse && !readOnly) {
|
|
653
|
+
this.createSearchItem(splitButtonItems);
|
|
654
|
+
}
|
|
655
|
+
this.createDropdownItem(splitButtonItems);
|
|
656
|
+
dropdownButton = react_1.default.createElement(splitbutton_1.SplitButton, { model: splitButtonItems, className: 'x-splitbutton-only-dropdown' + XUtils_1.XUtils.mobileCssSuffix(), menuClassName: 'x-splitbutton-only-dropdown-menu' + XUtils_1.XUtils.mobileCssSuffix(), disabled: readOnly });
|
|
383
657
|
}
|
|
384
|
-
|
|
385
|
-
|
|
658
|
+
else {
|
|
659
|
+
// mame len 1 operaciu - dame jednoduchy button
|
|
660
|
+
dropdownButton = react_1.default.createElement(button_1.Button, { icon: "pi pi-chevron-down", onClick: function (e) { return _this.onOpenDropdown(e); }, className: 'x-dropdownbutton' + XUtils_1.XUtils.mobileCssSuffix() });
|
|
386
661
|
}
|
|
387
|
-
this.createDropdownItem(splitButtonItems);
|
|
388
|
-
dropdownButton = react_1.default.createElement(splitbutton_1.SplitButton, { model: splitButtonItems, className: 'x-splitbutton-only-dropdown' + XUtils_1.XUtils.mobileCssSuffix(), menuClassName: 'x-splitbutton-only-dropdown-menu' + XUtils_1.XUtils.mobileCssSuffix(), disabled: readOnly });
|
|
389
662
|
}
|
|
390
663
|
else {
|
|
391
|
-
//
|
|
392
|
-
|
|
664
|
+
// readOnly
|
|
665
|
+
// ak mame valueForm a mame asociovany objekt, umoznime editovat asociovany objekt
|
|
666
|
+
if (this.props.valueForm && this.props.value !== null) {
|
|
667
|
+
dropdownButton = react_1.default.createElement(button_1.Button, { icon: "pi pi-pencil", onClick: function (e) { return _this.onEditAssocValue(); }, className: 'x-dropdownbutton' + XUtils_1.XUtils.mobileCssSuffix() });
|
|
668
|
+
}
|
|
669
|
+
else {
|
|
670
|
+
// dame disablovany button (z estetickych dovodov, zachovame sirku)
|
|
671
|
+
dropdownButton = react_1.default.createElement(button_1.Button, { icon: "pi pi-chevron-down", className: 'x-dropdownbutton' + XUtils_1.XUtils.mobileCssSuffix(), disabled: true });
|
|
672
|
+
}
|
|
393
673
|
}
|
|
394
674
|
// vypocitame inputValue
|
|
395
675
|
var inputValue = this.computeInputValue();
|
|
@@ -405,9 +685,9 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
405
685
|
// <DobrovolnikForm id={this.formDialogObjectId} object={this.formDialogInitValuesForInsert} onSaveOrCancel={this.formDialogOnSaveOrCancel}/>
|
|
406
686
|
// formgroup-inline lepi SplitButton na autocomplete a zarovna jeho vysku
|
|
407
687
|
return (react_1.default.createElement("div", { className: "x-auto-complete-base", style: { width: this.props.width } },
|
|
408
|
-
react_1.default.createElement(autocomplete_1.AutoComplete, __assign({ value: inputValue, suggestions: this.state.filteredSuggestions, completeMethod: this.completeMethod,
|
|
688
|
+
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))),
|
|
409
689
|
dropdownButton,
|
|
410
|
-
this.props.valueForm != undefined
|
|
690
|
+
this.props.valueForm != undefined ?
|
|
411
691
|
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, {
|
|
412
692
|
id: this.formDialogObjectId, initValues: this.formDialogInitValuesForInsert, onSaveOrCancel: this.formDialogOnSaveOrCancel
|
|
413
693
|
} /*, this.props.valueForm.children*/))
|
|
@@ -416,6 +696,13 @@ var XAutoCompleteBase = /** @class */ (function (_super) {
|
|
|
416
696
|
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*/))
|
|
417
697
|
: undefined));
|
|
418
698
|
};
|
|
699
|
+
XAutoCompleteBase.valueMoreSuggestions = "...";
|
|
700
|
+
XAutoCompleteBase.defaultProps = {
|
|
701
|
+
lazyLoadMaxRows: 10,
|
|
702
|
+
splitQueryValue: true,
|
|
703
|
+
minLength: 1,
|
|
704
|
+
scrollHeight: '15rem' // primereact has 200px
|
|
705
|
+
};
|
|
419
706
|
return XAutoCompleteBase;
|
|
420
707
|
}(react_1.Component));
|
|
421
708
|
exports.XAutoCompleteBase = XAutoCompleteBase;
|
|
@@ -3,24 +3,28 @@ 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
11
|
displayField: string;
|
|
10
12
|
searchBrowse?: JSX.Element;
|
|
11
13
|
assocForm?: JSX.Element;
|
|
12
|
-
filter?: XTableFieldFilterProp;
|
|
13
14
|
suggestions?: any[];
|
|
15
|
+
suggestionsLoad?: XSuggestionsLoadProp;
|
|
16
|
+
lazyLoadMaxRows?: number;
|
|
17
|
+
splitQueryValue?: boolean;
|
|
18
|
+
minLength?: number;
|
|
19
|
+
filter?: XTableFieldFilterProp;
|
|
20
|
+
sortField?: string | DataTableSortMeta[];
|
|
21
|
+
fields?: string[];
|
|
22
|
+
scrollHeight?: string;
|
|
14
23
|
}
|
|
15
24
|
export declare class XAutoCompleteDT extends XFormComponentDT<XAutoCompleteDTProps> {
|
|
16
25
|
protected xAssoc: XAssoc;
|
|
17
26
|
protected errorInBase: string | undefined;
|
|
18
|
-
state: {
|
|
19
|
-
suggestions: any[];
|
|
20
|
-
};
|
|
21
27
|
constructor(props: XAutoCompleteDTProps);
|
|
22
|
-
componentDidMount(): void;
|
|
23
|
-
readAndSetSuggestions(): Promise<void>;
|
|
24
28
|
getField(): string;
|
|
25
29
|
isNotNull(): boolean;
|
|
26
30
|
getValue(): any | null;
|