@onehat/ui 0.4.102 → 0.4.104

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 (56) hide show
  1. package/.github/copilot-instructions.md.bak.20260307094051 +65 -0
  2. package/package.json +1 -1
  3. package/src/Components/Accordion/Accordion.js +65 -6
  4. package/src/Components/Container/Container.js +10 -4
  5. package/src/Components/Form/Field/Combo/Combo.js +8 -2
  6. package/src/Components/Form/Form.js +17 -9
  7. package/src/Components/Grid/Grid.js +234 -154
  8. package/src/Components/Grid/GridRow.js +5 -1
  9. package/src/Components/Hoc/Secondary/withSecondaryEditor.js +18 -1
  10. package/src/Components/Hoc/withEditor.js +18 -1
  11. package/src/Components/Hoc/withPdfButtons.js +3 -0
  12. package/src/Components/Hoc/withPresetButtons.js +20 -6
  13. package/src/Components/Icons/ArrowsLeftRight.js +10 -0
  14. package/src/Components/Icons/Bar.js +10 -0
  15. package/src/Components/Icons/Box.js +11 -0
  16. package/src/Components/Icons/BoxOpen.js +11 -0
  17. package/src/Components/Icons/Bucket.js +10 -0
  18. package/src/Components/Icons/Bump.js +21 -0
  19. package/src/Components/Icons/Calculator.js +12 -0
  20. package/src/Components/Icons/Dots.js +20 -0
  21. package/src/Components/Icons/Fleets.js +26 -0
  22. package/src/Components/Icons/Microchip.js +12 -0
  23. package/src/Components/Icons/Num1.js +10 -0
  24. package/src/Components/Icons/Num2.js +10 -0
  25. package/src/Components/Icons/Num3.js +10 -0
  26. package/src/Components/Icons/Num4.js +10 -0
  27. package/src/Components/Icons/OilCan.js +11 -0
  28. package/src/Components/Icons/Operations.js +10 -0
  29. package/src/Components/Icons/OverduePms.js +10 -0
  30. package/src/Components/Icons/SackDollar.js +11 -0
  31. package/src/Components/Icons/ShortBar.js +15 -0
  32. package/src/Components/Icons/Tower.js +10 -0
  33. package/src/Components/Icons/UpcomingPms.js +10 -0
  34. package/src/Components/Layout/ScreenHeader.js +35 -3
  35. package/src/Components/Layout/SetupButton.js +31 -0
  36. package/src/Components/Layout/UserIndicator.js +35 -0
  37. package/src/Components/Panel/Panel.js +37 -9
  38. package/src/Components/Pms/Editor/BumpPmsEditor.js +9 -0
  39. package/src/Components/Pms/Editor/MetersEditor.js +173 -0
  40. package/src/Components/Pms/Editor/PmEventsEditor.js +291 -0
  41. package/src/Components/Pms/Grid/UpcomingPmsGrid.js +569 -0
  42. package/src/Components/Pms/Layout/TreeSpecific/MakeTreeSelection.js +11 -0
  43. package/src/Components/Pms/Layout/TreeSpecific/TreeSpecific.js +30 -0
  44. package/src/Components/Pms/Modals/BulkAssignTechnician.js +104 -0
  45. package/src/Components/Pms/Screens/PmsManager.js +136 -0
  46. package/src/Components/Pms/Window/BumpPmsEditorWindow.js +25 -0
  47. package/src/Components/Screens/Manager.js +5 -1
  48. package/src/Components/Toolbar/PaginationToolbar.js +5 -3
  49. package/src/Components/Tree/Tree.js +15 -6
  50. package/src/Components/Viewer/PmCalcDebugViewer.js +164 -146
  51. package/src/Components/Viewer/TextWithLinks.js +9 -1
  52. package/src/Components/Viewer/Viewer.js +43 -33
  53. package/src/Constants/PmSchedules.js +1 -0
  54. package/src/Functions/buildAdditionalButtons.js +5 -0
  55. package/src/Functions/flatten.js +39 -0
  56. package/src/Functions/verifyCanCrudPmEvents.js +33 -0
@@ -49,13 +49,21 @@ function TextWithLinksElement(props) {
49
49
  modifiedText = modifiedText.replace(link, key);
50
50
  });
51
51
 
52
- const
52
+ let
53
53
  textClassName = clsx(
54
54
  'TextWithLinks-Text',
55
55
  'text-base',
56
56
  'overflow-hidden',
57
+ styles.FORM_TEXT_CLASSNAME,
57
58
  ),
58
59
  textSegments = modifiedText.split(/(link_\d+)/);
60
+ if (props.className) {
61
+ const
62
+ classes = props.className.split(' '),
63
+ newClasses = _.reject(classes, (c) => c === 'overflow-auto'),
64
+ className = newClasses.join(' ');
65
+ textClassName += ' ' + className;
66
+ }
59
67
  if (textSegments.length === 1) {
60
68
  return <Text className={textClassName}>{modifiedText}</Text>;
61
69
  }
@@ -278,39 +278,47 @@ function Viewer(props) {
278
278
  value = record.properties[fkDisplayField].displayValue;
279
279
  }
280
280
  }
281
+ let element = null,
282
+ viewerFormatterReturnedReactComponent = false;
281
283
  if (viewerFormatter) {
282
- value = viewerFormatter(value, record, self);
283
- }
284
-
285
- let elementClassName = clsx(
286
- 'Viewer-field',
287
- 'basis-auto',
288
- 'grow',
289
- 'shrink',
290
- );
291
- const defaultsClassName = defaults.className;
292
- if (defaultsClassName) {
293
- elementClassName += ' ' + defaultsClassName;
294
- }
295
- const itemPropsToPassClassName = itemPropsToPass.className;
296
- if (itemPropsToPassClassName) {
297
- elementClassName += ' ' + itemPropsToPassClassName;
284
+ value = viewerFormatter(value, record, self); // viewerFormatter can return either a primitive value or a React component.
285
+ if (isValidElement(value)) {
286
+ // if it's a React component, render it directly
287
+ element = value;
288
+ viewerFormatterReturnedReactComponent = true;
289
+ }
298
290
  }
299
- const viewerTypeClassName = viewerTypeProps.className;
300
- if (viewerTypeClassName) {
301
- elementClassName += ' ' + viewerTypeClassName;
291
+ if (!viewerFormatterReturnedReactComponent) {
292
+ let elementClassName = clsx(
293
+ 'Viewer-field',
294
+ 'basis-auto',
295
+ 'grow',
296
+ 'shrink',
297
+ );
298
+ const defaultsClassName = defaults.className;
299
+ if (defaultsClassName) {
300
+ elementClassName += ' ' + defaultsClassName;
301
+ }
302
+ const itemPropsToPassClassName = itemPropsToPass.className;
303
+ if (itemPropsToPassClassName) {
304
+ elementClassName += ' ' + itemPropsToPassClassName;
305
+ }
306
+ const viewerTypeClassName = viewerTypeProps.className;
307
+ if (viewerTypeClassName) {
308
+ elementClassName += ' ' + viewerTypeClassName;
309
+ }
310
+
311
+ element = <Element
312
+ {...testProps('field-' + name)}
313
+ value={value}
314
+ isEditable={false}
315
+ parent={self}
316
+ reference={name}
317
+ {...itemPropsToPass}
318
+ {...viewerTypeProps}
319
+ className={elementClassName}
320
+ />;
302
321
  }
303
-
304
- let element = <Element
305
- {...testProps('field-' + name)}
306
- value={value}
307
- isEditable={false}
308
- parent={self}
309
- reference={name}
310
- {...itemPropsToPass}
311
- {...viewerTypeProps}
312
- className={elementClassName}
313
- />;
314
322
 
315
323
  if (item.additionalViewButtons) {
316
324
  element = <HStack className="Viewer-HStack1 flex-wrap">
@@ -342,9 +350,11 @@ function Viewer(props) {
342
350
  return <HStack key={ix} className="Viewer-HStack4 px-2 pb-1">{element}</HStack>;
343
351
  },
344
352
  buildAncillary = () => {
345
- const components = [];
353
+ const
354
+ validAncillaryItems = _.filter(ancillaryItems, (item) => !!item), // filter out any null/undefined items
355
+ components = [];
346
356
  setAncillaryButtons([]);
347
- if (ancillaryItems.length) {
357
+ if (validAncillaryItems.length) {
348
358
 
349
359
  // add the "scroll to top" button
350
360
  getAncillaryButtons().push({
@@ -355,7 +365,7 @@ function Viewer(props) {
355
365
  tooltip: 'Scroll to top',
356
366
  });
357
367
 
358
- _.each(ancillaryItems, (item, ix) => {
368
+ _.each(validAncillaryItems, (item, ix) => {
359
369
  let {
360
370
  type,
361
371
  title = null,
@@ -0,0 +1 @@
1
+ export const PM_SCHEDULES__ONE_OFF = 200;
@@ -5,6 +5,11 @@ import _ from 'lodash';
5
5
  export default function buildAdditionalButtons(configs, self, handlerArgs = {}) {
6
6
  const additionalButtons = [];
7
7
  _.each(configs, (config) => {
8
+
9
+ if (!config) {
10
+ return;
11
+ }
12
+
8
13
  const {
9
14
  key,
10
15
  color = '#fff',
@@ -0,0 +1,39 @@
1
+ // This function takes a nested JSON object and flattens it into a single-level object with dot notation keys.
2
+ // For example, { a: { b: 1 } } becomes { 'a.b': 1 }
3
+ // or { a: [ { b: 1 }, { c: 2 } ] } becomes { 'a.0.b': 1, 'a.1.c': 2 }
4
+ function isPlainObject(value) {
5
+ if (value === null || typeof value !== 'object') {
6
+ return false;
7
+ }
8
+
9
+ const prototype = Object.getPrototypeOf(value);
10
+ return prototype === Object.prototype || prototype === null;
11
+ }
12
+
13
+ export default function flatten(obj, prefix = '', result = {}) {
14
+ if (obj === null || typeof obj !== 'object') {
15
+ return result;
16
+ }
17
+
18
+ for (const key of Object.keys(obj)) {
19
+ const
20
+ newKey = prefix ? `${prefix}.${key}` : key,
21
+ value = obj[key];
22
+
23
+ if (isPlainObject(value)) {
24
+ flatten(value, newKey, result);
25
+ } else if (Array.isArray(value)) {
26
+ value.forEach((item, index) => {
27
+ const arrayKey = `${newKey}.${index}`;
28
+ if (isPlainObject(item) || Array.isArray(item)) {
29
+ flatten(item, arrayKey, result);
30
+ } else {
31
+ result[arrayKey] = item;
32
+ }
33
+ });
34
+ } else {
35
+ result[newKey] = value;
36
+ }
37
+ }
38
+ return result;
39
+ }
@@ -0,0 +1,33 @@
1
+ import {
2
+ PM_EVENT_TYPES__COMPLETE,
3
+ PM_EVENT_TYPES__RESET,
4
+ PM_EVENT_TYPES__DELAY_BY_DAYS,
5
+ PM_EVENT_TYPES__DELAY_BY_METER,
6
+ PM_EVENT_TYPES__SCHEDULE_PM,
7
+ PM_EVENT_TYPES__WILL_CALL,
8
+ PM_EVENT_TYPES__ASSIGN_TECHNICIAN,
9
+ PM_EVENT_TYPES__COMMENT,
10
+ } from '../Constants/PmEventTypes.js';
11
+ import inArray from './inArray.js';
12
+ import _ from 'lodash';
13
+
14
+ export default function verifyCanCrudPmEvents(selection) {
15
+ let canCrud = true;
16
+ _.each(selection, (entity) => {
17
+ if (!inArray(entity.pm_events__pm_event_type_id, [
18
+ // manual types
19
+ PM_EVENT_TYPES__COMPLETE,
20
+ PM_EVENT_TYPES__RESET,
21
+ PM_EVENT_TYPES__DELAY_BY_DAYS,
22
+ PM_EVENT_TYPES__DELAY_BY_METER,
23
+ PM_EVENT_TYPES__SCHEDULE_PM,
24
+ PM_EVENT_TYPES__WILL_CALL,
25
+ PM_EVENT_TYPES__ASSIGN_TECHNICIAN,
26
+ PM_EVENT_TYPES__COMMENT,
27
+ ])) {
28
+ canCrud = false;
29
+ return false;
30
+ }
31
+ });
32
+ return canCrud;
33
+ };