@serhii.olishevskyi/docs 1.1.7 → 1.1.9
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/dist/{UserPopoverComponent-5F4S3X4F.mjs → UserPopoverComponent-TEHD5DSA.mjs} +1 -1
- package/dist/{chunk-UA57YNRJ.mjs → chunk-ZIMI3BRO.mjs} +1 -0
- package/dist/index.d.mts +17 -2
- package/dist/index.d.ts +17 -2
- package/dist/index.js +161 -2
- package/dist/index.mjs +161 -4
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
|
|
3
|
+
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
|
|
4
4
|
import * as _supabase_supabase_js from '@supabase/supabase-js';
|
|
5
5
|
import { SupabaseClient, User, Session } from '@supabase/supabase-js';
|
|
6
6
|
|
|
@@ -224,6 +224,13 @@ interface MyAvatarComponentProps {
|
|
|
224
224
|
sx?: SxProps<Theme>;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
interface ExpandableNoteComponentProps extends Omit<TypographyProps, 'children'> {
|
|
228
|
+
overrideNamespace?: string;
|
|
229
|
+
text?: string;
|
|
230
|
+
maxLength?: number;
|
|
231
|
+
label?: React__default.ReactNode;
|
|
232
|
+
}
|
|
233
|
+
|
|
227
234
|
declare const UI: {
|
|
228
235
|
Inputs: {
|
|
229
236
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
@@ -243,6 +250,7 @@ declare const UI: {
|
|
|
243
250
|
UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
|
|
244
251
|
UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
|
|
245
252
|
MyAvatar: React$1.FC<MyAvatarComponentProps>;
|
|
253
|
+
ExpandableNote: React$1.FC<ExpandableNoteComponentProps>;
|
|
246
254
|
};
|
|
247
255
|
Widgets: {
|
|
248
256
|
ProtectedLanguageSelector: React$1.FC<{}>;
|
|
@@ -563,10 +571,17 @@ declare const Services: {
|
|
|
563
571
|
};
|
|
564
572
|
};
|
|
565
573
|
|
|
574
|
+
type UserStatusType = 'online' | 'away' | 'offline';
|
|
575
|
+
|
|
566
576
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
567
577
|
|
|
568
578
|
declare const Hooks: {
|
|
569
579
|
readonly useDebounce: typeof useDebounce;
|
|
580
|
+
readonly useUserStatus: (userId?: string, initialLastSeenAt?: string | null, currentAuthUserId?: string) => {
|
|
581
|
+
status: UserStatusType;
|
|
582
|
+
isOnline: boolean;
|
|
583
|
+
lastSeen: string | null;
|
|
584
|
+
};
|
|
570
585
|
};
|
|
571
586
|
|
|
572
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
|
587
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
|
|
3
|
+
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
|
|
4
4
|
import * as _supabase_supabase_js from '@supabase/supabase-js';
|
|
5
5
|
import { SupabaseClient, User, Session } from '@supabase/supabase-js';
|
|
6
6
|
|
|
@@ -224,6 +224,13 @@ interface MyAvatarComponentProps {
|
|
|
224
224
|
sx?: SxProps<Theme>;
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
interface ExpandableNoteComponentProps extends Omit<TypographyProps, 'children'> {
|
|
228
|
+
overrideNamespace?: string;
|
|
229
|
+
text?: string;
|
|
230
|
+
maxLength?: number;
|
|
231
|
+
label?: React__default.ReactNode;
|
|
232
|
+
}
|
|
233
|
+
|
|
227
234
|
declare const UI: {
|
|
228
235
|
Inputs: {
|
|
229
236
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
@@ -243,6 +250,7 @@ declare const UI: {
|
|
|
243
250
|
UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
|
|
244
251
|
UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
|
|
245
252
|
MyAvatar: React$1.FC<MyAvatarComponentProps>;
|
|
253
|
+
ExpandableNote: React$1.FC<ExpandableNoteComponentProps>;
|
|
246
254
|
};
|
|
247
255
|
Widgets: {
|
|
248
256
|
ProtectedLanguageSelector: React$1.FC<{}>;
|
|
@@ -563,10 +571,17 @@ declare const Services: {
|
|
|
563
571
|
};
|
|
564
572
|
};
|
|
565
573
|
|
|
574
|
+
type UserStatusType = 'online' | 'away' | 'offline';
|
|
575
|
+
|
|
566
576
|
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
567
577
|
|
|
568
578
|
declare const Hooks: {
|
|
569
579
|
readonly useDebounce: typeof useDebounce;
|
|
580
|
+
readonly useUserStatus: (userId?: string, initialLastSeenAt?: string | null, currentAuthUserId?: string) => {
|
|
581
|
+
status: UserStatusType;
|
|
582
|
+
isOnline: boolean;
|
|
583
|
+
lastSeen: string | null;
|
|
584
|
+
};
|
|
570
585
|
};
|
|
571
586
|
|
|
572
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
|
587
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.js
CHANGED
|
@@ -4311,6 +4311,72 @@ var SelectComponent = ({
|
|
|
4311
4311
|
);
|
|
4312
4312
|
};
|
|
4313
4313
|
|
|
4314
|
+
// src/UI/components/data.display/ExpandableNoteComponent.tsx
|
|
4315
|
+
var import_react27 = require("react");
|
|
4316
|
+
var import_material20 = require("@mui/material");
|
|
4317
|
+
init_context();
|
|
4318
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
4319
|
+
var ExpandableNoteComponent = ({
|
|
4320
|
+
overrideNamespace,
|
|
4321
|
+
text,
|
|
4322
|
+
maxLength = 100,
|
|
4323
|
+
label,
|
|
4324
|
+
sx,
|
|
4325
|
+
...restProps
|
|
4326
|
+
}) => {
|
|
4327
|
+
const [isExpanded, setIsExpanded] = (0, import_react27.useState)(false);
|
|
4328
|
+
if (!text) return null;
|
|
4329
|
+
const isLong = text.length > maxLength;
|
|
4330
|
+
const displayedText = isExpanded || !isLong ? text : `${text.slice(0, maxLength).trim()}...`;
|
|
4331
|
+
const toggleExpand = (e) => {
|
|
4332
|
+
e.stopPropagation();
|
|
4333
|
+
setIsExpanded((prev) => !prev);
|
|
4334
|
+
};
|
|
4335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4336
|
+
import_material20.Typography,
|
|
4337
|
+
{
|
|
4338
|
+
variant: "caption",
|
|
4339
|
+
sx: {
|
|
4340
|
+
color: "text.secondary",
|
|
4341
|
+
fontStyle: "italic",
|
|
4342
|
+
display: "inline-block",
|
|
4343
|
+
...sx
|
|
4344
|
+
},
|
|
4345
|
+
...restProps,
|
|
4346
|
+
children: [
|
|
4347
|
+
label !== void 0 ? label : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
4348
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Note" }),
|
|
4349
|
+
": "
|
|
4350
|
+
] }),
|
|
4351
|
+
" ",
|
|
4352
|
+
displayedText,
|
|
4353
|
+
" ",
|
|
4354
|
+
isLong && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4355
|
+
import_material20.Link,
|
|
4356
|
+
{
|
|
4357
|
+
component: "button",
|
|
4358
|
+
type: "button",
|
|
4359
|
+
variant: "caption",
|
|
4360
|
+
underline: "hover",
|
|
4361
|
+
onClick: toggleExpand,
|
|
4362
|
+
sx: {
|
|
4363
|
+
fontStyle: "normal",
|
|
4364
|
+
fontWeight: "bold",
|
|
4365
|
+
ml: 0.5,
|
|
4366
|
+
cursor: "pointer",
|
|
4367
|
+
verticalAlign: "baseline"
|
|
4368
|
+
},
|
|
4369
|
+
children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "less" }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
4370
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "more" }),
|
|
4371
|
+
"..."
|
|
4372
|
+
] })
|
|
4373
|
+
}
|
|
4374
|
+
)
|
|
4375
|
+
]
|
|
4376
|
+
}
|
|
4377
|
+
);
|
|
4378
|
+
};
|
|
4379
|
+
|
|
4314
4380
|
// src/UI/index.ts
|
|
4315
4381
|
var UI = {
|
|
4316
4382
|
Inputs: {
|
|
@@ -4330,7 +4396,8 @@ var UI = {
|
|
|
4330
4396
|
UserPopover: UserPopoverComponent_default,
|
|
4331
4397
|
UserRoleChip: UserRoleChipComponent,
|
|
4332
4398
|
UserStatusChip: UserStatusChipComponent,
|
|
4333
|
-
MyAvatar: MyAvatarComponent
|
|
4399
|
+
MyAvatar: MyAvatarComponent,
|
|
4400
|
+
ExpandableNote: ExpandableNoteComponent
|
|
4334
4401
|
},
|
|
4335
4402
|
/*Layout: {
|
|
4336
4403
|
Row: FormRow,
|
|
@@ -4360,9 +4427,101 @@ var Services = {
|
|
|
4360
4427
|
}
|
|
4361
4428
|
};
|
|
4362
4429
|
|
|
4430
|
+
// src/hooks/useUserStatus.ts
|
|
4431
|
+
var import_react28 = require("react");
|
|
4432
|
+
init_deviceId();
|
|
4433
|
+
init_context();
|
|
4434
|
+
var ONLINE_THRESHOLD_MINUTES = 2;
|
|
4435
|
+
var AWAY_THRESHOLD_MINUTES = 15;
|
|
4436
|
+
var useUserStatus2 = (userId, initialLastSeenAt, currentAuthUserId) => {
|
|
4437
|
+
const supabase = useSupabase();
|
|
4438
|
+
const [status, setStatus] = (0, import_react28.useState)("offline");
|
|
4439
|
+
const [lastSeen, setLastSeen] = (0, import_react28.useState)(initialLastSeenAt ?? null);
|
|
4440
|
+
const lastSeenRef = (0, import_react28.useRef)(initialLastSeenAt ?? null);
|
|
4441
|
+
lastSeenRef.current = lastSeen;
|
|
4442
|
+
const calculateStatus = (isOnline, lastSeenIso) => {
|
|
4443
|
+
if (isOnline) return "online";
|
|
4444
|
+
if (!lastSeenIso) return "offline";
|
|
4445
|
+
const lastSeenTime = new Date(lastSeenIso).getTime();
|
|
4446
|
+
if (isNaN(lastSeenTime)) return "offline";
|
|
4447
|
+
const diffInMinutes = (Date.now() - lastSeenTime) / (1e3 * 60);
|
|
4448
|
+
if (diffInMinutes >= 0 && diffInMinutes <= ONLINE_THRESHOLD_MINUTES) {
|
|
4449
|
+
return "online";
|
|
4450
|
+
}
|
|
4451
|
+
if (diffInMinutes > ONLINE_THRESHOLD_MINUTES && diffInMinutes <= AWAY_THRESHOLD_MINUTES) {
|
|
4452
|
+
return "away";
|
|
4453
|
+
}
|
|
4454
|
+
return "offline";
|
|
4455
|
+
};
|
|
4456
|
+
(0, import_react28.useEffect)(() => {
|
|
4457
|
+
if (!userId) return;
|
|
4458
|
+
let isMounted = true;
|
|
4459
|
+
const isSelf = currentAuthUserId && userId === currentAuthUserId;
|
|
4460
|
+
const fetchLastSeen = async () => {
|
|
4461
|
+
if (initialLastSeenAt !== void 0) return;
|
|
4462
|
+
let query = supabase.from("user_sessions").select("last_seen_at").eq("user_id", userId);
|
|
4463
|
+
if (isSelf) {
|
|
4464
|
+
query = query.eq("device_id", getDeviceId());
|
|
4465
|
+
} else {
|
|
4466
|
+
query = query.order("last_seen_at", { ascending: false });
|
|
4467
|
+
}
|
|
4468
|
+
const { data, error } = await query.limit(1).maybeSingle();
|
|
4469
|
+
if (error) {
|
|
4470
|
+
console.warn(`[useUserStatus] Error fetching session for ${userId}:`, error.message);
|
|
4471
|
+
return;
|
|
4472
|
+
}
|
|
4473
|
+
if (data && isMounted) {
|
|
4474
|
+
setLastSeen(data.last_seen_at);
|
|
4475
|
+
setStatus(calculateStatus(false, data.last_seen_at));
|
|
4476
|
+
}
|
|
4477
|
+
};
|
|
4478
|
+
fetchLastSeen();
|
|
4479
|
+
const channel = supabase.channel(`presence_user_${userId}`);
|
|
4480
|
+
channel.on("presence", { event: "sync" }, () => {
|
|
4481
|
+
const state = channel.presenceState();
|
|
4482
|
+
const isOnline = Object.keys(state).length > 0;
|
|
4483
|
+
if (isMounted) {
|
|
4484
|
+
setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
|
|
4485
|
+
}
|
|
4486
|
+
}).on("presence", { event: "join" }, () => {
|
|
4487
|
+
if (isMounted) setStatus("online");
|
|
4488
|
+
}).on("presence", { event: "leave" }, () => {
|
|
4489
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
4490
|
+
if (isMounted) {
|
|
4491
|
+
setLastSeen(nowIso);
|
|
4492
|
+
setStatus(calculateStatus(false, nowIso));
|
|
4493
|
+
}
|
|
4494
|
+
}).on(
|
|
4495
|
+
"postgres_changes",
|
|
4496
|
+
{
|
|
4497
|
+
event: "*",
|
|
4498
|
+
schema: "public",
|
|
4499
|
+
table: "user_sessions",
|
|
4500
|
+
filter: isSelf ? `device_id=eq.${getDeviceId()}` : `user_id=eq.${userId}`
|
|
4501
|
+
},
|
|
4502
|
+
(payload) => {
|
|
4503
|
+
if (!isMounted) return;
|
|
4504
|
+
const newLastSeen = payload.new?.last_seen_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
4505
|
+
setLastSeen(newLastSeen);
|
|
4506
|
+
setStatus(calculateStatus(false, newLastSeen));
|
|
4507
|
+
}
|
|
4508
|
+
).subscribe();
|
|
4509
|
+
return () => {
|
|
4510
|
+
isMounted = false;
|
|
4511
|
+
supabase.removeChannel(channel);
|
|
4512
|
+
};
|
|
4513
|
+
}, [userId, initialLastSeenAt, currentAuthUserId]);
|
|
4514
|
+
return {
|
|
4515
|
+
status,
|
|
4516
|
+
isOnline: status === "online",
|
|
4517
|
+
lastSeen
|
|
4518
|
+
};
|
|
4519
|
+
};
|
|
4520
|
+
|
|
4363
4521
|
// src/hooks/index.ts
|
|
4364
4522
|
var Hooks = {
|
|
4365
|
-
useDebounce
|
|
4523
|
+
useDebounce,
|
|
4524
|
+
useUserStatus: useUserStatus2
|
|
4366
4525
|
};
|
|
4367
4526
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4368
4527
|
0 && (module.exports = {
|
package/dist/index.mjs
CHANGED
|
@@ -21,6 +21,7 @@ import {
|
|
|
21
21
|
UserStatusChipComponent,
|
|
22
22
|
fetchCompanySessions,
|
|
23
23
|
fetchUserSessions,
|
|
24
|
+
getDeviceId,
|
|
24
25
|
getUserLastSeenAt,
|
|
25
26
|
getUsersLastSeenMap,
|
|
26
27
|
groupSessionsByUser,
|
|
@@ -40,7 +41,7 @@ import {
|
|
|
40
41
|
useTranslationEdit,
|
|
41
42
|
useTranslationNamespace,
|
|
42
43
|
useUserSettings
|
|
43
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-ZIMI3BRO.mjs";
|
|
44
45
|
|
|
45
46
|
// src/UI/components/inputs/TextFieldComponent.tsx
|
|
46
47
|
import { useState } from "react";
|
|
@@ -738,7 +739,7 @@ var EmailInputComponent = ({
|
|
|
738
739
|
import { useState as useState5, useEffect as useEffect2, lazy, Suspense } from "react";
|
|
739
740
|
import { Avatar, Tooltip as Tooltip3, Typography as Typography2 } from "@mui/material";
|
|
740
741
|
import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
741
|
-
var LazyUserPopover = lazy(() => import("./UserPopoverComponent-
|
|
742
|
+
var LazyUserPopover = lazy(() => import("./UserPopoverComponent-TEHD5DSA.mjs"));
|
|
742
743
|
var getInitials = (name) => {
|
|
743
744
|
if (!name) return "?";
|
|
744
745
|
const parts = name.trim().split(" ");
|
|
@@ -1585,6 +1586,71 @@ var SelectComponent = ({
|
|
|
1585
1586
|
);
|
|
1586
1587
|
};
|
|
1587
1588
|
|
|
1589
|
+
// src/UI/components/data.display/ExpandableNoteComponent.tsx
|
|
1590
|
+
import { useState as useState10 } from "react";
|
|
1591
|
+
import { Typography as Typography5, Link } from "@mui/material";
|
|
1592
|
+
import { Fragment as Fragment8, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1593
|
+
var ExpandableNoteComponent = ({
|
|
1594
|
+
overrideNamespace,
|
|
1595
|
+
text,
|
|
1596
|
+
maxLength = 100,
|
|
1597
|
+
label,
|
|
1598
|
+
sx,
|
|
1599
|
+
...restProps
|
|
1600
|
+
}) => {
|
|
1601
|
+
const [isExpanded, setIsExpanded] = useState10(false);
|
|
1602
|
+
if (!text) return null;
|
|
1603
|
+
const isLong = text.length > maxLength;
|
|
1604
|
+
const displayedText = isExpanded || !isLong ? text : `${text.slice(0, maxLength).trim()}...`;
|
|
1605
|
+
const toggleExpand = (e) => {
|
|
1606
|
+
e.stopPropagation();
|
|
1607
|
+
setIsExpanded((prev) => !prev);
|
|
1608
|
+
};
|
|
1609
|
+
return /* @__PURE__ */ jsxs9(
|
|
1610
|
+
Typography5,
|
|
1611
|
+
{
|
|
1612
|
+
variant: "caption",
|
|
1613
|
+
sx: {
|
|
1614
|
+
color: "text.secondary",
|
|
1615
|
+
fontStyle: "italic",
|
|
1616
|
+
display: "inline-block",
|
|
1617
|
+
...sx
|
|
1618
|
+
},
|
|
1619
|
+
...restProps,
|
|
1620
|
+
children: [
|
|
1621
|
+
label !== void 0 ? label : /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
1622
|
+
/* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Note" }),
|
|
1623
|
+
": "
|
|
1624
|
+
] }),
|
|
1625
|
+
" ",
|
|
1626
|
+
displayedText,
|
|
1627
|
+
" ",
|
|
1628
|
+
isLong && /* @__PURE__ */ jsx10(
|
|
1629
|
+
Link,
|
|
1630
|
+
{
|
|
1631
|
+
component: "button",
|
|
1632
|
+
type: "button",
|
|
1633
|
+
variant: "caption",
|
|
1634
|
+
underline: "hover",
|
|
1635
|
+
onClick: toggleExpand,
|
|
1636
|
+
sx: {
|
|
1637
|
+
fontStyle: "normal",
|
|
1638
|
+
fontWeight: "bold",
|
|
1639
|
+
ml: 0.5,
|
|
1640
|
+
cursor: "pointer",
|
|
1641
|
+
verticalAlign: "baseline"
|
|
1642
|
+
},
|
|
1643
|
+
children: isExpanded ? /* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "less" }) : /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
1644
|
+
/* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "more" }),
|
|
1645
|
+
"..."
|
|
1646
|
+
] })
|
|
1647
|
+
}
|
|
1648
|
+
)
|
|
1649
|
+
]
|
|
1650
|
+
}
|
|
1651
|
+
);
|
|
1652
|
+
};
|
|
1653
|
+
|
|
1588
1654
|
// src/UI/index.ts
|
|
1589
1655
|
var UI = {
|
|
1590
1656
|
Inputs: {
|
|
@@ -1604,7 +1670,8 @@ var UI = {
|
|
|
1604
1670
|
UserPopover: UserPopoverComponent_default,
|
|
1605
1671
|
UserRoleChip: UserRoleChipComponent,
|
|
1606
1672
|
UserStatusChip: UserStatusChipComponent,
|
|
1607
|
-
MyAvatar: MyAvatarComponent
|
|
1673
|
+
MyAvatar: MyAvatarComponent,
|
|
1674
|
+
ExpandableNote: ExpandableNoteComponent
|
|
1608
1675
|
},
|
|
1609
1676
|
/*Layout: {
|
|
1610
1677
|
Row: FormRow,
|
|
@@ -1629,9 +1696,99 @@ var Services = {
|
|
|
1629
1696
|
}
|
|
1630
1697
|
};
|
|
1631
1698
|
|
|
1699
|
+
// src/hooks/useUserStatus.ts
|
|
1700
|
+
import { useEffect as useEffect6, useRef, useState as useState11 } from "react";
|
|
1701
|
+
var ONLINE_THRESHOLD_MINUTES = 2;
|
|
1702
|
+
var AWAY_THRESHOLD_MINUTES = 15;
|
|
1703
|
+
var useUserStatus = (userId, initialLastSeenAt, currentAuthUserId) => {
|
|
1704
|
+
const supabase = useSupabase();
|
|
1705
|
+
const [status, setStatus] = useState11("offline");
|
|
1706
|
+
const [lastSeen, setLastSeen] = useState11(initialLastSeenAt ?? null);
|
|
1707
|
+
const lastSeenRef = useRef(initialLastSeenAt ?? null);
|
|
1708
|
+
lastSeenRef.current = lastSeen;
|
|
1709
|
+
const calculateStatus = (isOnline, lastSeenIso) => {
|
|
1710
|
+
if (isOnline) return "online";
|
|
1711
|
+
if (!lastSeenIso) return "offline";
|
|
1712
|
+
const lastSeenTime = new Date(lastSeenIso).getTime();
|
|
1713
|
+
if (isNaN(lastSeenTime)) return "offline";
|
|
1714
|
+
const diffInMinutes = (Date.now() - lastSeenTime) / (1e3 * 60);
|
|
1715
|
+
if (diffInMinutes >= 0 && diffInMinutes <= ONLINE_THRESHOLD_MINUTES) {
|
|
1716
|
+
return "online";
|
|
1717
|
+
}
|
|
1718
|
+
if (diffInMinutes > ONLINE_THRESHOLD_MINUTES && diffInMinutes <= AWAY_THRESHOLD_MINUTES) {
|
|
1719
|
+
return "away";
|
|
1720
|
+
}
|
|
1721
|
+
return "offline";
|
|
1722
|
+
};
|
|
1723
|
+
useEffect6(() => {
|
|
1724
|
+
if (!userId) return;
|
|
1725
|
+
let isMounted = true;
|
|
1726
|
+
const isSelf = currentAuthUserId && userId === currentAuthUserId;
|
|
1727
|
+
const fetchLastSeen = async () => {
|
|
1728
|
+
if (initialLastSeenAt !== void 0) return;
|
|
1729
|
+
let query = supabase.from("user_sessions").select("last_seen_at").eq("user_id", userId);
|
|
1730
|
+
if (isSelf) {
|
|
1731
|
+
query = query.eq("device_id", getDeviceId());
|
|
1732
|
+
} else {
|
|
1733
|
+
query = query.order("last_seen_at", { ascending: false });
|
|
1734
|
+
}
|
|
1735
|
+
const { data, error } = await query.limit(1).maybeSingle();
|
|
1736
|
+
if (error) {
|
|
1737
|
+
console.warn(`[useUserStatus] Error fetching session for ${userId}:`, error.message);
|
|
1738
|
+
return;
|
|
1739
|
+
}
|
|
1740
|
+
if (data && isMounted) {
|
|
1741
|
+
setLastSeen(data.last_seen_at);
|
|
1742
|
+
setStatus(calculateStatus(false, data.last_seen_at));
|
|
1743
|
+
}
|
|
1744
|
+
};
|
|
1745
|
+
fetchLastSeen();
|
|
1746
|
+
const channel = supabase.channel(`presence_user_${userId}`);
|
|
1747
|
+
channel.on("presence", { event: "sync" }, () => {
|
|
1748
|
+
const state = channel.presenceState();
|
|
1749
|
+
const isOnline = Object.keys(state).length > 0;
|
|
1750
|
+
if (isMounted) {
|
|
1751
|
+
setStatus(isOnline ? "online" : calculateStatus(false, lastSeenRef.current));
|
|
1752
|
+
}
|
|
1753
|
+
}).on("presence", { event: "join" }, () => {
|
|
1754
|
+
if (isMounted) setStatus("online");
|
|
1755
|
+
}).on("presence", { event: "leave" }, () => {
|
|
1756
|
+
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
1757
|
+
if (isMounted) {
|
|
1758
|
+
setLastSeen(nowIso);
|
|
1759
|
+
setStatus(calculateStatus(false, nowIso));
|
|
1760
|
+
}
|
|
1761
|
+
}).on(
|
|
1762
|
+
"postgres_changes",
|
|
1763
|
+
{
|
|
1764
|
+
event: "*",
|
|
1765
|
+
schema: "public",
|
|
1766
|
+
table: "user_sessions",
|
|
1767
|
+
filter: isSelf ? `device_id=eq.${getDeviceId()}` : `user_id=eq.${userId}`
|
|
1768
|
+
},
|
|
1769
|
+
(payload) => {
|
|
1770
|
+
if (!isMounted) return;
|
|
1771
|
+
const newLastSeen = payload.new?.last_seen_at ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
1772
|
+
setLastSeen(newLastSeen);
|
|
1773
|
+
setStatus(calculateStatus(false, newLastSeen));
|
|
1774
|
+
}
|
|
1775
|
+
).subscribe();
|
|
1776
|
+
return () => {
|
|
1777
|
+
isMounted = false;
|
|
1778
|
+
supabase.removeChannel(channel);
|
|
1779
|
+
};
|
|
1780
|
+
}, [userId, initialLastSeenAt, currentAuthUserId]);
|
|
1781
|
+
return {
|
|
1782
|
+
status,
|
|
1783
|
+
isOnline: status === "online",
|
|
1784
|
+
lastSeen
|
|
1785
|
+
};
|
|
1786
|
+
};
|
|
1787
|
+
|
|
1632
1788
|
// src/hooks/index.ts
|
|
1633
1789
|
var Hooks = {
|
|
1634
|
-
useDebounce
|
|
1790
|
+
useDebounce,
|
|
1791
|
+
useUserStatus
|
|
1635
1792
|
};
|
|
1636
1793
|
export {
|
|
1637
1794
|
AIProvider,
|