Skip to content

Commit 1f86470

Browse files
committed
chore(dashboard): wrap up UI changes, use open source fonts
1 parent 47bdafc commit 1f86470

File tree

19 files changed

+142
-153
lines changed

19 files changed

+142
-153
lines changed

packages/apps/app-dashboard/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<link rel="preload" as="image" href="/vincent-main-logo.png" fetchpriority="high">
88

99
<!-- Fonts -->
10-
<link rel="stylesheet" href="/fonts/itc-avant-garde/medium/style.css">
10+
<link rel="stylesheet" href="/fonts/glacial-indifference/style.css">
1111
<link rel="stylesheet" href="/fonts/encode-sans-semi-expanded/style.css">
1212

1313
<!-- Favicon -->
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@font-face {
2+
font-family: 'Glacial Indifference';
3+
src: url('GlacialIndifference-Regular.otf') format('opentype');
4+
font-weight: normal;
5+
font-style: normal;
6+
font-display: swap;
7+
size-adjust: 115%;
8+
}
Binary file not shown.

packages/apps/app-dashboard/public/fonts/itc-avant-garde/medium/style.css

Lines changed: 0 additions & 9 deletions
This file was deleted.

packages/apps/app-dashboard/src/components/developer-dashboard/ability/wrappers/ui/UndeleteAbilityButton.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useEffect } from 'react';
22
import { useNavigate } from 'react-router-dom';
3+
import { RotateCcw } from 'lucide-react';
34
import { reactClient as vincentApiClient } from '@lit-protocol/vincent-registry-sdk';
45
import { StatusMessage } from '@/components/shared/ui/statusMessage';
56
import { getErrorMessage } from '@/utils/developer-dashboard/app-forms';
67
import Loading from '@/components/shared/ui/Loading';
7-
import { ArchiveRestore } from 'lucide-react';
88
import { Ability } from '@/types/developer-dashboard/appTypes';
9+
import { theme, fonts } from '@/components/user-dashboard/connect/ui/theme';
910

1011
interface UndeleteAbilityWrapperProps {
1112
ability: Ability;
@@ -54,11 +55,15 @@ export function UndeleteAbilityButton({ ability }: UndeleteAbilityWrapperProps)
5455

5556
return (
5657
<button
57-
onClick={() => handleSubmit()}
58-
className="inline-flex items-center gap-2 px-4 py-2 border border-green-200 dark:border-green-500/30 rounded-lg text-sm font-medium text-green-600 dark:text-green-400 bg-white dark:bg-neutral-800 hover:bg-green-50 dark:hover:bg-green-500/10 transition-colors relative z-10 !opacity-100 shadow-sm"
58+
onClick={(e) => {
59+
e.stopPropagation();
60+
handleSubmit();
61+
}}
62+
className={`inline-flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-xs font-medium transition-colors ${theme.itemBg} hover:bg-green-500/10 text-green-600 dark:text-green-400 border border-transparent hover:border-green-500/30`}
63+
style={fonts.body}
5964
>
60-
<ArchiveRestore className="h-4 w-4" />
61-
Undelete Ability
65+
<RotateCcw className="h-3.5 w-3.5" />
66+
Restore
6267
</button>
6368
);
6469
}

packages/apps/app-dashboard/src/components/developer-dashboard/app/wrappers/AppOverviewWrapper.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { useState, useEffect } from 'react';
22
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
33
import { reactClient as vincentApiClient } from '@lit-protocol/vincent-registry-sdk';
4+
import { getClient } from '@lit-protocol/vincent-contracts-sdk';
5+
import * as Sentry from '@sentry/react';
46

7+
import { initPkpSigner } from '@/utils/developer-dashboard/initPkpSigner';
8+
import useReadAuthInfo from '@/hooks/user-dashboard/useAuthInfo';
59
import { AppDetailsView } from '../views/AppDetailsView';
610
import { EditAppForm } from '../forms/EditAppForm';
711
import { CreateAppVersionForm } from '../forms/CreateAppVersionForm';
@@ -36,6 +40,7 @@ export function AppOverviewWrapper() {
3640
const [searchParams, setSearchParams] = useSearchParams();
3741
const [currentView, setCurrentView] = useState<ViewType>('details');
3842
const [isSubmitting, setIsSubmitting] = useState(false);
43+
const { authInfo, sessionSigs } = useReadAuthInfo();
3944

4045
const {
4146
data: app,
@@ -142,9 +147,37 @@ export function AppOverviewWrapper() {
142147
const handleDeleteAppSubmit = async () => {
143148
setIsSubmitting(true);
144149
try {
150+
const isPublished = blockchainAppData !== null;
151+
152+
// Step 1: Delete in registry (always do this)
145153
await deleteApp({ appId: Number(appId) }).unwrap();
146154

147-
// Success - navigate back to apps list immediately
155+
// Step 2: If published on-chain, also delete on-chain
156+
if (isPublished) {
157+
try {
158+
const pkpSigner = await initPkpSigner({ authInfo, sessionSigs });
159+
const client = getClient({ signer: pkpSigner });
160+
161+
await client.deleteApp({
162+
appId: Number(appId),
163+
});
164+
} catch (onChainError) {
165+
console.error('Failed to delete app on-chain:', onChainError);
166+
// If on-chain deletion fails, log to Sentry but still navigate away
167+
// The mismatch resolution UI will handle fixing the inconsistent state
168+
Sentry.captureException(onChainError, {
169+
extra: {
170+
context: 'AppOverviewWrapper.handleDeleteAppSubmit',
171+
appId: appId,
172+
registryDeleted: true,
173+
onChainDeleted: false,
174+
userPkp: authInfo?.userPKP?.ethAddress,
175+
},
176+
});
177+
}
178+
}
179+
180+
// Success - navigate back to apps list
148181
navigate('/developer/apps');
149182
} catch (error) {
150183
console.error('Failed to delete app:', error);

packages/apps/app-dashboard/src/components/developer-dashboard/app/wrappers/ui/AppPublishedButtons.tsx

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getClient } from '@lit-protocol/vincent-contracts-sdk';
55
import { reactClient as vincentApiClient } from '@lit-protocol/vincent-registry-sdk';
66
import { App } from '@/types/developer-dashboard/appTypes';
77
import { App as ContractApp } from '@lit-protocol/vincent-contracts-sdk';
8-
import MutationButtonStates, { SkeletonButton } from '@/components/shared/ui/MutationButtonStates';
8+
import MutationButtonStates from '@/components/shared/ui/MutationButtonStates';
99
import { AppMismatchResolution } from './AppMismatchResolution';
1010
import { initPkpSigner } from '@/utils/developer-dashboard/initPkpSigner';
1111
import useReadAuthInfo from '@/hooks/user-dashboard/useAuthInfo';
@@ -46,19 +46,19 @@ export function AppPublishedButtons({
4646
setIsProcessing(true);
4747

4848
try {
49-
// Step 1: Update registry
50-
await undeleteAppInRegistry({
51-
appId: appData.appId,
52-
});
53-
54-
// Step 2: Update on-chain
49+
// Step 1: Update on-chain first (if published)
5550
const pkpSigner = await initPkpSigner({ authInfo, sessionSigs });
5651
const client = getClient({ signer: pkpSigner });
5752

5853
await client.undeleteApp({
5954
appId: appData.appId,
6055
});
6156

57+
// Step 2: Update registry (only after on-chain succeeds)
58+
await undeleteAppInRegistry({
59+
appId: appData.appId,
60+
});
61+
6262
setSuccess(`App undeleted successfully!`);
6363

6464
setTimeout(() => {
@@ -198,24 +198,16 @@ export function AppPublishedButtons({
198198
)}
199199

200200
{/* Undelete button when deleted */}
201-
{registryDeleted &&
202-
(isLoading ? (
203-
<div className="flex items-center justify-center">
204-
<SkeletonButton />
205-
</div>
206-
) : (
207-
<ActionButton
208-
icon={RotateCcw}
209-
title="Undelete App"
210-
description="Restore this app to active status"
211-
onClick={handleUndelete}
212-
variant="success"
213-
iconBg="rgb(220 252 231)"
214-
iconColor="rgb(22 163 74)"
215-
borderColor="rgb(187 247 208 / 0.5)"
216-
hoverBorderColor="rgb(34 197 94)"
217-
/>
218-
))}
201+
{registryDeleted && (
202+
<ActionButton
203+
icon={RotateCcw}
204+
title="Undelete App"
205+
description="Restore this app to active status"
206+
onClick={handleUndelete}
207+
isLoading={isLoading}
208+
variant="success"
209+
/>
210+
)}
219211
</div>
220212
);
221213
}

packages/apps/app-dashboard/src/components/developer-dashboard/app/wrappers/ui/UndeleteAppButton.tsx

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { useEffect } from 'react';
22
import { useNavigate } from 'react-router-dom';
3+
import { ArchiveRestore } from 'lucide-react';
34
import { reactClient as vincentApiClient } from '@lit-protocol/vincent-registry-sdk';
5+
46
import { StatusMessage } from '@/components/shared/ui/statusMessage';
57
import { getErrorMessage } from '@/utils/developer-dashboard/app-forms';
6-
import Loading from '@/components/shared/ui/Loading';
7-
import { ArchiveRestore } from 'lucide-react';
88
import { App } from '@/types/developer-dashboard/appTypes';
9+
import { ActionButton } from '@/components/developer-dashboard/ui/ActionButton';
910

1011
interface UndeleteAppWrapperProps {
1112
app: App;
@@ -26,21 +27,15 @@ export function UndeleteAppButton({ app }: UndeleteAppWrapperProps) {
2627
}
2728
}, [isSuccess, data, app]);
2829

29-
// Loading states
30-
if (isLoading) return <Loading />;
31-
3230
// Error states
3331
if (!app) return <StatusMessage message={`App not found`} type="error" />;
3432

35-
// Mutation states
36-
if (isLoading) {
37-
return <StatusMessage message="Undeleting app..." type="info" />;
38-
}
39-
33+
// Success state
4034
if (isSuccess && data) {
4135
return <StatusMessage message="App undeleted successfully!" type="success" />;
4236
}
4337

38+
// Error state
4439
if (isError && error) {
4540
const errorMessage = getErrorMessage(error, 'Failed to undelete app');
4641
return <StatusMessage message={errorMessage} type="error" />;
@@ -53,12 +48,13 @@ export function UndeleteAppButton({ app }: UndeleteAppWrapperProps) {
5348
};
5449

5550
return (
56-
<button
57-
onClick={() => handleSubmit()}
58-
className="inline-flex items-center gap-2 px-4 py-2 border border-green-200 dark:border-green-500/30 rounded-lg text-sm font-medium text-green-600 dark:text-green-400 bg-white dark:bg-neutral-800 hover:bg-green-50 dark:hover:bg-green-500/10 transition-colors relative z-10 !opacity-100 shadow-sm"
59-
>
60-
<ArchiveRestore className="h-4 w-4" />
61-
Undelete App
62-
</button>
51+
<ActionButton
52+
icon={ArchiveRestore}
53+
title="Undelete App"
54+
description="Restore this application from the deleted state"
55+
onClick={handleSubmit}
56+
isLoading={isLoading}
57+
variant="success"
58+
/>
6359
);
6460
}
Lines changed: 4 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,11 @@
1-
import { useState } from 'react';
2-
import { useNavigate, useSearchParams } from 'react-router-dom';
1+
import { useNavigate } from 'react-router-dom';
32
import { useUserPolicies } from '@/hooks/developer-dashboard/policy/useUserPolicies';
43
import Loading from '@/components/shared/ui/Loading';
54
import { StatusMessage } from '@/components/shared/ui/statusMessage';
65
import { PolicyListView } from '../views/PolicyListView';
7-
import { CreatePolicyForm, type CreatePolicyFormData } from '../forms/CreatePolicyForm';
8-
import { reactClient as vincentApiClient } from '@lit-protocol/vincent-registry-sdk';
9-
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/shared/ui/dialog';
10-
import { fonts } from '@/components/user-dashboard/connect/ui/theme';
116

127
export function PoliciesWrapper() {
138
const navigate = useNavigate();
14-
const [searchParams, setSearchParams] = useSearchParams();
15-
const [isCreating, setIsCreating] = useState(false);
169

1710
const {
1811
data: policies,
@@ -21,63 +14,23 @@ export function PoliciesWrapper() {
2114
isError: policiesError,
2215
} = useUserPolicies();
2316

24-
const [createPolicy] = vincentApiClient.useCreatePolicyMutation();
25-
26-
// Check if we should open the create modal from URL
27-
const showCreateModal = searchParams.get('action') === 'create-policy';
28-
2917
// Loading states first
3018
if (policiesLoading) return <Loading />;
3119

3220
// Combined error states
3321
if (policiesError) return <StatusMessage message="Failed to load policies" type="error" />;
3422

35-
const handleOpenCreateModal = () => {
36-
setSearchParams({ action: 'create-policy' });
37-
};
38-
39-
const handleCloseCreateModal = () => {
40-
setSearchParams({});
41-
};
42-
43-
const handleCreatePolicy = async (data: CreatePolicyFormData) => {
44-
const { packageName, ...policyCreateData } = data;
45-
setIsCreating(true);
46-
try {
47-
const result = await createPolicy({
48-
packageName,
49-
policyCreate: { ...policyCreateData },
50-
}).unwrap();
51-
52-
setTimeout(() => {
53-
handleCloseCreateModal();
54-
navigate(`/developer/policies/policy/${encodeURIComponent(result.packageName)}`);
55-
}, 1500);
56-
} catch (error) {
57-
setIsCreating(false);
58-
throw error;
59-
}
23+
const handleNavigateToCreate = () => {
24+
navigate('/developer/policies/create-policy');
6025
};
6126

6227
return (
6328
<>
6429
<PolicyListView
6530
policies={policies}
6631
deletedPolicies={deletedPolicies}
67-
onCreatePolicy={handleOpenCreateModal}
32+
onCreatePolicy={handleNavigateToCreate}
6833
/>
69-
70-
{/* Create Policy Modal */}
71-
<Dialog open={showCreateModal} onOpenChange={handleCloseCreateModal}>
72-
<DialogContent className="max-w-4xl max-h-[90vh] overflow-y-auto bg-white dark:bg-gray-950">
73-
<DialogHeader>
74-
<DialogTitle className="text-lg font-semibold" style={fonts.heading}>
75-
Create New Policy
76-
</DialogTitle>
77-
</DialogHeader>
78-
<CreatePolicyForm onSubmit={handleCreatePolicy} isSubmitting={isCreating} />
79-
</DialogContent>
80-
</Dialog>
8134
</>
8235
);
8336
}

0 commit comments

Comments
 (0)