@agilemotion/oui-react-js 1.8.27 → 1.8.29

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.
Files changed (33) hide show
  1. package/dist/ApplicationManager.js +13 -8
  2. package/dist/DateUtils.js +78 -0
  3. package/dist/DynamicJS.js +5 -0
  4. package/dist/RestService.js +2 -3
  5. package/dist/Utils.js +3 -3
  6. package/dist/components/DataGrid.js +5 -1
  7. package/dist/components/DataGridColumn.js +25 -4
  8. package/dist/components/HtmlPanel.js +4 -2
  9. package/dist/components/Icon.js +3 -0
  10. package/dist/components/PDFViewer.js +6 -1
  11. package/dist/components/TabPanel.js +6 -0
  12. package/dist/components/TableCellContent.js +46 -1
  13. package/dist/components/facialRecognition/FaceRecognitionComponent.js +205 -0
  14. package/dist/components/facialRecognition/FacialRecognition.css +3 -0
  15. package/dist/components/facialRecognition/FacialRegistration.js +73 -0
  16. package/dist/components/facialRecognition/FacialVerification.js +84 -0
  17. package/dist/components/facialRecognition/Modal.js +33 -0
  18. package/dist/components/facialRecognition/service/faceApi.js +55 -0
  19. package/dist/components/form/BaseField.js +1 -4
  20. package/dist/components/form/FieldSet.js +4 -2
  21. package/dist/components/form/Form.js +1 -0
  22. package/dist/components/form/GridField.js +5 -5
  23. package/dist/components/form/ImageEditor.js +200 -84
  24. package/dist/components/form/LookupField.js +3 -4
  25. package/dist/components/form/RadioGroup.js +1 -1
  26. package/dist/components/layout/Layout.js +16 -0
  27. package/dist/components/layout/View.js +2 -0
  28. package/dist/components/signatures/DocumentContainer.js +1 -1
  29. package/dist/components/signatures/ViewUtils.js +1 -1
  30. package/dist/event/ActionHandlers.js +1 -1
  31. package/dist/event/ServiceCallActionHandler.js +2 -1
  32. package/dist/js/Validators.js +2 -1
  33. package/package.json +13 -4
@@ -645,14 +645,19 @@ class ApplicationManager {
645
645
  objValue = null;
646
646
  }
647
647
  if (_this2.isExpression(objValue)) {
648
- let scriptValue = _DynamicJS.default.executeScript(`resolveParam_${Math.random().toString().replace('.', '_')}`, objValue, null, null, eventData);
649
- if (typeof scriptValue === 'undefined') {
650
- scriptValue = null;
651
- }
652
- let objKey = key === 'valueExpression' ? 'value' : key;
653
- updated[objKey] = scriptValue !== null && scriptValue.instanceType === 'TypedValue' ? scriptValue.value : scriptValue;
654
- if (typeof updated[objKey] === 'undefined') {
655
- delete updated.type;
648
+ try {
649
+ let scriptValue = _DynamicJS.default.executeScript(`resolveParam_${Math.random().toString().replace('.', '_')}`, objValue, null, null, eventData);
650
+ if (typeof scriptValue === 'undefined') {
651
+ scriptValue = null;
652
+ }
653
+ let objKey = key === 'valueExpression' ? 'value' : key;
654
+ updated[objKey] = scriptValue !== null && scriptValue.instanceType === 'TypedValue' ? scriptValue.value : scriptValue;
655
+ if (typeof updated[objKey] === 'undefined') {
656
+ delete updated.type;
657
+ }
658
+ } catch (e) {
659
+ console.error("Error processing parameter expression : " + objValue);
660
+ throw e;
656
661
  }
657
662
  } else {
658
663
  updated[key] = objValue;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.makeDateReplacer = makeDateReplacer;
7
+ // Build "YYYY-MM-DDTHH:mm:ss.SSS+HH:MM" for a given time zone
8
+ function zonedISOString(date) {
9
+ let timeZone = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Africa/Johannesburg';
10
+ // 1) Get wall-clock parts in the target zone
11
+ const dtf = new Intl.DateTimeFormat('en-CA', {
12
+ timeZone,
13
+ hour12: false,
14
+ year: 'numeric',
15
+ month: '2-digit',
16
+ day: '2-digit',
17
+ hour: '2-digit',
18
+ minute: '2-digit',
19
+ second: '2-digit'
20
+ });
21
+ const parts = Object.fromEntries(dtf.formatToParts(date).map(p => [p.type, p.value]));
22
+ const ms = String(date.getMilliseconds()).padStart(3, '0');
23
+
24
+ // 2) Compute numeric offset (+/- minutes) for that zone at this instant
25
+ // (works across DST if your zone observes it)
26
+ const asUTC = Date.UTC(Number(parts.year), Number(parts.month) - 1, Number(parts.day), Number(parts.hour), Number(parts.minute), Number(parts.second), date.getMilliseconds());
27
+ const offsetMinutes = Math.round((asUTC - date.getTime()) / 60000); // e.g. +120 for SAST
28
+ const sign = offsetMinutes >= 0 ? '+' : '-';
29
+ const abs = Math.abs(offsetMinutes);
30
+ const offHH = String(Math.trunc(abs / 60)).padStart(2, '0');
31
+ const offMM = String(abs % 60).padStart(2, '0');
32
+ const offset = `${sign}${offHH}:${offMM}`;
33
+ return `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}.${ms}${offset}`;
34
+ }
35
+
36
+ // Replacer: converts Date instances anywhere in the object graph
37
+ function makeDateReplacer() {
38
+ let {
39
+ timeZone = 'Africa/Johannesburg',
40
+ mode = 'zoned-iso'
41
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
42
+ return function replacer(_key, value) {
43
+ if (value instanceof Date) {
44
+ if (mode === 'epoch-ms') return value.getTime(); // 1732575600000
45
+ if (mode === 'utc-iso') return value.toISOString(); // 2025-11-25T22:00:00.000Z
46
+ return zonedISOString(value, timeZone); // default: SAST ISO with +02:00
47
+ }
48
+ return value;
49
+ };
50
+ }
51
+
52
+ // Usage
53
+ const obj = {
54
+ data: {
55
+ person: {
56
+ dob: new Date('2025-11-25T22:00:00.000Z')
57
+ },
58
+ when: new Date(),
59
+ // now
60
+ list: [1, new Date('2025-06-01T10:00:00Z')]
61
+ }
62
+ };
63
+
64
+ // Serialize with SAST (UTC+02:00)
65
+ const jsonSAST = JSON.stringify(obj, makeDateReplacer({
66
+ timeZone: 'Africa/Johannesburg'
67
+ }));
68
+ console.log(jsonSAST);
69
+
70
+ // If you prefer epoch millis everywhere (more portable)
71
+ const jsonEpoch = JSON.stringify(obj, makeDateReplacer({
72
+ mode: 'epoch-ms'
73
+ }));
74
+
75
+ // If you want to keep UTC ISO but be explicit (baseline behavior)
76
+ const jsonUTC = JSON.stringify(obj, makeDateReplacer({
77
+ mode: 'utc-iso'
78
+ }));
package/dist/DynamicJS.js CHANGED
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = exports.TEMPLATE_REGEX = void 0;
7
7
  var _ApplicationManager = _interopRequireWildcard(require("./ApplicationManager"));
8
8
  var _Utils = _interopRequireDefault(require("./Utils"));
9
+ var _DateUtils = require("./DateUtils");
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
11
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
11
12
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
@@ -40,6 +41,9 @@ class DynamicJS {
40
41
  return _Utils.default.isNull(value) || value.toString().trim().length === 0;
41
42
  }
42
43
  evaluateExpression = expression => {
44
+ if (typeof expression !== 'string') {
45
+ return expression;
46
+ }
43
47
  return _ApplicationManager.default.resolveExpressionValue(expression);
44
48
  };
45
49
  parseScript = (script, componentId, isScriptlet) => {
@@ -88,6 +92,7 @@ class DynamicJS {
88
92
  eventParam.data = event.data;
89
93
  }
90
94
  try {
95
+ // NB : The javascript serializer uses UCT for dates and it is 2 hours behind. TODO : use DateUtils.makeDateReplacer
91
96
  let func = new Function(parsedScript.replace(/\$event/g, JSON.stringify(eventParam)));
92
97
  if (!_Utils.default.isNull(name)) {
93
98
  DynamicJS.prototype[name] = func;
@@ -43,7 +43,7 @@ class RestService {
43
43
  let requestBodyParamFound = false;
44
44
  for (const parameter of service.parameters) {
45
45
  let parameterValue = _ApplicationManager.default.resolveParameterValue(parameter, request.event ? request.event.data : null);
46
- if (!_Utils.default.isNull(parameter.validator) && !_Utils.default.evaluateBooleanExpression(parameter.validator.nullable, parameter.name) && this.isParamValueNull(parameterValue)) {
46
+ if (!_Utils.default.isNull(parameter.validator) && (parameter.validator.nullable && !_Utils.default.evaluateBooleanExpression(parameter.validator.nullable, parameter.name) || _Utils.default.evaluateBooleanExpression(parameter.validator.required && _Utils.default.evaluateBooleanExpression(parameter.validator.required, parameter.name))) && this.isParamValueNull(parameterValue)) {
47
47
  reject({
48
48
  errorType: 'INVALID_PARAMETER',
49
49
  parameter
@@ -188,8 +188,7 @@ class RestService {
188
188
  if (_Utils.default.isNull(parameter.type)) {
189
189
  parameter.type = 'String';
190
190
  }
191
- if (!_Utils.default.isNull(parameterConfig.validator) && _Utils.default.evaluateBooleanExpression(parameterConfig.validator.nullable, parameterConfig.name) === false && this.isParamValueNull(parameter)) {
192
- console.error('INVALID PARAMETER : ', parameter);
191
+ if (!_Utils.default.isNull(parameter.validator) && (parameter.validator.nullable && !_Utils.default.evaluateBooleanExpression(parameter.validator.nullable, parameter.name) || _Utils.default.evaluateBooleanExpression(parameter.validator.required && _Utils.default.evaluateBooleanExpression(parameter.validator.required, parameter.name))) && this.isParamValueNull(parameter.value)) {
193
192
  reject({
194
193
  errorType: 'INVALID_PARAMETER',
195
194
  parameter
package/dist/Utils.js CHANGED
@@ -13,7 +13,7 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
13
13
  const colors = ['#F44336', '#e91e63', '#9c27b0', '#673ab7', '#ff9800', '#ff5722', '#795548', '#607d8b', '#3f51b5', '#2196F3', '#00bcd4', '#009688', '#2196F3', '#32c787', '#00BCD4', '#ff5652', '#ffc107', '#ff85af', '#FF9800', '#39bbb0', '#4CAF50', '#ffeb3b', '#ffc107'];
14
14
  class Utils {
15
15
  constructor() {}
16
- static SYSTEM_ERROR_MESSAGE = "A system error has accured. Please contact your system administrator";
16
+ static SYSTEM_ERROR_MESSAGE = "A system error has occurred. Please contact your system administrator";
17
17
  static isNull(value) {
18
18
  return value === null || typeof value === 'undefined';
19
19
  }
@@ -147,7 +147,7 @@ class Utils {
147
147
  return JSON.stringify(request);
148
148
  }
149
149
  static getFieldColspan = field => {
150
- return !Utils.isNull(field.attributes) && !Utils.isNull(field.attributes['colspan']) ? parseFloat(field.attributes['colspan']) : 1;
150
+ return !Utils.isNull(field.attributes) && !Utils.isNull(field.attributes['colspan']) ? parseInt(typeof field.attributes.colspan === 'string' ? _DynamicJS.default.executeScript("__colspan_" + field.id, field.attributes.colspan) : field.attributes.colspan) : 1;
151
151
  };
152
152
  static createRow = () => {
153
153
  let row = {};
@@ -353,7 +353,7 @@ class Utils {
353
353
  };
354
354
  static publishSystemErrorMessage = function (viewId) {
355
355
  let component = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
356
- Utils.publishErrorMessage('A system error has accured. Please try again later', viewId, component);
356
+ Utils.publishErrorMessage('A system error has occurred. Please try again later', viewId, component);
357
357
  };
358
358
  static base64ToArrayBuffer = base64 => {
359
359
  const binaryString = window.atob(base64);
@@ -276,6 +276,9 @@ const DataGrid = exports.DataGrid = /*#__PURE__*/_react.default.memo(/*#__PURE__
276
276
  if (!_Utils.default.isNull(props.config.visible)) {
277
277
  setVisible(_Utils.default.evaluateBooleanExpression(props.config.visible, props.config.id));
278
278
  }
279
+ },
280
+ set visible(visible) {
281
+ setVisible(visible);
279
282
  }
280
283
  };
281
284
  };
@@ -917,7 +920,8 @@ const DataGrid = exports.DataGrid = /*#__PURE__*/_react.default.memo(/*#__PURE__
917
920
  dataBinding: !_Utils.default.isNull(column.dataBinding) ? column.dataBinding : column.id,
918
921
  row: row,
919
922
  contentType: column.fieldType || column.editor?.fieldType,
920
- cellFormatter: column.cellFormatter
923
+ cellFormatter: column.cellFormatter,
924
+ criteria: criteria
921
925
  }))));
922
926
  })))), _Utils.default.isNull(props.pagination) || props.pagination === true ? /*#__PURE__*/_react.default.createElement(_TablePagination.default, {
923
927
  rowsPerPageOptions: rowsPerPageOptions,
@@ -11,6 +11,8 @@ var _reactSuperResponsiveTable = require("react-super-responsive-table");
11
11
  var _TableSortLabel = _interopRequireDefault(require("@mui/material/TableSortLabel"));
12
12
  require("./DataGrid.css");
13
13
  var _styles = require("@mui/styles");
14
+ var _Tooltip = _interopRequireDefault(require("@mui/material/Tooltip"));
15
+ var _Box = _interopRequireDefault(require("@mui/material/Box"));
14
16
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
17
  const useStyles = (0, _styles.makeStyles)(theme => ({
16
18
  tableHeaderCell: {
@@ -148,11 +150,30 @@ const DataGridColumn = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.defa
148
150
  },
149
151
  onMouseDown: e => handleResizeStart(e, props.config.id)
150
152
  }), /*#__PURE__*/_react.default.createElement(_TableSortLabel.default, {
151
- active: config.attributes['sortable'] === true,
152
- direction: 'desc',
153
+ active: false,
154
+ direction: "desc",
153
155
  onClick: props.createSortHandler(config.id)
154
- }, label + postfix, 'id' === config.id ? /*#__PURE__*/_react.default.createElement("span", {
156
+ // keep the sort icon from squashing the text
157
+ ,
158
+ sx: {
159
+ '& .MuiTableSortLabel-icon': {
160
+ flexShrink: 0
161
+ }
162
+ }
163
+ }, /*#__PURE__*/_react.default.createElement(_Tooltip.default, {
164
+ title: label + postfix
165
+ }, /*#__PURE__*/_react.default.createElement(_Box.default, {
166
+ component: "span",
167
+ sx: {
168
+ display: 'inline-block',
169
+ maxWidth: '100%',
170
+ overflow: 'hidden',
171
+ textOverflow: 'ellipsis',
172
+ whiteSpace: 'nowrap',
173
+ verticalAlign: 'bottom'
174
+ }
175
+ }, label + postfix)), 'id' === config.id ? /*#__PURE__*/_react.default.createElement("span", {
155
176
  className: classes.visuallyHidden
156
- }, 'sorted descending') : null));
177
+ }, "sorted descending") : null));
157
178
  }));
158
179
  var _default = exports.default = DataGridColumn;
@@ -83,9 +83,11 @@ const HtmlPanel = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.default.f
83
83
  get id() {
84
84
  return props.config.id;
85
85
  },
86
- loadData: actionConfig => {
86
+ loadData: (actionConfig, event) => {
87
87
  if (actionConfig && actionConfig.value) {
88
- let data = _ApplicationManager.default.resolveExpressionValue(actionConfig.value);
88
+ console.log("\n\n\n\n\n HTML PANEL : ", actionConfig.value);
89
+ let data = _ApplicationManager.default.resolveExpressionValue(actionConfig.value, event?.data);
90
+ console.log("DATA : ", data);
89
91
  let templateScript = Handlebars.compile(template);
90
92
  setContent(templateScript(data));
91
93
  }
@@ -26,6 +26,7 @@ var _Notifications = _interopRequireDefault(require("@mui/icons-material/Notific
26
26
  var _Person = _interopRequireDefault(require("@mui/icons-material/Person"));
27
27
  var _Refresh = _interopRequireDefault(require("@mui/icons-material/Refresh"));
28
28
  var _Folder = _interopRequireDefault(require("@mui/icons-material/Folder"));
29
+ var _FolderOpen = _interopRequireDefault(require("@mui/icons-material/FolderOpen"));
29
30
  var _AttachFile = _interopRequireDefault(require("@mui/icons-material/AttachFile"));
30
31
  var _CalendarToday = _interopRequireDefault(require("@mui/icons-material/CalendarToday"));
31
32
  var _react = _interopRequireWildcard(require("react"));
@@ -166,6 +167,8 @@ class Icon extends _react.Component {
166
167
  });
167
168
  } else if (this.props.id === 'FOLDER') {
168
169
  return /*#__PURE__*/_react.default.createElement(_Folder.default, null);
170
+ } else if (this.props.id === 'FOLDER_OPEN') {
171
+ return /*#__PURE__*/_react.default.createElement(_FolderOpen.default, null);
169
172
  } else if (this.props.id === 'CALENDAR') {
170
173
  return /*#__PURE__*/_react.default.createElement(_CalendarToday.default, null);
171
174
  } else if (this.props.id === 'SIGN') {
@@ -4,10 +4,12 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _react = _interopRequireDefault(require("react"));
7
+ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactPdf = require("react-pdf");
9
9
  var _Utils = _interopRequireDefault(require("../Utils"));
10
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
12
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
11
13
  _reactPdf.pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${_reactPdf.pdfjs.version}/pdf.worker.js`;
12
14
  const PDFViewer = props => {
13
15
  const [pageNumber, setPageNumber] = _react.default.useState(1);
@@ -21,6 +23,9 @@ const PDFViewer = props => {
21
23
  props.onDocumentLoadSuccess(numPages);
22
24
  }
23
25
  };
26
+ (0, _react.useEffect)(() => {
27
+ setPageNumber(1);
28
+ }, [props.file]);
24
29
  const changePage = offset => {
25
30
  setPageNumber(pageNumber + offset);
26
31
  };
@@ -110,6 +110,12 @@ const TabPanel = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.default.fo
110
110
  }
111
111
  return children;
112
112
  },
113
+ set value(value) {
114
+ setTabValue(value);
115
+ },
116
+ get value() {
117
+ return tabValue;
118
+ },
113
119
  setPageHasError: (pageId, hasError) => {
114
120
  setErrors({
115
121
  ...errors,
@@ -16,6 +16,7 @@ const TableCellContent = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.de
16
16
  const [refresher, setRefresher] = _react.default.useState(true);
17
17
  const [editor, setEditor] = _react.default.useState(null);
18
18
  const editorValue = _react.default.useRef(null);
19
+ const escapeRegex = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
19
20
  const formatter = new Intl.NumberFormat("en-ZA", {
20
21
  style: "currency",
21
22
  currency: "ZAR",
@@ -97,6 +98,45 @@ const TableCellContent = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.de
97
98
  const formatted = `${String(date.getDate()).padStart(2, '0')}/` + `${String(date.getMonth() + 1).padStart(2, '0')}/` + `${date.getFullYear()}`;
98
99
  return formatted;
99
100
  };
101
+
102
+ // Build flat, deduped list of search terms from criteria.parameters
103
+ const buildSearchTerms = parameters => {
104
+ const set = new Set();
105
+ for (const p of parameters || []) {
106
+ if (p?.value && typeof p.value === 'string') {
107
+ for (const term of p.value.split(/\s+/)) {
108
+ const t = term.trim();
109
+ if (t) set.add(t.toLowerCase());
110
+ }
111
+ }
112
+ }
113
+ return Array.from(set); // lowercase terms
114
+ };
115
+ const highlightTokens = (value, terms) => {
116
+ if (!value || !terms?.length) return value;
117
+
118
+ // Combine terms into a single capturing group for split
119
+ const pattern = `(${terms.map(t => escapeRegex(t)).join('|')})`;
120
+ const splitRegex = new RegExp(pattern, 'gi');
121
+ const exactRegex = new RegExp(`^(?:${pattern})$`, 'i'); // to test parts
122
+
123
+ const parts = value.split(splitRegex);
124
+ return parts.map((part, i) => {
125
+ const isMatch = exactRegex.test(part);
126
+ return isMatch ? /*#__PURE__*/_react.default.createElement("span", {
127
+ key: i,
128
+ style: {
129
+ backgroundColor: '#ffeb3b',
130
+ color: '#000',
131
+ borderRadius: '4px',
132
+ fontWeight: 'bold',
133
+ boxShadow: '0 0 3px rgba(0,0,0,0.3)'
134
+ }
135
+ }, part) : /*#__PURE__*/_react.default.createElement("span", {
136
+ key: i
137
+ }, part);
138
+ });
139
+ };
100
140
  const getStaticDisplayValue = () => {
101
141
  let displayValue;
102
142
  let contentValue;
@@ -133,7 +173,12 @@ const TableCellContent = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.de
133
173
  // TODO : First check if the editor has a display template. If it does, use it to get the display value
134
174
  displayValue = contentValue.dataRecordDescription;
135
175
  } else {
136
- displayValue = contentValue;
176
+ if (props.criteria && props.criteria.parameters) {
177
+ const terms = buildSearchTerms(props.criteria.parameters);
178
+ return highlightTokens(contentValue, terms);
179
+ } else {
180
+ return contentValue;
181
+ }
137
182
  }
138
183
  }
139
184
  if (props.cellFormatter) {
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var faceapi = _interopRequireWildcard(require("face-api.js"));
9
+ var _faceApi2 = require("./service/faceApi");
10
+ var _reactRouterDom = require("react-router-dom");
11
+ require("./FacialRecognition.css");
12
+ var _Button = _interopRequireDefault(require("@mui/material/Button"));
13
+ var _Utils = _interopRequireDefault(require("../../Utils"));
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
+ const FaceRecognitionComponent = _ref => {
18
+ let {
19
+ mode,
20
+ processingPath,
21
+ onComplete
22
+ } = _ref;
23
+ const [imageUrl, setImageUrl] = (0, _react.useState)(null);
24
+ const [boxes, setBoxes] = (0, _react.useState)([]);
25
+ const [step, setStep] = (0, _react.useState)(1);
26
+ const [modelsLoaded, setModelsLoaded] = (0, _react.useState)(false);
27
+ const [loading, setLoading] = (0, _react.useState)(false);
28
+ const [resultMessage, setResultMessage] = (0, _react.useState)(null);
29
+ const [resultSuccess, setResultSuccess] = (0, _react.useState)(null);
30
+ const videoRef = (0, _react.useRef)(null);
31
+ const streamRef = (0, _react.useRef)(null);
32
+ const canvasRef = (0, _react.useRef)(null);
33
+ const navigate = (0, _reactRouterDom.useNavigate)();
34
+ (0, _react.useEffect)(() => {
35
+ const loadModels = async () => {
36
+ await faceapi.nets.ssdMobilenetv1.loadFromUri('/models');
37
+ await faceapi.nets.faceLandmark68Net.loadFromUri('/models');
38
+ await faceapi.nets.faceRecognitionNet.loadFromUri('/models');
39
+ setModelsLoaded(true);
40
+ };
41
+ loadModels();
42
+ }, []);
43
+ (0, _react.useEffect)(() => {
44
+ if (step === 2 && videoRef.current) {
45
+ loadCamera();
46
+ } else if (step === 3 && streamRef.current) {
47
+ const stream = streamRef.current;
48
+ stream?.getTracks().forEach(track => track.stop());
49
+ }
50
+ }, [step]);
51
+ (0, _react.useEffect)(() => {
52
+ const video = videoRef.current;
53
+ if (!video || !modelsLoaded || step !== 2) return;
54
+ const detect = () => detectFace();
55
+ video.addEventListener('canplay', detect);
56
+ const interval = setInterval(detect, 200);
57
+ return () => {
58
+ video.removeEventListener('canplay', detect);
59
+ clearInterval(interval);
60
+ };
61
+ }, [modelsLoaded, step]);
62
+ const loadCamera = async () => {
63
+ try {
64
+ const stream = await navigator.mediaDevices.getUserMedia({
65
+ video: true
66
+ });
67
+ if (videoRef.current) {
68
+ videoRef.current.srcObject = stream;
69
+ }
70
+ streamRef.current = stream;
71
+ } catch (err) {
72
+ console.error('Error accessing webcam:', err);
73
+ }
74
+ };
75
+ (0, _react.useEffect)(() => {
76
+ // 👇 THIS is the cleanup for stopping the webcam
77
+ return () => {
78
+ const stream = streamRef.current;
79
+ stream?.getTracks().forEach(track => track.stop());
80
+ };
81
+ }, []);
82
+ const detectFace = async () => {
83
+ const video = videoRef.current;
84
+ const canvas = canvasRef.current;
85
+ if (!video || !canvas) return;
86
+ canvas.width = video.videoWidth;
87
+ canvas.height = video.videoHeight;
88
+ const detections = await faceapi.detectAllFaces(video).withFaceLandmarks().withFaceDescriptors();
89
+ const resizedDetections = faceapi.resizeResults(detections, {
90
+ width: video.videoWidth,
91
+ height: video.videoHeight
92
+ });
93
+ setBoxes(resizedDetections.map(d => d.detection.box));
94
+ const ctx = canvas.getContext('2d');
95
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
96
+ faceapi.draw.drawDetections(canvas, resizedDetections);
97
+ faceapi.draw.drawFaceLandmarks(canvas, resizedDetections);
98
+ };
99
+ const captureImage = async () => {
100
+ if (loading) return;
101
+ setLoading(true);
102
+ const video = videoRef.current;
103
+ try {
104
+ const detection = await faceapi.detectSingleFace(video).withFaceLandmarks().withFaceDescriptor();
105
+ if (!detection) {
106
+ alert("No face detected.");
107
+ return;
108
+ }
109
+ const box = detection.detection.box;
110
+ const croppedCanvas = document.createElement('canvas');
111
+ croppedCanvas.width = box.width;
112
+ croppedCanvas.height = box.height;
113
+ const ctx = croppedCanvas.getContext('2d');
114
+ ctx.drawImage(video, box.x, box.y, box.width, box.height, 0, 0, box.width, box.height);
115
+ const faceDataUrl = croppedCanvas.toDataURL();
116
+ const descriptor = detection.descriptor;
117
+ setImageUrl(faceDataUrl);
118
+ const response = mode === 'register' ? await (0, _faceApi2.registerFace)(descriptor, faceDataUrl, processingPath) : await (0, _faceApi2.verifyFace)(descriptor, processingPath);
119
+ if (response.outcome !== 'SUCCESS') {
120
+ setStep(3);
121
+ setResultMessage(response.message || `Failed to ${mode} face.`);
122
+ setResultSuccess(false);
123
+ onComplete(response);
124
+ return;
125
+ }
126
+ setResultMessage(response.message || `${mode === 'register' ? 'Registered' : 'Verified'} successfully!`);
127
+ setResultSuccess(true);
128
+ setStep(3);
129
+ onComplete(response);
130
+ } catch (err) {
131
+ //console.log('API errors:', err);
132
+ setResultMessage('Verification failed.' || `${mode === 'verify' ? 'Verification' : 'Registeration'} failed!`);
133
+ setStep(3);
134
+ //alert('Something went wrong while processing your face. Please try again.');
135
+ } finally {
136
+ setLoading(false);
137
+ }
138
+ };
139
+ return /*#__PURE__*/_react.default.createElement("div", {
140
+ style: {
141
+ display: 'flex',
142
+ alignContent: 'center',
143
+ justifyContent: 'center'
144
+ }
145
+ }, /*#__PURE__*/_react.default.createElement("div", {
146
+ style: {
147
+ maxWidth: '28rem',
148
+ textAlign: 'center'
149
+ }
150
+ }, step < 3 ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h2", {
151
+ className: "text-xl font-bold mb-2"
152
+ }, mode === 'register' ? "Let's register your face" : "Facial verification"), /*#__PURE__*/_react.default.createElement("p", {
153
+ className: "text-gray-600 mb-6"
154
+ }, mode === 'register' ? 'Look into the camera to register your face.' : 'Look into the camera for verification.'), step === 1 && /*#__PURE__*/_react.default.createElement(_Button.default, {
155
+ variant: 'contained',
156
+ size: "large",
157
+ color: 'primary',
158
+ onClick: () => setStep(2)
159
+ }, "Start ", mode === 'register' ? 'Registration' : 'Verification'), step === 2 && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
160
+ style: {
161
+ display: 'flex',
162
+ alignContent: 'center',
163
+ justifyContent: 'center',
164
+ position: 'relative',
165
+ aspectRatio: '16 / 9',
166
+ margin: '1em 0',
167
+ height: 'auto',
168
+ borderRadius: '4px'
169
+ }
170
+ }, /*#__PURE__*/_react.default.createElement("video", {
171
+ ref: videoRef,
172
+ autoPlay: true,
173
+ muted: true,
174
+ playsInline: true,
175
+ style: {
176
+ width: '100%',
177
+ height: 'auto'
178
+ }
179
+ }), /*#__PURE__*/_react.default.createElement("canvas", {
180
+ ref: canvasRef,
181
+ style: {
182
+ position: 'absolute',
183
+ top: 0,
184
+ left: 0,
185
+ width: '100%',
186
+ height: '100%'
187
+ },
188
+ className: "absolute top-0 left-0 w-full h-full"
189
+ })), /*#__PURE__*/_react.default.createElement(_Button.default, {
190
+ variant: 'contained',
191
+ size: "large",
192
+ color: 'primary',
193
+ onClick: captureImage,
194
+ disabled: loading || !videoRef.current
195
+ }, loading ? 'Processing...' : 'Capture'))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("h2", {
196
+ className: `text-xl font-bold mb-2 ${resultSuccess ? 'text-green-600' : 'text-red-600'}`
197
+ }, resultSuccess ? mode === 'register' ? "" : "" : "Something went wrong"), /*#__PURE__*/_react.default.createElement("p", {
198
+ className: `text-xl font-bold mb-2 ${resultSuccess ? 'text-green-600' : 'text-red-600'}`
199
+ }, resultMessage || `Face ${mode} result.`), imageUrl && /*#__PURE__*/_react.default.createElement("img", {
200
+ src: imageUrl,
201
+ alt: "Captured Face",
202
+ className: "rounded-xl border shadow-lg w-full"
203
+ }))));
204
+ };
205
+ var _default = exports.default = FaceRecognitionComponent;
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;