@onehat/ui 0.4.88 → 0.4.91

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.4.88",
3
+ "version": "0.4.91",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -57,12 +57,12 @@
57
57
  "@hookform/resolvers": "^5.0.0",
58
58
  "@k-renwick/colour-mixer": "^1.2.1",
59
59
  "@legendapp/motion": "^2.4.0",
60
- "@onehat/data": "^1.22.0",
61
- "@react-native-community/slider": "^4.5.2",
62
- "@reduxjs/toolkit": "^2.6.1",
60
+ "@onehat/data": "^1.22.31",
61
+ "@react-native-community/slider": "^5.1.1",
62
+ "@reduxjs/toolkit": "^2.11.2",
63
63
  "clsx": "^2.1.1",
64
- "decimal.js": "^10.5.0",
65
- "inflector-js": "^1.0.1",
64
+ "decimal.js": "^10.6.0",
65
+ "inflector-js": "^2.0.1",
66
66
  "js-cookie": "^3.0.5",
67
67
  "nativewind": "4.1.23",
68
68
  "normalize-css-color": "^1.0.2",
@@ -71,7 +71,7 @@
71
71
  "react-redux": "^9.2.0",
72
72
  "tailwind-scrollbar": "^3.1.0",
73
73
  "tailwindcss": "^3.4.17",
74
- "yup": "^1.6.1"
74
+ "yup": "^1.7.1"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "@ckeditor/ckeditor5-react": "^6.3.0",
@@ -339,13 +339,13 @@ function Form(props) {
339
339
  if (renderer) {
340
340
  value = renderer(record);
341
341
  } else {
342
- if (record?.properties && record.properties[fieldName]) {
342
+ if (record?.properties?.hasOwnProperty(fieldName)) {
343
343
  value = record.properties[fieldName].displayValue;
344
344
  }
345
- if (_.isNil(value) && record && record[fieldName]) {
345
+ if (_.isNil(value) && record?.hasOwnProperty(fieldName)) {
346
346
  value = record[fieldName];
347
347
  }
348
- if (_.isNil(value) && startingValues && startingValues[fieldName]) {
348
+ if (_.isNil(value) && startingValues?.hasOwnProperty(fieldName)) {
349
349
  value = startingValues[fieldName];
350
350
  }
351
351
  }
@@ -1569,9 +1569,6 @@ function GridComponent(props) {
1569
1569
  console.log(`${getMeasurementPhase()}, placeholder onLayout, call setIsInited(true)`);
1570
1570
  }
1571
1571
  setIsInited(true);
1572
- if (onLayout) {
1573
- onLayout(e);
1574
- }
1575
1572
  }}
1576
1573
  className="w-full flex-1"
1577
1574
  />;
@@ -1716,6 +1713,10 @@ function GridComponent(props) {
1716
1713
  onLayout={(e) => {
1717
1714
  const containerHeight = e.nativeEvent.layout.height;
1718
1715
  debouncedAdjustPageSizeToHeight(containerHeight);
1716
+
1717
+ if (onLayout) {
1718
+ onLayout(e);
1719
+ }
1719
1720
  }}
1720
1721
  className={className}
1721
1722
  style={style}
@@ -1,4 +1,4 @@
1
- import { forwardRef, useState, useRef } from 'react';
1
+ import { forwardRef, useState } from 'react';
2
2
  import {
3
3
  Icon,
4
4
  Modal, ModalBackdrop, ModalHeader, ModalContent, ModalCloseButton, ModalBody, ModalFooter,
@@ -44,8 +44,6 @@ export default function withModal(WrappedComponent) {
44
44
  [body, setBody] = useState(),
45
45
  [whichModal, setWhichModal] = useState(),
46
46
  [testID, setTestID] = useState('Modal'),
47
- autoFocusRef = useRef(null),
48
- cancelRef = useRef(null),
49
47
  [windowWidth, windowHeight] = useAdjustedWindowSize(w, h),
50
48
  hideModal = () => {
51
49
  setIsModalShown(false);
@@ -113,7 +111,6 @@ export default function withModal(WrappedComponent) {
113
111
  key="cancelBtn"
114
112
  onPress={onCancel || hideModal}
115
113
  colorScheme="coolGray"
116
- ref={cancelRef}
117
114
  className="mr-2"
118
115
  text="Cancel"
119
116
  variant="outline" // or unstyled
@@ -133,7 +130,6 @@ export default function withModal(WrappedComponent) {
133
130
  buttons.push(<Button
134
131
  {...testProps('okBtn')}
135
132
  key="okBtn"
136
- ref={autoFocusRef}
137
133
  onPress={onOk}
138
134
  text={okBtnLabel}
139
135
  className="text-white"
@@ -143,7 +139,6 @@ export default function withModal(WrappedComponent) {
143
139
  buttons.push(<Button
144
140
  {...testProps('yesBtn')}
145
141
  key="yesBtn"
146
- ref={autoFocusRef}
147
142
  onPress={onYes}
148
143
  text="Yes"
149
144
  className="text-white"
@@ -319,14 +319,58 @@ export default function withPdfButtons(WrappedComponent) {
319
319
  />,
320
320
  });
321
321
  },
322
- getPdf = (data) => {
322
+ getPdf = async (data) => {
323
+ // NOTE: we previously used a simple window.open() with the URL to view the PDF,
324
+ // but this doesn't work when authentication headers are required.
325
+ // So now we fetch the PDF ourselves, then open it in a new window.
326
+
323
327
  data.id = selection[0].id;
324
328
 
325
329
  const
326
- url = UiGlobals.baseURL + model + '/viewModelPdf?',
327
- queryString = qs.stringify(data);
330
+ url = UiGlobals.baseURL + model + '/viewModelPdf',
331
+ queryString = qs.stringify(data),
332
+ fullUrl = url + '?' + queryString;
333
+
334
+ try {
335
+ // Show loading indicator
336
+ const
337
+ dispatch = UiGlobals.redux.dispatch,
338
+ setIsWaitModalShownAction = UiGlobals.systemReducer.setIsWaitModalShownAction;
339
+ dispatch(setIsWaitModalShownAction(true));
340
+
341
+ // Fetch with auth headers
342
+ const response = await fetch(fullUrl, {
343
+ method: 'GET',
344
+ headers: {
345
+ ...Repository.headers,
346
+ },
347
+ });
328
348
 
329
- window.open(url + queryString, '_blank');
349
+ dispatch(setIsWaitModalShownAction(false));
350
+
351
+ if (!response.ok) {
352
+ throw new Error(`HTTP error! status: ${response.status}`);
353
+ }
354
+
355
+ // Get the PDF blob
356
+ const blob = await response.blob();
357
+
358
+ // Create a blob URL
359
+ const blobUrl = URL.createObjectURL(blob);
360
+
361
+ // Open in new window
362
+ window.open(blobUrl, '_blank');
363
+
364
+ // Clean up the blob URL after a delay
365
+ // (give it time to load in the new window)
366
+ setTimeout(() => {
367
+ URL.revokeObjectURL(blobUrl);
368
+ }, 1000);
369
+
370
+ } catch (error) {
371
+ console.error('Failed to fetch PDF:', error);
372
+ alert('Failed to load PDF. Please try again.');
373
+ }
330
374
  },
331
375
  sendEmail = async (data) => {
332
376
 
@@ -27,18 +27,52 @@ export default function WaitMessage(props) {
27
27
  if (CURRENT_MODE === UI_MODE_NATIVE) {
28
28
  // Gluestack's ModalBackdrop was not working on Native,
29
29
  // so workaround is to do it manually for now
30
- modalBackdrop = <Box
30
+ return <Modal
31
+ {...testProps('WaitMessage')}
32
+ isOpen={true}
33
+ className="Modal"
34
+ aria-disabled={true}
35
+ >
36
+ <Box
37
+ className={clsx(
38
+ 'WaitMessage-ModalBackdrop-replacment',
39
+ 'h-full',
40
+ 'w-full',
41
+ 'absolute',
42
+ 'top-0',
43
+ 'left-0',
44
+ 'bg-[#000]',
45
+ 'opacity-50',
46
+ )}
47
+ />
48
+ {/* <ModalContent
49
+ className={clsx(
50
+ 'ModalContent',
51
+ 'w-[200px]',
52
+ CURRENT_MODE === UI_MODE_WEB ? 'h-[50px]' : '',
53
+ 'shadow-lg',
54
+ )}
55
+ > */}
56
+ <HStack
31
57
  className={clsx(
32
- 'WaitMessage-ModalBackdrop-replacment',
33
- 'h-full',
34
- 'w-full',
35
- 'absolute',
36
- 'top-0',
37
- 'left-0',
38
- 'bg-[#000]',
39
- 'opacity-50',
58
+ 'HStack',
59
+ 'items-center',
60
+ 'justify-center',
61
+ 'bg-white',
62
+ 'p-4',
63
+ 'rounded-md',
40
64
  )}
41
- />;
65
+ >
66
+ <Spinner
67
+ className={clsx(
68
+ 'mr-2',
69
+ 'focus:outline-none',
70
+ )}
71
+ />
72
+ <Text className="text-black">{text}</Text>
73
+ </HStack>
74
+ {/* </ModalContent> */}
75
+ </Modal>;
42
76
  }
43
77
 
44
78
  return <Modal
@@ -47,7 +81,7 @@ export default function WaitMessage(props) {
47
81
  className="Modal"
48
82
  aria-disabled={true}
49
83
  >
50
- {modalBackdrop}
84
+ <ModalBackdrop className="WaitMessage-ModalBackdrop" />
51
85
  <ModalContent
52
86
  className={clsx(
53
87
  'ModalContent',
@@ -257,7 +257,13 @@ function Viewer(props) {
257
257
  label = propertyDef.title;
258
258
  }
259
259
 
260
- let value = record?.properties?.[name]?.displayValue || record?.[name] || null;
260
+ let value = null;
261
+ if (record?.properties?.hasOwnProperty(name)) {
262
+ value = record.properties[name].displayValue;
263
+ }
264
+ if (_.isNil(value) && record?.hasOwnProperty(name)) {
265
+ value = record[name];
266
+ }
261
267
  const
262
268
  schema = record?.repository?.getSchema(),
263
269
  propertyDefinition = schema?.getPropertyDefinition(name);
@@ -385,7 +385,7 @@ function AttachmentsElement(props) {
385
385
 
386
386
  alert('Files cannot be downloaded and viewed within an iOS PWA. Please use the Safari browser instead.');
387
387
  } else {
388
- downloadInBackground(url);
388
+ downloadInBackground(url, {}, Attachments.headers);
389
389
  }
390
390
  },
391
391