@taskforcehq/taskforce 0.3.301 → 0.3.303
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/Taskforce.module.css +37 -2
- package/dist/TaskforceCore.filter-persistence.test.js +1 -1
- package/dist/TaskforceCore.js +72 -33
- package/dist/TaskforceCore.test.js +848 -130
- package/dist/components/features/TaskSettings.js +14 -82
- package/dist/components/features/TaskSettings.test.js +33 -70
- package/dist/components/features/settings/TaxonomyLibraryManager.js +8 -2
- package/dist/components/features/settings/TaxonomyLibraryManager.test.js +1 -1
- package/dist/components/task/TaskActionHeader.js +6 -3
- package/dist/components/task/TaskCard.js +6 -3
- package/dist/components/task/TaskForm.js +2 -2
- package/dist/components/task/TaskForm.test.js +41 -2
- package/dist/components/task/TaskKanban.test.js +17 -0
- package/dist/components/ui/ReferenceBadgeButton.js +1 -1
- package/dist/components/views/PlansPage.d.ts +3 -1
- package/dist/components/views/PlansPage.js +109 -49
- package/dist/components/views/PlansPage.test.d.ts +1 -0
- package/dist/components/views/PlansPage.test.js +100 -0
- package/dist/components/views/StandaloneLayout.d.ts +1 -0
- package/dist/components/views/StandaloneLayout.js +473 -256
- package/dist/components/views/panels/PlanningDrawer.js +18 -1
- package/dist/components/views/standalone/modals/AccountHubModal.d.ts +48 -0
- package/dist/components/views/standalone/modals/AccountHubModal.js +36 -0
- package/dist/components/views/standalone/modals/AccountHubModal.test.d.ts +1 -0
- package/dist/components/views/standalone/modals/AccountHubModal.test.js +26 -0
- package/dist/components/views/standalone/modals/CreateWorkspaceConfirmModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/CreateWorkspaceConfirmModal.js +8 -0
- package/dist/components/views/standalone/modals/EditProfileModal.d.ts +26 -0
- package/dist/components/views/standalone/modals/EditProfileModal.js +10 -0
- package/dist/components/views/standalone/modals/HelpModal.d.ts +9 -0
- package/dist/components/views/standalone/modals/HelpModal.js +8 -0
- package/dist/components/views/standalone/modals/ScheduleWarningModal.d.ts +13 -0
- package/dist/components/views/standalone/modals/ScheduleWarningModal.js +6 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +61 -0
- package/dist/components/views/standalone/modals/SyncStatusModal.js +38 -0
- package/dist/components/views/standalone/modals/TeamManagementModal.d.ts +64 -0
- package/dist/components/views/standalone/modals/TeamManagementModal.js +10 -0
- package/dist/components/views/standalone/modals/types.d.ts +2 -0
- package/dist/components/views/standalone/modals/types.js +1 -0
- package/dist/components/views/teamManagementAccess.d.ts +1 -1
- package/dist/components/views/teamManagementAccess.js +2 -2
- package/dist/components/views/teamManagementAccess.test.js +3 -3
- package/dist/config/deployment.js +2 -2
- package/dist/config/deployment.test.js +5 -3
- package/dist/core/AiProfileService.js +7 -2
- package/dist/core/AiProfiles.test.js +19 -0
- package/dist/core/EntitlementsPolicy.test.js +2 -2
- package/dist/core/GlobalSettingsService.js +78 -18
- package/dist/core/PlanEntitlementService.d.ts +29 -5
- package/dist/core/PlanEntitlementService.js +297 -219
- package/dist/core/SignupMonetizationSettings.test.js +173 -49
- package/dist/core/SyncReconciliationService.d.ts +2 -0
- package/dist/core/SyncReconciliationService.js +3 -0
- package/dist/core/SystemAdmin.test.js +186 -96
- package/dist/core/TaskAuditTimeline.test.js +40 -0
- package/dist/core/Taskforce.d.ts +100 -10
- package/dist/core/Taskforce.ids.test.js +133 -0
- package/dist/core/Taskforce.js +459 -127
- package/dist/core/Taskforce.mcpAuth.test.js +0 -2
- package/dist/core/UserProfileAvatarDrafts.test.d.ts +1 -0
- package/dist/core/UserProfileAvatarDrafts.test.js +111 -0
- package/dist/core/taskReferencePolicy.d.ts +28 -0
- package/dist/core/taskReferencePolicy.js +189 -0
- package/dist/core/types.d.ts +13 -12
- package/dist/hooks/tasks/useTaskFormActions.js +3 -0
- package/dist/hooks/useSyncOrchestrator.js +17 -3
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +97 -5
- package/dist/hooks/useTaskData.js +3 -2
- package/dist/hooks/useTaskData.test.js +66 -0
- package/dist/hooks/useTaskforce.d.ts +8 -0
- package/dist/hooks/useTaskforce.js +72 -19
- package/dist/hooks/useTaskforce.sync-behavior.test.js +185 -6
- package/dist/mcp/aiProfileBootstrap.d.ts +29 -0
- package/dist/mcp/aiProfileBootstrap.js +80 -0
- package/dist/mcp/aiProfileBootstrap.test.d.ts +1 -0
- package/dist/mcp/aiProfileBootstrap.test.js +68 -0
- package/dist/mcp/clientIntegrations.d.ts +2 -8
- package/dist/mcp/clientIntegrations.js +21 -40
- package/dist/mcp/clientIntegrations.test.js +28 -2
- package/dist/mcp/clientProfileDefaults.d.ts +12 -0
- package/dist/mcp/clientProfileDefaults.js +37 -0
- package/dist/mcp/runtime.d.ts +10 -7
- package/dist/mcp/runtime.js +131 -48
- package/dist/mcp/runtime.test.js +321 -83
- package/dist/migrations/billingSchemaParity.test.js +3 -0
- package/dist/migrations/taskSchemaMigrations.js +68 -1
- package/dist/qaOpen.test.d.ts +1 -0
- package/dist/qaOpen.test.js +56 -0
- package/dist/server/index.cookieProxy.test.js +2 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +17 -1
- package/dist/server/index.test.js +15 -1
- package/dist/server/mockStripe.d.ts +1 -0
- package/dist/server/mockStripe.js +2 -0
- package/dist/server/routes/admin.js +105 -45
- package/dist/server/routes/auth.d.ts +6 -0
- package/dist/server/routes/auth.js +505 -30
- package/dist/server/routes/billing.js +517 -24
- package/dist/server/routes/billing.test.js +967 -45
- package/dist/server/routes/documents.js +6 -1
- package/dist/server/routes/shared.d.ts +1 -1
- package/dist/server/routes/shared.js +16 -6
- package/dist/server/routes/sync.integration.test.js +290 -0
- package/dist/server/routes/sync.js +234 -1922
- package/dist/server/routes/tasks.js +18 -4
- package/dist/server/routes.js +29 -22
- package/dist/server/routes.test.js +639 -82
- package/dist/shared/runtimeContract.d.ts +1 -1
- package/dist/sync/cloudSyncApi.d.ts +1 -0
- package/dist/sync/collaborationSyncPayload.d.ts +17 -0
- package/dist/sync/collaborationSyncPayload.js +131 -0
- package/dist/sync/collaborationSyncPayload.test.d.ts +1 -0
- package/dist/sync/collaborationSyncPayload.test.js +104 -0
- package/dist/sync/collaborationSyncState.d.ts +15 -0
- package/dist/sync/collaborationSyncState.js +60 -0
- package/dist/sync/contentSyncPayload.d.ts +45 -0
- package/dist/sync/contentSyncPayload.js +104 -0
- package/dist/sync/contentSyncPayload.test.d.ts +1 -0
- package/dist/sync/contentSyncPayload.test.js +104 -0
- package/dist/sync/contentSyncState.d.ts +98 -0
- package/dist/sync/contentSyncState.js +1004 -0
- package/dist/sync/planningSyncPayload.d.ts +9 -0
- package/dist/sync/planningSyncPayload.js +82 -0
- package/dist/sync/planningSyncPayload.test.d.ts +1 -0
- package/dist/sync/planningSyncPayload.test.js +68 -0
- package/dist/sync/syncApplyHandlers.d.ts +83 -0
- package/dist/sync/syncApplyHandlers.js +445 -0
- package/dist/sync/syncService.d.ts +1 -0
- package/dist/sync/syncService.js +21 -8
- package/dist/sync/taskSyncPayload.d.ts +33 -0
- package/dist/sync/taskSyncPayload.js +126 -0
- package/dist/sync/taskSyncPayload.test.d.ts +1 -0
- package/dist/sync/taskSyncPayload.test.js +54 -0
- package/dist/sync/workspacePullFeed.d.ts +38 -0
- package/dist/sync/workspacePullFeed.js +349 -0
- package/dist/sync/workspacePullFeed.test.d.ts +1 -0
- package/dist/sync/workspacePullFeed.test.js +278 -0
- package/dist/sync/workspaceSyncModel.d.ts +4 -1
- package/dist/sync/workspaceSyncModel.js +9 -2
- package/dist/sync/workspaceSyncModel.test.js +29 -0
- package/dist/test/setup.js +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/ui/assets/{AgentsModule-Bdq3T1Ts.js → AgentsModule-CpsTmrIW.js} +1 -1
- package/dist/ui/assets/{AnnotatedAttachmentWorkspace-jKUVo-PJ.js → AnnotatedAttachmentWorkspace-C_TmXZwA.js} +1 -1
- package/dist/ui/assets/{DocumentWorkspace-DuQa-uIC.js → DocumentWorkspace-C3GyzrWm.js} +2 -2
- package/dist/ui/assets/{InitiativesModule-C8Pi2VTk.js → InitiativesModule-4-Rh2K2n.js} +1 -1
- package/dist/ui/assets/PlansPage-BP7AYOqr.js +1 -0
- package/dist/ui/assets/TaskSettings-BOC5F6Ag.js +8 -0
- package/dist/ui/assets/{TaskSettings-BwB9NtmJ.css → TaskSettings-CnIBL_Eb.css} +1 -1
- package/dist/ui/assets/{WorkflowsModule-b6TLuHwJ.js → WorkflowsModule-CGk9s3NJ.js} +1 -1
- package/dist/ui/assets/index-CLIMgR6g.js +6 -0
- package/dist/ui/assets/index-DneETxcu.css +1 -0
- package/dist/ui/assets/{vendor-icons-QZyhEwgT.js → vendor-icons-pWocEipT.js} +1 -1
- package/dist/ui/index.html +3 -3
- package/dist/utils/accountProfileSummaryCache.d.ts +31 -0
- package/dist/utils/accountProfileSummaryCache.js +97 -0
- package/dist/utils/accountProfileSummaryCache.test.d.ts +1 -0
- package/dist/utils/accountProfileSummaryCache.test.js +63 -0
- package/dist/utils/taskActivity.js +17 -4
- package/dist/utils/taskActivity.test.js +27 -0
- package/dist/utils/taskNormalization.js +10 -2
- package/dist/utils/taskReferences.d.ts +11 -1
- package/dist/utils/taskReferences.js +33 -1
- package/package.json +4 -3
- package/scripts/qa-open-lib.mjs +175 -0
- package/scripts/qa-open-lib.mjs.d.ts +49 -0
- package/scripts/qa-open.mjs +352 -0
- package/dist/ui/assets/PlansPage-B6BDECSi.js +0 -1
- package/dist/ui/assets/TaskSettings-DUJgRTPU.js +0 -8
- package/dist/ui/assets/index-BiiF1cLQ.css +0 -1
- package/dist/ui/assets/index-xBWLPOEb.js +0 -6
|
@@ -173,6 +173,7 @@
|
|
|
173
173
|
display: inline-flex;
|
|
174
174
|
align-items: center;
|
|
175
175
|
justify-content: center;
|
|
176
|
+
gap: 6px;
|
|
176
177
|
background: var(--surface-page);
|
|
177
178
|
color: var(--text-secondary);
|
|
178
179
|
font-size: 12px;
|
|
@@ -185,6 +186,16 @@
|
|
|
185
186
|
margin-left: 8px;
|
|
186
187
|
}
|
|
187
188
|
|
|
189
|
+
.taskCountBadgeIcon {
|
|
190
|
+
flex: 0 0 auto;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.taskCountBadgeAlert {
|
|
194
|
+
color: #f87171;
|
|
195
|
+
border-color: color-mix(in srgb, #ef4444 45%, var(--border-default));
|
|
196
|
+
box-shadow: 0 0 10px rgba(239, 68, 68, 0.18);
|
|
197
|
+
}
|
|
198
|
+
|
|
188
199
|
.headerActions {
|
|
189
200
|
display: flex;
|
|
190
201
|
align-items: center;
|
|
@@ -595,7 +606,7 @@
|
|
|
595
606
|
}
|
|
596
607
|
|
|
597
608
|
.taskIdBadge {
|
|
598
|
-
display: flex;
|
|
609
|
+
display: inline-flex;
|
|
599
610
|
align-items: center;
|
|
600
611
|
gap: 5px;
|
|
601
612
|
background: color-mix(in srgb, var(--color-info, #3b82f6) 12%, transparent);
|
|
@@ -611,9 +622,20 @@
|
|
|
611
622
|
position: relative;
|
|
612
623
|
z-index: 5;
|
|
613
624
|
white-space: nowrap;
|
|
625
|
+
min-width: 0;
|
|
626
|
+
max-width: min(100%, 12rem);
|
|
614
627
|
box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-info, #3b82f6) 8%, transparent);
|
|
615
628
|
}
|
|
616
629
|
|
|
630
|
+
.taskIdBadgeLabel {
|
|
631
|
+
display: block;
|
|
632
|
+
min-width: 0;
|
|
633
|
+
max-width: 100%;
|
|
634
|
+
overflow: hidden;
|
|
635
|
+
text-overflow: ellipsis;
|
|
636
|
+
white-space: nowrap;
|
|
637
|
+
}
|
|
638
|
+
|
|
617
639
|
.taskIdBadge:hover {
|
|
618
640
|
background: color-mix(in srgb, var(--color-info, #3b82f6) 18%, transparent);
|
|
619
641
|
color: var(--color-info, #3b82f6);
|
|
@@ -2861,6 +2883,19 @@
|
|
|
2861
2883
|
line-height: 1;
|
|
2862
2884
|
}
|
|
2863
2885
|
|
|
2886
|
+
.taskHierarchyMeta {
|
|
2887
|
+
display: inline-flex;
|
|
2888
|
+
align-items: center;
|
|
2889
|
+
padding: 2px 8px;
|
|
2890
|
+
border-radius: 999px;
|
|
2891
|
+
border: 1px solid rgba(245, 158, 11, 0.24);
|
|
2892
|
+
background: rgba(245, 158, 11, 0.14);
|
|
2893
|
+
color: var(--text-secondary);
|
|
2894
|
+
font-size: 11px;
|
|
2895
|
+
font-weight: 600;
|
|
2896
|
+
line-height: 1.2;
|
|
2897
|
+
}
|
|
2898
|
+
|
|
2864
2899
|
.taskHierarchyAddBtn {
|
|
2865
2900
|
justify-content: center;
|
|
2866
2901
|
padding-inline: 6px;
|
|
@@ -3838,7 +3873,7 @@
|
|
|
3838
3873
|
.codeBlock {
|
|
3839
3874
|
margin: 0;
|
|
3840
3875
|
background: #1e1e2e !important;
|
|
3841
|
-
padding:
|
|
3876
|
+
padding: 14px 16px !important;
|
|
3842
3877
|
border: none !important;
|
|
3843
3878
|
overflow-x: auto;
|
|
3844
3879
|
border-radius: 0 !important;
|
|
@@ -91,7 +91,7 @@ function installFetchStub(persistedState, options) {
|
|
|
91
91
|
vi.stubGlobal('fetch', vi.fn((url, init) => {
|
|
92
92
|
const method = String(init?.method || 'GET').toUpperCase();
|
|
93
93
|
if (url.includes('/api/taskforce/auth/runtime-config')) {
|
|
94
|
-
return Promise.resolve({ ok: true, json: () => Promise.resolve({ config: { runtimeMode: 'local', workspaceMode: 'single-local', authSource: '
|
|
94
|
+
return Promise.resolve({ ok: true, json: () => Promise.resolve({ config: { runtimeMode: 'local', workspaceMode: 'single-local', authSource: 'cloud' } }) });
|
|
95
95
|
}
|
|
96
96
|
if (url.includes('/api/taskforce/auth/session')) {
|
|
97
97
|
return Promise.resolve({ ok: true, json: () => Promise.resolve({ authenticated: false, authRequiredForApi: false, userId: 'anonymous', email: '', workspaceId: 'default' }) });
|
package/dist/TaskforceCore.js
CHANGED
|
@@ -20,14 +20,6 @@ function isDebugModeEnabled() {
|
|
|
20
20
|
return runtimeOverride;
|
|
21
21
|
return typeof __DEBUG_MODE__ !== 'undefined' && __DEBUG_MODE__;
|
|
22
22
|
}
|
|
23
|
-
function buildDebugRegistrationCredentials() {
|
|
24
|
-
const suffix = Date.now().toString(36);
|
|
25
|
-
return {
|
|
26
|
-
email: `debug+${suffix}@example.com`,
|
|
27
|
-
password: 'DebugPass123!',
|
|
28
|
-
displayName: `Debug ${suffix.slice(-4).toUpperCase()}`
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
23
|
function defaultSetupTaxonomySections(pack) {
|
|
32
24
|
return {
|
|
33
25
|
categories: Boolean(pack?.categories?.length),
|
|
@@ -35,6 +27,16 @@ function defaultSetupTaxonomySections(pack) {
|
|
|
35
27
|
priorities: Boolean(pack?.priorities?.length),
|
|
36
28
|
};
|
|
37
29
|
}
|
|
30
|
+
function buildPlansPath(params = {}) {
|
|
31
|
+
const query = new URLSearchParams();
|
|
32
|
+
query.set('screen', 'plans');
|
|
33
|
+
for (const [key, value] of Object.entries(params)) {
|
|
34
|
+
const normalized = String(value || '').trim();
|
|
35
|
+
if (normalized)
|
|
36
|
+
query.set(key, normalized);
|
|
37
|
+
}
|
|
38
|
+
return `/?${query.toString()}`;
|
|
39
|
+
}
|
|
38
40
|
function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange, onHeaderMouseDown, isDragging, onClose, mode = 'standalone' }) {
|
|
39
41
|
const location = useLocation();
|
|
40
42
|
const routeQuery = useMemo(() => new URLSearchParams(location.search), [location.search]);
|
|
@@ -44,13 +46,15 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
44
46
|
const isPricingRoute = location.pathname === '/pricing';
|
|
45
47
|
const isPlansRoute = location.pathname === '/plans';
|
|
46
48
|
const isPlansScreen = location.pathname === '/' && String(routeQuery.get('screen') || '').trim().toLowerCase() === 'plans';
|
|
47
|
-
const planSelectionPath = '
|
|
49
|
+
const planSelectionPath = buildPlansPath({ gate: 'plan_selection_required' });
|
|
48
50
|
const navigate = useNavigate();
|
|
49
51
|
const [loginEmail, setLoginEmail] = useState('');
|
|
50
52
|
const [loginDisplayName, setLoginDisplayName] = useState('');
|
|
51
53
|
const [loginPassword, setLoginPassword] = useState('');
|
|
52
54
|
const [authMode, setAuthMode] = useState('login');
|
|
53
55
|
const [verificationToken, setVerificationToken] = useState('');
|
|
56
|
+
const [pendingVerificationWorkspaceSetupRequired, setPendingVerificationWorkspaceSetupRequired] = useState(false);
|
|
57
|
+
const [pendingVerificationRedirectPath, setPendingVerificationRedirectPath] = useState(null);
|
|
54
58
|
const [resetToken, setResetToken] = useState('');
|
|
55
59
|
const [inviteToken, setInviteToken] = useState('');
|
|
56
60
|
const [inviteEmail, setInviteEmail] = useState(null);
|
|
@@ -126,6 +130,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
126
130
|
&& !isPricingRoute
|
|
127
131
|
&& !isPlansRoute
|
|
128
132
|
&& !isPlansScreen;
|
|
133
|
+
const directRegistrationEnabled = cloudAuthConfigured;
|
|
129
134
|
const setupStep = useMemo(() => String(new URLSearchParams(location.search).get('step') || '').trim().toLowerCase(), [location.search]);
|
|
130
135
|
const setupIntent = useMemo(() => String(new URLSearchParams(location.search).get('intent') || '').trim().toLowerCase(), [location.search]);
|
|
131
136
|
const isCreateWorkspaceIntent = isSetupRoute && setupStep === 'workspace' && setupIntent === 'create-workspace';
|
|
@@ -207,12 +212,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
207
212
|
if (cancelled || !res.ok)
|
|
208
213
|
return;
|
|
209
214
|
const gate = String(payload?.gate || '').trim().toLowerCase();
|
|
210
|
-
if (gate !== 'ok' && gate !== 'plan_selection_required' && gate !== 'misconfigured' && gate !== 'missing_entitlement') {
|
|
215
|
+
if (gate !== 'ok' && gate !== 'plan_selection_required' && gate !== 'checkout_pending' && gate !== 'misconfigured' && gate !== 'missing_entitlement') {
|
|
211
216
|
setAccountAccessGate(null);
|
|
212
217
|
return;
|
|
213
218
|
}
|
|
214
219
|
setAccountAccessGate({
|
|
215
|
-
gate,
|
|
220
|
+
gate: gate,
|
|
216
221
|
canAccessApp: payload?.canAccessApp === true,
|
|
217
222
|
canAccessPlans: payload?.canAccessPlans !== false,
|
|
218
223
|
message: typeof payload?.message === 'string' ? payload.message : null
|
|
@@ -358,25 +363,51 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
358
363
|
return '/';
|
|
359
364
|
return raw;
|
|
360
365
|
}, [location.search]);
|
|
366
|
+
const resolvedSignupInterval = selectedSignupInterval === 'year' ? 'year' : 'month';
|
|
367
|
+
const resolvePostRegistrationPath = useCallback((input) => {
|
|
368
|
+
if (input?.planSelectionRequired || input?.commercialState === 'pending_plan_selection') {
|
|
369
|
+
return planSelectionPath;
|
|
370
|
+
}
|
|
371
|
+
if (input?.checkoutPending || input?.commercialState === 'checkout_pending') {
|
|
372
|
+
return buildPlansPath({
|
|
373
|
+
gate: 'checkout_pending',
|
|
374
|
+
checkout: selectedSignupPlanVersionId ? 'start' : null,
|
|
375
|
+
planId: selectedSignupPlanId || null,
|
|
376
|
+
planVersionId: selectedSignupPlanVersionId || null,
|
|
377
|
+
interval: selectedSignupPlanVersionId ? resolvedSignupInterval : null
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
return nextPath;
|
|
381
|
+
}, [
|
|
382
|
+
nextPath,
|
|
383
|
+
planSelectionPath,
|
|
384
|
+
resolvedSignupInterval,
|
|
385
|
+
selectedSignupPlanId,
|
|
386
|
+
selectedSignupPlanVersionId
|
|
387
|
+
]);
|
|
361
388
|
const loginRouteMode = useMemo(() => {
|
|
362
389
|
const modeRaw = String(new URLSearchParams(location.search).get('mode') || '').trim().toLowerCase();
|
|
363
|
-
if (modeRaw === 'register'
|
|
390
|
+
if (modeRaw === 'register') {
|
|
391
|
+
return directRegistrationEnabled ? 'register' : 'login';
|
|
392
|
+
}
|
|
393
|
+
if (modeRaw === 'verify' || modeRaw === 'forgot' || modeRaw === 'reset' || modeRaw === 'invite') {
|
|
364
394
|
return modeRaw;
|
|
365
395
|
}
|
|
366
396
|
return 'login';
|
|
367
|
-
}, [location.search]);
|
|
397
|
+
}, [directRegistrationEnabled, location.search]);
|
|
368
398
|
const loginRouteToken = useMemo(() => String(new URLSearchParams(location.search).get('token') || '').trim(), [location.search]);
|
|
369
399
|
const setLoginMode = useCallback((mode) => {
|
|
370
400
|
const params = new URLSearchParams(location.search);
|
|
371
|
-
|
|
401
|
+
const nextMode = mode === 'register' && !directRegistrationEnabled ? 'login' : mode;
|
|
402
|
+
if (nextMode === 'login') {
|
|
372
403
|
params.delete('mode');
|
|
373
404
|
}
|
|
374
405
|
else {
|
|
375
|
-
params.set('mode',
|
|
406
|
+
params.set('mode', nextMode);
|
|
376
407
|
}
|
|
377
408
|
const query = params.toString();
|
|
378
409
|
navigate(`/login${query ? `?${query}` : ''}`, { replace: true });
|
|
379
|
-
}, [location.search, navigate]);
|
|
410
|
+
}, [directRegistrationEnabled, location.search, navigate]);
|
|
380
411
|
const routeToWorkspaceSetupIfNeeded = useCallback(async (hintWorkspaceSetupRequired) => {
|
|
381
412
|
if (!workspaceSwitchingEnabled)
|
|
382
413
|
return false;
|
|
@@ -408,6 +439,14 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
408
439
|
if (loginRouteMode === 'invite' && loginRouteToken)
|
|
409
440
|
setInviteToken(loginRouteToken);
|
|
410
441
|
}, [isLoginRoute, loginRouteMode, loginRouteToken]);
|
|
442
|
+
useEffect(() => {
|
|
443
|
+
if (authMode === 'verify')
|
|
444
|
+
return;
|
|
445
|
+
if (isLoginRoute && loginRouteMode === 'verify')
|
|
446
|
+
return;
|
|
447
|
+
setPendingVerificationWorkspaceSetupRequired(false);
|
|
448
|
+
setPendingVerificationRedirectPath(null);
|
|
449
|
+
}, [authMode, isLoginRoute, loginRouteMode]);
|
|
411
450
|
useEffect(() => {
|
|
412
451
|
if (!isLoginRoute || authMode !== 'invite' || !inviteToken.trim())
|
|
413
452
|
return;
|
|
@@ -625,15 +664,7 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
625
664
|
? 'New password'
|
|
626
665
|
: (authMode === 'invite'
|
|
627
666
|
? (invitePasswordRequired ? 'Create password' : 'Password')
|
|
628
|
-
: 'Password'), onChange: (event) => setLoginPassword(event.target.value) })), authMode === '
|
|
629
|
-
const credentials = buildDebugRegistrationCredentials();
|
|
630
|
-
setLoginEmail(credentials.email);
|
|
631
|
-
setLoginDisplayName(credentials.displayName);
|
|
632
|
-
setLoginPassword(credentials.password);
|
|
633
|
-
setLoginNotice(null);
|
|
634
|
-
setLoginError(null);
|
|
635
|
-
setLoginErrorCode(null);
|
|
636
|
-
}, children: "Fill Form" })), authMode === 'verify' && (_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: verificationToken, placeholder: "Verification token", onChange: (event) => setVerificationToken(event.target.value) })), authMode === 'reset' && (_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: resetToken, placeholder: "Reset token", onChange: (event) => setResetToken(event.target.value) })), authMode === 'invite' && (_jsxs(_Fragment, { children: [_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: inviteToken, placeholder: "Invite token", onChange: (event) => setInviteToken(event.target.value) }), inviteEmail && (_jsxs("p", { className: authStyles.loginSubtitle, children: ["Invite for: ", _jsx("strong", { children: inviteEmail }), inviteWorkspaceId ? ` · Workspace: ${inviteWorkspaceId}` : ''] }))] })), loginNotice && _jsx("p", { className: authStyles.loginSubtitle, children: loginNotice }), loginError && _jsx("p", { className: authStyles.loginError, children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
|
|
667
|
+
: 'Password'), onChange: (event) => setLoginPassword(event.target.value) })), authMode === 'verify' && (_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: verificationToken, placeholder: "Verification token", onChange: (event) => setVerificationToken(event.target.value) })), authMode === 'reset' && (_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: resetToken, placeholder: "Reset token", onChange: (event) => setResetToken(event.target.value) })), authMode === 'invite' && (_jsxs(_Fragment, { children: [_jsx("input", { className: `${styles.input} ${authStyles.loginInput}`, type: "text", value: inviteToken, placeholder: "Invite token", onChange: (event) => setInviteToken(event.target.value) }), inviteEmail && (_jsxs("p", { className: authStyles.loginSubtitle, children: ["Invite for: ", _jsx("strong", { children: inviteEmail }), inviteWorkspaceId ? ` · Workspace: ${inviteWorkspaceId}` : ''] }))] })), loginNotice && _jsx("p", { className: authStyles.loginSubtitle, children: loginNotice }), loginError && _jsx("p", { className: authStyles.loginError, children: loginError }), authMode === 'login' && loginErrorCode === 'EMAIL_NOT_VERIFIED' && loginEmail.trim() && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: async () => {
|
|
637
668
|
setLoginBusy(true);
|
|
638
669
|
setLoginNotice(null);
|
|
639
670
|
const sent = await requestEmailVerification(loginEmail);
|
|
@@ -721,11 +752,10 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
721
752
|
}
|
|
722
753
|
}
|
|
723
754
|
else if (authMode === 'register') {
|
|
724
|
-
|
|
725
|
-
setLoginBusy(false);
|
|
726
|
-
return;
|
|
727
|
-
}
|
|
755
|
+
const postRegistrationPath = resolvePostRegistrationPath(result);
|
|
728
756
|
if (result.verificationRequired) {
|
|
757
|
+
setPendingVerificationWorkspaceSetupRequired(Boolean(result.workspaceSetupRequired));
|
|
758
|
+
setPendingVerificationRedirectPath(postRegistrationPath);
|
|
729
759
|
if (result.verificationToken)
|
|
730
760
|
setVerificationToken(result.verificationToken);
|
|
731
761
|
setVerifyCooldownUntil(Date.now() + 30_000);
|
|
@@ -735,17 +765,26 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
735
765
|
: 'Account created. Check your email for verification instructions.');
|
|
736
766
|
}
|
|
737
767
|
else {
|
|
768
|
+
await retryBootstrapChecks();
|
|
769
|
+
if (await routeToWorkspaceSetupIfNeeded(result.workspaceSetupRequired)) {
|
|
770
|
+
setLoginBusy(false);
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
738
773
|
setLoginEmail('');
|
|
739
774
|
setLoginDisplayName('');
|
|
740
775
|
setLoginPassword('');
|
|
741
|
-
navigate(
|
|
776
|
+
navigate(postRegistrationPath, { replace: true });
|
|
742
777
|
}
|
|
743
778
|
}
|
|
744
779
|
else if (authMode === 'verify') {
|
|
745
780
|
await retryBootstrapChecks();
|
|
781
|
+
if (await routeToWorkspaceSetupIfNeeded(pendingVerificationWorkspaceSetupRequired)) {
|
|
782
|
+
setLoginBusy(false);
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
746
785
|
setLoginEmail('');
|
|
747
786
|
setLoginPassword('');
|
|
748
|
-
navigate(nextPath, { replace: true });
|
|
787
|
+
navigate(pendingVerificationRedirectPath || nextPath, { replace: true });
|
|
749
788
|
}
|
|
750
789
|
else if (authMode === 'forgot') {
|
|
751
790
|
if (result.resetToken)
|
|
@@ -810,12 +849,12 @@ function TaskforceCoreWithRouter({ config = {}, initialTaskId, onTaskCountChange
|
|
|
810
849
|
? 'Reset Password'
|
|
811
850
|
: (inviteResolution === 'existing_user_signed_out'
|
|
812
851
|
? 'Sign In to Continue'
|
|
813
|
-
: (invitePasswordRequired ? 'Create Account and Join' : 'Join Workspace'))) }), authMode === 'register' && (_jsxs("p", { className: authStyles.registerConsent, children: ["By creating an account, you agree to the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/terms", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/privacy", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }), "."] })), (authMode === 'login' || authMode === 'register') && (_jsxs("p", { className: authStyles.authModeSwitch, children: [authMode === 'login' ? 'Need an account?' : 'Already have an account?', ' ', _jsx("button", { className: authStyles.authModeSwitchLink, disabled: loginBusy, onClick: () => {
|
|
852
|
+
: (invitePasswordRequired ? 'Create Account and Join' : 'Join Workspace'))) }), authMode === 'register' && (_jsxs("p", { className: authStyles.registerConsent, children: ["By creating an account, you agree to the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/terms", target: "_blank", rel: "noopener noreferrer", children: "Terms of Service" }), ' ', "and acknowledge the", ' ', _jsx("a", { className: authStyles.registerConsentLink, href: "https://taskforcehq.com/legal/privacy", target: "_blank", rel: "noopener noreferrer", children: "Privacy Policy" }), "."] })), directRegistrationEnabled && (authMode === 'login' || authMode === 'register') && (_jsxs("p", { className: authStyles.authModeSwitch, children: [authMode === 'login' ? 'Need an account?' : 'Already have an account?', ' ', _jsx("button", { className: authStyles.authModeSwitchLink, disabled: loginBusy, onClick: () => {
|
|
814
853
|
setLoginError(null);
|
|
815
854
|
setLoginErrorCode(null);
|
|
816
855
|
setLoginNotice(null);
|
|
817
856
|
setLoginMode(authMode === 'login' ? 'register' : 'login');
|
|
818
|
-
}, children: authMode === 'login' ? 'Register' : 'Sign In' })] })), _jsxs("div", { className: authStyles.authModeLinks, children: [(authMode === 'login' || authMode === 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('verify'); }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('invite'); }, children: "Accept Invite" })] })), (authMode !== 'login' && authMode !== 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('login'); }, children: "Sign In" }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('register'); }, children: "Register" }), authMode === 'reset' && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }))] }))] })] }) }) }));
|
|
857
|
+
}, children: authMode === 'login' ? 'Register' : 'Sign In' })] })), _jsxs("div", { className: authStyles.authModeLinks, children: [(authMode === 'login' || authMode === 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || verifyCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('verify'); }, children: verifyCooldownActive ? `Resend Verification (${verifyCooldownSeconds}s)` : 'Resend Verification' }), _jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('invite'); }, children: "Accept Invite" })] })), (authMode !== 'login' && authMode !== 'register') && (_jsxs(_Fragment, { children: [_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('login'); }, children: "Sign In" }), directRegistrationEnabled && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('register'); }, children: "Register" })), authMode === 'reset' && (_jsx("button", { className: authStyles.authModeLink, disabled: loginBusy || resetCooldownActive, onClick: () => { setLoginError(null); setLoginErrorCode(null); setLoginNotice(null); setLoginMode('forgot'); }, children: resetCooldownActive ? `Forgot Password (${resetCooldownSeconds}s)` : 'Forgot Password' }))] }))] })] }) }) }));
|
|
819
858
|
}
|
|
820
859
|
if (shouldForceLogin && !isLoginRoute) {
|
|
821
860
|
return (_jsx("div", { className: shellStyles.standaloneWrapper, "data-theme": currentTheme, children: _jsx("div", { className: authStyles.loginView, children: _jsxs("div", { className: authStyles.loginCard, children: [_jsxs("div", { className: authStyles.authBrandRow, children: [_jsx("img", { src: authBrandLogo, alt: "Taskforce", className: authStyles.loginLogo }), _jsx("h1", { className: authStyles.loginTitle, children: "Loading Taskforce" })] }), _jsx("p", { className: authStyles.loginSubtitle, children: "Redirecting to sign in..." })] }) }) }));
|