@gnar-engine/cli 1.0.3 → 1.0.5

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 (259) hide show
  1. package/bootstrap/deploy.localdev.yml +44 -30
  2. package/bootstrap/secrets.localdev.yml +20 -14
  3. package/bootstrap/services/control/src/config.js +4 -0
  4. package/bootstrap/services/{agent → page}/Dockerfile +3 -3
  5. package/bootstrap/services/page/package.json +16 -0
  6. package/bootstrap/services/page/src/app.js +50 -0
  7. package/bootstrap/services/page/src/commands/block.handler.js +94 -0
  8. package/bootstrap/services/page/src/commands/page.handler.js +167 -0
  9. package/bootstrap/services/page/src/config.js +62 -0
  10. package/bootstrap/services/page/src/controllers/block.http.controller.js +87 -0
  11. package/bootstrap/services/page/src/controllers/message.controller.js +51 -0
  12. package/bootstrap/services/page/src/controllers/page.http.controller.js +89 -0
  13. package/bootstrap/services/page/src/policies/block.policy.js +50 -0
  14. package/bootstrap/services/page/src/policies/page.policy.js +49 -0
  15. package/bootstrap/services/page/src/schema/page.schema.js +139 -0
  16. package/bootstrap/services/page/src/services/block.service.js +83 -0
  17. package/bootstrap/services/page/src/services/page.service.js +83 -0
  18. package/bootstrap/services/portal/Dockerfile +7 -10
  19. package/bootstrap/services/portal/README.md +66 -15
  20. package/bootstrap/services/portal/index.html +13 -0
  21. package/bootstrap/services/portal/nginx.conf +5 -12
  22. package/bootstrap/services/portal/package.json +27 -53
  23. package/bootstrap/services/portal/public/vite.svg +1 -0
  24. package/bootstrap/services/portal/react-router.config.js +7 -0
  25. package/bootstrap/services/portal/src/App.jsx +16 -0
  26. package/bootstrap/services/portal/src/assets/gnar-engine-white-logo.svg +9 -0
  27. package/bootstrap/services/portal/src/assets/icon-agent.svg +6 -0
  28. package/bootstrap/services/portal/src/assets/icon-cog.svg +4 -0
  29. package/bootstrap/services/portal/src/assets/icon-delete.svg +3 -0
  30. package/bootstrap/services/portal/src/assets/icon-home.svg +3 -0
  31. package/bootstrap/services/portal/src/assets/icon-padlock.svg +3 -0
  32. package/bootstrap/services/portal/src/assets/icon-page.svg +6 -0
  33. package/bootstrap/services/portal/src/assets/icon-reports.svg +3 -0
  34. package/bootstrap/services/portal/src/assets/icon-user.svg +3 -0
  35. package/bootstrap/services/portal/src/assets/icon-users.svg +3 -0
  36. package/bootstrap/services/portal/src/assets/login-green-rad-back-1.jpg +0 -0
  37. package/bootstrap/services/portal/src/assets/react.svg +1 -0
  38. package/bootstrap/services/portal/src/components/CrudList/CrudList.jsx +85 -0
  39. package/bootstrap/services/portal/src/components/CrudList/CrudList.less +59 -0
  40. package/bootstrap/services/portal/src/{ui/customSelect → components/CustomSelect}/CustomSelect.jsx +21 -3
  41. package/bootstrap/services/portal/src/components/LoginForm/LoginForm.jsx +58 -0
  42. package/bootstrap/services/portal/src/components/PageBlockSwitch/PageBlockSwitch.jsx +129 -0
  43. package/bootstrap/services/portal/src/components/Sidebar/Sidebar.jsx +33 -0
  44. package/bootstrap/services/portal/src/components/Sidebar/Sidebar.less +37 -0
  45. package/bootstrap/services/portal/src/components/Topbar/Topbar.jsx +19 -0
  46. package/bootstrap/services/portal/src/components/Topbar/Topbar.less +22 -0
  47. package/bootstrap/services/portal/src/components/UserInfo/UserInfo.jsx +33 -0
  48. package/bootstrap/services/portal/src/components/UserInfo/UserInfo.less +21 -0
  49. package/bootstrap/services/portal/src/css/style.css +446 -742
  50. package/bootstrap/services/portal/src/data/pages.data.js +10 -0
  51. package/bootstrap/services/portal/src/elements/CustomSelect/CustomSelect.jsx +65 -0
  52. package/bootstrap/services/portal/src/{ui/customSelect/customSelect.less → elements/CustomSelect/CustomSelect.less} +17 -7
  53. package/bootstrap/services/portal/src/elements/ImageInput/ImageInput.jsx +115 -0
  54. package/bootstrap/services/portal/src/elements/ImageInput/ImageInput.less +43 -0
  55. package/bootstrap/services/portal/src/elements/ImageMultiInput/ImageMultiInput.jsx +124 -0
  56. package/bootstrap/services/portal/src/elements/ImageMultiInput/ImageMultiInput.less +0 -0
  57. package/bootstrap/services/portal/src/elements/Repeater/Repeater.jsx +52 -0
  58. package/bootstrap/services/portal/src/elements/Repeater/Repeater.less +70 -0
  59. package/bootstrap/services/portal/src/elements/RichTextInput/RichTextInput.jsx +18 -0
  60. package/bootstrap/services/portal/src/elements/RichTextInput/RichTextInput.less +37 -0
  61. package/bootstrap/services/portal/src/elements/SaveButton/SaveButton.jsx +45 -0
  62. package/bootstrap/services/portal/src/elements/SelectRepeater/SelectRepeater.jsx +63 -0
  63. package/bootstrap/services/portal/src/elements/SelectRepeater/SelectRepeater.less +23 -0
  64. package/bootstrap/services/portal/src/elements/TextInput/TextInput.jsx +17 -0
  65. package/bootstrap/services/portal/src/layouts/Card/Card.jsx +15 -0
  66. package/bootstrap/services/portal/src/layouts/PortalLayout/PortalLayout.jsx +29 -0
  67. package/bootstrap/services/portal/src/layouts/PortalLayout/PortalLayout.less +49 -0
  68. package/bootstrap/services/portal/src/main.jsx +51 -0
  69. package/bootstrap/services/portal/src/pages/BlockSinglePage/BlockSinglePage.jsx +277 -0
  70. package/bootstrap/services/portal/src/pages/BlocksPage/BlocksPage.jsx +23 -0
  71. package/bootstrap/services/portal/src/pages/DashboardPage/DashboardPage.jsx +11 -0
  72. package/bootstrap/services/portal/src/pages/DashboardPage/DashboardPage.less +0 -0
  73. package/bootstrap/services/portal/src/pages/LoginPage/LoginPage.jsx +21 -0
  74. package/bootstrap/services/portal/src/pages/LoginPage/LoginPage.less +51 -0
  75. package/bootstrap/services/portal/src/pages/PageSinglePage/PageSinglePage.jsx +338 -0
  76. package/bootstrap/services/portal/src/pages/PagesPage/PagesPage.jsx +23 -0
  77. package/bootstrap/services/portal/src/pages/UserSinglePage/UserSinglePage.jsx +9 -0
  78. package/bootstrap/services/portal/src/pages/UserSinglePage/UserSinglePage.less +0 -0
  79. package/bootstrap/services/portal/src/pages/UsersPage/UsersPage.jsx +25 -0
  80. package/bootstrap/services/portal/src/pages/UsersPage/UsersPage.less +0 -0
  81. package/bootstrap/services/portal/src/services/block.js +28 -0
  82. package/bootstrap/services/portal/src/services/client.js +67 -0
  83. package/bootstrap/services/portal/src/services/gravatar.js +14 -0
  84. package/bootstrap/services/portal/src/services/page.js +28 -0
  85. package/bootstrap/services/portal/src/services/storage.js +62 -0
  86. package/bootstrap/services/portal/src/services/user.js +41 -0
  87. package/bootstrap/services/portal/src/slices/authSlice.js +44 -14
  88. package/bootstrap/services/portal/src/store/configureStore.js +1 -3
  89. package/bootstrap/services/portal/src/style/cards.less +57 -0
  90. package/bootstrap/services/portal/src/{styles → style}/global.less +90 -45
  91. package/bootstrap/services/portal/src/style/icons.less +21 -0
  92. package/bootstrap/services/portal/src/style/inputs.less +52 -0
  93. package/bootstrap/services/portal/src/style/main.less +28 -0
  94. package/bootstrap/services/portal/src/utils/utils.js +9 -0
  95. package/bootstrap/services/portal/vite.config.js +12 -0
  96. package/bootstrap/services/user/Dockerfile +1 -1
  97. package/bootstrap/services/user/src/app.js +6 -1
  98. package/bootstrap/services/user/src/commands/user.handler.js +0 -3
  99. package/bootstrap/services/user/src/config.js +5 -1
  100. package/bootstrap/services/user/src/policies/user.policy.js +3 -1
  101. package/bootstrap/services/user/src/tests/commands/user.test.js +22 -0
  102. package/install-from-clone.sh +30 -0
  103. package/package.json +1 -1
  104. package/src/cli.js +8 -0
  105. package/src/config.js +2 -1
  106. package/src/dev/commands.js +10 -2
  107. package/src/dev/dev.service.js +167 -52
  108. package/src/provisioner/Dockerfile +27 -0
  109. package/src/provisioner/package.json +19 -0
  110. package/src/provisioner/src/app.js +56 -0
  111. package/src/provisioner/src/services/mongodb.js +58 -0
  112. package/src/provisioner/src/services/mysql.js +51 -0
  113. package/src/provisioner/src/services/secrets.js +84 -0
  114. package/src/scaffolder/commands.js +12 -5
  115. package/src/scaffolder/scaffolder.handler.js +256 -58
  116. package/templates/service/Dockerfile.hbs +4 -1
  117. package/templates/service/package.json.hbs +14 -16
  118. package/templates/service/src/app.js.hbs +53 -0
  119. package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +2 -3
  120. package/templates/service/src/mongodb.config.js.hbs +49 -0
  121. package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +10 -0
  122. package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
  123. package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
  124. package/bootstrap/services/agent/notes.md +0 -28
  125. package/bootstrap/services/agent/package.json +0 -16
  126. package/bootstrap/services/agent/src/app.js +0 -52
  127. package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
  128. package/bootstrap/services/agent/src/config.js +0 -52
  129. package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
  130. package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
  131. package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
  132. package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
  133. package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
  134. package/bootstrap/services/agent/src/services/agent.service.js +0 -259
  135. package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
  136. package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
  137. package/bootstrap/services/portal/Dockerfile.remote +0 -40
  138. package/bootstrap/services/portal/public/favicon.ico +0 -0
  139. package/bootstrap/services/portal/public/gnar-white.png +0 -0
  140. package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
  141. package/bootstrap/services/portal/public/index.html +0 -43
  142. package/bootstrap/services/portal/public/logo192.png +0 -0
  143. package/bootstrap/services/portal/public/logo512.png +0 -0
  144. package/bootstrap/services/portal/public/manifest.json +0 -25
  145. package/bootstrap/services/portal/public/robots.txt +0 -3
  146. package/bootstrap/services/portal/src/App.js +0 -56
  147. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
  148. package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
  149. package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
  150. package/bootstrap/services/portal/src/assets/activity.svg +0 -3
  151. package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
  152. package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
  153. package/bootstrap/services/portal/src/assets/bin.svg +0 -3
  154. package/bootstrap/services/portal/src/assets/check.svg +0 -3
  155. package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
  156. package/bootstrap/services/portal/src/assets/contact.svg +0 -3
  157. package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
  158. package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
  159. package/bootstrap/services/portal/src/assets/eye.svg +0 -4
  160. package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
  161. package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
  162. package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
  163. package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
  164. package/bootstrap/services/portal/src/assets/home.svg +0 -3
  165. package/bootstrap/services/portal/src/assets/link.svg +0 -3
  166. package/bootstrap/services/portal/src/assets/lock.svg +0 -3
  167. package/bootstrap/services/portal/src/assets/package.svg +0 -4
  168. package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
  169. package/bootstrap/services/portal/src/assets/settings.svg +0 -4
  170. package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
  171. package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
  172. package/bootstrap/services/portal/src/assets/user.svg +0 -3
  173. package/bootstrap/services/portal/src/assets/users.svg +0 -3
  174. package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
  175. package/bootstrap/services/portal/src/data/data.js +0 -70
  176. package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
  177. package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
  178. package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
  179. package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
  180. package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
  181. package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
  182. package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
  183. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
  184. package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
  185. package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
  186. package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
  187. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
  188. package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
  189. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
  190. package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
  191. package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
  192. package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
  193. package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
  194. package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
  195. package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
  196. package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
  197. package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
  198. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
  199. package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
  200. package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
  201. package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
  202. package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
  203. package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
  204. package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
  205. package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
  206. package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
  207. package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
  208. package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
  209. package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
  210. package/bootstrap/services/portal/src/features/user/user.less +0 -57
  211. package/bootstrap/services/portal/src/includes/utilities.js +0 -259
  212. package/bootstrap/services/portal/src/index.js +0 -14
  213. package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
  214. package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
  215. package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
  216. package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
  217. package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
  218. package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
  219. package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
  220. package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
  221. package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
  222. package/bootstrap/services/portal/src/pages/login/login.less +0 -10
  223. package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
  224. package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
  225. package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
  226. package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
  227. package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
  228. package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
  229. package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
  230. package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
  231. package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
  232. package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
  233. package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
  234. package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
  235. package/bootstrap/services/portal/src/pages/users/users.less +0 -25
  236. package/bootstrap/services/portal/src/styles/inputs.less +0 -157
  237. package/bootstrap/services/portal/src/styles/main.less +0 -26
  238. package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
  239. package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
  240. package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
  241. package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
  242. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
  243. package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
  244. package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
  245. package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
  246. package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
  247. package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
  248. package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
  249. package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
  250. package/bootstrap/services/user/src/tests/user.test.js +0 -126
  251. package/templates/service/app.js.hbs +0 -38
  252. package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
  253. /package/bootstrap/services/portal/src/{ui/saveButton/saveButton.less → components/CustomSelect/CustomSelect.less} +0 -0
  254. /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
  255. /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
  256. /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
  257. /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
  258. /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
  259. /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
@@ -1,402 +0,0 @@
1
- import React, { useState, useEffect } from 'react';
2
- import CustomSelect from '../../ui/customSelect/CustomSelect';
3
- import { userRoles } from '../../data/data';
4
- import gnarEngine from '@gnar-engine/js-client';
5
- import SaveButton from '../../ui/saveButton/SaveButton';
6
- import Eye from '../../assets/eye.svg'
7
- import EyeOff from '../../assets/eye-off.svg'
8
- import arrow from '../../assets/arrow.svg';
9
- import { useSelector } from 'react-redux';
10
-
11
-
12
- const CrudUserSingle = ({selectedUser, setUser, setView, loading, setLoading, refreshSelectedUser, fetchUsers, formatDate, setSelectedSingleItemId}) => {
13
-
14
- const user = useSelector(state => state.auth.authUser);
15
- const [formData, setFormData] = useState({
16
- email: '',
17
- username: '',
18
- role: '',
19
- apiKey: ''
20
- });
21
- const [validationErrors, setValidationErrors] = useState([]);
22
- const [passwordResetSuccess, setPasswordResetSuccess] = useState(false);
23
- const [showPassword, setShowPassword] = useState(false);
24
- const [selectedAction, setSelectedAction] = useState(null);
25
-
26
-
27
- // prepare form data for editing existing user
28
- useEffect(() => {
29
- console.log('user:', selectedUser);
30
- // set form data for updating user
31
- if (selectedUser && selectedUser.id) {
32
- const newFormData = {...selectedUser};
33
- setFormData(newFormData);
34
- }
35
-
36
- // set back to default if no user is selected
37
- else {
38
- setFormData({
39
- email: ''
40
- });
41
- }
42
-
43
- setLoading(null);
44
- }, [selectedUser]);
45
-
46
- // handle form data changes
47
- const handleChange = (e) => {
48
- setValidationErrors([]);
49
-
50
- const { name, value } = e.target;
51
- setFormData(prevData => ({
52
- ...prevData,
53
- [name]: value
54
- }));
55
- };
56
-
57
-
58
- // handle delete user
59
- const handleDelete = async (selectedUser) => {
60
- if (window.confirm('Are you sure you want to delete this user?')) {
61
- try {
62
- setLoading('loading');
63
-
64
- console.log('selectedUser:', selectedUser);
65
-
66
- await gnarEngine.user.delete(selectedUser.id);
67
-
68
- setLoading('success');
69
- setTimeout(() => {
70
- setLoading(null);
71
- }, 3000);
72
-
73
- refreshSelectedUser();
74
- await fetchUsers();
75
- setView('list');
76
-
77
- } catch (error) {
78
-
79
- setLoading('error');
80
- console.error('Error deleting user:', error);
81
- }
82
- } else {
83
- console.log('Deletion canceled');
84
- }
85
- };
86
-
87
- const handleSubmit = async (e) => {
88
- e.preventDefault();
89
- setValidationErrors([]); // Clear any previous validation errors
90
-
91
- // Set loading state to 'loading'
92
- setLoading('loading');
93
-
94
- try {
95
- if (selectedUser) {
96
- // Update existing user
97
- const data = { ...formData };
98
- delete data.created_at;
99
- delete data.updated_at;
100
- delete data.id;
101
-
102
- const updatedUserResponse = await gnarEngine.user.update(selectedUser.id, data);
103
-
104
- setLoading('success');
105
- setTimeout(() => {
106
- setLoading(null);
107
- refreshSelectedUser(updatedUserResponse.user);
108
- }, 3000);
109
-
110
- } else {
111
- // Creating a new user
112
- await gnarEngine.user.createUser(formData);
113
-
114
- setLoading('success');
115
- setTimeout(() => {
116
- setLoading(null);
117
- fetchUsers();
118
- setView('list');
119
-
120
- }, 3000);
121
- }
122
- } catch (error) {
123
- // Collect server-side validation errors, if any
124
- const errors = [];
125
-
126
- if (error.response?.data?.errors) {
127
- Object.keys(error.response.data.errors).forEach((key) => {
128
- errors.push(error.response.data.errors[key]);
129
- });
130
- } else if (error.response?.data?.message) {
131
- errors.push(error.response.data.message);
132
- }
133
-
134
- setValidationErrors(errors); // Set validation errors to be displayed
135
- console.error('Error saving user:', error);
136
-
137
- setLoading('error');
138
- setTimeout(() => {
139
- setLoading(null);
140
- }, 3000);
141
- }
142
- };
143
-
144
- const handleAction = () => {
145
- if (!selectedAction) {
146
- alert("Please select an action first!");
147
- return;
148
- }
149
-
150
- if (selectedAction.id === "delete") {
151
- handleDelete(selectedUser);
152
- } else if (selectedAction.id === "export") {
153
- console.log("Export action triggered");
154
- }
155
- };
156
-
157
-
158
-
159
- const handlePasswordReset = async () => {
160
- if (!selectedUser || !selectedUser.id) {
161
- return;
162
- }
163
-
164
- setPasswordResetSuccess(true); // Show success message
165
- setTimeout(() => {
166
- setPasswordResetSuccess(false); // Hide it after 3 seconds
167
- }, 3000);
168
-
169
- try {
170
- await gnarEngine.sendPasswordReset({ email: selectedUser.email });
171
-
172
- } catch (error) {
173
- const errors = [];
174
-
175
- if (error.response.data.errors) {
176
- Object.keys(error.response.data.errors).forEach((key) => {
177
- errors.push(error.response.data.errors[key]);
178
- });
179
- } else if (error.response.data.message && error.response.data.error) {
180
- errors.push(error.response.data.message);
181
- errors.push(error.response.data.error);
182
- }
183
-
184
- setValidationErrors(errors);
185
- console.error('Error sending password reset:', error);
186
- }
187
- }
188
-
189
- const routeKey = 'manage-users';
190
- const handleMenuBtnClick = () => setView({ isBackToList: true });
191
-
192
- // add event listener to sidebar buttons to change view
193
- useEffect(() => {
194
- const sidebarButtons = document.querySelectorAll('.sidebar a[href^="/portal/' + routeKey + '"]');
195
- sidebarButtons.forEach(button => {
196
- // if it doesn't already have an event listener
197
- if (!button.hasEventListener) {
198
- button.addEventListener('click', handleMenuBtnClick);
199
- }
200
- })
201
-
202
- // Cleanup to prevent memory leaks and double bindings
203
- return () => {
204
- sidebarButtons.forEach(button => {
205
- button.removeEventListener('click', handleMenuBtnClick);
206
- });
207
- };
208
- }, []);
209
-
210
- return (
211
- <div className="single-edit user">
212
- <div className='single-edit-header'>
213
- <div className='single-edit-header-left'>
214
- {selectedUser && selectedUser.id &&
215
- <>
216
- <p><strong>User ID:&nbsp;</strong>{selectedUser.id}</p>
217
- <p><strong>Email:&nbsp;</strong>{selectedUser.email}</p>
218
- <p><strong>Role:&nbsp;</strong>{selectedUser.role}</p>
219
- <p><strong>Date Added:&nbsp;</strong>{formatDate(selectedUser?.createdAt)}</p>
220
- </>
221
- }
222
- </div>
223
- <div className='single-edit-header-right'>
224
- <div className="flex-row-buttons-cont">
225
- <button onClick={() => {
226
- setView('list');
227
- setUser(null);
228
- setSelectedSingleItemId(null);
229
- }} className="secondaryButton">
230
- Back
231
- </button>
232
- <button onClick={() => handleDelete(selectedUser)} className="secondaryButton">Delete</button>
233
- <SaveButton
234
- save={handleSubmit}
235
- loading={loading}
236
- textCreate="Add User"
237
- textCreateLoading="Saving..."
238
- textCreateSuccess="Saved"
239
- textCreateError="Error"
240
- textUpdate="Save"
241
- textUpdateLoading="Updating..."
242
- textUpdateSuccess="Updated"
243
- textUpdateError="Error"
244
- isUpdating={!!selectedUser}
245
- />
246
- </div>
247
- {validationErrors.length > 0 &&
248
- <div className="error-messages">
249
- {validationErrors.map((error, index) => {
250
- return <p key={index}>{error}</p>
251
- })}
252
- </div>
253
- }
254
- </div>
255
-
256
- </div>
257
-
258
- <h2>Details</h2>
259
-
260
- <div className='card account'>
261
- <div className='card-header'>
262
- <h2>Account</h2>
263
- </div>
264
- <div className='card-content'>
265
- <form className='user-form' onSubmit={handleSubmit}>
266
- <div className='form-group'>
267
- <label>Email:</label>
268
- <input
269
- type="text"
270
- name="email"
271
- value={formData.email}
272
- onChange={handleChange}
273
- required
274
- />
275
- </div>
276
-
277
- {selectedUser && selectedUser.id &&
278
- <div className='form-group'>
279
- <label>Username:</label>
280
- <input
281
- type="text"
282
- name="username"
283
- value={formData.username}
284
- onChange={handleChange}
285
- required
286
- />
287
- </div>
288
- }
289
-
290
- {!selectedUser &&
291
- <div>
292
- <label>Password:</label>
293
- <input
294
- type="password"
295
- name="password"
296
- value={formData.password}
297
- onChange={handleChange}
298
- required
299
- />
300
- </div>
301
- }
302
-
303
-
304
- <div className='form-group'>
305
- <label>User Role:</label>
306
- <CustomSelect
307
- name="select-user-role"
308
- placeholder="Select User Role"
309
- options={userRoles}
310
- labelKey="name"
311
- setSelectedOption={(option) => setFormData(prev => ({ ...prev, role: option.role }))}
312
- selectedOption={userRoles.find(role => role.role === formData.role) || null}
313
- required
314
- />
315
- </div>
316
- </form>
317
- {selectedUser && selectedUser.id &&
318
- <div className='form-group'>
319
- <a onClick={() => handlePasswordReset()} className="password-reset-btn">Send password reset</a>
320
- {passwordResetSuccess && <p>Password reset email sent successfully!</p>}
321
- </div>
322
- }
323
- </div>
324
- </div>
325
-
326
- {selectedUser && selectedUser.id &&
327
- <div className='card contacts'>
328
- <div className='card-header'>
329
- <h2>Contacts</h2>
330
- </div>
331
- <div className='card-content'>
332
- <p>Contact details associated with this user.</p>
333
- <form onSubmit={handleSubmit}>
334
- <div className='form-group'>
335
- <label>Type</label>
336
- <input
337
- type="text"
338
- name="email"
339
- value={formData.type}
340
- onChange={handleChange}
341
- required
342
- />
343
- </div>
344
-
345
- <div className='form-group'>
346
- <label>Name</label>
347
- <input
348
- type="text"
349
- name="name"
350
- value={formData.name}
351
- onChange={handleChange}
352
- required
353
- />
354
- </div>
355
- <button className="secondaryButton">View / Edit</button>
356
- </form>
357
- </div>
358
- </div>
359
- }
360
-
361
- {user && user.id && user.role === 'service_admin' || !selectedUser &&
362
- <>
363
- <h2>API Access (Service Admin Only)</h2>
364
- <div className='card api-key'>
365
- <div className='card-header'>
366
- <h2>API Keys</h2>
367
- </div>
368
- <div className='card-content'>
369
- <form onSubmit={handleSubmit}>
370
- <div className='form-group'>
371
- <label>Key</label>
372
- <input
373
- type={showPassword ? "text" : "password"}
374
- name="apiKey"
375
- value={formData.apiKey}
376
- onChange={handleChange}
377
- required
378
- />
379
- <button
380
- type="button"
381
- onClick={() => setShowPassword((prev) => !prev)}
382
- style={{
383
- position: "absolute",
384
- right: "0",
385
- background: "none",
386
- border: "none",
387
- cursor: "pointer"
388
- }}
389
- >
390
- <img src={showPassword ? Eye : EyeOff} alt="Show password" />
391
- </button>
392
- </div>
393
- </form>
394
- </div>
395
- </div>
396
- </>
397
- }
398
- </div>
399
- );
400
- };
401
-
402
- export default CrudUserSingle;
@@ -1,30 +0,0 @@
1
- import bin from '../../assets/bin.svg';
2
- import { useState } from 'react';
3
- import { currencies, taxClasses } from '../../data/data';
4
- import CustomSelect from '../../ui/customSelect/CustomSelect';
5
-
6
- const InventoryFormRow = ({ item, onChange, remove }) => {
7
-
8
-
9
- return (
10
- <div className='form-row'>
11
- <input
12
- type="text"
13
- name='price'
14
- value={item.price}
15
- onChange={(e) => onChange("price", Number(e.target.value))}
16
- />
17
- <input
18
- type="text"
19
- name='salePrice'
20
- value={item.salePrice}
21
- onChange={(e) => onChange("price", Number(e.target.value))}
22
- />
23
-
24
- <button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
25
- </div>
26
- )
27
- }
28
-
29
-
30
- export default InventoryFormRow;
@@ -1,113 +0,0 @@
1
- const LineItems = ({order}) => {
2
-
3
- return (
4
- <div className="card">
5
- <div className='card-header'>
6
- <h2>Line Items & Totals</h2>
7
- </div>
8
- <div className='card-content'>
9
- <div className="line-items-totals-cont">
10
-
11
- {/* Line Items Section */}
12
- <div className="line-items-cont">
13
- <div className="line-items-body">
14
- {order?.lineItems && order.lineItems.length > 0 ? (
15
- <table className="line-items-table">
16
-
17
- {order?.originalSubscriptionOrderId && (
18
- <>
19
- <thead>
20
- <tr>
21
- <th>Product</th>
22
- <th>SKU</th>
23
- <th>Price</th>
24
- <th>Quantity</th>
25
- <th>Discount</th>
26
- <th>Subtotal</th>
27
- </tr>
28
- </thead>
29
- <tbody>
30
- {order.lineItems.map((item, index) => (
31
- <tr key={index}>
32
- <td>{item.sku.replace(/-/g, ' ').toUpperCase()}</td>
33
- <td>{item.sku}</td>
34
- <td>£{item.price.toFixed(2)}</td>
35
- <td>x{item.quantity}</td>
36
- <td>£{'0.00' ||item.discount}</td>
37
- <td>£{(item.quantity * item.price).toFixed(2)}</td>
38
- </tr>
39
- ))}
40
- </tbody>
41
- </>
42
- )}
43
-
44
- {order?.type === 'order' && (
45
- <>
46
- <thead>
47
- <tr>
48
- <th>Product</th>
49
- <th>SKU</th>
50
- <th>Price</th>
51
- <th>Quantity</th>
52
- <th>Type</th>
53
- <th>Subtotal</th>
54
- </tr>
55
- </thead>
56
- <tbody>
57
- {order.lineItems.map((item, index) => (
58
- <tr key={index}>
59
- <td>{item.sku.replace(/-/g, ' ').toUpperCase()}</td>
60
- <td>{item.sku}</td>
61
- <td>£{item.price.price.toFixed(2)}</td>
62
- <td>x{item.quantity}</td>
63
- <td>{item.type}</td>
64
- <td>£{(item.quantity * item.price.price).toFixed(2)}</td>
65
- </tr>
66
- ))}
67
- </tbody>
68
- </>
69
- )}
70
- </table>
71
- ) : (
72
- <p>No line items found.</p>
73
- )}
74
- </div>
75
- </div>
76
-
77
- {/* Order Totals Section */}
78
- <div className="totals-cont">
79
- <div className="totals-body">
80
- <table className="totals-table">
81
- <tbody>
82
- <tr>
83
- <td>Currency:</td>
84
- <td>{order?.currency}</td>
85
- </tr>
86
- <tr>
87
- <td>Items Subtotal:</td>
88
- <td>£{(order?.subTotal ?? order?.subTotal)?.toFixed(2)}</td>
89
- </tr>
90
- <tr>
91
- <td>Shipping:</td>
92
- <td>£{'0.00' || order?.shipping.toFixed(2)}</td>
93
- </tr>
94
- <tr>
95
- <td>Tax:</td>
96
- <td>£{(order?.tax ?? order?.tax)?.toFixed(2)}</td>
97
- </tr>
98
- <tr className="order-total">
99
- <td><strong>Total:</strong></td>
100
- <td><strong>£{order?.total?.toFixed(2)}</strong></td>
101
- </tr>
102
- </tbody>
103
- </table>
104
- </div>
105
- </div>
106
-
107
- </div>
108
- </div>
109
- </div>
110
- );
111
- }
112
-
113
- export default LineItems;
@@ -1,56 +0,0 @@
1
- import React, {useState, useEffect} from "react";
2
- import {useDispatch, useSelector} from "react-redux";
3
- import { login } from "../../slices/authSlice";
4
- import { Link } from "react-router-dom";
5
-
6
- const LoginForm = () => {
7
-
8
- const saltRounds = 12;
9
- const dispatch = useDispatch();
10
- const [username, setUsername] = useState("");
11
- const [password, setPassword] = useState("");
12
- const [loginMessage, setLoginMessage] = useState("");
13
- const {authError} = useSelector(state => state.auth);
14
-
15
- const handleLogin = async (e) => {
16
- e.preventDefault();
17
-
18
- if (username === "" || password === "") {
19
- setLoginMessage("Please enter your email and password");
20
- return;
21
- }
22
- try {
23
- dispatch(login({username, password}));
24
-
25
- } catch (error) {
26
- setLoginMessage("Error logging in: " + error.response?.data?.message || "Unknown error");
27
- console.error('Error logging in:', error);
28
- }
29
- }
30
-
31
- useEffect(() => {
32
- if (authError) {
33
- setLoginMessage(authError);
34
- }
35
- }, [authError])
36
-
37
- return (
38
- <div className="login">
39
- <form className="login-form" onSubmit={handleLogin}>
40
- <div className="input-container">
41
- <input type="text" placeholder="Email address / Username" className="email-input-icon" value={username} onChange={(e) => { setUsername(e.target.value); setLoginMessage(''); }} />
42
- </div>
43
- <div className="input-container">
44
- <input type="password" placeholder="Password" className="password-input-icon" value={password} onChange={(e) => { setPassword(e.target.value); setLoginMessage(''); }}/>
45
- </div>
46
- <div>
47
- <button type="submit">Sign in</button>
48
- <Link to="/login/forgotten-password">password reset</Link>
49
- </div>
50
- <span id="login-message">{loginMessage}</span>
51
- </form>
52
- </div>
53
- );
54
- }
55
-
56
- export default LoginForm;
@@ -1,56 +0,0 @@
1
- .login {
2
- display: flex;
3
- flex-direction: column;
4
- align-items: center;
5
- justify-content: center;
6
-
7
- .login-form {
8
- display: flex;
9
- flex-direction: column;
10
- width: 400px;
11
-
12
- #login-message {
13
- color: @red-1;
14
- min-height: 40px;
15
- }
16
-
17
- button.loading {
18
- opacity: 0.6;
19
- cursor: not-allowed;
20
- }
21
-
22
- a {
23
- text-decoration: none;
24
- color: @green-1;
25
- margin-left: 10px;
26
- }
27
-
28
- .input-container {
29
- position: relative;
30
-
31
- input {
32
- padding-left: 50px;
33
- }
34
-
35
- &::before {
36
- content: '';
37
- position: absolute;
38
- top: 50%;
39
- left: 18px;
40
- transform: translateY(-50%);
41
- width: 20px;
42
- height: 20px;
43
- background-size: contain;
44
- background-repeat: no-repeat;
45
- }
46
-
47
- &:nth-child(1)::before {
48
- background-image: url('../assets/user-black.svg');
49
- }
50
-
51
- &:nth-child(2)::before {
52
- background-image: url('../assets/lock.svg');
53
- }
54
- }
55
- }
56
- }
@@ -1,18 +0,0 @@
1
- import bin from '../../assets/bin.svg';
2
-
3
- const Notes = ({ item, onChange, remove }) => {
4
- return (
5
- <div className="note-item">
6
- <div className="note-item-body">
7
- <textarea
8
- value={item.note || ''}
9
- onChange={(e) => onChange({ note: e.target.value })}
10
- placeholder="Add a note..."
11
- />
12
- </div>
13
- <button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
14
- </div>
15
- );
16
- };
17
-
18
- export default Notes;