@solidxai/core-ui 0.1.9-beta.12 → 0.1.9-beta.14

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 (98) hide show
  1. package/dist/components/common/SettingsComponent.js +1 -1
  2. package/dist/components/common/SettingsComponent.js.map +1 -1
  3. package/dist/components/common/SettingsComponent.module.css +17 -0
  4. package/dist/components/common/SettingsComponent.tsx +1 -1
  5. package/dist/components/core/chatter/SolidChatter.d.ts.map +1 -1
  6. package/dist/components/core/chatter/SolidChatter.js +24 -11
  7. package/dist/components/core/chatter/SolidChatter.js.map +1 -1
  8. package/dist/components/core/chatter/SolidChatter.tsx +20 -6
  9. package/dist/components/core/chatter/SolidChatterHeader.d.ts.map +1 -1
  10. package/dist/components/core/chatter/SolidChatterHeader.js +1 -1
  11. package/dist/components/core/chatter/SolidChatterHeader.js.map +1 -1
  12. package/dist/components/core/chatter/SolidChatterHeader.tsx +4 -0
  13. package/dist/components/core/chatter/SolidChatterMessageBox.d.ts +1 -0
  14. package/dist/components/core/chatter/SolidChatterMessageBox.d.ts.map +1 -1
  15. package/dist/components/core/chatter/SolidChatterMessageBox.js +150 -11
  16. package/dist/components/core/chatter/SolidChatterMessageBox.js.map +1 -1
  17. package/dist/components/core/chatter/SolidChatterMessageBox.tsx +252 -11
  18. package/dist/components/core/chatter/SolidMessageComposer.js +2 -2
  19. package/dist/components/core/chatter/SolidMessageComposer.js.map +1 -1
  20. package/dist/components/core/chatter/SolidMessageComposer.tsx +2 -2
  21. package/dist/components/core/chatter/chatter.module.css +1 -1
  22. package/dist/components/core/common/SolidGlobalSearchElement.d.ts.map +1 -1
  23. package/dist/components/core/common/SolidGlobalSearchElement.js +13 -2
  24. package/dist/components/core/common/SolidGlobalSearchElement.js.map +1 -1
  25. package/dist/components/core/common/SolidGlobalSearchElement.tsx +11 -2
  26. package/dist/components/core/form/SolidFormView.d.ts.map +1 -1
  27. package/dist/components/core/form/SolidFormView.js +6 -2
  28. package/dist/components/core/form/SolidFormView.js.map +1 -1
  29. package/dist/components/core/form/SolidFormView.tsx +6 -1
  30. package/dist/components/core/form/field-quality-check-fixes.md +201 -0
  31. package/dist/components/core/form/fields/SolidLongTextField.d.ts +0 -1
  32. package/dist/components/core/form/fields/SolidLongTextField.d.ts.map +1 -1
  33. package/dist/components/core/form/fields/SolidLongTextField.js +0 -52
  34. package/dist/components/core/form/fields/SolidLongTextField.js.map +1 -1
  35. package/dist/components/core/form/fields/SolidLongTextField.tsx +0 -95
  36. package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.d.ts.map +1 -1
  37. package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.js +16 -14
  38. package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.js.map +1 -1
  39. package/dist/components/core/form/fields/relations/SolidRelationManyToManyField.tsx +9 -1
  40. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.d.ts.map +1 -1
  41. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js +12 -12
  42. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.js.map +1 -1
  43. package/dist/components/core/form/fields/relations/SolidRelationManyToOneField.tsx +10 -6
  44. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.d.ts.map +1 -1
  45. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js +9 -7
  46. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.js.map +1 -1
  47. package/dist/components/core/form/fields/relations/SolidRelationOneToManyField.tsx +7 -1
  48. package/dist/components/core/list/SolidListView.d.ts.map +1 -1
  49. package/dist/components/core/list/SolidListView.js +2 -0
  50. package/dist/components/core/list/SolidListView.js.map +1 -1
  51. package/dist/components/core/list/SolidListView.tsx +2 -0
  52. package/dist/components/core/list/SolidListViewColumn.d.ts +2 -1
  53. package/dist/components/core/list/SolidListViewColumn.d.ts.map +1 -1
  54. package/dist/components/core/list/SolidListViewColumn.js +2 -2
  55. package/dist/components/core/list/SolidListViewColumn.js.map +1 -1
  56. package/dist/components/core/list/SolidListViewColumn.tsx +4 -3
  57. package/dist/components/core/list/columns/SolidRelationColumn.d.ts +1 -1
  58. package/dist/components/core/list/columns/SolidRelationColumn.d.ts.map +1 -1
  59. package/dist/components/core/list/columns/SolidRelationColumn.js +2 -2
  60. package/dist/components/core/list/columns/SolidRelationColumn.js.map +1 -1
  61. package/dist/components/core/list/columns/SolidRelationColumn.tsx +2 -2
  62. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.d.ts +2 -2
  63. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.d.ts.map +1 -1
  64. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js +9 -4
  65. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.js.map +1 -1
  66. package/dist/components/core/list/columns/relations/SolidRelationManyToOneColumn.tsx +14 -4
  67. package/dist/components/core/list/field-quality-check-fixes.md +178 -0
  68. package/dist/components/layout/AdminTopHeader.d.ts.map +1 -1
  69. package/dist/components/layout/AdminTopHeader.js +5 -1
  70. package/dist/components/layout/AdminTopHeader.js.map +1 -1
  71. package/dist/components/layout/AdminTopHeader.tsx +5 -1
  72. package/dist/components/shad-cn-ui/SolidAutocomplete.d.ts +2 -1
  73. package/dist/components/shad-cn-ui/SolidAutocomplete.d.ts.map +1 -1
  74. package/dist/components/shad-cn-ui/SolidAutocomplete.js +45 -6
  75. package/dist/components/shad-cn-ui/SolidAutocomplete.js.map +1 -1
  76. package/dist/components/shad-cn-ui/SolidAutocomplete.tsx +68 -22
  77. package/dist/components/shad-cn-ui/SolidDialog.d.ts.map +1 -1
  78. package/dist/components/shad-cn-ui/SolidDialog.js +38 -4
  79. package/dist/components/shad-cn-ui/SolidDialog.js.map +1 -1
  80. package/dist/components/shad-cn-ui/SolidDialog.tsx +47 -3
  81. package/dist/helpers/registry.js.map +1 -1
  82. package/dist/helpers/registry.ts +1 -1
  83. package/dist/index.d.ts +1 -1
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js.map +1 -1
  86. package/dist/index.ts +1 -0
  87. package/dist/redux/api/solidChatterMessageApi.d.ts +2 -1
  88. package/dist/redux/api/solidChatterMessageApi.d.ts.map +1 -1
  89. package/dist/redux/api/solidChatterMessageApi.js +11 -1
  90. package/dist/redux/api/solidChatterMessageApi.js.map +1 -1
  91. package/dist/redux/api/solidChatterMessageApi.ts +10 -1
  92. package/dist/redux/store/defaultStoreConfig.d.ts +1 -0
  93. package/dist/redux/store/defaultStoreConfig.d.ts.map +1 -1
  94. package/dist/resources/globals.css +5 -0
  95. package/dist/resources/shadcn-base.css +24 -0
  96. package/dist/types/index.d.ts +2 -0
  97. package/dist/types/solid-core.d.ts +1 -0
  98. package/package.json +1 -1
@@ -1,18 +1,20 @@
1
1
 
2
2
  import { getTextColor, stringToColor } from '../../../helpers/getRandomColors'
3
3
  import Image from "../../common/Image"
4
- import { useMemo, useState } from 'react'
4
+ import { useEffect, useMemo, useRef, useState } from 'react'
5
5
  import styles from './chatter.module.css'
6
6
  import { SolidChatterCustomMessage } from './SolidChatterCustomMessage'
7
7
  import { SolidChatterAuditMessage } from './SolidChatterAuditMessage'
8
- import { Check, GitBranch, MessageSquare } from 'lucide-react'
9
- import { SolidButton, SolidLightbox, SolidTag, SolidTooltip, SolidTooltipContent, SolidTooltipTrigger, SolidIcon, type SolidIconName } from '../../shad-cn-ui'
8
+ import { Check, GitBranch, MessageSquare, Paperclip, Pencil, Trash2, X } from 'lucide-react'
9
+ import { SolidButton, SolidLightbox, SolidTag, SolidTooltip, SolidTooltipContent, SolidTooltipTrigger, SolidIcon, SolidTextarea, type SolidIconName } from '../../shad-cn-ui'
10
10
  import type { SolidLightboxSlide } from '../../shad-cn-ui/SolidLightbox'
11
- import { usePatchChatterMessageMutation } from '../../../redux/api/solidChatterMessageApi'
11
+ import { usePatchChatterMessageMutation, useUpdateChatterNoteMessageMutation } from '../../../redux/api/solidChatterMessageApi'
12
+ import { useSession } from '../../../hooks/useSession'
12
13
 
13
14
  interface Props {
14
15
  messageId?: number | string,
15
16
  user: string,
17
+ userId?: number,
16
18
  messageType?: string,
17
19
  message?: any,
18
20
  time?: string,
@@ -54,11 +56,22 @@ const getFileIcon = (mimeType: string): SolidIconName => {
54
56
  };
55
57
 
56
58
  export const SolidChatterMessageBox = (props: Props) => {
57
- const { messageId, user, messageType, message, time, auditRecord, media, messageSubType, status, modelDisplayName, modelUserKey, onRefresh } = props;
59
+ const { messageId, user, userId, messageType, message, time, auditRecord, media, messageSubType, status, modelDisplayName, modelUserKey, onRefresh } = props;
58
60
  const [lightboxSlides, setLightboxSlides] = useState<SolidLightboxSlide[]>([]);
59
61
  const [openLightbox, setOpenLightbox] = useState(false);
60
62
  const [taskStatus, setTaskStatus] = useState<string | undefined>(status);
63
+ const [isEditing, setIsEditing] = useState(false);
64
+ const [localMessage, setLocalMessage] = useState(message ?? '');
65
+ const [editedMessage, setEditedMessage] = useState(message ?? '');
66
+ const [hasPendingOptimisticUpdate, setHasPendingOptimisticUpdate] = useState(false);
67
+ const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
68
+ const [removedAttachmentIds, setRemovedAttachmentIds] = useState<number[]>([]);
69
+ const [optimisticRemovedAttachmentIds, setOptimisticRemovedAttachmentIds] = useState<number[]>([]);
70
+ const [hasPendingOptimisticAttachmentUpdate, setHasPendingOptimisticAttachmentUpdate] = useState(false);
71
+ const fileInputRef = useRef<HTMLInputElement>(null);
61
72
  const [patchChatterMessage, { isLoading: isUpdatingTaskStatus }] = usePatchChatterMessageMutation();
73
+ const [updateChatterNoteMessage, { isLoading: isUpdatingNote }] = useUpdateChatterNoteMessageMutation();
74
+ const { data: session } = useSession();
62
75
 
63
76
  const avatarStyle = useMemo(() => {
64
77
  const bg = stringToColor(user)
@@ -116,6 +129,56 @@ export const SolidChatterMessageBox = (props: Props) => {
116
129
 
117
130
  const isTaskMessage = messageSubType === 'task';
118
131
  const isTaskCompleted = (taskStatus ?? '').toLowerCase() === 'completed';
132
+ const isCustomMessage = messageType === 'custom';
133
+ const isEditableSubtype = messageSubType === 'custom' || messageSubType === 'note';
134
+ const isCurrentUserAuthor = !!(session?.user?.id && userId && Number(session.user.id) === Number(userId));
135
+ const canEditNote = Boolean(messageId && isCustomMessage && isEditableSubtype && isCurrentUserAuthor);
136
+
137
+ useEffect(() => {
138
+ const incomingMessage = message ?? '';
139
+
140
+ // Keep optimistic message visible until server data catches up.
141
+ if (hasPendingOptimisticUpdate && incomingMessage !== localMessage) {
142
+ return;
143
+ }
144
+
145
+ if (hasPendingOptimisticUpdate && incomingMessage === localMessage) {
146
+ setHasPendingOptimisticUpdate(false);
147
+ }
148
+
149
+ setLocalMessage(incomingMessage);
150
+ if (!isEditing) {
151
+ setEditedMessage(incomingMessage);
152
+ }
153
+ }, [message, isEditing, hasPendingOptimisticUpdate, localMessage]);
154
+
155
+ useEffect(() => {
156
+ if (!isEditing) {
157
+ setSelectedFiles([]);
158
+ if (!hasPendingOptimisticAttachmentUpdate) {
159
+ setRemovedAttachmentIds([]);
160
+ }
161
+ }
162
+ }, [isEditing, hasPendingOptimisticAttachmentUpdate]);
163
+
164
+ useEffect(() => {
165
+ if (!hasPendingOptimisticAttachmentUpdate) return;
166
+ const latestAttachmentIds = (media?.messageAttachments || []).map((attachment) => attachment.id);
167
+ const stillPresent = optimisticRemovedAttachmentIds.some((id) => latestAttachmentIds.includes(id));
168
+ if (!stillPresent) {
169
+ setHasPendingOptimisticAttachmentUpdate(false);
170
+ setOptimisticRemovedAttachmentIds([]);
171
+ setRemovedAttachmentIds([]);
172
+ }
173
+ }, [media?.messageAttachments, hasPendingOptimisticAttachmentUpdate, optimisticRemovedAttachmentIds]);
174
+
175
+ const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {
176
+ if (event.target.files) {
177
+ const files = Array.from(event.target.files);
178
+ setSelectedFiles(prev => [...prev, ...files]);
179
+ event.target.value = '';
180
+ }
181
+ };
119
182
 
120
183
  const handleMarkTaskDone = async () => {
121
184
  if (!messageId || isUpdatingTaskStatus) return;
@@ -128,6 +191,72 @@ export const SolidChatterMessageBox = (props: Props) => {
128
191
  }
129
192
  };
130
193
 
194
+ const handleEditSave = async () => {
195
+ if (!messageId || isUpdatingNote) return;
196
+ const trimmedMessage = editedMessage?.trim();
197
+ const hasBodyChange = trimmedMessage && trimmedMessage !== (message ?? '').trim();
198
+ const hasAttachmentOps = removedAttachmentIds.length > 0 || selectedFiles.length > 0;
199
+ if (!hasBodyChange && !hasAttachmentOps) return;
200
+ if (!trimmedMessage) return;
201
+ const nextMessage = trimmedMessage;
202
+ // Optimistic local update to remove UI lag before refetch resolves.
203
+ setLocalMessage(nextMessage);
204
+ setHasPendingOptimisticUpdate(true);
205
+ if (removedAttachmentIds.length > 0) {
206
+ setOptimisticRemovedAttachmentIds((prev) => Array.from(new Set([...prev, ...removedAttachmentIds])));
207
+ setHasPendingOptimisticAttachmentUpdate(true);
208
+ }
209
+ setIsEditing(false);
210
+ try {
211
+ const formData = new FormData();
212
+ formData.append('messageBody', nextMessage);
213
+ if (removedAttachmentIds.length > 0) {
214
+ formData.append('removeAttachmentIds', removedAttachmentIds.join(','));
215
+ }
216
+ selectedFiles.forEach((file) => formData.append('messageAttachments', file));
217
+
218
+ await updateChatterNoteMessage({ id: messageId, data: formData }).unwrap();
219
+ onRefresh?.();
220
+ } catch (e) {
221
+ // Revert optimistic update on failure.
222
+ setLocalMessage(message ?? '');
223
+ setHasPendingOptimisticUpdate(false);
224
+ setHasPendingOptimisticAttachmentUpdate(false);
225
+ setOptimisticRemovedAttachmentIds([]);
226
+ setIsEditing(true);
227
+ }
228
+ };
229
+
230
+ const handleCancelEdit = () => {
231
+ setEditedMessage(localMessage ?? '');
232
+ setSelectedFiles([]);
233
+ setRemovedAttachmentIds([]);
234
+ setIsEditing(false);
235
+ };
236
+
237
+ const formatFileSize = (size: number) => {
238
+ if (!size) return '';
239
+ return size >= 1024 * 1024
240
+ ? `${(size / (1024 * 1024)).toFixed(1)} MB`
241
+ : `${(size / 1024).toFixed(1)} KB`;
242
+ };
243
+
244
+ const hiddenAttachmentIds = new Set([
245
+ ...removedAttachmentIds,
246
+ ...optimisticRemovedAttachmentIds,
247
+ ]);
248
+ const visibleAttachments = (media?.messageAttachments || []).filter(
249
+ (attachment) => !hiddenAttachmentIds.has(attachment.id)
250
+ );
251
+
252
+ const toggleRemoveAttachment = (attachmentId: number) => {
253
+ setRemovedAttachmentIds(prev =>
254
+ prev.includes(attachmentId)
255
+ ? prev.filter(id => id !== attachmentId)
256
+ : [...prev, attachmentId]
257
+ );
258
+ };
259
+
131
260
  return (
132
261
  <div className={styles.solidChatterMessageBox}>
133
262
  <div className={styles.solidChatterMessageCard}>
@@ -153,7 +282,21 @@ export const SolidChatterMessageBox = (props: Props) => {
153
282
  </SolidTooltipContent>
154
283
  </SolidTooltip>
155
284
  </div>
156
- <span className={styles.solidChatterTime}>{time}</span>
285
+ <div className='flex align-items-center gap-2'>
286
+ {canEditNote && !isEditing && (
287
+ <SolidButton
288
+ type="button"
289
+ size="sm"
290
+ variant="ghost"
291
+ className="solid-icon-button"
292
+ leftIcon={<Pencil size={12} />}
293
+ onClick={() => setIsEditing(true)}
294
+ aria-label="Edit note"
295
+ title="Edit note"
296
+ />
297
+ )}
298
+ <span className={styles.solidChatterTime}>{time}</span>
299
+ </div>
157
300
  </div>
158
301
  {modelDisplayName && (
159
302
  <p className={`${styles.solidChatterMeta} m-0`}>
@@ -161,17 +304,115 @@ export const SolidChatterMessageBox = (props: Props) => {
161
304
  {modelUserKey && <> · <span className='font-medium'>{modelUserKey}</span></>}
162
305
  </p>
163
306
  )}
164
- {message && (
307
+ {localMessage && !isEditing && (
165
308
  <div className={styles.solidMessageWrapper}>
166
- {renderMessageContent()}
309
+ {messageType === 'audit'
310
+ ? <SolidChatterAuditMessage auditRecord={auditRecord} />
311
+ : <SolidChatterCustomMessage message={localMessage} />}
312
+ </div>
313
+ )}
314
+ {isEditing && (
315
+ <div className='flex flex-column gap-2'>
316
+ <SolidTextarea
317
+ value={editedMessage}
318
+ onChange={(e) => setEditedMessage(e.target.value)}
319
+ rows={4}
320
+ className="w-full py-2"
321
+ />
322
+ <div className='flex flex-column gap-2'>
323
+ <input
324
+ ref={fileInputRef}
325
+ id={`note-edit-file-${messageId}`}
326
+ type="file"
327
+ multiple
328
+ onChange={handleFileSelect}
329
+ style={{ display: 'none' }}
330
+ />
331
+ {selectedFiles.length > 0 && (
332
+ <div className='flex flex-column gap-1'>
333
+ {selectedFiles.map((file, index) => (
334
+ <div key={`${file.name}-${index}`} className='flex align-items-center justify-content-between text-xs'>
335
+ <span>{file.name} ({formatFileSize(file.size)})</span>
336
+ <SolidButton
337
+ type="button"
338
+ size="sm"
339
+ variant="ghost"
340
+ className='solid-icon-button'
341
+ leftIcon={<X size={12} />}
342
+ onClick={() => setSelectedFiles(prev => prev.filter((_, i) => i !== index))}
343
+ aria-label={`Remove ${file.name}`}
344
+ />
345
+ </div>
346
+ ))}
347
+ </div>
348
+ )}
349
+ </div>
350
+ <div className='flex align-items-center justify-content-between gap-2 flex-wrap'>
351
+ <div className='flex align-items-center gap-2'>
352
+ <SolidButton
353
+ type="button"
354
+ size="sm"
355
+ variant="ghost"
356
+ className="solid-icon-button"
357
+ leftIcon={<Paperclip size={14} />}
358
+ onClick={() => fileInputRef.current?.click()}
359
+ aria-label="Attach files"
360
+ title="Attach files"
361
+ />
362
+ <span className='text-xs text-color-secondary'>Attach file</span>
363
+ </div>
364
+ <div className='flex align-items-center justify-content-end gap-2'>
365
+ <SolidButton
366
+ type="button"
367
+ size="sm"
368
+ variant="outline"
369
+ leftIcon={<X size={12} />}
370
+ onClick={handleCancelEdit}
371
+ >
372
+ Cancel
373
+ </SolidButton>
374
+ <SolidButton
375
+ type="button"
376
+ size="sm"
377
+ variant="primary"
378
+ loading={isUpdatingNote}
379
+ leftIcon={<Check size={12} />}
380
+ onClick={handleEditSave}
381
+ disabled={!editedMessage?.trim() || (removedAttachmentIds.length === 0 && selectedFiles.length === 0 && editedMessage.trim() === (message ?? '').trim())}
382
+ >
383
+ Save
384
+ </SolidButton>
385
+ </div>
386
+ </div>
167
387
  </div>
168
388
  )}
169
- {media?.messageAttachments && media.messageAttachments.length > 0 && (
389
+ {visibleAttachments.length > 0 && (
170
390
  <div className={styles.solidChatterAttachments}>
171
- {media.messageAttachments.map((attachment) => {
391
+ {visibleAttachments.map((attachment) => {
172
392
  const isImage = attachment.mimeType.startsWith('image/');
173
393
  return (
174
- <div key={attachment.id} className={styles.solidChatterAttachment}>
394
+ <div key={attachment.id} className={styles.solidChatterAttachment} style={{ position: 'relative' }}>
395
+ {isEditing && canEditNote && (
396
+ <SolidButton
397
+ type="button"
398
+ size="sm"
399
+ variant="ghost"
400
+ className="solid-icon-button"
401
+ leftIcon={<Trash2 size={12} color="#dc2626" />}
402
+ onClick={() => toggleRemoveAttachment(attachment.id)}
403
+ aria-label={`Remove ${attachment.originalFileName}`}
404
+ title={`Remove ${attachment.originalFileName}`}
405
+ style={{
406
+ position: 'absolute',
407
+ top: -8,
408
+ right: -8,
409
+ zIndex: 2,
410
+ background: '#fff',
411
+ border: '1px solid #fecaca',
412
+ borderRadius: '999px',
413
+ }}
414
+ />
415
+ )}
175
416
  {isImage ? (
176
417
  <div
177
418
  className='cursor-pointer'
@@ -84,7 +84,7 @@ export var SolidMessageComposer = function (_a) {
84
84
  _a.trys.push([1, 3, , 4]);
85
85
  formData_1 = new FormData();
86
86
  formData_1.append('messageType', "custom");
87
- formData_1.append('messageSubType', "custom");
87
+ formData_1.append('messageSubType', "note");
88
88
  formData_1.append('messageBody', message);
89
89
  formData_1.append('coModelEntityId', id);
90
90
  formData_1.append('coModelName', modelSingularName);
@@ -120,7 +120,7 @@ export var SolidMessageComposer = function (_a) {
120
120
  ? "".concat((size / (1024 * 1024)).toFixed(1), " MB")
121
121
  : "".concat((size / 1024).toFixed(1), " KB");
122
122
  };
123
- return (_jsxs("form", { className: styles.chatterMessageComposer, onSubmit: handleSubmit, children: [_jsxs("div", { className: "".concat(styles.solidMessageWrapper, " flex flex-column gap-2 w-full"), children: [_jsx("div", { className: 'flex align-items-center justify-content-between', children: _jsx("p", { className: 'form-field-label m-0', children: type === 'email' ? 'Email Message' : 'Internal Note' }) }), _jsx(SolidTextarea, { value: message, onChange: function (e) { return setMessage(e.target.value); }, placeholder: type === 'email' ? 'Send a message to followers' : 'Log an internal note.', className: "w-full p-1", rows: 4 }), _jsxs("div", { className: 'flex align-items-center justify-content-between flex-wrap gap-2', children: [_jsxs("div", { className: 'flex align-items-center gap-2', children: [_jsx("input", { type: "file", ref: fileInputRef, onChange: handleFileSelect, multiple: true, style: { display: 'none' } }), _jsx(SolidButton, { type: "button", variant: "outline", size: "sm", className: "solid-icon-button", leftIcon: _jsx(Paperclip, { size: 14 }), onClick: function () { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, "aria-label": "Attach files", title: "Attach files" }), _jsx("span", { className: 'text-xs text-color-secondary', children: "Attach file" })] }), _jsxs("div", { className: 'flex align-items-center gap-2', children: [_jsx(SolidButton, { type: 'submit', size: 'sm', className: 'gap-2 solid-purple-button', variant: 'primary', loading: isLoading, children: type === 'email' ? 'Send' : 'Log' }), _jsx(SolidButton, { type: 'button', size: 'sm', variant: 'ghost', onClick: function () {
123
+ return (_jsxs("form", { className: styles.chatterMessageComposer, onSubmit: handleSubmit, children: [_jsxs("div", { className: "".concat(styles.solidMessageWrapper, " flex flex-column gap-2 w-full"), children: [_jsx("div", { className: 'flex align-items-center justify-content-between', children: _jsx("p", { className: 'form-field-label m-0', children: type === 'email' ? 'Email Message' : 'Internal Note' }) }), _jsx(SolidTextarea, { value: message, onChange: function (e) { return setMessage(e.target.value); }, placeholder: type === 'email' ? 'Send a message to followers' : 'Log an internal note.', className: "w-full p-2", rows: 4 }), _jsxs("div", { className: 'flex align-items-center justify-content-between flex-wrap gap-2', children: [_jsxs("div", { className: 'flex align-items-center gap-2', children: [_jsx("input", { type: "file", ref: fileInputRef, onChange: handleFileSelect, multiple: true, style: { display: 'none' } }), _jsx(SolidButton, { type: "button", variant: "outline", size: "sm", className: "solid-icon-button", leftIcon: _jsx(Paperclip, { size: 14 }), onClick: function () { var _a; return (_a = fileInputRef.current) === null || _a === void 0 ? void 0 : _a.click(); }, "aria-label": "Attach files", title: "Attach files" }), _jsx("span", { className: 'text-xs text-color-secondary', children: "Attach file" })] }), _jsxs("div", { className: 'flex align-items-center gap-2', children: [_jsx(SolidButton, { type: 'submit', size: 'sm', className: 'gap-2 solid-purple-button', variant: 'primary', loading: isLoading, children: type === 'email' ? 'Send' : 'Log' }), _jsx(SolidButton, { type: 'button', size: 'sm', variant: 'ghost', onClick: function () {
124
124
  setMessage('');
125
125
  setSelectedFiles([]);
126
126
  onCancel === null || onCancel === void 0 ? void 0 : onCancel();
@@ -1 +1 @@
1
- {"version":3,"file":"SolidMessageComposer.js","sourceRoot":"","sources":["../../../../src/components/core/chatter/SolidMessageComposer.tsx"],"names":[],"mappings":"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","sourcesContent":["import styles from './chatter.module.css'\nimport { useCreateChatterMessageMutation } from '../../../redux/api/solidChatterMessageApi'\nimport { useEffect, useState, useRef } from 'react'\nimport { ERROR_MESSAGES } from '../../../constants/error-messages'\nimport { useSession } from '../../../hooks/useSession'\nimport { SolidButton, SolidTextarea } from '../../shad-cn-ui'\nimport { FileText, Paperclip, X } from 'lucide-react'\n\ninterface SolidMessageComposerProps {\n type?: string;\n modelSingularName?: any;\n refetch?: any;\n id?: any;\n onCancel?: () => void;\n modelUserKey?: string;\n}\n\nexport const SolidMessageComposer = ({ type, modelSingularName, refetch, id, onCancel, modelUserKey }: SolidMessageComposerProps) => {\n const [message, setMessage] = useState('');\n const [selectedFiles, setSelectedFiles] = useState<File[]>([]);\n\n const { data: session, status } = useSession();\n const user = session?.user;\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // const { data: viewLayoutData } = useGetSolidViewLayoutQuery(null);\n const [createChatterMessage, { isLoading, isSuccess, isError }] = useCreateChatterMessageMutation();\n\n const tempEmails = [\n \"johndoe@gmal.com\",\n \"tempmail@gmail.com\",\n \"example@mail.com\"\n ]\n\n const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) {\n const files = Array.from(event.target.files);\n setSelectedFiles(prev => [...prev, ...files]);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!message.trim() && selectedFiles.length === 0) return;\n\n try {\n const formData = new FormData();\n formData.append('messageType', \"custom\");\n formData.append('messageSubType', \"custom\");\n formData.append('messageBody', message);\n formData.append('coModelEntityId', id);\n formData.append('coModelName', modelSingularName);\n formData.append('userId', user?.id || 1);\n\n if (modelUserKey) formData.append('modelUserKey', modelUserKey);\n selectedFiles.forEach((file, index) => {\n formData.append(`messageAttachments`, file);\n });\n\n await createChatterMessage(formData).unwrap();\n setMessage('');\n setSelectedFiles([]);\n } catch (error) {\n console.error(ERROR_MESSAGES.FETCHING_MESSAGE, error);\n }\n };\n\n useEffect(() => {\n if (isSuccess) {\n refetch()\n }\n }, [isSuccess]);\n\n const formatFileSize = (size: number) => {\n if (!size) return \"\";\n return size >= 1024 * 1024\n ? `${(size / (1024 * 1024)).toFixed(1)} MB`\n : `${(size / 1024).toFixed(1)} KB`;\n };\n\n return (\n <form className={styles.chatterMessageComposer} onSubmit={handleSubmit}>\n {/* {type === 'email' &&\n <div className='flex align-items-center gap-1 text-sm mb-2'>\n <span className='font-bold'>To:</span>\n <div className={styles.chatterEmails}>\n {tempEmails.map((mail, index) => (\n <span key={index}>\n {mail}\n </span>\n ))}\n </div>\n <div className={`si si-sort-down-fill text-primary ${styles.emailTooltipIcon}`} style={{ fontSize: 8 }}>\n <div className={styles.emailsTooltip}>\n {tempEmails.map((mail, index) => (\n <span key={index} className='text-color text-sm'>\n {mail}\n </span>\n ))}\n </div>\n </div>\n </div>\n } */}\n <div className={`${styles.solidMessageWrapper} flex flex-column gap-2 w-full`}>\n <div className='flex align-items-center justify-content-between'>\n <p className='form-field-label m-0'>\n {type === 'email' ? 'Email Message' : 'Internal Note'}\n </p>\n </div>\n <SolidTextarea\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n placeholder={type === 'email' ? 'Send a message to followers' : 'Log an internal note.'}\n className=\"w-full p-1\"\n rows={4}\n />\n <div className='flex align-items-center justify-content-between flex-wrap gap-2'>\n <div className='flex align-items-center gap-2'>\n <input\n type=\"file\"\n ref={fileInputRef}\n onChange={handleFileSelect}\n multiple\n style={{ display: 'none' }}\n />\n <SolidButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"solid-icon-button\"\n leftIcon={<Paperclip size={14} />}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Attach files\"\n title=\"Attach files\"\n />\n <span className='text-xs text-color-secondary'>Attach file</span>\n </div>\n <div className='flex align-items-center gap-2'>\n <SolidButton\n type='submit'\n size='sm'\n className='gap-2 solid-purple-button'\n variant='primary'\n loading={isLoading}\n >\n {type === 'email' ? 'Send' : 'Log'}\n </SolidButton>\n <SolidButton\n type='button'\n size='sm'\n variant='ghost'\n onClick={() => {\n setMessage('');\n setSelectedFiles([]);\n onCancel?.();\n }}\n >\n Cancel\n </SolidButton>\n </div>\n </div>\n </div>\n {selectedFiles.length > 0 && (\n <div className={styles.chatterSelectedFiles}>\n {selectedFiles.map((file, index) => (\n <div key={index} className={styles.chatterSelectedFileCard}>\n <div className={styles.chatterSelectedFileIcon}>\n <FileText size={16} />\n </div>\n <div className={styles.chatterSelectedFileMeta}>\n <p className={styles.chatterSelectedFileName}>{file.name}</p>\n <span className={styles.chatterSelectedFileSize}>{formatFileSize(file.size)}</span>\n </div>\n <SolidButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"solid-icon-button\"\n leftIcon={<X size={12} />}\n onClick={() => setSelectedFiles(prev => prev.filter((_, i) => i !== index))}\n aria-label={`Remove ${file.name}`}\n />\n </div>\n ))}\n </div>\n )}\n </form>\n )\n}\n"]}
1
+ {"version":3,"file":"SolidMessageComposer.js","sourceRoot":"","sources":["../../../../src/components/core/chatter/SolidMessageComposer.tsx"],"names":[],"mappings":"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","sourcesContent":["import styles from './chatter.module.css'\nimport { useCreateChatterMessageMutation } from '../../../redux/api/solidChatterMessageApi'\nimport { useEffect, useState, useRef } from 'react'\nimport { ERROR_MESSAGES } from '../../../constants/error-messages'\nimport { useSession } from '../../../hooks/useSession'\nimport { SolidButton, SolidTextarea } from '../../shad-cn-ui'\nimport { FileText, Paperclip, X } from 'lucide-react'\n\ninterface SolidMessageComposerProps {\n type?: string;\n modelSingularName?: any;\n refetch?: any;\n id?: any;\n onCancel?: () => void;\n modelUserKey?: string;\n}\n\nexport const SolidMessageComposer = ({ type, modelSingularName, refetch, id, onCancel, modelUserKey }: SolidMessageComposerProps) => {\n const [message, setMessage] = useState('');\n const [selectedFiles, setSelectedFiles] = useState<File[]>([]);\n\n const { data: session, status } = useSession();\n const user = session?.user;\n const fileInputRef = useRef<HTMLInputElement>(null);\n\n // const { data: viewLayoutData } = useGetSolidViewLayoutQuery(null);\n const [createChatterMessage, { isLoading, isSuccess, isError }] = useCreateChatterMessageMutation();\n\n const tempEmails = [\n \"johndoe@gmal.com\",\n \"tempmail@gmail.com\",\n \"example@mail.com\"\n ]\n\n const handleFileSelect = (event: React.ChangeEvent<HTMLInputElement>) => {\n if (event.target.files) {\n const files = Array.from(event.target.files);\n setSelectedFiles(prev => [...prev, ...files]);\n }\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!message.trim() && selectedFiles.length === 0) return;\n\n try {\n const formData = new FormData();\n formData.append('messageType', \"custom\");\n formData.append('messageSubType', \"note\");\n formData.append('messageBody', message);\n formData.append('coModelEntityId', id);\n formData.append('coModelName', modelSingularName);\n formData.append('userId', user?.id || 1);\n\n if (modelUserKey) formData.append('modelUserKey', modelUserKey);\n selectedFiles.forEach((file, index) => {\n formData.append(`messageAttachments`, file);\n });\n\n await createChatterMessage(formData).unwrap();\n setMessage('');\n setSelectedFiles([]);\n } catch (error) {\n console.error(ERROR_MESSAGES.FETCHING_MESSAGE, error);\n }\n };\n\n useEffect(() => {\n if (isSuccess) {\n refetch()\n }\n }, [isSuccess]);\n\n const formatFileSize = (size: number) => {\n if (!size) return \"\";\n return size >= 1024 * 1024\n ? `${(size / (1024 * 1024)).toFixed(1)} MB`\n : `${(size / 1024).toFixed(1)} KB`;\n };\n\n return (\n <form className={styles.chatterMessageComposer} onSubmit={handleSubmit}>\n {/* {type === 'email' &&\n <div className='flex align-items-center gap-1 text-sm mb-2'>\n <span className='font-bold'>To:</span>\n <div className={styles.chatterEmails}>\n {tempEmails.map((mail, index) => (\n <span key={index}>\n {mail}\n </span>\n ))}\n </div>\n <div className={`si si-sort-down-fill text-primary ${styles.emailTooltipIcon}`} style={{ fontSize: 8 }}>\n <div className={styles.emailsTooltip}>\n {tempEmails.map((mail, index) => (\n <span key={index} className='text-color text-sm'>\n {mail}\n </span>\n ))}\n </div>\n </div>\n </div>\n } */}\n <div className={`${styles.solidMessageWrapper} flex flex-column gap-2 w-full`}>\n <div className='flex align-items-center justify-content-between'>\n <p className='form-field-label m-0'>\n {type === 'email' ? 'Email Message' : 'Internal Note'}\n </p>\n </div>\n <SolidTextarea\n value={message}\n onChange={(e) => setMessage(e.target.value)}\n placeholder={type === 'email' ? 'Send a message to followers' : 'Log an internal note.'}\n className=\"w-full p-2\"\n rows={4}\n />\n <div className='flex align-items-center justify-content-between flex-wrap gap-2'>\n <div className='flex align-items-center gap-2'>\n <input\n type=\"file\"\n ref={fileInputRef}\n onChange={handleFileSelect}\n multiple\n style={{ display: 'none' }}\n />\n <SolidButton\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n className=\"solid-icon-button\"\n leftIcon={<Paperclip size={14} />}\n onClick={() => fileInputRef.current?.click()}\n aria-label=\"Attach files\"\n title=\"Attach files\"\n />\n <span className='text-xs text-color-secondary'>Attach file</span>\n </div>\n <div className='flex align-items-center gap-2'>\n <SolidButton\n type='submit'\n size='sm'\n className='gap-2 solid-purple-button'\n variant='primary'\n loading={isLoading}\n >\n {type === 'email' ? 'Send' : 'Log'}\n </SolidButton>\n <SolidButton\n type='button'\n size='sm'\n variant='ghost'\n onClick={() => {\n setMessage('');\n setSelectedFiles([]);\n onCancel?.();\n }}\n >\n Cancel\n </SolidButton>\n </div>\n </div>\n </div>\n {selectedFiles.length > 0 && (\n <div className={styles.chatterSelectedFiles}>\n {selectedFiles.map((file, index) => (\n <div key={index} className={styles.chatterSelectedFileCard}>\n <div className={styles.chatterSelectedFileIcon}>\n <FileText size={16} />\n </div>\n <div className={styles.chatterSelectedFileMeta}>\n <p className={styles.chatterSelectedFileName}>{file.name}</p>\n <span className={styles.chatterSelectedFileSize}>{formatFileSize(file.size)}</span>\n </div>\n <SolidButton\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"solid-icon-button\"\n leftIcon={<X size={12} />}\n onClick={() => setSelectedFiles(prev => prev.filter((_, i) => i !== index))}\n aria-label={`Remove ${file.name}`}\n />\n </div>\n ))}\n </div>\n )}\n </form>\n )\n}\n"]}
@@ -46,7 +46,7 @@ export const SolidMessageComposer = ({ type, modelSingularName, refetch, id, onC
46
46
  try {
47
47
  const formData = new FormData();
48
48
  formData.append('messageType', "custom");
49
- formData.append('messageSubType', "custom");
49
+ formData.append('messageSubType', "note");
50
50
  formData.append('messageBody', message);
51
51
  formData.append('coModelEntityId', id);
52
52
  formData.append('coModelName', modelSingularName);
@@ -111,7 +111,7 @@ export const SolidMessageComposer = ({ type, modelSingularName, refetch, id, onC
111
111
  value={message}
112
112
  onChange={(e) => setMessage(e.target.value)}
113
113
  placeholder={type === 'email' ? 'Send a message to followers' : 'Log an internal note.'}
114
- className="w-full p-1"
114
+ className="w-full p-2"
115
115
  rows={4}
116
116
  />
117
117
  <div className='flex align-items-center justify-content-between flex-wrap gap-2'>
@@ -1,5 +1,5 @@
1
1
  .chatterTitle {
2
- padding: 0.2rem 0 0.55rem;
2
+ padding: 0.2rem 0 0.55rem 2.75rem;
3
3
  border-bottom: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
4
4
  }
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"SolidGlobalSearchElement.d.ts","sourceRoot":"","sources":["../../../../src/components/core/common/SolidGlobalSearchElement.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgF,MAAM,OAAO,CAAC;AAYrG,OAA0B,EAAE,eAAe,EAAE,YAAY,EAAsB,MAAM,qBAAqB,CAAC;AA0B3G,MAAM,MAAM,eAAe,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,MAAM,CAAC;CAClC,CAAA;AA2TD,eAAO,MAAM,2BAA2B,sBAAuB,GAAG,aAAa,GAAG,yBAAyB,MAAM,iBAAiB,MAAM,QAavI,CAAA;AAGD,eAAO,MAAM,mBAAmB,iBAAkB,GAAG,gBAAgB,GAAG,eAAe,GAAG,qBAAqB,GAAG,kBAAkB,YAAY,EAAE,qBAAqB,eAAe,EAAE,QAwBvL,CAAA;AA0HD,eAAO,MAAM,wBAAwB,kFAumDnC,CAAC"}
1
+ {"version":3,"file":"SolidGlobalSearchElement.d.ts","sourceRoot":"","sources":["../../../../src/components/core/common/SolidGlobalSearchElement.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgF,MAAM,OAAO,CAAC;AAYrG,OAA0B,EAAE,eAAe,EAAE,YAAY,EAAsB,MAAM,qBAAqB,CAAC;AA0B3G,MAAM,MAAM,eAAe,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,EAAE,MAAM,CAAC;CAClC,CAAA;AAoUD,eAAO,MAAM,2BAA2B,sBAAuB,GAAG,aAAa,GAAG,yBAAyB,MAAM,iBAAiB,MAAM,QAavI,CAAA;AAGD,eAAO,MAAM,mBAAmB,iBAAkB,GAAG,gBAAgB,GAAG,eAAe,GAAG,qBAAqB,GAAG,kBAAkB,YAAY,EAAE,qBAAqB,eAAe,EAAE,QAwBvL,CAAA;AA0HD,eAAO,MAAM,wBAAwB,kFAumDnC,CAAC"}
@@ -185,8 +185,19 @@ var transformRulesToFilters = function (input, viewData) {
185
185
  var _a, _b, _c, _d;
186
186
  var _e, _f;
187
187
  if (rule.value !== undefined && rule.value !== null) {
188
- // Ensure rule.value is always an array
189
- var values = typeof rule.value[0] === "object" ? rule.value.map(function (i) { return (i === null || i === void 0 ? void 0 : i.value) ? i === null || i === void 0 ? void 0 : i.value : i; }) : rule === null || rule === void 0 ? void 0 : rule.value;
188
+ // Ensure rule.value is always an array of primitive values.
189
+ // Mixed arrays like ["failed", { label: "pending", value: "pending" }]
190
+ // must be normalized before query serialization.
191
+ var rawValues = Array.isArray(rule === null || rule === void 0 ? void 0 : rule.value) ? rule.value : [rule === null || rule === void 0 ? void 0 : rule.value];
192
+ var values = rawValues.map(function (item) {
193
+ if (item && typeof item === "object") {
194
+ if (Object.prototype.hasOwnProperty.call(item, "value"))
195
+ return item.value;
196
+ if (Object.prototype.hasOwnProperty.call(item, "label"))
197
+ return item.label;
198
+ }
199
+ return item;
200
+ });
190
201
  if (rule.matchMode !== '$in' && rule.matchMode !== '$notIn' && rule.matchMode !== '$between' && rule.matchMode !== '$null' && rule.matchMode !== '$notNull') {
191
202
  values = values[0];
192
203
  }