@ram_28/kf-ai-sdk 1.0.10 → 1.0.12
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/README.md +55 -48
- package/dist/api/client.d.ts +23 -13
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/datetime.d.ts +5 -5
- package/dist/api/datetime.d.ts.map +1 -1
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/metadata.d.ts +2 -2
- package/dist/api/metadata.d.ts.map +1 -1
- package/dist/api.cjs +1 -0
- package/dist/api.d.ts +4 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.mjs +27 -0
- package/dist/api.types.cjs +1 -0
- package/dist/api.types.d.ts +4 -0
- package/dist/api.types.d.ts.map +1 -0
- package/dist/api.types.mjs +1 -0
- package/dist/auth/AuthProvider.d.ts +3 -3
- package/dist/auth/AuthProvider.d.ts.map +1 -1
- package/dist/auth/authClient.d.ts +4 -4
- package/dist/auth/authClient.d.ts.map +1 -1
- package/dist/auth/authConfig.d.ts +5 -5
- package/dist/auth/authConfig.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/types.d.ts +21 -21
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/auth/useAuth.d.ts +2 -2
- package/dist/auth/useAuth.d.ts.map +1 -1
- package/dist/auth.cjs +1 -0
- package/dist/auth.d.ts +5 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.mjs +280 -0
- package/dist/auth.types.cjs +1 -0
- package/dist/auth.types.d.ts +2 -0
- package/dist/auth.types.d.ts.map +1 -0
- package/dist/auth.types.mjs +1 -0
- package/dist/base-types.d.ts +2 -0
- package/dist/base-types.d.ts.map +1 -0
- package/dist/client-C15j4O5B.cjs +1 -0
- package/dist/client-CfvLiGfP.js +233 -0
- package/dist/cn-Dr87sK3i.js +2775 -0
- package/dist/cn-mXUIg4vp.cjs +1 -0
- package/dist/components/hooks/index.d.ts +3 -3
- package/dist/components/hooks/index.d.ts.map +1 -1
- package/dist/components/hooks/useFilter/index.d.ts +2 -2
- package/dist/components/hooks/useFilter/index.d.ts.map +1 -1
- package/dist/components/hooks/useFilter/types.d.ts +19 -31
- package/dist/components/hooks/useFilter/types.d.ts.map +1 -1
- package/dist/components/hooks/useFilter/useFilter.d.ts +2 -2
- package/dist/components/hooks/useFilter/useFilter.d.ts.map +1 -1
- package/dist/components/hooks/useForm/apiClient.d.ts +6 -6
- package/dist/components/hooks/useForm/apiClient.d.ts.map +1 -1
- package/dist/components/hooks/useForm/expressionValidator.utils.d.ts +7 -7
- package/dist/components/hooks/useForm/expressionValidator.utils.d.ts.map +1 -1
- package/dist/components/hooks/useForm/index.d.ts +5 -5
- package/dist/components/hooks/useForm/index.d.ts.map +1 -1
- package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts +10 -10
- package/dist/components/hooks/useForm/optimizedExpressionValidator.utils.d.ts.map +1 -1
- package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts +7 -12
- package/dist/components/hooks/useForm/ruleClassifier.utils.d.ts.map +1 -1
- package/dist/components/hooks/useForm/schemaParser.utils.d.ts +7 -7
- package/dist/components/hooks/useForm/schemaParser.utils.d.ts.map +1 -1
- package/dist/components/hooks/useForm/types.d.ts +79 -70
- package/dist/components/hooks/useForm/types.d.ts.map +1 -1
- package/dist/components/hooks/useForm/useForm.d.ts +2 -2
- package/dist/components/hooks/useForm/useForm.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/apiClient.d.ts +16 -16
- package/dist/components/hooks/useKanban/apiClient.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/context.d.ts +3 -3
- package/dist/components/hooks/useKanban/context.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/dragDropManager.d.ts +7 -7
- package/dist/components/hooks/useKanban/dragDropManager.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/index.d.ts +1 -1
- package/dist/components/hooks/useKanban/index.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/types.d.ts +65 -67
- package/dist/components/hooks/useKanban/types.d.ts.map +1 -1
- package/dist/components/hooks/useKanban/useKanban.d.ts +2 -2
- package/dist/components/hooks/useKanban/useKanban.d.ts.map +1 -1
- package/dist/components/hooks/useTable/index.d.ts +1 -1
- package/dist/components/hooks/useTable/index.d.ts.map +1 -1
- package/dist/components/hooks/useTable/types.d.ts +10 -10
- package/dist/components/hooks/useTable/types.d.ts.map +1 -1
- package/dist/components/hooks/useTable/useTable.d.ts +2 -2
- package/dist/components/hooks/useTable/useTable.d.ts.map +1 -1
- package/dist/filter.cjs +1 -0
- package/dist/filter.d.ts +3 -0
- package/dist/filter.d.ts.map +1 -0
- package/dist/filter.mjs +6 -0
- package/dist/filter.types.cjs +1 -0
- package/dist/filter.types.d.ts +2 -0
- package/dist/filter.types.d.ts.map +1 -0
- package/dist/filter.types.mjs +1 -0
- package/dist/form.cjs +1 -0
- package/dist/form.d.ts +3 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/form.mjs +1346 -0
- package/dist/form.types.cjs +1 -0
- package/dist/form.types.d.ts +2 -0
- package/dist/form.types.d.ts.map +1 -0
- package/dist/form.types.mjs +1 -0
- package/dist/jsx-runtime-BYECrxsp.cjs +30 -0
- package/dist/jsx-runtime-DGlMoOmv.js +630 -0
- package/dist/kanban.cjs +13 -0
- package/dist/kanban.d.ts +5 -0
- package/dist/kanban.d.ts.map +1 -0
- package/dist/kanban.mjs +694 -0
- package/dist/kanban.types.cjs +1 -0
- package/dist/kanban.types.d.ts +2 -0
- package/dist/kanban.types.d.ts.map +1 -0
- package/dist/kanban.types.mjs +1 -0
- package/dist/kanban.ui.cjs +1 -0
- package/dist/kanban.ui.d.ts +2 -0
- package/dist/kanban.ui.d.ts.map +1 -0
- package/dist/kanban.ui.mjs +104 -0
- package/dist/metadata-2FLBsFcf.cjs +1 -0
- package/dist/metadata-DBcoDth-.js +43 -0
- package/dist/table.cjs +1 -0
- package/dist/table.d.ts +2 -0
- package/dist/table.d.ts.map +1 -0
- package/dist/table.mjs +148 -0
- package/dist/table.types.cjs +1 -0
- package/dist/table.types.d.ts +2 -0
- package/dist/table.types.d.ts.map +1 -0
- package/dist/table.types.mjs +1 -0
- package/dist/types/base-fields.d.ts +45 -45
- package/dist/types/base-fields.d.ts.map +1 -1
- package/dist/types/common.d.ts +45 -61
- package/dist/types/common.d.ts.map +1 -1
- package/dist/types.cjs +1 -0
- package/dist/types.mjs +1 -0
- package/dist/useFilter-CXFqEHyI.js +129 -0
- package/dist/useFilter-D-bCDo6Z.cjs +1 -0
- package/dist/utils/formatting.d.ts +4 -4
- package/dist/utils/formatting.d.ts.map +1 -1
- package/dist/utils.cjs +4 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.mjs +105 -0
- package/package.json +147 -9
- package/sdk/api/client.ts +76 -49
- package/sdk/api/datetime.ts +5 -5
- package/sdk/api/index.ts +28 -33
- package/sdk/api/metadata.ts +4 -4
- package/sdk/api.ts +24 -0
- package/sdk/api.types.ts +58 -0
- package/sdk/auth/AuthProvider.tsx +18 -18
- package/sdk/auth/authClient.ts +9 -9
- package/sdk/auth/authConfig.ts +9 -9
- package/sdk/auth/index.ts +5 -5
- package/sdk/auth/types.ts +21 -21
- package/sdk/auth/useAuth.ts +2 -2
- package/sdk/auth.ts +22 -0
- package/sdk/auth.types.ts +28 -0
- package/sdk/base-types.ts +45 -0
- package/sdk/components/hooks/index.ts +22 -22
- package/sdk/components/hooks/useFilter/index.ts +8 -14
- package/sdk/components/hooks/useFilter/types.ts +29 -58
- package/sdk/components/hooks/useFilter/useFilter.ts +41 -44
- package/sdk/components/hooks/useForm/apiClient.ts +8 -8
- package/sdk/components/hooks/useForm/expressionValidator.utils.ts +18 -18
- package/sdk/components/hooks/useForm/index.ts +24 -24
- package/sdk/components/hooks/useForm/optimizedExpressionValidator.utils.ts +22 -22
- package/sdk/components/hooks/useForm/ruleClassifier.utils.ts +26 -62
- package/sdk/components/hooks/useForm/schemaParser.utils.ts +24 -24
- package/sdk/components/hooks/useForm/types.ts +85 -75
- package/sdk/components/hooks/useForm/useForm.ts +160 -40
- package/sdk/components/hooks/useKanban/apiClient.ts +54 -54
- package/sdk/components/hooks/useKanban/context.ts +3 -3
- package/sdk/components/hooks/useKanban/dragDropManager.ts +19 -19
- package/sdk/components/hooks/useKanban/index.ts +26 -26
- package/sdk/components/hooks/useKanban/types.ts +69 -71
- package/sdk/components/hooks/useKanban/useKanban.ts +43 -51
- package/sdk/components/hooks/useKanban/useKanbanSimple.ts +4 -4
- package/sdk/components/hooks/useTable/index.ts +5 -1
- package/sdk/components/hooks/useTable/types.ts +10 -10
- package/sdk/components/hooks/useTable/useTable.ts +10 -10
- package/sdk/filter.ts +13 -0
- package/sdk/filter.types.ts +17 -0
- package/sdk/form.ts +15 -0
- package/sdk/form.types.ts +46 -0
- package/sdk/kanban.ts +23 -0
- package/sdk/kanban.types.ts +50 -0
- package/sdk/kanban.ui.ts +16 -0
- package/sdk/table.ts +7 -0
- package/sdk/table.types.ts +13 -0
- package/sdk/types/base-fields.ts +47 -47
- package/sdk/types/common.ts +47 -71
- package/sdk/types/index.ts +1 -1
- package/sdk/utils/formatting.ts +4 -4
- package/sdk/utils.ts +10 -0
- package/dist/index.cjs +0 -45
- package/dist/index.mjs +0 -6327
|
@@ -9,11 +9,11 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
9
9
|
import type { Path } from "react-hook-form";
|
|
10
10
|
|
|
11
11
|
import type {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
UseFormOptionsType,
|
|
13
|
+
UseFormReturnType,
|
|
14
|
+
BDOSchemaType,
|
|
15
|
+
FormSchemaConfigType,
|
|
16
|
+
FormFieldConfigType,
|
|
17
17
|
} from "./types";
|
|
18
18
|
|
|
19
19
|
import { processSchema, extractReferenceFields } from "./schemaParser.utils";
|
|
@@ -39,8 +39,8 @@ import {
|
|
|
39
39
|
// ============================================================
|
|
40
40
|
|
|
41
41
|
export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
42
|
-
options:
|
|
43
|
-
):
|
|
42
|
+
options: UseFormOptionsType<T>
|
|
43
|
+
): UseFormReturnType<T> {
|
|
44
44
|
const {
|
|
45
45
|
source,
|
|
46
46
|
operation,
|
|
@@ -52,19 +52,27 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
52
52
|
onSchemaError,
|
|
53
53
|
skipSchemaFetch = false,
|
|
54
54
|
schema: manualSchema,
|
|
55
|
-
|
|
55
|
+
interactionMode = "interactive",
|
|
56
56
|
} = options;
|
|
57
57
|
|
|
58
|
+
// Derived interaction mode flags
|
|
59
|
+
const isInteractiveMode = interactionMode === "interactive";
|
|
60
|
+
|
|
58
61
|
// ============================================================
|
|
59
62
|
// STATE MANAGEMENT
|
|
60
63
|
// ============================================================
|
|
61
64
|
|
|
62
65
|
const [schemaConfig, setSchemaConfig] =
|
|
63
|
-
useState<
|
|
66
|
+
useState<FormSchemaConfigType | null>(null);
|
|
64
67
|
const [referenceData, setReferenceData] = useState<Record<string, any[]>>({});
|
|
65
68
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
66
69
|
const [lastFormValues] = useState<Partial<T>>({});
|
|
67
70
|
|
|
71
|
+
// Interactive mode state
|
|
72
|
+
const [draftId, setDraftId] = useState<string | null>(null);
|
|
73
|
+
const [isCreatingDraft, setIsCreatingDraft] = useState(false);
|
|
74
|
+
const [draftError, setDraftError] = useState<Error | null>(null);
|
|
75
|
+
|
|
68
76
|
// Prevent infinite loop in API calls
|
|
69
77
|
const isComputingRef = useRef(false);
|
|
70
78
|
const computeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
@@ -189,6 +197,61 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
189
197
|
}
|
|
190
198
|
}, [schemaError]);
|
|
191
199
|
|
|
200
|
+
// ============================================================
|
|
201
|
+
// INTERACTIVE MODE - INITIAL DRAFT CREATION
|
|
202
|
+
// ============================================================
|
|
203
|
+
|
|
204
|
+
// Create initial draft for interactive create mode
|
|
205
|
+
useEffect(() => {
|
|
206
|
+
// Only run for interactive mode + create operation + schema loaded + no draft yet
|
|
207
|
+
if (
|
|
208
|
+
!isInteractiveMode ||
|
|
209
|
+
operation !== "create" ||
|
|
210
|
+
!schemaConfig ||
|
|
211
|
+
!enabled ||
|
|
212
|
+
draftId
|
|
213
|
+
) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const createInitialDraft = async () => {
|
|
218
|
+
setIsCreatingDraft(true);
|
|
219
|
+
setDraftError(null);
|
|
220
|
+
|
|
221
|
+
try {
|
|
222
|
+
const client = api<T>(source);
|
|
223
|
+
// Call PATCH /{bdo_id}/draft with empty payload to get draft ID
|
|
224
|
+
const response = await client.draftInteraction({});
|
|
225
|
+
|
|
226
|
+
// Store the draft ID
|
|
227
|
+
setDraftId(response._id);
|
|
228
|
+
|
|
229
|
+
// Apply any computed fields returned from API
|
|
230
|
+
if (response && typeof response === "object") {
|
|
231
|
+
Object.entries(response).forEach(([fieldName, value]) => {
|
|
232
|
+
// Skip _id as it's the draft ID, not a form field
|
|
233
|
+
if (fieldName === "_id") return;
|
|
234
|
+
|
|
235
|
+
const currentValue = rhfForm.getValues(fieldName as any);
|
|
236
|
+
if (currentValue !== value) {
|
|
237
|
+
rhfForm.setValue(fieldName as any, value as any, {
|
|
238
|
+
shouldDirty: false,
|
|
239
|
+
shouldValidate: false,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error("Failed to create initial draft:", error);
|
|
246
|
+
setDraftError(error as Error);
|
|
247
|
+
} finally {
|
|
248
|
+
setIsCreatingDraft(false);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
createInitialDraft();
|
|
253
|
+
}, [isInteractiveMode, operation, schemaConfig, enabled, draftId, source, rhfForm]);
|
|
254
|
+
|
|
192
255
|
// ============================================================
|
|
193
256
|
// COMPUTED FIELD DEPENDENCY TRACKING AND OPTIMIZATION
|
|
194
257
|
// ============================================================
|
|
@@ -253,21 +316,28 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
253
316
|
// Manual computation trigger - called on blur after validation passes
|
|
254
317
|
const triggerComputationAfterValidation = useCallback(
|
|
255
318
|
async (fieldName: string) => {
|
|
256
|
-
if (!schemaConfig
|
|
319
|
+
if (!schemaConfig) {
|
|
257
320
|
return;
|
|
258
321
|
}
|
|
259
322
|
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
const shouldTrigger =
|
|
264
|
-
|
|
265
|
-
computedFieldDependencies.
|
|
323
|
+
// Determine if draft should be triggered based on interaction mode
|
|
324
|
+
// Interactive mode: Always trigger draft API on blur
|
|
325
|
+
// Non-interactive mode: Only trigger for computed field dependencies
|
|
326
|
+
const shouldTrigger = isInteractiveMode
|
|
327
|
+
? true // Interactive mode: always trigger
|
|
328
|
+
: (computedFieldDependencies.length > 0 &&
|
|
329
|
+
computedFieldDependencies.includes(fieldName as Path<T>));
|
|
266
330
|
|
|
267
331
|
if (!shouldTrigger) {
|
|
268
332
|
return;
|
|
269
333
|
}
|
|
270
334
|
|
|
335
|
+
// For interactive create, check that we have a draftId (except for initial draft creation)
|
|
336
|
+
if (isInteractiveMode && operation === "create" && !draftId) {
|
|
337
|
+
console.warn("Interactive create mode: waiting for draft ID");
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
|
|
271
341
|
// Prevent concurrent API calls
|
|
272
342
|
if (isComputingRef.current) {
|
|
273
343
|
return;
|
|
@@ -305,6 +375,11 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
305
375
|
(changedFields as any)._id = (currentValues as any)._id;
|
|
306
376
|
}
|
|
307
377
|
|
|
378
|
+
// For interactive create mode, include draft _id
|
|
379
|
+
if (isInteractiveMode && operation === "create" && draftId) {
|
|
380
|
+
(changedFields as any)._id = draftId;
|
|
381
|
+
}
|
|
382
|
+
|
|
308
383
|
// Use lastSyncedValues if available, otherwise use recordData (for update) or empty object (for create)
|
|
309
384
|
const baseline =
|
|
310
385
|
lastSyncedValuesRef.current ??
|
|
@@ -357,10 +432,18 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
357
432
|
|
|
358
433
|
lastSyncedValuesRef.current = baselineBeforeApiCall;
|
|
359
434
|
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
435
|
+
// Choose API method based on operation and interaction mode
|
|
436
|
+
let computedFieldsResponse;
|
|
437
|
+
if (operation === "update" && recordId) {
|
|
438
|
+
// Update mode: use draftPatch (both interactive and non-interactive)
|
|
439
|
+
computedFieldsResponse = await client.draftPatch(recordId, payload);
|
|
440
|
+
} else if (isInteractiveMode && draftId) {
|
|
441
|
+
// Interactive create: use draftInteraction with _id
|
|
442
|
+
computedFieldsResponse = await client.draftInteraction(payload);
|
|
443
|
+
} else {
|
|
444
|
+
// Non-interactive create: use draft (POST)
|
|
445
|
+
computedFieldsResponse = await client.draft(payload);
|
|
446
|
+
}
|
|
364
447
|
|
|
365
448
|
// Apply computed fields returned from API
|
|
366
449
|
if (
|
|
@@ -412,7 +495,8 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
412
495
|
source,
|
|
413
496
|
rhfForm,
|
|
414
497
|
computedFieldDependencies,
|
|
415
|
-
|
|
498
|
+
isInteractiveMode,
|
|
499
|
+
draftId,
|
|
416
500
|
]
|
|
417
501
|
);
|
|
418
502
|
|
|
@@ -539,21 +623,51 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
539
623
|
recordData as Partial<T> | undefined
|
|
540
624
|
);
|
|
541
625
|
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
recordId
|
|
548
|
-
);
|
|
626
|
+
let result;
|
|
627
|
+
|
|
628
|
+
if (isInteractiveMode) {
|
|
629
|
+
// Interactive mode submission
|
|
630
|
+
const client = api<T>(source);
|
|
549
631
|
|
|
550
|
-
|
|
551
|
-
|
|
632
|
+
if (operation === "create") {
|
|
633
|
+
// Interactive create: must have draftId
|
|
634
|
+
if (!draftId) {
|
|
635
|
+
throw new Error(
|
|
636
|
+
"Interactive create mode requires a draft ID. Draft creation may have failed."
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
// POST /{bdo_id}/draft with _id in payload
|
|
640
|
+
const response = await client.draft({
|
|
641
|
+
...cleanedData,
|
|
642
|
+
_id: draftId,
|
|
643
|
+
} as any);
|
|
644
|
+
result = { success: true, data: response };
|
|
645
|
+
} else {
|
|
646
|
+
// Interactive update: POST /{bdo_id}/{id}/draft
|
|
647
|
+
const response = await client.draftUpdate(recordId!, cleanedData);
|
|
648
|
+
result = { success: true, data: response };
|
|
649
|
+
}
|
|
650
|
+
} else {
|
|
651
|
+
// Non-interactive mode: use existing submitFormData
|
|
652
|
+
result = await submitFormData<T>(
|
|
653
|
+
source,
|
|
654
|
+
operation,
|
|
655
|
+
cleanedData,
|
|
656
|
+
recordId
|
|
657
|
+
);
|
|
658
|
+
|
|
659
|
+
if (!result.success) {
|
|
660
|
+
throw result.error || new Error("Submission failed");
|
|
661
|
+
}
|
|
552
662
|
}
|
|
553
663
|
|
|
554
664
|
// Reset form for create operations
|
|
555
665
|
if (operation === "create") {
|
|
556
666
|
rhfForm.reset();
|
|
667
|
+
// Clear draft state for interactive mode
|
|
668
|
+
if (isInteractiveMode) {
|
|
669
|
+
setDraftId(null);
|
|
670
|
+
}
|
|
557
671
|
}
|
|
558
672
|
|
|
559
673
|
// Success callback with response data
|
|
@@ -579,6 +693,8 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
579
693
|
operation,
|
|
580
694
|
recordId,
|
|
581
695
|
recordData,
|
|
696
|
+
isInteractiveMode,
|
|
697
|
+
draftId,
|
|
582
698
|
]
|
|
583
699
|
);
|
|
584
700
|
|
|
@@ -587,16 +703,16 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
587
703
|
// ============================================================
|
|
588
704
|
|
|
589
705
|
const getField = useCallback(
|
|
590
|
-
<K extends keyof T>(fieldName: K):
|
|
706
|
+
<K extends keyof T>(fieldName: K): FormFieldConfigType | null => {
|
|
591
707
|
return schemaConfig?.fields[fieldName as string] || null;
|
|
592
708
|
},
|
|
593
709
|
[schemaConfig]
|
|
594
710
|
);
|
|
595
711
|
|
|
596
|
-
const getFields = useCallback((): Record<keyof T,
|
|
597
|
-
if (!schemaConfig) return {} as Record<keyof T,
|
|
712
|
+
const getFields = useCallback((): Record<keyof T, FormFieldConfigType> => {
|
|
713
|
+
if (!schemaConfig) return {} as Record<keyof T, FormFieldConfigType>;
|
|
598
714
|
|
|
599
|
-
const typedFields: Record<keyof T,
|
|
715
|
+
const typedFields: Record<keyof T, FormFieldConfigType> = {} as any;
|
|
600
716
|
Object.entries(schemaConfig.fields).forEach(([key, field]) => {
|
|
601
717
|
(typedFields as any)[key] = field;
|
|
602
718
|
});
|
|
@@ -645,10 +761,13 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
645
761
|
// COMPUTED PROPERTIES
|
|
646
762
|
// ============================================================
|
|
647
763
|
|
|
764
|
+
// Loading state includes interactive mode draft creation
|
|
648
765
|
const isLoadingInitialData =
|
|
649
|
-
isLoadingSchema ||
|
|
766
|
+
isLoadingSchema ||
|
|
767
|
+
(operation === "update" && isLoadingRecord) ||
|
|
768
|
+
(isInteractiveMode && operation === "create" && isCreatingDraft);
|
|
650
769
|
const isLoading = isLoadingInitialData || isSubmitting;
|
|
651
|
-
const loadError = schemaError || recordError;
|
|
770
|
+
const loadError = schemaError || recordError || draftError;
|
|
652
771
|
const hasError = !!loadError;
|
|
653
772
|
|
|
654
773
|
const computedFields = useMemo<Array<keyof T>>(
|
|
@@ -801,20 +920,21 @@ export function useForm<T extends Record<string, any> = Record<string, any>>(
|
|
|
801
920
|
isSubmitting: rhfForm.formState.isSubmitting || isSubmitting,
|
|
802
921
|
isSubmitSuccessful: rhfForm.formState.isSubmitSuccessful,
|
|
803
922
|
|
|
804
|
-
// BACKWARD COMPATIBILITY - Keep formState for existing components
|
|
805
|
-
formState: rhfForm.formState,
|
|
806
|
-
|
|
807
923
|
// Loading states
|
|
808
924
|
isLoadingInitialData,
|
|
809
925
|
isLoadingRecord,
|
|
810
926
|
isLoading,
|
|
811
927
|
|
|
928
|
+
// Interactive mode state
|
|
929
|
+
draftId,
|
|
930
|
+
isCreatingDraft,
|
|
931
|
+
|
|
812
932
|
// Error handling
|
|
813
933
|
loadError: loadError as Error | null,
|
|
814
934
|
hasError,
|
|
815
935
|
|
|
816
936
|
// Schema information
|
|
817
|
-
schema: schema as
|
|
937
|
+
schema: schema as BDOSchemaType | null,
|
|
818
938
|
schemaConfig,
|
|
819
939
|
computedFields,
|
|
820
940
|
requiredFields,
|
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
// Follows the same structure as useForm and useTable API clients
|
|
6
6
|
|
|
7
7
|
import { api } from "../../../api";
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
import type {
|
|
9
|
+
ListOptionsType,
|
|
10
|
+
ListResponseType,
|
|
11
|
+
CreateUpdateResponseType,
|
|
12
|
+
DeleteResponseType,
|
|
13
|
+
CountResponseType
|
|
14
14
|
} from "../../../types/common";
|
|
15
15
|
import type {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
KanbanCardType,
|
|
17
|
+
KanbanColumnType,
|
|
18
|
+
BulkCardUpdateRequestType,
|
|
19
|
+
BulkColumnUpdateRequestType
|
|
20
20
|
} from "./types";
|
|
21
21
|
|
|
22
22
|
// ============================================================
|
|
@@ -28,18 +28,18 @@ import type {
|
|
|
28
28
|
*/
|
|
29
29
|
export async function fetchColumns<T>(
|
|
30
30
|
source: string,
|
|
31
|
-
options?:
|
|
32
|
-
): Promise<
|
|
33
|
-
const client = api<
|
|
31
|
+
options?: ListOptionsType
|
|
32
|
+
): Promise<KanbanColumnType<T>[]> {
|
|
33
|
+
const client = api<KanbanColumnType<T>>(source);
|
|
34
34
|
|
|
35
35
|
// Build API options for columns query
|
|
36
|
-
const apiOptions:
|
|
36
|
+
const apiOptions: ListOptionsType = {
|
|
37
37
|
...options,
|
|
38
38
|
// Default sort by position if no sort specified - using correct API format
|
|
39
39
|
Sort: options?.Sort || [{ position: "ASC" }]
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
const response:
|
|
42
|
+
const response: ListResponseType<KanbanColumnType<T>> = await client.list(apiOptions);
|
|
43
43
|
|
|
44
44
|
// Initialize empty cards array for each column
|
|
45
45
|
// Cards will be fetched separately and merged
|
|
@@ -54,14 +54,14 @@ export async function fetchColumns<T>(
|
|
|
54
54
|
*/
|
|
55
55
|
export async function createColumn<T>(
|
|
56
56
|
source: string,
|
|
57
|
-
column: Partial<
|
|
57
|
+
column: Partial<KanbanColumnType<T>>
|
|
58
58
|
): Promise<string> {
|
|
59
|
-
const client = api<
|
|
59
|
+
const client = api<KanbanColumnType<T>>(source);
|
|
60
60
|
|
|
61
61
|
// Exclude cards array from creation payload
|
|
62
62
|
const { cards, ...columnData } = column;
|
|
63
63
|
|
|
64
|
-
const response:
|
|
64
|
+
const response: CreateUpdateResponseType = await client.create(columnData);
|
|
65
65
|
return response._id;
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -71,9 +71,9 @@ export async function createColumn<T>(
|
|
|
71
71
|
export async function updateColumn<T>(
|
|
72
72
|
source: string,
|
|
73
73
|
id: string,
|
|
74
|
-
updates: Partial<
|
|
74
|
+
updates: Partial<KanbanColumnType<T>>
|
|
75
75
|
): Promise<void> {
|
|
76
|
-
const client = api<
|
|
76
|
+
const client = api<KanbanColumnType<T>>(source);
|
|
77
77
|
|
|
78
78
|
// Exclude cards array from update payload
|
|
79
79
|
const { cards, ...columnUpdates } = updates;
|
|
@@ -99,7 +99,7 @@ export async function reorderColumns<T>(
|
|
|
99
99
|
source: string,
|
|
100
100
|
columnIds: string[]
|
|
101
101
|
): Promise<void> {
|
|
102
|
-
const client = api<
|
|
102
|
+
const client = api<KanbanColumnType<T>>(source);
|
|
103
103
|
|
|
104
104
|
// Update position for each column
|
|
105
105
|
const updates = columnIds.map((id, index) => ({
|
|
@@ -124,12 +124,12 @@ export async function reorderColumns<T>(
|
|
|
124
124
|
*/
|
|
125
125
|
export async function fetchCards<T>(
|
|
126
126
|
source: string,
|
|
127
|
-
options?:
|
|
128
|
-
): Promise<
|
|
129
|
-
const client = api<
|
|
127
|
+
options?: ListOptionsType
|
|
128
|
+
): Promise<KanbanCardType<T>[]> {
|
|
129
|
+
const client = api<KanbanCardType<T>>(source);
|
|
130
130
|
|
|
131
131
|
// Build API options for cards query
|
|
132
|
-
const apiOptions:
|
|
132
|
+
const apiOptions: ListOptionsType = {
|
|
133
133
|
...options,
|
|
134
134
|
// Default sort by column and position if no sort specified - using correct API format
|
|
135
135
|
Sort: options?.Sort || [
|
|
@@ -138,7 +138,7 @@ export async function fetchCards<T>(
|
|
|
138
138
|
]
|
|
139
139
|
};
|
|
140
140
|
|
|
141
|
-
const response:
|
|
141
|
+
const response: ListResponseType<KanbanCardType<T>> = await client.list(apiOptions);
|
|
142
142
|
return response.Data;
|
|
143
143
|
}
|
|
144
144
|
|
|
@@ -147,11 +147,11 @@ export async function fetchCards<T>(
|
|
|
147
147
|
*/
|
|
148
148
|
export async function createCard<T>(
|
|
149
149
|
source: string,
|
|
150
|
-
card: Partial<
|
|
150
|
+
card: Partial<KanbanCardType<T>> & { columnId: string }
|
|
151
151
|
): Promise<string> {
|
|
152
|
-
const client = api<
|
|
152
|
+
const client = api<KanbanCardType<T>>(source);
|
|
153
153
|
|
|
154
|
-
const response:
|
|
154
|
+
const response: CreateUpdateResponseType = await client.create(card);
|
|
155
155
|
return response._id;
|
|
156
156
|
}
|
|
157
157
|
|
|
@@ -161,9 +161,9 @@ export async function createCard<T>(
|
|
|
161
161
|
export async function updateCard<T>(
|
|
162
162
|
source: string,
|
|
163
163
|
id: string,
|
|
164
|
-
updates: Partial<
|
|
164
|
+
updates: Partial<KanbanCardType<T>>
|
|
165
165
|
): Promise<void> {
|
|
166
|
-
const client = api<
|
|
166
|
+
const client = api<KanbanCardType<T>>(source);
|
|
167
167
|
await client.update(id, updates);
|
|
168
168
|
}
|
|
169
169
|
|
|
@@ -187,7 +187,7 @@ export async function moveCard<T>(
|
|
|
187
187
|
toColumnId: string,
|
|
188
188
|
position?: number
|
|
189
189
|
): Promise<void> {
|
|
190
|
-
const client = api<
|
|
190
|
+
const client = api<KanbanCardType<T>>(source);
|
|
191
191
|
|
|
192
192
|
const updates: any = {
|
|
193
193
|
columnId: toColumnId,
|
|
@@ -205,7 +205,7 @@ export async function reorderCards<T>(
|
|
|
205
205
|
cardIds: string[],
|
|
206
206
|
columnId: string
|
|
207
207
|
): Promise<void> {
|
|
208
|
-
const client = api<
|
|
208
|
+
const client = api<KanbanCardType<T>>(source);
|
|
209
209
|
|
|
210
210
|
// Update position for each card
|
|
211
211
|
const updates = cardIds.map((id, index) => ({
|
|
@@ -230,9 +230,9 @@ export async function reorderCards<T>(
|
|
|
230
230
|
*/
|
|
231
231
|
export async function bulkUpdateCards<T>(
|
|
232
232
|
source: string,
|
|
233
|
-
request:
|
|
233
|
+
request: BulkCardUpdateRequestType<T>
|
|
234
234
|
): Promise<void> {
|
|
235
|
-
const client = api<
|
|
235
|
+
const client = api<KanbanCardType<T>>(source);
|
|
236
236
|
|
|
237
237
|
await Promise.all(
|
|
238
238
|
request.updates.map(update =>
|
|
@@ -246,9 +246,9 @@ export async function bulkUpdateCards<T>(
|
|
|
246
246
|
*/
|
|
247
247
|
export async function bulkUpdateColumns<T>(
|
|
248
248
|
source: string,
|
|
249
|
-
request:
|
|
249
|
+
request: BulkColumnUpdateRequestType<T>
|
|
250
250
|
): Promise<void> {
|
|
251
|
-
const client = api<
|
|
251
|
+
const client = api<KanbanColumnType<T>>(source);
|
|
252
252
|
|
|
253
253
|
await Promise.all(
|
|
254
254
|
request.updates.map(update =>
|
|
@@ -266,7 +266,7 @@ export async function bulkMoveCards<T>(
|
|
|
266
266
|
toColumnId: string,
|
|
267
267
|
startPosition = 0
|
|
268
268
|
): Promise<void> {
|
|
269
|
-
const client = api<
|
|
269
|
+
const client = api<KanbanCardType<T>>(cardSource);
|
|
270
270
|
|
|
271
271
|
const updates = cardIds.map((cardId, index) => ({
|
|
272
272
|
cardId,
|
|
@@ -296,7 +296,7 @@ export async function getCardCount(
|
|
|
296
296
|
): Promise<number> {
|
|
297
297
|
const client = api(source);
|
|
298
298
|
|
|
299
|
-
const options:
|
|
299
|
+
const options: ListOptionsType = {
|
|
300
300
|
Filter: {
|
|
301
301
|
Operator: "And",
|
|
302
302
|
Condition: [
|
|
@@ -310,7 +310,7 @@ export async function getCardCount(
|
|
|
310
310
|
}
|
|
311
311
|
};
|
|
312
312
|
|
|
313
|
-
const response:
|
|
313
|
+
const response: CountResponseType = await client.count(options);
|
|
314
314
|
return response.Count;
|
|
315
315
|
}
|
|
316
316
|
|
|
@@ -319,10 +319,10 @@ export async function getCardCount(
|
|
|
319
319
|
*/
|
|
320
320
|
export async function getTotalCardCount(
|
|
321
321
|
source: string,
|
|
322
|
-
options?:
|
|
322
|
+
options?: ListOptionsType
|
|
323
323
|
): Promise<number> {
|
|
324
324
|
const client = api(source);
|
|
325
|
-
const response:
|
|
325
|
+
const response: CountResponseType = await client.count(options);
|
|
326
326
|
return response.Count;
|
|
327
327
|
}
|
|
328
328
|
|
|
@@ -332,11 +332,11 @@ export async function getTotalCardCount(
|
|
|
332
332
|
export async function searchCards<T>(
|
|
333
333
|
source: string,
|
|
334
334
|
searchQuery: string,
|
|
335
|
-
additionalOptions?:
|
|
336
|
-
): Promise<
|
|
337
|
-
const client = api<
|
|
335
|
+
additionalOptions?: ListOptionsType
|
|
336
|
+
): Promise<KanbanCardType<T>[]> {
|
|
337
|
+
const client = api<KanbanCardType<T>>(source);
|
|
338
338
|
|
|
339
|
-
const options:
|
|
339
|
+
const options: ListOptionsType = {
|
|
340
340
|
...additionalOptions,
|
|
341
341
|
Search: searchQuery,
|
|
342
342
|
Sort: additionalOptions?.Sort || [
|
|
@@ -345,7 +345,7 @@ export async function searchCards<T>(
|
|
|
345
345
|
]
|
|
346
346
|
};
|
|
347
347
|
|
|
348
|
-
const response:
|
|
348
|
+
const response: ListResponseType<KanbanCardType<T>> = await client.list(options);
|
|
349
349
|
return response.Data;
|
|
350
350
|
}
|
|
351
351
|
|
|
@@ -357,9 +357,9 @@ export async function searchCards<T>(
|
|
|
357
357
|
* Merge cards into their respective columns
|
|
358
358
|
*/
|
|
359
359
|
export function mergeCardsIntoColumns<T>(
|
|
360
|
-
columns:
|
|
361
|
-
cards:
|
|
362
|
-
):
|
|
360
|
+
columns: KanbanColumnType<T>[],
|
|
361
|
+
cards: KanbanCardType<T>[]
|
|
362
|
+
): KanbanColumnType<T>[] {
|
|
363
363
|
// Group cards by columnId
|
|
364
364
|
const cardsByColumn = cards.reduce((acc, card) => {
|
|
365
365
|
if (!acc[card.columnId]) {
|
|
@@ -367,7 +367,7 @@ export function mergeCardsIntoColumns<T>(
|
|
|
367
367
|
}
|
|
368
368
|
acc[card.columnId].push(card);
|
|
369
369
|
return acc;
|
|
370
|
-
}, {} as Record<string,
|
|
370
|
+
}, {} as Record<string, KanbanCardType<T>[]>);
|
|
371
371
|
|
|
372
372
|
// Assign cards to their respective columns
|
|
373
373
|
return columns.map(column => ({
|
|
@@ -381,7 +381,7 @@ export function mergeCardsIntoColumns<T>(
|
|
|
381
381
|
* Calculate optimal position for inserting a new card
|
|
382
382
|
*/
|
|
383
383
|
export function calculateCardPosition<T>(
|
|
384
|
-
column:
|
|
384
|
+
column: KanbanColumnType<T>,
|
|
385
385
|
insertIndex?: number
|
|
386
386
|
): number {
|
|
387
387
|
if (column.cards.length === 0) {
|
|
@@ -410,7 +410,7 @@ export function calculateCardPosition<T>(
|
|
|
410
410
|
* Calculate optimal position for inserting a new column
|
|
411
411
|
*/
|
|
412
412
|
export function calculateColumnPosition<T>(
|
|
413
|
-
columns:
|
|
413
|
+
columns: KanbanColumnType<T>[],
|
|
414
414
|
insertIndex?: number
|
|
415
415
|
): number {
|
|
416
416
|
if (columns.length === 0) {
|
|
@@ -478,7 +478,7 @@ export function handleKanbanApiError(
|
|
|
478
478
|
export function validateApiResponse<T>(
|
|
479
479
|
response: any,
|
|
480
480
|
expectedType: 'list' | 'single' | 'create' | 'delete'
|
|
481
|
-
): response is
|
|
481
|
+
): response is ListResponseType<T> | T | CreateUpdateResponseType | DeleteResponseType {
|
|
482
482
|
switch (expectedType) {
|
|
483
483
|
case 'list':
|
|
484
484
|
return response && Array.isArray(response.Data);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createContext, useContext } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { UseKanbanReturnType } from "./types";
|
|
3
3
|
|
|
4
|
-
export const KanbanContext = createContext<
|
|
4
|
+
export const KanbanContext = createContext<UseKanbanReturnType<any> | null>(null);
|
|
5
5
|
|
|
6
6
|
export function useKanbanContext<T extends Record<string, any> = any>() {
|
|
7
7
|
const context = useContext(KanbanContext);
|
|
@@ -10,5 +10,5 @@ export function useKanbanContext<T extends Record<string, any> = any>() {
|
|
|
10
10
|
"Kanban components must be used within a KanbanBoard component"
|
|
11
11
|
);
|
|
12
12
|
}
|
|
13
|
-
return context as
|
|
13
|
+
return context as UseKanbanReturnType<T>;
|
|
14
14
|
}
|