sitepaige-mcp-server 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/components/IntegrationComponent.tsx +1 -0
  2. package/components/admin.tsx +30 -27
  3. package/components/auth.tsx +9 -9
  4. package/components/cta.tsx +3 -10
  5. package/components/headerlogin.tsx +19 -37
  6. package/components/login.tsx +7 -4
  7. package/components/logincallback.tsx +1 -0
  8. package/components/menu.tsx +0 -6
  9. package/components/profile.tsx +304 -47
  10. package/defaultapp/api/Auth/resend-verification/route.ts +1 -1
  11. package/defaultapp/api/Auth/route.ts +39 -39
  12. package/defaultapp/api/Auth/signup/route.ts +1 -1
  13. package/defaultapp/api/Auth/verify-email/route.ts +6 -6
  14. package/defaultapp/api/admin/users/route.ts +5 -3
  15. package/defaultapp/api/profile/route.ts +154 -0
  16. package/defaultapp/auth/auth.ts +9 -9
  17. package/defaultapp/db-mysql.ts +1 -1
  18. package/defaultapp/db-postgres.ts +1 -1
  19. package/defaultapp/db-sqlite.ts +1 -1
  20. package/defaultapp/db-users.ts +64 -64
  21. package/defaultapp/profile/page.tsx +6 -0
  22. package/dist/blueprintWriter.js.map +1 -1
  23. package/dist/components/IntegrationComponent.tsx +1 -0
  24. package/dist/components/admin.tsx +30 -27
  25. package/dist/components/auth.tsx +9 -9
  26. package/dist/components/cta.tsx +3 -10
  27. package/dist/components/headerlogin.tsx +19 -37
  28. package/dist/components/login.tsx +7 -4
  29. package/dist/components/logincallback.tsx +1 -0
  30. package/dist/components/menu.tsx +0 -6
  31. package/dist/components/profile.tsx +304 -47
  32. package/dist/defaultapp/api/Auth/resend-verification/route.ts +1 -1
  33. package/dist/defaultapp/api/Auth/route.ts +39 -39
  34. package/dist/defaultapp/api/Auth/signup/route.ts +1 -1
  35. package/dist/defaultapp/api/Auth/verify-email/route.ts +6 -6
  36. package/dist/defaultapp/api/admin/users/route.ts +5 -3
  37. package/dist/defaultapp/api/profile/route.ts +154 -0
  38. package/dist/defaultapp/auth/auth.ts +9 -9
  39. package/dist/defaultapp/db-mysql.ts +1 -1
  40. package/dist/defaultapp/db-postgres.ts +1 -1
  41. package/dist/defaultapp/db-sqlite.ts +1 -1
  42. package/dist/defaultapp/db-users.ts +64 -64
  43. package/dist/defaultapp/profile/page.tsx +6 -0
  44. package/dist/generators/env-example-template.txt +4 -3
  45. package/dist/generators/sql.js +11 -3
  46. package/dist/generators/sql.js.map +1 -1
  47. package/dist/generators/views.js +2 -2
  48. package/dist/sitepaige.js +2 -1
  49. package/dist/sitepaige.js.map +1 -1
  50. package/package.json +1 -1
  51. package/defaultapp/admin/page.tsx +0 -6
@@ -59,6 +59,7 @@ export default function IntegrationComponent({
59
59
  headers: {
60
60
  'Content-Type': 'application/json',
61
61
  },
62
+ credentials: 'include',
62
63
  body: JSON.stringify({
63
64
  description: editedPrompt || 'Create integration code',
64
65
  projectId: projectId,
@@ -5,15 +5,15 @@ import { useRouter } from 'next/navigation';
5
5
 
6
6
  interface User {
7
7
  userid: string;
8
- OAuthID: string;
9
- Source: string;
10
- UserName: string;
11
- Email?: string;
12
- AvatarURL?: string;
13
- UserLevel: number;
14
- LastLoginDate: string;
15
- CreatedDate: string;
16
- IsActive: boolean;
8
+ oauthid: string;
9
+ source: string;
10
+ username: string;
11
+ email?: string;
12
+ avatarurl?: string;
13
+ userlevel: number;
14
+ lastlogindate: string;
15
+ createddate: string;
16
+ isactive: boolean;
17
17
  }
18
18
 
19
19
  interface UserStats {
@@ -46,7 +46,9 @@ export default function AdminPanel() {
46
46
  setError(null);
47
47
 
48
48
  // Fetch users - authorization is handled server-side via session cookie
49
- const response = await fetch('/api/admin/users');
49
+ const response = await fetch('/api/admin/users', {
50
+ credentials: 'include'
51
+ });
50
52
  if (!response.ok) {
51
53
  if (response.status === 401) {
52
54
  setError('Access denied. Admin privileges required.');
@@ -80,6 +82,7 @@ export default function AdminPanel() {
80
82
  headers: {
81
83
  'Content-Type': 'application/json',
82
84
  },
85
+ credentials: 'include',
83
86
  body: JSON.stringify({
84
87
  userId,
85
88
  permissionLevel: newLevel,
@@ -169,13 +172,13 @@ export default function AdminPanel() {
169
172
 
170
173
  // Filter users based on search and permission level
171
174
  const filteredUsers = users.filter(user => {
172
- const matchesSearch = user.UserName.toLowerCase().includes(searchTerm.toLowerCase()) ||
173
- (user.Email && user.Email.toLowerCase().includes(searchTerm.toLowerCase()));
175
+ const matchesSearch = user.username.toLowerCase().includes(searchTerm.toLowerCase()) ||
176
+ (user.email && user.email.toLowerCase().includes(searchTerm.toLowerCase()));
174
177
 
175
178
  const matchesFilter = filterLevel === 'all' ||
176
- (filterLevel === 'admin' && user.UserLevel === 2) ||
177
- (filterLevel === 'registered' && user.UserLevel === 1) ||
178
- (filterLevel === 'guest' && user.UserLevel === 0);
179
+ (filterLevel === 'admin' && user.userlevel === 2) ||
180
+ (filterLevel === 'registered' && user.userlevel === 1) ||
181
+ (filterLevel === 'guest' && user.userlevel === 0);
179
182
 
180
183
  return matchesSearch && matchesFilter;
181
184
  });
@@ -298,26 +301,26 @@ export default function AdminPanel() {
298
301
  <tr key={user.userid} className="hover:bg-gray-50">
299
302
  <td className="px-6 py-4 whitespace-nowrap">
300
303
  <div className="flex items-center">
301
- {user.AvatarURL ? (
304
+ {user.avatarurl ? (
302
305
  <img
303
306
  className="h-10 w-10 rounded-full"
304
- src={user.AvatarURL}
305
- alt={user.UserName}
307
+ src={user.avatarurl}
308
+ alt={user.username}
306
309
  />
307
310
  ) : (
308
311
  <div className="h-10 w-10 rounded-full bg-gray-300 flex items-center justify-center">
309
312
  <span className="text-gray-600 font-medium">
310
- {user.UserName.charAt(0).toUpperCase()}
313
+ {user.username.charAt(0).toUpperCase()}
311
314
  </span>
312
315
  </div>
313
316
  )}
314
317
  <div className="ml-4">
315
318
  <div className="text-sm font-medium text-gray-900">
316
- {user.UserName}
319
+ {user.username}
317
320
  </div>
318
- {user.Email && (
321
+ {user.email && (
319
322
  <div className="text-sm text-gray-500">
320
- {user.Email}
323
+ {user.email}
321
324
  </div>
322
325
  )}
323
326
  </div>
@@ -325,15 +328,15 @@ export default function AdminPanel() {
325
328
  </td>
326
329
  <td className="px-6 py-4 whitespace-nowrap">
327
330
  <span className="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">
328
- {user.Source}
331
+ {user.source}
329
332
  </span>
330
333
  </td>
331
334
  <td className="px-6 py-4 whitespace-nowrap">
332
335
  <select
333
- value={user.UserLevel}
336
+ value={user.userlevel}
334
337
  onChange={(e) => handlePermissionChange(user.userid, parseInt(e.target.value))}
335
338
  disabled={isUpdating === user.userid}
336
- className={`px-2 py-1 text-xs leading-5 font-semibold rounded-full ${getPermissionLevelColor(user.UserLevel)} cursor-pointer hover:opacity-80 disabled:opacity-50 disabled:cursor-not-allowed`}
339
+ className={`px-2 py-1 text-xs leading-5 font-semibold rounded-full ${getPermissionLevelColor(user.userlevel)} cursor-pointer hover:opacity-80 disabled:opacity-50 disabled:cursor-not-allowed`}
337
340
  >
338
341
  <option value={0}>Guest</option>
339
342
  <option value={1}>Registered User</option>
@@ -341,11 +344,11 @@ export default function AdminPanel() {
341
344
  </select>
342
345
  </td>
343
346
  <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
344
- {formatDate(user.LastLoginDate)}
347
+ {formatDate(user.lastlogindate)}
345
348
  </td>
346
349
  <td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
347
350
  <button
348
- onClick={() => handleDeleteUser(user.userid, user.UserName)}
351
+ onClick={() => handleDeleteUser(user.userid, user.username)}
349
352
  disabled={isDeleting === user.userid}
350
353
  className="text-red-600 hover:text-red-900 disabled:opacity-50 disabled:cursor-not-allowed"
351
354
  >
@@ -11,11 +11,11 @@ import { useUserStore } from '@/store/user';
11
11
 
12
12
  interface AuthProps {
13
13
  auth: {
14
- ID: string;
15
- UserName: string;
16
- AvatarURL: string;
17
- UserLevel: string;
18
- IsAdmin: boolean;
14
+ id: string;
15
+ username: string;
16
+ avatarurl: string;
17
+ userlevel: string;
18
+ isadmin: boolean;
19
19
  } | null;
20
20
  }
21
21
 
@@ -25,10 +25,10 @@ export default function Auth({ auth }: AuthProps) {
25
25
  useEffect(() => {
26
26
  if (auth) {
27
27
  setIsAuthenticated(true);
28
- setUserLevel(auth.UserLevel);
29
- setIsAdmin(auth.IsAdmin);
30
- setUserName(auth.UserName);
31
- setAvatarURL(auth.AvatarURL);
28
+ setUserLevel(auth.userlevel);
29
+ setIsAdmin(auth.isadmin);
30
+ setUserName(auth.username);
31
+ setAvatarURL(auth.avatarurl);
32
32
  } else {
33
33
  setIsAuthenticated(false);
34
34
  setUserLevel('0');
@@ -28,10 +28,9 @@ interface CTAData {
28
28
  interface RCTAProps {
29
29
  custom_view_description: string;
30
30
  onNavigate: (pageId: string) => void;
31
- isPaigeLoading?: boolean;
32
31
  }
33
32
 
34
- const RCTA: React.FC<RCTAProps> = ({ custom_view_description, onNavigate, isPaigeLoading = false }) => {
33
+ const RCTA: React.FC<RCTAProps> = ({ custom_view_description, onNavigate }) => {
35
34
  let ctaData: CTAData;
36
35
 
37
36
  try {
@@ -101,10 +100,6 @@ const RCTA: React.FC<RCTAProps> = ({ custom_view_description, onNavigate, isPaig
101
100
  };
102
101
 
103
102
  const handleButtonClick = (pageId: string) => {
104
- if (isPaigeLoading) {
105
- console.log('Navigation blocked: Paige is currently processing a request');
106
- return;
107
- }
108
103
  if (pageId) {
109
104
  onNavigate(pageId);
110
105
  }
@@ -175,11 +170,9 @@ const RCTA: React.FC<RCTAProps> = ({ custom_view_description, onNavigate, isPaig
175
170
  <button
176
171
  key={index}
177
172
  onClick={() => handleButtonClick(button.page)}
178
- className={`px-6 py-3 rounded-lg transition-all ${hoverClass} ${
179
- isPaigeLoading ? 'opacity-50 cursor-not-allowed' : ''
180
- } ${!button.page ? 'opacity-75 cursor-not-allowed' : ''}`}
173
+ className={`px-6 py-3 rounded-lg transition-all ${hoverClass} ${!button.page ? 'opacity-75 cursor-not-allowed' : ''}`}
181
174
  style={buttonStyles}
182
- disabled={isPaigeLoading || !button.page}
175
+ disabled={!button.page}
183
176
  >
184
177
  {button.buttonTitle || 'Button'}
185
178
  </button>
@@ -17,11 +17,11 @@ interface MenuItem {
17
17
 
18
18
  interface UserData {
19
19
  userid: string;
20
- UserName: string;
21
- AvatarURL: string;
22
- Email: string;
23
- UserLevel: number;
24
- IsAdmin: boolean;
20
+ username: string;
21
+ avatarurl: string;
22
+ email: string;
23
+ userlevel: number;
24
+ isadmin: boolean;
25
25
  }
26
26
 
27
27
  const getLocalizedText = (text: string, language: string = 'English'): string => {
@@ -45,7 +45,6 @@ const LoginSection: React.FC<LoginSectionProps> = ({ websiteLanguage = 'English'
45
45
  const [userData, setUserData] = useState<UserData | null>(null);
46
46
  const [isLoading, setIsLoading] = useState(true);
47
47
  const [isAuthenticated, setIsAuthenticated] = useState(false);
48
- const [profileMenuItems, setProfileMenuItems] = useState<MenuItem[]>([]);
49
48
  const userMenuRef = useRef<HTMLDivElement>(null);
50
49
 
51
50
  // Hardcoded values
@@ -53,33 +52,16 @@ const LoginSection: React.FC<LoginSectionProps> = ({ websiteLanguage = 'English'
53
52
  const align = 'Right' as "Left" | "Center" | "Right";
54
53
  const mobileViewMode = 'desktop' as 'desktop' | 'phone' | 'sm-tablet' | 'lg-tablet';
55
54
 
56
- // Load profile menu items from localStorage
57
- useEffect(() => {
58
- const loadProfileMenuItems = () => {
59
- try {
60
- const storedMenuData = localStorage.getItem('blueprint_profile_menu');
61
- if (storedMenuData) {
62
- const menuData = JSON.parse(storedMenuData);
63
- setProfileMenuItems(menuData);
64
- } else {
65
- // Default fallback menu items
66
- setProfileMenuItems([
67
- { label: 'Profile', link: '/profile' },
68
- { label: 'Settings', link: '/settings' }
69
- ]);
70
- }
71
- } catch (error) {
72
- console.error('Failed to load profile menu from localStorage:', error);
73
- // Default fallback menu items
74
- setProfileMenuItems([
75
- { label: 'Profile', link: '/profile' },
76
- { label: 'Settings', link: '/settings' }
77
- ]);
78
- }
79
- };
80
-
81
- loadProfileMenuItems();
82
- }, []);
55
+ // Build menu items based on user level
56
+ const profileMenuItems: MenuItem[] = [
57
+ { label: 'Dashboard', link: '/dashboard' },
58
+ { label: 'Profile', link: '/profile' }
59
+ ];
60
+
61
+ // Add Admin Dashboard only if user is an admin (userlevel == 2)
62
+ if (userData?.userlevel === 2) {
63
+ profileMenuItems.push({ label: 'Admin Dashboard', link: '/admin_dashboard' });
64
+ }
83
65
 
84
66
  // Fetch user authentication status and data
85
67
  useEffect(() => {
@@ -210,11 +192,11 @@ const LoginSection: React.FC<LoginSectionProps> = ({ websiteLanguage = 'English'
210
192
  className="flex items-center focus:outline-none relative group cursor-pointer"
211
193
  style={{ color: textColor }}
212
194
  >
213
- <span className="mr-2" style={{ color: textColor }}>{userData.UserName || getLocalizedText('Sample User', websiteLanguage)}</span>
195
+ <span className="mr-2" style={{ color: textColor }}>{userData.username || getLocalizedText('Sample User', websiteLanguage)}</span>
214
196
  <div className="relative">
215
- {userData.AvatarURL ? (
197
+ {userData.avatarurl ? (
216
198
  <img
217
- src={userData.AvatarURL}
199
+ src={userData.avatarurl}
218
200
  alt="User avatar"
219
201
  className="w-10 h-10 rounded-full"
220
202
  referrerPolicy="no-referrer"
@@ -222,7 +204,7 @@ const LoginSection: React.FC<LoginSectionProps> = ({ websiteLanguage = 'English'
222
204
  />
223
205
  ) : (
224
206
  <div className="w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-semibold">
225
- {userData.UserName ? userData.UserName.charAt(0).toUpperCase() : 'U'}
207
+ {userData.username ? userData.username.charAt(0).toUpperCase() : 'U'}
226
208
  </div>
227
209
  )}
228
210
  </div>
@@ -9,7 +9,7 @@ checked in the system build settings. It is safe to modify this file without it
9
9
  import React, { useState } from 'react';
10
10
 
11
11
  interface LoginProps {
12
- providers: ('apple' | 'facebook' | 'github' | 'google' | 'username')[];
12
+ providers: ('apple' | 'facebook' | 'github' | 'google' | 'userpass')[];
13
13
  }
14
14
 
15
15
  export default function Login({ providers }: LoginProps) {
@@ -62,6 +62,7 @@ export default function Login({ providers }: LoginProps) {
62
62
  headers: {
63
63
  'Content-Type': 'application/json'
64
64
  },
65
+ credentials: 'include', // Include cookies in request
65
66
  body: JSON.stringify({ email: resendEmail || email })
66
67
  });
67
68
 
@@ -101,6 +102,7 @@ export default function Login({ providers }: LoginProps) {
101
102
  headers: {
102
103
  'Content-Type': 'application/json'
103
104
  },
105
+ credentials: 'include', // Include cookies in request
104
106
  body: JSON.stringify({ email, password })
105
107
  });
106
108
 
@@ -121,7 +123,8 @@ export default function Login({ providers }: LoginProps) {
121
123
  headers: {
122
124
  'Content-Type': 'application/json'
123
125
  },
124
- body: JSON.stringify({ email, password, provider: 'username' })
126
+ credentials: 'include', // Include cookies in request
127
+ body: JSON.stringify({ email, password, provider: 'userpass' })
125
128
  });
126
129
 
127
130
  const data = await response.json();
@@ -145,8 +148,8 @@ export default function Login({ providers }: LoginProps) {
145
148
  }
146
149
  };
147
150
 
148
- const showUsernamePasswordForm = providers?.includes('username');
149
- const oauthProviders = providers?.filter(p => p !== 'username') || [];
151
+ const showUsernamePasswordForm = providers?.includes('userpass');
152
+ const oauthProviders = providers?.filter(p => p !== 'userpass') || [];
150
153
 
151
154
  return (
152
155
  <div className="flex flex-col items-center justify-center min-h-[500px] p-4">
@@ -44,6 +44,7 @@ export default function LoginCallback({ code, state }: LoginCallbackProps) {
44
44
  headers: {
45
45
  'Content-Type': 'application/json',
46
46
  },
47
+ credentials: 'include',
47
48
  body: JSON.stringify({
48
49
  code,
49
50
  provider
@@ -60,7 +60,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
60
60
  const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
61
61
  const [isMobile, setIsMobile] = useState(false);
62
62
  const [selectedPage, setSelectedPage] = useState<string | null>(null);
63
- const [isPaigeLoading, setIsPaigeLoading] = useState(false);
64
63
 
65
64
  // Handle case where menu is undefined/null
66
65
  if (!menu) {
@@ -230,7 +229,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
230
229
  items-center
231
230
  justify-center
232
231
  ${isSelected ? 'border-blue-600 bg-blue-50' : ''}
233
- ${isPaigeLoading ? 'opacity-50 cursor-not-allowed' : ''}
234
232
  `}>
235
233
  <h3
236
234
  className={`${isSelected ? 'font-bold' : 'font-medium'} text-gray-800`}
@@ -284,10 +282,6 @@ export default function Menu({ menu, onClick, pages = [] }: MenuProps) {
284
282
  href={linkUrl}
285
283
  onClick={(e) => {
286
284
  e.preventDefault();
287
- if (isPaigeLoading) {
288
- console.log('Navigation blocked: Paige is currently processing a request');
289
- return;
290
- }
291
285
  setSelectedPage(item.page);
292
286
  onClick?.();
293
287
  }}