@gnar-engine/cli 1.0.2 → 1.0.4

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 (161) hide show
  1. package/bootstrap/deploy.localdev.yml +18 -31
  2. package/bootstrap/secrets.localdev.yml +7 -12
  3. package/bootstrap/services/user/Dockerfile +1 -1
  4. package/install.sh +32 -0
  5. package/package.json +1 -1
  6. package/src/config.js +2 -1
  7. package/src/dev/dev.service.js +44 -16
  8. package/src/scaffolder/commands.js +11 -4
  9. package/src/scaffolder/scaffolder.handler.js +228 -55
  10. package/templates/service/Dockerfile.hbs +4 -1
  11. package/templates/service/package.json.hbs +14 -16
  12. package/templates/service/{app.js.hbs → src/app.js.hbs} +8 -4
  13. package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +1 -2
  14. package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs} +11 -18
  15. package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +6 -0
  16. package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
  17. package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
  18. package/bootstrap/services/agent/Dockerfile +0 -23
  19. package/bootstrap/services/agent/notes.md +0 -28
  20. package/bootstrap/services/agent/package.json +0 -16
  21. package/bootstrap/services/agent/src/app.js +0 -52
  22. package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
  23. package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
  24. package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
  25. package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
  26. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
  27. package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
  28. package/bootstrap/services/agent/src/services/agent.service.js +0 -259
  29. package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
  30. package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
  31. package/bootstrap/services/portal/Dockerfile +0 -23
  32. package/bootstrap/services/portal/Dockerfile.remote +0 -40
  33. package/bootstrap/services/portal/README.md +0 -22
  34. package/bootstrap/services/portal/nginx.conf +0 -12
  35. package/bootstrap/services/portal/package.json +0 -59
  36. package/bootstrap/services/portal/public/favicon.ico +0 -0
  37. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  38. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  39. package/bootstrap/services/portal/public/index.html +0 -43
  40. package/bootstrap/services/portal/public/logo192.png +0 -0
  41. package/bootstrap/services/portal/public/logo512.png +0 -0
  42. package/bootstrap/services/portal/public/manifest.json +0 -25
  43. package/bootstrap/services/portal/public/robots.txt +0 -3
  44. package/bootstrap/services/portal/src/App.js +0 -56
  45. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
  46. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
  47. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
  48. package/bootstrap/services/portal/src/assets/activity.svg +0 -3
  49. package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
  50. package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
  51. package/bootstrap/services/portal/src/assets/bin.svg +0 -3
  52. package/bootstrap/services/portal/src/assets/check.svg +0 -3
  53. package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
  54. package/bootstrap/services/portal/src/assets/contact.svg +0 -3
  55. package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
  56. package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
  57. package/bootstrap/services/portal/src/assets/eye.svg +0 -4
  58. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
  59. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
  60. package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
  61. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  62. package/bootstrap/services/portal/src/assets/home.svg +0 -3
  63. package/bootstrap/services/portal/src/assets/link.svg +0 -3
  64. package/bootstrap/services/portal/src/assets/lock.svg +0 -3
  65. package/bootstrap/services/portal/src/assets/package.svg +0 -4
  66. package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
  67. package/bootstrap/services/portal/src/assets/settings.svg +0 -4
  68. package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
  69. package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
  70. package/bootstrap/services/portal/src/assets/user.svg +0 -3
  71. package/bootstrap/services/portal/src/assets/users.svg +0 -3
  72. package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
  73. package/bootstrap/services/portal/src/css/style.css +0 -1007
  74. package/bootstrap/services/portal/src/data/data.js +0 -70
  75. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
  76. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
  77. package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
  78. package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
  79. package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
  80. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
  81. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
  82. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
  83. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
  84. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
  85. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
  86. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
  87. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
  88. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
  89. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
  90. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
  91. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
  92. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
  93. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
  94. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
  95. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
  96. package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
  97. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
  98. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
  99. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
  100. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
  101. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
  102. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
  103. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
  104. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
  105. package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
  106. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
  107. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
  108. package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
  109. package/bootstrap/services/portal/src/features/user/user.less +0 -57
  110. package/bootstrap/services/portal/src/includes/utilities.js +0 -259
  111. package/bootstrap/services/portal/src/index.js +0 -14
  112. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
  113. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
  114. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
  115. package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
  116. package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
  117. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
  118. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
  119. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
  120. package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
  121. package/bootstrap/services/portal/src/pages/login/login.less +0 -10
  122. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
  123. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
  124. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
  125. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
  126. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
  127. package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
  128. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
  129. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
  130. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
  131. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
  132. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
  133. package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
  134. package/bootstrap/services/portal/src/pages/users/users.less +0 -25
  135. package/bootstrap/services/portal/src/slices/authSlice.js +0 -71
  136. package/bootstrap/services/portal/src/store/configureStore.js +0 -12
  137. package/bootstrap/services/portal/src/styles/global.less +0 -159
  138. package/bootstrap/services/portal/src/styles/inputs.less +0 -157
  139. package/bootstrap/services/portal/src/styles/main.less +0 -26
  140. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
  141. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
  142. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
  143. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
  144. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
  145. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
  146. package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +0 -63
  147. package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +0 -92
  148. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
  149. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
  150. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
  151. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
  152. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
  153. package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
  154. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
  155. package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
  156. /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
  157. /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
  158. /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
  159. /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
  160. /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
  161. /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
@@ -1,199 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import CrudLayout from "../../layouts/CrudLayout";
3
- import gnarEngine from "@gnar-engine/js-client";
4
- import CustomSelect from "../../ui/customSelect/CustomSelect";
5
- import arrow from '../../assets/arrow.svg';
6
- import CrudSubscriptionList from "../../features/crudSubscription/CrudSubscriptionList";
7
- import CrudSubscriptionSingle from "../../features/crudSubscription/CrudSubscriptionSingle";
8
-
9
- const Subscriptions = () => {
10
-
11
- const [view, setView] = useState("list");
12
- const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
13
- const [selectedSubscription, setSubscription] = useState(null);
14
- const [loading, setLoading] = useState(false);
15
- const [selectedAction, setSelectedAction] = useState(null);
16
- const [selectedSubscriptionIds, setSelectedSubscriptionIds] = useState(new Set());
17
- const [subscriptions, setSubscriptions] = useState([]);
18
- const [message, setMessage] = useState('');
19
- const [currentPage, setCurrentPage] = useState(1);
20
-
21
-
22
- const fetchSubscriptions = async () => {
23
- try {
24
- const data = await gnarEngine.subscription.getSubscriptions();
25
- console.log('data:', data);
26
-
27
- const subscriptionsList = data.subscriptions.map(order => ({
28
- id: order._id,
29
- firstName: order.billingAddress.firstName,
30
- lastName: order.billingAddress.lastName,
31
- date: new Date(order.createdAt).toLocaleDateString(),
32
- status: order.status,
33
- total: '£' + order.total?.toFixed(2),
34
- createdAt: formatDate(order.createdAt),
35
- }));
36
-
37
- setSubscriptions(subscriptionsList);
38
- setMessage(subscriptionsList.length > 0 ? '' : 'No subscriptions found');
39
- } catch (error) {
40
- console.error('Error fetching subscriptions:', error);
41
- setSubscriptions([]);
42
- }
43
- }
44
-
45
- useEffect(() => {
46
- fetchSubscriptions();
47
- }, []);
48
-
49
- const formatDate = (isoString) => {
50
- if (!isoString) return "N/A";
51
-
52
- const date = new Date(isoString);
53
- if (isNaN(date.getTime())) return "N/A"; // Checks if the date is invalid
54
-
55
- return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} at ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
56
- };
57
-
58
-
59
- const handleAddNew = () => {
60
- setView("single");
61
- setSelectedSingleItemId(null);
62
- setSubscription(null);
63
- }
64
-
65
- const refreshSelectedSubscription = () => {
66
- if (!selectedSingleItemId) {
67
- return;
68
- }
69
- (async () => {
70
- try {
71
- const data = await gnarEngine.subscription.getSubscriptions(selectedSingleItemId);
72
- setSubscription(data.subscription);
73
- } catch (error) {
74
- console.error('Error fetching subscription:', error);
75
- }
76
- })();
77
- }
78
-
79
- useEffect(() => {
80
- (async () => {
81
- if (!selectedSingleItemId) {
82
- return;
83
- }
84
- try {
85
- // fetch contact data
86
- const data = await gnarEngine.subscription.getSubscription(selectedSingleItemId);
87
- setSubscription(data.subscription);
88
-
89
- } catch (error) {
90
- console.error('Error fetching subscription:', error);
91
- }
92
- })();
93
- }, [selectedSingleItemId]);
94
-
95
- const handleAction = () => {
96
- if (!selectedAction) {
97
- alert("Please select an action first!");
98
- return;
99
- }
100
-
101
- if (selectedAction.id === "delete") {
102
- handleDelete();
103
- } else if (selectedAction.id === "export") {
104
- console.log("Export action triggered");
105
- }
106
- };
107
-
108
- const handleDelete = () => {
109
- if (selectedSubscriptionIds.size === 0) {
110
- alert("Please select a subscription to delete first!");
111
- return;
112
- }
113
- if (!window.confirm(`Are you sure you want to delete ${selectedSubscriptionIds.size} subscription(s)?`)) {
114
- return;
115
- }
116
- (async () => {
117
- try {
118
- for (const subscriptionId of selectedSubscriptionIds) {
119
- await gnarEngine.subscription.deleteSubscription(subscriptionId);
120
- }
121
- setSelectedSubscriptionIds(new Set());
122
- setSelectedAction(null);
123
- await fetchSubscriptions();
124
- } catch (error) {
125
- console.error('Error deleting subscription:', error);
126
- }
127
- })();
128
- };
129
-
130
- return (
131
- <CrudLayout
132
- view={view}
133
- setView={setView}
134
- selectedSingleItemId={selectedSingleItemId}
135
- setSelectedSingleItemId={setSelectedSingleItemId}
136
- >
137
- <div className="crud-page">
138
-
139
- {view === "list" ? (
140
- <div className="crud-list-cont">
141
- <div className="crud-list-controls">
142
- <div className="controls-left-col">
143
- <button onClick={handleAddNew} className="add-new">Add new</button>
144
- </div>
145
- <div className="controls-right-col">
146
- <CustomSelect
147
- name="filter-contacts"
148
- placeholder="filter by"
149
- options={[
150
- { id: "all", name: "All" },
151
- { id: "admin", name: "Admin" },
152
- { id: "contact", name: "User" }
153
- ]}
154
- labelKey="name"
155
- setSelectedOption={() => {}}
156
- selectedOption={null}
157
- />
158
- <CustomSelect
159
- name="action"
160
- placeholder="action"
161
- options={[
162
- { id: "delete", name: "Delete" },
163
- // { id: "export", name: "Export" }
164
- ]}
165
- labelKey="name"
166
- setSelectedOption={setSelectedAction}
167
- selectedOption={selectedAction}
168
- />
169
- <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
170
- </div>
171
- </div>
172
- <CrudSubscriptionList
173
- setSelectedSingleItemId={setSelectedSingleItemId}
174
- setView={() => setView('single')}
175
- selectedSubscriptionIds={selectedSubscriptionIds}
176
- setSelectedSubscriptionIds={setSelectedSubscriptionIds}
177
- subscriptions={subscriptions}
178
- message={message}
179
- />
180
- </div>
181
- ) : (
182
- <CrudSubscriptionSingle
183
- loading={loading}
184
- setLoading={setLoading}
185
- subscription={selectedSubscription}
186
- setView={() => setView('list')}
187
- refreshSelectedSubscription={refreshSelectedSubscription}
188
- setSubscription={setSubscription}
189
- fetchSubscriptions={fetchSubscriptions}
190
- setSelectedSingleItemId={setSelectedSingleItemId}
191
- formatDate={formatDate}
192
- />
193
- )}
194
- </div>
195
- </CrudLayout>
196
- );
197
- }
198
-
199
- export default Subscriptions;
@@ -1,193 +0,0 @@
1
- import React, { useState, useEffect } from "react";
2
- import CrudLayout from "../../layouts/CrudLayout";
3
- import CrudUserList from '../../features/crudUser/CrudUserList';
4
- import CrudUserSingle from '../../features/crudUser/CrudUserSingle';
5
- import gnarEngine from "@gnar-engine/js-client";
6
- import CustomSelect from "../../ui/customSelect/CustomSelect";
7
- import arrow from '../../assets/arrow.svg';
8
-
9
- const ManageUsers = () => {
10
-
11
- const [view, setView] = useState("list");
12
- const [selectedSingleItemId, setSelectedSingleItemId] = useState(null);
13
- const [selectedUser, setUser] = useState(null);
14
- const [loading, setLoading] = useState(false);
15
- const [selectedAction, setSelectedAction] = useState(null);
16
- const [selectedUserIds, setSelectedUserIds] = useState(new Set());
17
- const [users, setUsers] = useState([]);
18
- const [message, setMessage] = useState('');
19
- const [currentPage, setCurrentPage] = useState(1);
20
-
21
- const fetchUsers = async () => {
22
- try {
23
- const data = await gnarEngine.user.getMany();
24
- const usersList = data.users.map(user => ({
25
- id: user.id,
26
- email: user.email,
27
- username: user.username,
28
- userRole: user.role,
29
- createdAt: formatDate(user.createdAt),
30
- }));
31
- setUsers(usersList);
32
- setMessage(usersList.length > 0 ? '' : 'No users found');
33
- } catch (error) {
34
- console.error('Error fetching users:', error);
35
- setMessage('Error fetching users');
36
- setUsers([]);
37
- }
38
- };
39
-
40
-
41
- useEffect(() => {
42
- fetchUsers();
43
- }, []);
44
-
45
-
46
- const formatDate = (isoString) => {
47
- if (!isoString) return "N/A";
48
-
49
- const date = new Date(isoString);
50
- if (isNaN(date.getTime())) return "N/A"; // Checks if the date is invalid
51
-
52
- return `${date.getFullYear()}/${String(date.getMonth() + 1).padStart(2, '0')}/${String(date.getDate()).padStart(2, '0')} at ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
53
- };
54
-
55
-
56
- const handleAddNew = () => {
57
- setView("single");
58
- setSelectedSingleItemId(null);
59
- setUser(null);
60
- }
61
-
62
- const refreshSelectedUser = (user) => {
63
- setUser(user);
64
- }
65
-
66
- useEffect(() => {
67
- (async () => {
68
- if (!selectedSingleItemId) {
69
- return;
70
- }
71
- try {
72
- // fetch user data
73
- const data = await gnarEngine.user.getUser(selectedSingleItemId);
74
- setUser(data.user);
75
-
76
- } catch (error) {
77
- console.error('Error fetching user:', error);
78
- }
79
- })();
80
- }, [selectedSingleItemId]);
81
-
82
-
83
- const handleAction = () => {
84
- if (!selectedAction) {
85
- alert("Please select an action first!");
86
- return;
87
- }
88
-
89
- if (selectedAction.id === "delete") {
90
- handleDelete();
91
- } else if (selectedAction.id === "export") {
92
- console.log("Export action triggered");
93
- }
94
- };
95
-
96
-
97
- const handleDelete = () => {
98
- if (selectedUserIds.size === 0) {
99
- alert("Please select at least one user to delete.");
100
- return;
101
- }
102
-
103
- if (!window.confirm(`Are you sure you want to delete ${selectedUserIds.size} user(s)?`)) {
104
- return;
105
- }
106
-
107
- (async () => {
108
- try {
109
- setLoading(true);
110
- for (let userId of selectedUserIds) {
111
- await gnarEngine.user.delete(userId);
112
- }
113
- setSelectedUserIds(new Set());
114
- setLoading(false);
115
- await fetchUsers();
116
- } catch (error) {
117
- console.error('Error deleting users:', error);
118
- setLoading(false);
119
- }
120
- })();
121
- };
122
-
123
-
124
- return (
125
- <CrudLayout
126
- view={view}
127
- setView={setView}
128
- selectedSingleItemId={selectedSingleItemId}
129
- setSelectedSingleItemId={setSelectedSingleItemId}
130
- >
131
- <div className="crud-page">
132
-
133
- {view === "list" ? (
134
- <div className="crud-list-cont">
135
- <div className="crud-list-controls">
136
- <div className="controls-left-col">
137
- <button onClick={handleAddNew} className="add-new">Add new</button>
138
- </div>
139
- <div className="controls-right-col">
140
- <CustomSelect
141
- name="filter-users"
142
- placeholder="filter by"
143
- options={[
144
- { id: "all", name: "All" },
145
- { id: "admin", name: "Admin" },
146
- { id: "user", name: "User" }
147
- ]}
148
- labelKey="name"
149
- setSelectedOption={() => {}}
150
- selectedOption={null}
151
- />
152
- <CustomSelect
153
- name="action"
154
- placeholder="action"
155
- options={[
156
- { id: "delete", name: "Delete" },
157
- // { id: "export", name: "Export" }
158
- ]}
159
- labelKey="name"
160
- setSelectedOption={setSelectedAction}
161
- selectedOption={selectedAction}
162
- />
163
- <button className="arrowButton" onClick={handleAction}><img src={arrow} alt="right arrow icon" /></button>
164
- </div>
165
- </div>
166
- <CrudUserList
167
- setSelectedSingleItemId={setSelectedSingleItemId}
168
- setView={() => setView('single')}
169
- selectedUserIds={selectedUserIds}
170
- setSelectedUserIds={setSelectedUserIds}
171
- users={users}
172
- message={message}
173
- />
174
- </div>
175
- ) : (
176
- <CrudUserSingle
177
- loading={loading}
178
- setLoading={setLoading}
179
- selectedUser={selectedUser}
180
- setView={() => setView('list')}
181
- refreshSelectedUser={refreshSelectedUser}
182
- setUser={setUser}
183
- fetchUsers={fetchUsers}
184
- formatDate={formatDate}
185
- setSelectedSingleItemId={setSelectedSingleItemId}
186
- />
187
- )}
188
- </div>
189
- </CrudLayout>
190
- );
191
- }
192
-
193
- export default ManageUsers;
@@ -1,25 +0,0 @@
1
- .crud-page {
2
- .crud-list-cont {
3
- .crud-list-header {
4
- text-align: right;
5
- }
6
-
7
- .crud-list-controls {
8
- display: flex;
9
- justify-content: space-between;
10
- align-items: center;
11
- margin-bottom: 20px;
12
-
13
- .controls-left-col {
14
- display: flex;
15
- gap: 20px;
16
- }
17
-
18
- .controls-right-col {
19
- display: flex;
20
- gap: 20px;
21
- }
22
- }
23
-
24
- }
25
- }
@@ -1,71 +0,0 @@
1
- import {createSlice, createAsyncThunk, createAction} from '@reduxjs/toolkit';
2
- import { getAuthToken, getAuthUser, setAuthToken, setAuthUser, removeAuthToken, removeAuthUser } from '@gnar-engine/js-client/src/storage';
3
- import gnarEngine from '@gnar-engine/js-client';
4
-
5
-
6
- export const login = createAsyncThunk('auth/login', async ({username, password}) => {
7
-
8
- let response;
9
-
10
- try {
11
- response = await gnarEngine.user.authenticate(username, password);;
12
- } catch (error) {
13
- response = error.response;
14
- }
15
-
16
- return response;
17
- })
18
-
19
- export const logout = createAction('auth/logout');
20
-
21
- export const authSlice = createSlice({
22
- name: 'auth',
23
- initialState: {
24
- authUser: getAuthUser() ? JSON.parse(getAuthUser()) : null,
25
- accessToken: getAuthToken() ? getAuthToken() : '',
26
- authLoading: false,
27
- authError: ''
28
- },
29
- reducers: {
30
- },
31
- extraReducers: builder => {
32
- builder
33
- .addCase(login.pending, (state, action) => {
34
- state.authLoading = true;
35
- state.authError = '';
36
- })
37
- .addCase(login.fulfilled, (state, action) => {
38
- state.authLoading = false;
39
- state.authError = action.payload.data?.error ? action.payload.data.message : '';
40
-
41
- if (action.payload.token) {
42
- state.accessToken = action.payload.token;
43
- state.authUser = action.payload.user;
44
-
45
- // store in local storage
46
- setAuthToken(action.payload.token);
47
- setAuthUser(JSON.stringify(action.payload.user));
48
-
49
- // redirect to portal
50
- window.location.href= '/portal';
51
- } else {
52
- // Handle error case
53
- console.error('Login failed:', action.payload);
54
- }
55
- })
56
- .addCase(logout, (state, action) => {
57
- // Clear auth state
58
- state.authUser = '';
59
- state.accessToken = '';
60
-
61
- // Remove from local storage
62
- removeAuthToken();
63
- removeAuthUser();
64
-
65
- // Redirect to login page
66
- window.location.href = '/login';
67
- });
68
- }
69
- })
70
-
71
- export default authSlice;
@@ -1,12 +0,0 @@
1
- import { configureStore } from '@reduxjs/toolkit';
2
- import authSlice from '../slices/authSlice';
3
-
4
-
5
- const store = configureStore({
6
-
7
- reducer: {
8
- auth: authSlice.reducer
9
- }
10
- })
11
-
12
- export default store;
@@ -1,159 +0,0 @@
1
-
2
- /* vars */
3
-
4
- @green-1: #479E78;
5
- @dark-grey-1: #434343;
6
- @mid-grey-1: #73768C;
7
- @orange-1: #E8896D;
8
- @orange-2: #EFA12C;
9
- @dark-1: #3C5063;
10
- @grey-light-1: #F6F8F9;
11
- @grey-mid-1: #E4E4E4;
12
- @grey-dark-1: #B3B3B3;
13
- @white: #FFFFFF;
14
- @red-1: #c73939;
15
- @red-2: #ffeeee;
16
- @green-2: #359E59;
17
-
18
- @content-width: 1550px;
19
-
20
- /* Fonts */
21
-
22
- // @import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap');
23
-
24
- body {
25
- font-family: ubuntu, sans-serif;
26
- color: @dark-1;
27
- font-size: 14px;
28
- }
29
-
30
- /* Global styles */
31
-
32
- h1 {
33
- margin-top: 0px;
34
- font-size: 28px;
35
- font-weight: 600;
36
- }
37
- h2 {
38
- font-size: 15px;
39
- font-weight: 500;
40
- }
41
- body {
42
- margin: 0px;
43
-
44
- &, #root {
45
- min-height: 100vh;
46
- }
47
- }
48
-
49
- .separator {
50
- margin-top: 20px;
51
- margin-bottom: 20px;
52
- height: 0px;
53
- border-top: 1px solid @grey-mid-1;
54
- }
55
- .content-wrap {
56
- display: flex;
57
- justify-content: center;
58
- }
59
- .content {
60
- width: 100%;
61
- max-width: @content-width;
62
- margin-left: auto;
63
- margin-right: auto;
64
- padding-left: 20px;
65
- padding-right: 20px;
66
- }
67
- .instruction {
68
- font-size: 12px;
69
- margin-top: 10px;
70
- margin-bottom: 10px;
71
- }
72
- .flex-row {
73
- display: flex;
74
- flex-direction: row;
75
- justify-content: space-between;
76
- gap: 20px;
77
- }
78
- .flex-row-end{
79
- align-items: flex-end;
80
- }
81
- .form-cont {
82
- width: 100%;
83
- margin-bottom: 30px;
84
- }
85
-
86
- .full-width-select-cont,
87
- .full-width-select-cont .custom-select {
88
- min-width: 100%;
89
- }
90
- .flex-row-select-cont {
91
- min-width: 100%;
92
- display: flex;
93
- flex-direction: row;
94
- justify-content: space-between;
95
- gap: 20px;
96
-
97
- .custom-select {
98
- width: 100%;
99
- max-width: unset;
100
- }
101
- }
102
-
103
- .flex-row-checkbox-cont {
104
- min-width: 100%;
105
- display: flex;
106
- flex-direction: row;
107
- justify-content: space-between;
108
- gap: 20px;
109
-
110
- label {
111
- display: inline-block;
112
- }
113
- }
114
-
115
- .flex-row-buttons-cont {
116
- display: flex;
117
- flex-direction: row;
118
- justify-content: flex-end;
119
- gap: 20px;
120
- }
121
-
122
- .button {
123
- &.button-loading {
124
- background: @grey-mid-1 !important;
125
- cursor: not-allowed !important;
126
-
127
- &:disabled {
128
- cursor: not-allowed;
129
- opacity: 0.5;
130
- }
131
- }
132
- }
133
-
134
- .card {
135
- background: @white;
136
- border: 1px solid @grey-mid-1;
137
- border-radius: 10px;
138
- margin-top: 20px;
139
- box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.1);
140
-
141
- .card-header {
142
- width: 100%;
143
- background-color: @dark-grey-1;
144
- color: @white;
145
- border-top-left-radius: 10px;
146
- border-top-right-radius: 10px;
147
- display: flex;
148
- justify-content: space-between;
149
-
150
- h2 {
151
- padding: 20px;
152
- margin: 0px;
153
- }
154
- }
155
-
156
- .card-content {
157
- padding: 20px;
158
- }
159
- }