@makolabs/ripple 1.2.4 → 1.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/pagination/Pagination.svelte +1 -1
- package/dist/layout/table/Table.svelte +0 -1
- package/dist/layout/table/table.js +7 -7
- package/dist/user-management/UserManagement.svelte +117 -32
- package/dist/user-management/UserManagementTestWrapper.svelte +22 -36
- package/dist/user-management/UserManagementTestWrapper.svelte.d.ts +7 -1
- package/dist/user-management/UserModal.svelte +55 -19
- package/dist/user-management/UserViewModal.svelte +0 -6
- package/dist/user-management/adapters/UserManagement.remote.d.ts +68 -0
- package/dist/user-management/adapters/UserManagement.remote.js +487 -0
- package/dist/user-management/adapters/index.d.ts +10 -0
- package/dist/user-management/adapters/index.js +12 -0
- package/dist/user-management/adapters/mockUserManagement.d.ts +70 -0
- package/dist/user-management/adapters/mockUserManagement.js +187 -0
- package/dist/user-management/adapters/types.d.ts +24 -0
- package/dist/user-management/adapters/types.js +7 -0
- package/dist/user-management/index.d.ts +2 -0
- package/dist/user-management/user-management.d.ts +42 -15
- package/package.json +2 -1
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock User Management Functions
|
|
3
|
+
*
|
|
4
|
+
* Mock implementation of user management functions for testing and development.
|
|
5
|
+
* These are regular async functions that match the UserManagementAdapter interface.
|
|
6
|
+
* They store data in memory.
|
|
7
|
+
*
|
|
8
|
+
* Note: This file uses .remote.ts extension for naming consistency, but these are
|
|
9
|
+
* NOT actual SvelteKit remote functions. They are regular async functions that
|
|
10
|
+
* work in both test and library contexts.
|
|
11
|
+
*
|
|
12
|
+
* For actual remote functions in your app, see UserManagement.remote.ts template.
|
|
13
|
+
*
|
|
14
|
+
* To set initial data, use the resetState function:
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { resetState } from './mockUserManagement.js';
|
|
17
|
+
* await resetState({ initialUsers: [...], simulateDelay: false });
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
// Internal module-level state
|
|
21
|
+
let mockUsers = [];
|
|
22
|
+
let simulateDelay = false;
|
|
23
|
+
let delayMs = 300;
|
|
24
|
+
async function delay() {
|
|
25
|
+
if (simulateDelay) {
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Reset mock adapter state
|
|
31
|
+
*/
|
|
32
|
+
export async function resetState(options = {}) {
|
|
33
|
+
mockUsers = options.initialUsers || [];
|
|
34
|
+
simulateDelay = options.simulateDelay ?? false;
|
|
35
|
+
delayMs = options.delayMs ?? 300;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get users with pagination and sorting
|
|
39
|
+
* Matches UserManagementAdapter.getUsers signature
|
|
40
|
+
*/
|
|
41
|
+
export async function getUsers(options) {
|
|
42
|
+
await delay();
|
|
43
|
+
let filteredUsers = [...mockUsers];
|
|
44
|
+
// Apply search query if provided
|
|
45
|
+
if (options.query) {
|
|
46
|
+
const query = options.query.toLowerCase();
|
|
47
|
+
filteredUsers = filteredUsers.filter((user) => user.first_name?.toLowerCase().includes(query) ||
|
|
48
|
+
user.last_name?.toLowerCase().includes(query) ||
|
|
49
|
+
user.username?.toLowerCase().includes(query) ||
|
|
50
|
+
user.email_addresses?.[0]?.email_address?.toLowerCase().includes(query));
|
|
51
|
+
}
|
|
52
|
+
// Apply sorting
|
|
53
|
+
if (options.sortBy) {
|
|
54
|
+
filteredUsers.sort((a, b) => {
|
|
55
|
+
let aValue = '';
|
|
56
|
+
let bValue = '';
|
|
57
|
+
switch (options.sortBy) {
|
|
58
|
+
case 'first_name':
|
|
59
|
+
aValue = a.first_name || '';
|
|
60
|
+
bValue = b.first_name || '';
|
|
61
|
+
break;
|
|
62
|
+
case 'last_name':
|
|
63
|
+
aValue = a.last_name || '';
|
|
64
|
+
bValue = b.last_name || '';
|
|
65
|
+
break;
|
|
66
|
+
case 'email_address':
|
|
67
|
+
aValue = a.email_addresses?.[0]?.email_address || '';
|
|
68
|
+
bValue = b.email_addresses?.[0]?.email_address || '';
|
|
69
|
+
break;
|
|
70
|
+
case 'created_at':
|
|
71
|
+
aValue = a.created_at || 0;
|
|
72
|
+
bValue = b.created_at || 0;
|
|
73
|
+
break;
|
|
74
|
+
case 'last_sign_in_at':
|
|
75
|
+
aValue = a.last_sign_in_at || 0;
|
|
76
|
+
bValue = b.last_sign_in_at || 0;
|
|
77
|
+
break;
|
|
78
|
+
default:
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
if (typeof aValue === 'string' && typeof bValue === 'string') {
|
|
82
|
+
return options.sortOrder === 'desc'
|
|
83
|
+
? bValue.localeCompare(aValue)
|
|
84
|
+
: aValue.localeCompare(bValue);
|
|
85
|
+
}
|
|
86
|
+
else if (typeof aValue === 'number' && typeof bValue === 'number') {
|
|
87
|
+
return options.sortOrder === 'desc' ? bValue - aValue : aValue - bValue;
|
|
88
|
+
}
|
|
89
|
+
return 0;
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// Apply pagination
|
|
93
|
+
const start = (options.page - 1) * options.pageSize;
|
|
94
|
+
const end = start + options.pageSize;
|
|
95
|
+
const paginatedUsers = filteredUsers.slice(start, end);
|
|
96
|
+
return {
|
|
97
|
+
users: paginatedUsers,
|
|
98
|
+
totalUsers: filteredUsers.length
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create a new user
|
|
103
|
+
* Matches UserManagementAdapter.createUser signature
|
|
104
|
+
*/
|
|
105
|
+
export async function createUser(userData) {
|
|
106
|
+
await delay();
|
|
107
|
+
const newUser = {
|
|
108
|
+
id: `user_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
109
|
+
first_name: userData.first_name || '',
|
|
110
|
+
last_name: userData.last_name || '',
|
|
111
|
+
username: userData.username,
|
|
112
|
+
email_addresses: userData.email_addresses || [{ email_address: '' }],
|
|
113
|
+
phone_numbers: userData.phone_numbers || [],
|
|
114
|
+
role: userData.role,
|
|
115
|
+
permissions: userData.permissions || [],
|
|
116
|
+
created_at: Date.now(),
|
|
117
|
+
...userData
|
|
118
|
+
};
|
|
119
|
+
mockUsers.push(newUser);
|
|
120
|
+
return newUser;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Update an existing user
|
|
124
|
+
* Matches UserManagementAdapter.updateUser signature
|
|
125
|
+
*/
|
|
126
|
+
export async function updateUser(options) {
|
|
127
|
+
await delay();
|
|
128
|
+
const { userId, userData } = options;
|
|
129
|
+
const userIndex = mockUsers.findIndex((u) => u.id === userId);
|
|
130
|
+
if (userIndex === -1) {
|
|
131
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
132
|
+
}
|
|
133
|
+
const updatedUser = {
|
|
134
|
+
...mockUsers[userIndex],
|
|
135
|
+
...userData,
|
|
136
|
+
id: userId // Ensure ID doesn't change
|
|
137
|
+
};
|
|
138
|
+
mockUsers[userIndex] = updatedUser;
|
|
139
|
+
return updatedUser;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Delete a single user
|
|
143
|
+
* Matches UserManagementAdapter.deleteUser signature
|
|
144
|
+
*/
|
|
145
|
+
export async function deleteUser(userId) {
|
|
146
|
+
await delay();
|
|
147
|
+
const userIndex = mockUsers.findIndex((u) => u.id === userId);
|
|
148
|
+
if (userIndex === -1) {
|
|
149
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
150
|
+
}
|
|
151
|
+
mockUsers.splice(userIndex, 1);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Delete multiple users
|
|
155
|
+
* Matches UserManagementAdapter.deleteUsers signature
|
|
156
|
+
*/
|
|
157
|
+
export async function deleteUsers(userIds) {
|
|
158
|
+
await delay();
|
|
159
|
+
userIds.forEach((userId) => {
|
|
160
|
+
const userIndex = mockUsers.findIndex((u) => u.id === userId);
|
|
161
|
+
if (userIndex !== -1) {
|
|
162
|
+
mockUsers.splice(userIndex, 1);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Get permissions for a specific user
|
|
168
|
+
* Matches UserManagementAdapter.getUserPermissions signature
|
|
169
|
+
*/
|
|
170
|
+
export async function getUserPermissions(userId) {
|
|
171
|
+
await delay();
|
|
172
|
+
const user = mockUsers.find((u) => u.id === userId);
|
|
173
|
+
return user?.permissions || [];
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Update permissions for a specific user
|
|
177
|
+
* Matches UserManagementAdapter.updateUserPermissions signature
|
|
178
|
+
*/
|
|
179
|
+
export async function updateUserPermissions(options) {
|
|
180
|
+
await delay();
|
|
181
|
+
const { userId, permissions } = options;
|
|
182
|
+
const user = mockUsers.find((u) => u.id === userId);
|
|
183
|
+
if (!user) {
|
|
184
|
+
throw new Error(`User with ID ${userId} not found`);
|
|
185
|
+
}
|
|
186
|
+
user.permissions = permissions;
|
|
187
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User Management Adapter Types
|
|
3
|
+
*
|
|
4
|
+
* Shared types for user management adapters.
|
|
5
|
+
* These types are used by both remote function modules and the component.
|
|
6
|
+
*/
|
|
7
|
+
import type { User } from '../user-management.js';
|
|
8
|
+
/**
|
|
9
|
+
* Options for fetching users
|
|
10
|
+
*/
|
|
11
|
+
export interface GetUsersOptions {
|
|
12
|
+
page: number;
|
|
13
|
+
pageSize: number;
|
|
14
|
+
sortBy?: string;
|
|
15
|
+
sortOrder?: 'asc' | 'desc';
|
|
16
|
+
query?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Result of fetching users
|
|
20
|
+
*/
|
|
21
|
+
export interface GetUsersResult {
|
|
22
|
+
users: User[];
|
|
23
|
+
totalUsers: number;
|
|
24
|
+
}
|
|
@@ -7,4 +7,6 @@ export { default as UserTable } from './UserTable.svelte';
|
|
|
7
7
|
export { default as UserModal } from './UserModal.svelte';
|
|
8
8
|
export { default as UserViewModal } from './UserViewModal.svelte';
|
|
9
9
|
export type { User, UserEmail, UserPhone, Permission, Role, UserTableProps, UserModalProps, UserViewModalProps, UserManagementProps, FormErrors } from './user-management.js';
|
|
10
|
+
export type { GetUsersOptions, GetUsersResult } from './adapters/index.js';
|
|
11
|
+
export type { UserManagementAdapter } from './user-management.js';
|
|
10
12
|
export { createUser, getUserDisplayName, getUserInitials } from './user-management.js';
|
|
@@ -71,24 +71,51 @@ export interface UserViewModalProps {
|
|
|
71
71
|
onClose: () => void;
|
|
72
72
|
class?: ClassValue;
|
|
73
73
|
}
|
|
74
|
+
import type { GetUsersOptions, GetUsersResult } from './adapters/types.js';
|
|
75
|
+
/**
|
|
76
|
+
* User Management Adapter Interface
|
|
77
|
+
*
|
|
78
|
+
* Defines the contract for user management adapters.
|
|
79
|
+
* Adapters can be remote function modules (returning RemoteQuery/RemoteCommand)
|
|
80
|
+
* or regular async function modules (returning Promise).
|
|
81
|
+
*
|
|
82
|
+
* Uses PromiseLike to accept both Promise and RemoteQuery/RemoteCommand types.
|
|
83
|
+
*/
|
|
84
|
+
export interface UserManagementAdapter {
|
|
85
|
+
getUsers: (options: GetUsersOptions) => PromiseLike<GetUsersResult>;
|
|
86
|
+
createUser: (userData: Partial<User>) => PromiseLike<User>;
|
|
87
|
+
updateUser: (options: {
|
|
88
|
+
userId: string;
|
|
89
|
+
userData: Partial<User>;
|
|
90
|
+
}) => PromiseLike<User>;
|
|
91
|
+
deleteUser: (userId: string) => PromiseLike<void>;
|
|
92
|
+
deleteUsers: (userIds: string[]) => PromiseLike<void>;
|
|
93
|
+
getUserPermissions: (userId: string) => PromiseLike<string[]>;
|
|
94
|
+
updateUserPermissions: (options: {
|
|
95
|
+
userId: string;
|
|
96
|
+
permissions: string[];
|
|
97
|
+
}) => PromiseLike<void>;
|
|
98
|
+
}
|
|
74
99
|
export interface UserManagementProps {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
100
|
+
/**
|
|
101
|
+
* Adapter module containing remote functions or async functions
|
|
102
|
+
* Should be imported from a .remote.ts file
|
|
103
|
+
*
|
|
104
|
+
* Example:
|
|
105
|
+
* ```ts
|
|
106
|
+
* import * as adapter from './adapter.remote';
|
|
107
|
+
* <UserManagement adapter={adapter} roles={roles} />
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
adapter: UserManagementAdapter;
|
|
111
|
+
/**
|
|
112
|
+
* Available roles for user assignment
|
|
113
|
+
*/
|
|
80
114
|
roles?: Role[];
|
|
115
|
+
/**
|
|
116
|
+
* Available permissions for display (optional)
|
|
117
|
+
*/
|
|
81
118
|
permissions?: Permission[];
|
|
82
|
-
onPageChange: (page: number) => void;
|
|
83
|
-
onPageSizeChange: (size: number) => void;
|
|
84
|
-
onSort?: (state: {
|
|
85
|
-
column: string | null;
|
|
86
|
-
direction: 'asc' | 'desc' | null;
|
|
87
|
-
}) => void;
|
|
88
|
-
onCreateUser?: (userData: Partial<User>) => Promise<void>;
|
|
89
|
-
onUpdateUser?: (userId: string, userData: Partial<User>) => Promise<void>;
|
|
90
|
-
onDeleteUser?: (userId: string) => Promise<void>;
|
|
91
|
-
onDeleteUsers?: (userIds: string[]) => Promise<void>;
|
|
92
119
|
class?: ClassValue;
|
|
93
120
|
}
|
|
94
121
|
export interface FormErrors {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makolabs/ripple",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.9",
|
|
4
4
|
"description": "Simple Svelte 5 powered component library ✨",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|
|
@@ -117,6 +117,7 @@
|
|
|
117
117
|
"dependencies": {
|
|
118
118
|
"@friendofsvelte/mermaid": "^0.0.4",
|
|
119
119
|
"@friendofsvelte/state": "^0.0.6-ts",
|
|
120
|
+
"@makolabs/ripple": "^1.2.4",
|
|
120
121
|
"@sveltejs/adapter-static": "^3.0.9",
|
|
121
122
|
"compromise": "^14.14.4",
|
|
122
123
|
"dayjs": "^1.11.13",
|