@gnar-engine/cli 1.0.3 → 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.
- package/bootstrap/deploy.localdev.yml +18 -31
- package/bootstrap/secrets.localdev.yml +7 -12
- package/bootstrap/services/user/Dockerfile +1 -1
- package/package.json +1 -1
- package/src/config.js +2 -1
- package/src/dev/dev.service.js +44 -16
- package/src/scaffolder/commands.js +11 -4
- package/src/scaffolder/scaffolder.handler.js +228 -55
- package/templates/service/Dockerfile.hbs +4 -1
- package/templates/service/package.json.hbs +14 -16
- package/templates/service/{app.js.hbs → src/app.js.hbs} +8 -4
- package/templates/service/{commands → src/commands}/{{serviceName}}.handler.js.hbs +1 -2
- package/{bootstrap/services/agent/src/config.js → templates/service/src/mongodb.config.js.hbs} +11 -18
- package/templates/service/{config.js.hbs → src/mysql.config.js.hbs} +6 -0
- package/{bootstrap/services/agent/src/schema/Agent.schema.js → templates/service/src/schema/{{serviceName}}.schema.js.hbs} +3 -3
- package/templates/service/src/services/mongodb.{{serviceName}}.service.js.hbs +70 -0
- package/bootstrap/services/agent/Dockerfile +0 -23
- package/bootstrap/services/agent/notes.md +0 -28
- package/bootstrap/services/agent/package.json +0 -16
- package/bootstrap/services/agent/src/app.js +0 -52
- package/bootstrap/services/agent/src/commands/agent.handler.js +0 -104
- package/bootstrap/services/agent/src/controllers/http.controller.js +0 -44
- package/bootstrap/services/agent/src/controllers/message.controller.js +0 -51
- package/bootstrap/services/agent/src/db/migrations/01-init.js +0 -50
- package/bootstrap/services/agent/src/db/migrations/02-agent-service-init.js +0 -36
- package/bootstrap/services/agent/src/policies/agent.policy.js +0 -13
- package/bootstrap/services/agent/src/services/agent.service.js +0 -259
- package/bootstrap/services/agent/src/services/chatgpt.service.js +0 -46
- package/bootstrap/services/agent/src/services/manifest.service.js +0 -21
- package/bootstrap/services/portal/Dockerfile +0 -23
- package/bootstrap/services/portal/Dockerfile.remote +0 -40
- package/bootstrap/services/portal/README.md +0 -22
- package/bootstrap/services/portal/nginx.conf +0 -12
- package/bootstrap/services/portal/package.json +0 -59
- package/bootstrap/services/portal/public/favicon.ico +0 -0
- package/bootstrap/services/portal/public/gnar-white.png +0 -0
- package/bootstrap/services/portal/public/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/public/index.html +0 -43
- package/bootstrap/services/portal/public/logo192.png +0 -0
- package/bootstrap/services/portal/public/logo512.png +0 -0
- package/bootstrap/services/portal/public/manifest.json +0 -25
- package/bootstrap/services/portal/public/robots.txt +0 -3
- package/bootstrap/services/portal/src/App.js +0 -56
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black.svg +0 -1
- package/bootstrap/services/portal/src/assets/Logo_Anchord_Black_Green.svg +0 -1
- package/bootstrap/services/portal/src/assets/Logo_Anchord_White_Green.svg +0 -1
- package/bootstrap/services/portal/src/assets/activity.svg +0 -3
- package/bootstrap/services/portal/src/assets/arrow.svg +0 -3
- package/bootstrap/services/portal/src/assets/bin-white.svg +0 -3
- package/bootstrap/services/portal/src/assets/bin.svg +0 -3
- package/bootstrap/services/portal/src/assets/check.svg +0 -3
- package/bootstrap/services/portal/src/assets/chevron.svg +0 -3
- package/bootstrap/services/portal/src/assets/contact.svg +0 -3
- package/bootstrap/services/portal/src/assets/dots-vertical.svg +0 -5
- package/bootstrap/services/portal/src/assets/eye-off.svg +0 -3
- package/bootstrap/services/portal/src/assets/eye.svg +0 -4
- package/bootstrap/services/portal/src/assets/gnar-engine-black.svg +0 -47
- package/bootstrap/services/portal/src/assets/gnar-engine-white.svg +0 -47
- package/bootstrap/services/portal/src/assets/gnar_engine.svg +0 -3
- package/bootstrap/services/portal/src/assets/gnarengine-logo-black.png +0 -0
- package/bootstrap/services/portal/src/assets/home.svg +0 -3
- package/bootstrap/services/portal/src/assets/link.svg +0 -3
- package/bootstrap/services/portal/src/assets/lock.svg +0 -3
- package/bootstrap/services/portal/src/assets/package.svg +0 -4
- package/bootstrap/services/portal/src/assets/raffle.svg +0 -3
- package/bootstrap/services/portal/src/assets/settings.svg +0 -4
- package/bootstrap/services/portal/src/assets/shopping-bag.svg +0 -3
- package/bootstrap/services/portal/src/assets/user-black.svg +0 -3
- package/bootstrap/services/portal/src/assets/user.svg +0 -3
- package/bootstrap/services/portal/src/assets/users.svg +0 -3
- package/bootstrap/services/portal/src/assets/wallet.svg +0 -3
- package/bootstrap/services/portal/src/css/style.css +0 -1007
- package/bootstrap/services/portal/src/data/data.js +0 -70
- package/bootstrap/services/portal/src/features/attributeFormRow/AttributeFormRow.jsx +0 -32
- package/bootstrap/services/portal/src/features/billingShipping/BillingShipping.jsx +0 -160
- package/bootstrap/services/portal/src/features/crud/crudEdit.less +0 -230
- package/bootstrap/services/portal/src/features/crud/crudList.less +0 -134
- package/bootstrap/services/portal/src/features/crud/crudPage.less +0 -31
- package/bootstrap/services/portal/src/features/crudContact/CrudContactList.jsx +0 -108
- package/bootstrap/services/portal/src/features/crudContact/CrudContactSingle.jsx +0 -243
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderList.jsx +0 -109
- package/bootstrap/services/portal/src/features/crudOrder/CrudOrderSingle.jsx +0 -315
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductList.jsx +0 -104
- package/bootstrap/services/portal/src/features/crudProducts/CrudProductSingle.jsx +0 -388
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesList.jsx +0 -104
- package/bootstrap/services/portal/src/features/crudRaffles/CrudRafflesSingle.jsx +0 -208
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionList.jsx +0 -110
- package/bootstrap/services/portal/src/features/crudSubscription/CrudSubscriptionSingle.jsx +0 -261
- package/bootstrap/services/portal/src/features/crudUser/CrudUserList.jsx +0 -107
- package/bootstrap/services/portal/src/features/crudUser/CrudUserSingle.jsx +0 -402
- package/bootstrap/services/portal/src/features/inventoryFormRow/InventoryFormRow.jsx +0 -30
- package/bootstrap/services/portal/src/features/lineItems/LineItems.jsx +0 -113
- package/bootstrap/services/portal/src/features/loginForm/LoginForm.jsx +0 -56
- package/bootstrap/services/portal/src/features/loginForm/loginForm.less +0 -56
- package/bootstrap/services/portal/src/features/notes/Notes.jsx +0 -18
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetForm.jsx +0 -96
- package/bootstrap/services/portal/src/features/passwordReset/PasswordResetRequestForm.jsx +0 -74
- package/bootstrap/services/portal/src/features/priceFormRow/PriceFormRow.jsx +0 -102
- package/bootstrap/services/portal/src/features/priceFormRow/priceFormRow.less +0 -24
- package/bootstrap/services/portal/src/features/raffleEntriesList/RaffleEntriesList.jsx +0 -99
- package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx +0 -46
- package/bootstrap/services/portal/src/features/sidebar/Sidebar.jsx +0 -64
- package/bootstrap/services/portal/src/features/sidebar/sidebar.less +0 -49
- package/bootstrap/services/portal/src/features/skus/Skus.jsx +0 -109
- package/bootstrap/services/portal/src/features/subscriptionSchedule/SubscriptionSchedule.jsx +0 -44
- package/bootstrap/services/portal/src/features/taxonomyFormRow/TaxonomyFormRow.jsx +0 -32
- package/bootstrap/services/portal/src/features/user/User.jsx +0 -54
- package/bootstrap/services/portal/src/features/user/user.less +0 -57
- package/bootstrap/services/portal/src/includes/utilities.js +0 -259
- package/bootstrap/services/portal/src/index.js +0 -14
- package/bootstrap/services/portal/src/layouts/CrudLayout.jsx +0 -50
- package/bootstrap/services/portal/src/layouts/LoginLayout.jsx +0 -17
- package/bootstrap/services/portal/src/layouts/PortalLayout.jsx +0 -48
- package/bootstrap/services/portal/src/layouts/loginLayout.less +0 -33
- package/bootstrap/services/portal/src/layouts/portalLayout.less +0 -67
- package/bootstrap/services/portal/src/pages/contacts/Contacts.jsx +0 -199
- package/bootstrap/services/portal/src/pages/dashboard/Dashboard.jsx +0 -17
- package/bootstrap/services/portal/src/pages/integrations/Integrations.jsx +0 -10
- package/bootstrap/services/portal/src/pages/login/Login.jsx +0 -15
- package/bootstrap/services/portal/src/pages/login/login.less +0 -10
- package/bootstrap/services/portal/src/pages/orders/Orders.jsx +0 -199
- package/bootstrap/services/portal/src/pages/passwordReset/PasswordResetPage.jsx +0 -15
- package/bootstrap/services/portal/src/pages/passwordResetRequest/PasswordResetRequestPage.jsx +0 -15
- package/bootstrap/services/portal/src/pages/payments/Payments.jsx +0 -10
- package/bootstrap/services/portal/src/pages/portal/Portal.jsx +0 -43
- package/bootstrap/services/portal/src/pages/products/Products.jsx +0 -212
- package/bootstrap/services/portal/src/pages/raffleEntries/RaffleEntries.jsx +0 -124
- package/bootstrap/services/portal/src/pages/raffles/Raffles.jsx +0 -186
- package/bootstrap/services/portal/src/pages/reports/Reports.jsx +0 -10
- package/bootstrap/services/portal/src/pages/settings/Settings.jsx +0 -10
- package/bootstrap/services/portal/src/pages/subscriptions/Subscriptions.jsx +0 -199
- package/bootstrap/services/portal/src/pages/users/Users.jsx +0 -193
- package/bootstrap/services/portal/src/pages/users/users.less +0 -25
- package/bootstrap/services/portal/src/slices/authSlice.js +0 -71
- package/bootstrap/services/portal/src/store/configureStore.js +0 -12
- package/bootstrap/services/portal/src/styles/global.less +0 -159
- package/bootstrap/services/portal/src/styles/inputs.less +0 -157
- package/bootstrap/services/portal/src/styles/main.less +0 -26
- package/bootstrap/services/portal/src/ui/collapsible/Collapsible.jsx +0 -97
- package/bootstrap/services/portal/src/ui/collapsible/collapsible.less +0 -23
- package/bootstrap/services/portal/src/ui/customCheckbox/CustomCheckbox.jsx +0 -17
- package/bootstrap/services/portal/src/ui/customCheckbox/customCheckbox.less +0 -42
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelect.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customMultiSelect/CustomMultiSelectPeriod.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customSelect/CustomSelect.jsx +0 -63
- package/bootstrap/services/portal/src/ui/customSelect/customSelect.less +0 -92
- package/bootstrap/services/portal/src/ui/goBack/GoBack.jsx +0 -19
- package/bootstrap/services/portal/src/ui/loader/Loader.jsx +0 -12
- package/bootstrap/services/portal/src/ui/pagination/Pagination.jsx +0 -23
- package/bootstrap/services/portal/src/ui/repeater/Repeater.jsx +0 -29
- package/bootstrap/services/portal/src/ui/saveButton/SaveButton.jsx +0 -69
- package/bootstrap/services/portal/src/ui/saveButton/saveButton.less +0 -0
- package/bootstrap/services/user/src/db/seeders/development/02-portal-admin-user.js +0 -27
- package/templates/service/schema/{{serviceName}}.schema.js.hbs +0 -14
- /package/templates/service/{controllers → src/controllers}/http.controller.js.hbs +0 -0
- /package/templates/service/{controllers → src/controllers}/message.controller.js.hbs +0 -0
- /package/templates/service/{db → src/mysql.db}/migrations/01-init.js.hbs +0 -0
- /package/templates/service/{db → src/mysql.db}/migrations/02-{{lowerCase serviceName}}-service-init.js.hbs +0 -0
- /package/templates/service/{policies → src/policies}/{{serviceName}}.policy.js.hbs +0 -0
- /package/templates/service/{services/{{serviceName}}.service.js.hbs → src/services/mysql.{{serviceName}}.service.js.hbs} +0 -0
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react"
|
|
2
|
-
import gnarEngine from "@gnar-engine/js-client";
|
|
3
|
-
import { Link } from "react-router-dom";
|
|
4
|
-
|
|
5
|
-
const PasswordResetForm = () => {
|
|
6
|
-
|
|
7
|
-
const [email, setEmail] = useState("");
|
|
8
|
-
const [password, setPassword] = useState("");
|
|
9
|
-
const [confirmPassword, setConfirmPassword] = useState("");
|
|
10
|
-
const [message, setMessage] = useState("");
|
|
11
|
-
const [success, setSuccess] = useState(false);
|
|
12
|
-
const [loading, setLoading] = useState(false);
|
|
13
|
-
|
|
14
|
-
const handlePasswordResetSubmit = async (e) => {
|
|
15
|
-
|
|
16
|
-
e.preventDefault();
|
|
17
|
-
setLoading(true);
|
|
18
|
-
|
|
19
|
-
// get token from url
|
|
20
|
-
const path = window.location.pathname;
|
|
21
|
-
const token = path.split('/').pop();
|
|
22
|
-
|
|
23
|
-
if (email === "") {
|
|
24
|
-
setMessage("Please enter your email address");
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
if (token === "") {
|
|
29
|
-
setMessage("Invalid password reset link");
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (password === "") {
|
|
34
|
-
setMessage("Please enter a new password");
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
if (confirmPassword === "" || password !== confirmPassword) {
|
|
39
|
-
setMessage("Passwords do not match");
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
(async () => {
|
|
44
|
-
try {
|
|
45
|
-
console.log('Resetting password for email:', email, 'with token:', token);
|
|
46
|
-
// change password
|
|
47
|
-
await gnarEngine.user.changePassword({email, token , password});
|
|
48
|
-
await gnarEngine.user.authenticate(email, password);
|
|
49
|
-
|
|
50
|
-
setMessage('');
|
|
51
|
-
setSuccess(true);
|
|
52
|
-
} catch (error) {
|
|
53
|
-
if (error.response.data.message) {
|
|
54
|
-
setMessage("Error resetting password: " + error.response.data.message);
|
|
55
|
-
console.error('Error resetting password:', error);
|
|
56
|
-
} else if (error.response.data) {
|
|
57
|
-
setMessage("Error resetting password: " + error.response.data);
|
|
58
|
-
console.error('Error resetting password:', error);
|
|
59
|
-
}
|
|
60
|
-
} finally {
|
|
61
|
-
setLoading(false);
|
|
62
|
-
}
|
|
63
|
-
})();
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return (
|
|
67
|
-
<div className="login">
|
|
68
|
-
<h2>Password reset</h2>
|
|
69
|
-
|
|
70
|
-
<form className="login-form" onSubmit={handlePasswordResetSubmit}>
|
|
71
|
-
<input type="email" placeholder="Email address" className="email-input-icon" value={email} onChange={(e) => { setEmail(e.target.value); setMessage(''); }}/>
|
|
72
|
-
<input type="password" placeholder="Enter new password" className="password-input-icon" value={password} onChange={(e) => { setPassword(e.target.value); setMessage(''); }}/>
|
|
73
|
-
<input type="password" placeholder="Confirm new password" className="password-input-icon" value={confirmPassword} onChange={(e) => { setConfirmPassword(e.target.value); setMessage(''); }}/>
|
|
74
|
-
<div class="password-requirements">
|
|
75
|
-
<p>To ensure the security of your account, your new password must meet the following criteria:</p>
|
|
76
|
-
<ul>
|
|
77
|
-
<li><strong>Minimum Length</strong>: Your password must be at least <strong>8 characters</strong> long.</li>
|
|
78
|
-
<li><strong>Uppercase Letters</strong>: Include at least <strong>one uppercase letter</strong> (A-Z).</li>
|
|
79
|
-
<li><strong>Lowercase Letters</strong>: Include at least <strong>one lowercase letter</strong> (a-z).</li>
|
|
80
|
-
<li><strong>Numbers</strong>: Include at least <strong>one number</strong> (0-9).</li>
|
|
81
|
-
<li><strong>Special Characters</strong>: Include at least <strong>one special character</strong> from the following: <strong>@, $, !, %, *, ?, &</strong>.</li>
|
|
82
|
-
</ul>
|
|
83
|
-
<p>Please ensure your password meets all of these requirements before submitting.</p>
|
|
84
|
-
</div>
|
|
85
|
-
<button type="submit" disabled={loading}>Update password</button>
|
|
86
|
-
<span id="login-message">{message}</span>
|
|
87
|
-
|
|
88
|
-
{success &&
|
|
89
|
-
<span id="login-message">Password reset successful. <Link to="/login">Click here to login</Link></span>
|
|
90
|
-
}
|
|
91
|
-
</form>
|
|
92
|
-
</div>
|
|
93
|
-
);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
export default PasswordResetForm;
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react"
|
|
2
|
-
import gnarEngine from "@gnar-engine/js-client";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const PasswordResetForm = () => {
|
|
6
|
-
|
|
7
|
-
const [email, setEmail] = useState("");
|
|
8
|
-
const [message, setMessage] = useState("");
|
|
9
|
-
const [success, setSuccess] = useState(false);
|
|
10
|
-
const [loading, setLoading] = useState(null);
|
|
11
|
-
|
|
12
|
-
const handleRequestSubmit = async (e) => {
|
|
13
|
-
|
|
14
|
-
e.preventDefault();
|
|
15
|
-
|
|
16
|
-
setLoading('loading');
|
|
17
|
-
|
|
18
|
-
if (email === "") {
|
|
19
|
-
setMessage("Please enter your email address")
|
|
20
|
-
|
|
21
|
-
setLoading('error');
|
|
22
|
-
setTimeout(() => {
|
|
23
|
-
setLoading(null);
|
|
24
|
-
}, 3000);
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
(async () => {
|
|
29
|
-
try {
|
|
30
|
-
// reset password
|
|
31
|
-
await gnarEngine.sendPasswordReset({email});
|
|
32
|
-
|
|
33
|
-
setSuccess(true);
|
|
34
|
-
|
|
35
|
-
setLoading('success');
|
|
36
|
-
setTimeout(() => {
|
|
37
|
-
setLoading(null);
|
|
38
|
-
}, 3000);
|
|
39
|
-
|
|
40
|
-
} catch (error) {
|
|
41
|
-
if (error.response.data.message) {
|
|
42
|
-
setMessage("Error requesting password reset: " + error.response.data.message);
|
|
43
|
-
console.error('Error requesting password reset:', error);
|
|
44
|
-
} else if (error.response.data) {
|
|
45
|
-
setMessage("Error requesting password reset: " + error.response.data);
|
|
46
|
-
console.error('Error requesting password reset:', error);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
setLoading('error');
|
|
50
|
-
setTimeout(() => {
|
|
51
|
-
setLoading(null);
|
|
52
|
-
}, 3000);
|
|
53
|
-
}
|
|
54
|
-
})();
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return (
|
|
58
|
-
<div className="login">
|
|
59
|
-
<h2>Password reset</h2>
|
|
60
|
-
|
|
61
|
-
<form className="login-form" onSubmit={handleRequestSubmit}>
|
|
62
|
-
<input type="email" placeholder="Email address" className="email-input-icon" value={email} onChange={(e) => { setEmail(e.target.value); setMessage(''); }}/>
|
|
63
|
-
<button className={loading} type="submit">Reset password</button>
|
|
64
|
-
<span id="login-message">{message}</span>
|
|
65
|
-
|
|
66
|
-
{success &&
|
|
67
|
-
<span id="login-message">A reset password link will be emailed to this email if it exists as a user.</span>
|
|
68
|
-
}
|
|
69
|
-
</form>
|
|
70
|
-
</div>
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export default PasswordResetForm;
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { useState, useEffect } from 'react';
|
|
2
|
-
import bin from '../../assets/bin.svg';
|
|
3
|
-
import { currencies, productPriceTypes, productIntervals } from '../../data/data';
|
|
4
|
-
import CustomSelect from '../../ui/customSelect/CustomSelect';
|
|
5
|
-
|
|
6
|
-
const PriceFormRow = ({ item, onChange, remove, showLabels }) => {
|
|
7
|
-
|
|
8
|
-
const [selectedCurrency, setSelectedCurrency] = useState(null);
|
|
9
|
-
const [selectedInterval, setSelectedInterval] = useState(null);
|
|
10
|
-
const [selectedPriceType, setSelectedPriceType] = useState(null);
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (item.currency) {
|
|
14
|
-
const currency = currencies.find(currency => {
|
|
15
|
-
return currency.id === item.currency;
|
|
16
|
-
});
|
|
17
|
-
setSelectedCurrency(currency || null);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (item.type) {
|
|
21
|
-
const priceType = productPriceTypes.find(priceType => {
|
|
22
|
-
return priceType.id === item.type;
|
|
23
|
-
});
|
|
24
|
-
setSelectedPriceType(priceType || null);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (item.interval) {
|
|
28
|
-
const interval = productIntervals.find(interval => {
|
|
29
|
-
return interval.id === item.interval;
|
|
30
|
-
}
|
|
31
|
-
);
|
|
32
|
-
setSelectedInterval(interval || null);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
}, [item]);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div className='form-row'>
|
|
39
|
-
<div className="input-cont">
|
|
40
|
-
{showLabels && <label>Currency</label>}
|
|
41
|
-
<CustomSelect
|
|
42
|
-
name="currency"
|
|
43
|
-
placeholder="Select currency"
|
|
44
|
-
options={currencies}
|
|
45
|
-
labelKey="currency"
|
|
46
|
-
setSelectedOption={(currency) => onChange("currency", currency.id)}
|
|
47
|
-
selectedOption={selectedCurrency}
|
|
48
|
-
/>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<div className="input-cont">
|
|
52
|
-
{showLabels && <label>Price Type</label>}
|
|
53
|
-
<CustomSelect
|
|
54
|
-
name="type"
|
|
55
|
-
placeholder="Select price type"
|
|
56
|
-
options={productPriceTypes}
|
|
57
|
-
labelKey="type"
|
|
58
|
-
setSelectedOption={(type) => onChange("type", type.id)}
|
|
59
|
-
selectedOption={selectedPriceType}
|
|
60
|
-
/>
|
|
61
|
-
</div>
|
|
62
|
-
|
|
63
|
-
{item.type === 'recurring' && (
|
|
64
|
-
<div className="input-cont">
|
|
65
|
-
{showLabels && <label>Interval</label>}
|
|
66
|
-
<CustomSelect
|
|
67
|
-
name="interval"
|
|
68
|
-
placeholder="Select interval"
|
|
69
|
-
options={productIntervals}
|
|
70
|
-
labelKey="interval"
|
|
71
|
-
setSelectedOption={(interval) => onChange("interval", interval.id)}
|
|
72
|
-
selectedOption={selectedInterval}
|
|
73
|
-
/>
|
|
74
|
-
</div>
|
|
75
|
-
)}
|
|
76
|
-
|
|
77
|
-
<div className="input-cont">
|
|
78
|
-
{showLabels && <label>Price</label>}
|
|
79
|
-
<input
|
|
80
|
-
type="text"
|
|
81
|
-
name='price'
|
|
82
|
-
value={item.price}
|
|
83
|
-
onChange={(e) => onChange("price", Number(e.target.value))}
|
|
84
|
-
/>
|
|
85
|
-
</div>
|
|
86
|
-
|
|
87
|
-
<div className="input-cont">
|
|
88
|
-
{showLabels && <label>Sale price</label>}
|
|
89
|
-
<input
|
|
90
|
-
type="text"
|
|
91
|
-
name='salePrice'
|
|
92
|
-
value={item.salePrice}
|
|
93
|
-
onChange={(e) => onChange("salePrice", Number(e.target.value))}
|
|
94
|
-
/>
|
|
95
|
-
</div>
|
|
96
|
-
|
|
97
|
-
<button className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
|
|
98
|
-
</div>
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export default PriceFormRow;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
.form-row {
|
|
2
|
-
display: flex;
|
|
3
|
-
justify-content: space-between;
|
|
4
|
-
margin-bottom: 10px;
|
|
5
|
-
gap: 20px;
|
|
6
|
-
align-items: center;
|
|
7
|
-
flex-wrap: wrap;
|
|
8
|
-
|
|
9
|
-
.input-cont {
|
|
10
|
-
display: flex;
|
|
11
|
-
flex-direction: column;
|
|
12
|
-
|
|
13
|
-
input {
|
|
14
|
-
width: 250px;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
.form-group.categories {
|
|
20
|
-
width: 100%;
|
|
21
|
-
.custom-select-input {
|
|
22
|
-
min-width: 500px !important;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import CustomCheckbox from '../../ui/customCheckbox/CustomCheckbox';
|
|
3
|
-
|
|
4
|
-
const RaffleEntriesList = ({setSelectedSingleItemId, setView, selectedEntryIds, setSelectedEntryIds, raffleEntries, message }) => {
|
|
5
|
-
|
|
6
|
-
const allSelected = raffleEntries.length > 0 && selectedEntryIds.size === raffleEntries.length;
|
|
7
|
-
|
|
8
|
-
const toggleEntrySelection = (entryId) => {
|
|
9
|
-
setSelectedEntryIds(prev => {
|
|
10
|
-
const newSet = new Set(prev);
|
|
11
|
-
if (newSet.has(entryId)) {
|
|
12
|
-
newSet.delete(entryId);
|
|
13
|
-
} else {
|
|
14
|
-
newSet.add(entryId);
|
|
15
|
-
}
|
|
16
|
-
return newSet;
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const toggleSelectAll = () => {
|
|
21
|
-
if (allSelected) {
|
|
22
|
-
setSelectedEntryIds(new Set());
|
|
23
|
-
} else {
|
|
24
|
-
setSelectedEntryIds(new Set(raffleEntries.map(entry => entry.id)));
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const columns = [
|
|
29
|
-
{ columnLabel: 'Name', dataKey: 'user_name' },
|
|
30
|
-
{ columnLabel: 'Entry ID', dataKey: 'entry_id' },
|
|
31
|
-
{ columnLabel: 'Email', dataKey: 'user_email' },
|
|
32
|
-
{ columnLabel: 'Order ID', dataKey: 'order_id' },
|
|
33
|
-
{ columnLabel: 'Subscription ID', dataKey: 'subscription_id' },
|
|
34
|
-
{ columnLabel: 'Multiplier', dataKey: 'multiplier' }
|
|
35
|
-
];
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<div className="">
|
|
39
|
-
<div className='pagination-labels-cont'>
|
|
40
|
-
<div className='pagination-count'>
|
|
41
|
-
Showing {raffleEntries.length} of {raffleEntries.length} raffle entr{raffleEntries.length !== 1 ? 'ies' : 'y'}
|
|
42
|
-
</div>
|
|
43
|
-
<div className="pagination-count">
|
|
44
|
-
{selectedEntryIds.size} of {raffleEntries.length} selected
|
|
45
|
-
</div>
|
|
46
|
-
</div>
|
|
47
|
-
|
|
48
|
-
<div className='crud-list'>
|
|
49
|
-
<table className='custom-table'>
|
|
50
|
-
<thead>
|
|
51
|
-
<tr>
|
|
52
|
-
<th className="checkbox">
|
|
53
|
-
<CustomCheckbox
|
|
54
|
-
name="selectAll"
|
|
55
|
-
checked={allSelected}
|
|
56
|
-
setChecked={toggleSelectAll}
|
|
57
|
-
/>
|
|
58
|
-
</th>
|
|
59
|
-
{columns.map(column => (
|
|
60
|
-
<th key={column.dataKey}>{column.columnLabel}</th>
|
|
61
|
-
))}
|
|
62
|
-
</tr>
|
|
63
|
-
</thead>
|
|
64
|
-
|
|
65
|
-
<tbody>
|
|
66
|
-
{message ? (
|
|
67
|
-
<tr>
|
|
68
|
-
<td colSpan={columns.length + 1}>{message}</td>
|
|
69
|
-
</tr>
|
|
70
|
-
) : (
|
|
71
|
-
raffleEntries.length > 0 ? (
|
|
72
|
-
raffleEntries.map(entry => (
|
|
73
|
-
<tr key={entry.id}>
|
|
74
|
-
<td>
|
|
75
|
-
<CustomCheckbox
|
|
76
|
-
name={`checkbox-${entry.id}`}
|
|
77
|
-
checked={selectedEntryIds.has(entry.id)}
|
|
78
|
-
setChecked={() => toggleEntrySelection(entry.id)}
|
|
79
|
-
/>
|
|
80
|
-
</td>
|
|
81
|
-
{columns.map(column => (
|
|
82
|
-
<td key={column.dataKey}>{entry[column.dataKey]}</td>
|
|
83
|
-
))}
|
|
84
|
-
</tr>
|
|
85
|
-
))
|
|
86
|
-
) : (
|
|
87
|
-
<tr>
|
|
88
|
-
<td colSpan={columns.length + 1}>{message}</td>
|
|
89
|
-
</tr>
|
|
90
|
-
)
|
|
91
|
-
)}
|
|
92
|
-
</tbody>
|
|
93
|
-
</table>
|
|
94
|
-
</div>
|
|
95
|
-
</div>
|
|
96
|
-
);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export default RaffleEntriesList;
|
package/bootstrap/services/portal/src/features/raffleProductFormRow/RaffleProductFormRow.jsx
DELETED
|
@@ -1,46 +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 RaffleProductFormRow = ({ item, onChange, remove }) => {
|
|
7
|
-
return (
|
|
8
|
-
<div className='form-row'>
|
|
9
|
-
<div>
|
|
10
|
-
<label>Product SKU</label>
|
|
11
|
-
<input
|
|
12
|
-
type="text"
|
|
13
|
-
name='productSku'
|
|
14
|
-
value={item.productSku}
|
|
15
|
-
onChange={(e) => onChange("productSku", e.target.value)}
|
|
16
|
-
/>
|
|
17
|
-
</div>
|
|
18
|
-
|
|
19
|
-
<div>
|
|
20
|
-
<label>Type (one-time / recurring)</label>
|
|
21
|
-
<input
|
|
22
|
-
type="text"
|
|
23
|
-
name='type'
|
|
24
|
-
value={item.type}
|
|
25
|
-
onChange={(e) => onChange("type", e.target.value)}
|
|
26
|
-
/>
|
|
27
|
-
</div>
|
|
28
|
-
|
|
29
|
-
<div>
|
|
30
|
-
<label>Number of Entries</label>
|
|
31
|
-
<input
|
|
32
|
-
type="number"
|
|
33
|
-
name='numEntries'
|
|
34
|
-
min={1}
|
|
35
|
-
value={item.numEntries}
|
|
36
|
-
onChange={(e) => onChange("numEntries", Number(e.target.value))}
|
|
37
|
-
/>
|
|
38
|
-
</div>
|
|
39
|
-
|
|
40
|
-
<button type="button" className='bin-icon' onClick={remove}><img src={bin} alt="" /></button>
|
|
41
|
-
</div>
|
|
42
|
-
)
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
export default RaffleProductFormRow;
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import { useLocation, Link } from "react-router-dom";
|
|
3
|
-
import { useSelector } from "react-redux";
|
|
4
|
-
import home from '../../assets/home.svg';
|
|
5
|
-
import product from '../../assets/package.svg';
|
|
6
|
-
import activity from '../../assets/activity.svg';
|
|
7
|
-
import users from '../../assets/users.svg';
|
|
8
|
-
import settings from '../../assets/settings.svg';
|
|
9
|
-
import link from '../../assets/link.svg';
|
|
10
|
-
import wallet from '../../assets/wallet.svg';
|
|
11
|
-
import shoppingBag from '../../assets/shopping-bag.svg';
|
|
12
|
-
import contacts from '../../assets/contact.svg';
|
|
13
|
-
import raffle from '../../assets/raffle.svg';
|
|
14
|
-
|
|
15
|
-
const Sidebar = () => {
|
|
16
|
-
const location = useLocation();
|
|
17
|
-
const user = useSelector(state => state.auth.authUser);
|
|
18
|
-
|
|
19
|
-
// Helper function to check if the link is active
|
|
20
|
-
const isActive = (path) => location.pathname === path;
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<div className="sidebar">
|
|
24
|
-
<Link to="/portal/" className={`menu-item ${isActive("/portal/") ? "active" : ""}`}>
|
|
25
|
-
<img src={home} alt="Dashboard"/>Dashboard
|
|
26
|
-
</Link>
|
|
27
|
-
<Link to="/portal/products" className={`menu-item ${isActive("/portal/products") ? "active" : ""}`}>
|
|
28
|
-
<img src={product} alt="Products"/>Products
|
|
29
|
-
</Link>
|
|
30
|
-
<Link to="/portal/orders" className={`menu-item ${isActive("/portal/orders") ? "active" : ""}`}>
|
|
31
|
-
<img src={shoppingBag} alt="Order"/>Orders
|
|
32
|
-
</Link>
|
|
33
|
-
<Link to="/portal/subscriptions" className={`menu-item ${isActive("/portal/subscriptions") ? "active" : ""}`}>
|
|
34
|
-
<img src={shoppingBag} alt="Subscriptions"/>Subscriptions
|
|
35
|
-
</Link>
|
|
36
|
-
<Link to="/portal/integrations" className={`menu-item ${isActive("/portal/integrations") ? "active" : ""}`}>
|
|
37
|
-
<img src={link} alt="Integrations"/>Integrations
|
|
38
|
-
</Link>
|
|
39
|
-
<Link to="/portal/raffles" className={`menu-item ${isActive("/portal/raffles") ? "active" : ""}`}>
|
|
40
|
-
<img src={raffle} alt="Raffles"/>Raffles
|
|
41
|
-
</Link>
|
|
42
|
-
<Link to="/portal/raffle-entries" className={`menu-item ${isActive("/portal/raffle-entries") ? "active" : ""}`}>
|
|
43
|
-
<img src={raffle} alt="Raffle Entries"/>Raffle Entries
|
|
44
|
-
</Link>
|
|
45
|
-
<Link to="/portal/contacts" className={`menu-item ${isActive("/portal/contacts") ? "active" : ""}`}>
|
|
46
|
-
<img src={contacts} alt="Contacts"/>Contacts
|
|
47
|
-
</Link>
|
|
48
|
-
<Link to="/portal/payments" className={`menu-item ${isActive("/portal/payments") ? "active" : ""}`}>
|
|
49
|
-
<img src={wallet} alt="Payments"/>Payments
|
|
50
|
-
</Link>
|
|
51
|
-
<Link to="/portal/users" className={`menu-item ${isActive("/portal/users") ? "active" : ""}`}>
|
|
52
|
-
<img src={users} alt="Users"/>Users
|
|
53
|
-
</Link>
|
|
54
|
-
<Link to="/portal/reports" className={`menu-item ${isActive("/portal/reports") ? "active" : ""}`}>
|
|
55
|
-
<img src={activity} alt="Reports"/>Reports
|
|
56
|
-
</Link>
|
|
57
|
-
<Link to="/portal/settings" className={`menu-item ${isActive("/portal/settings") ? "active" : ""}`}>
|
|
58
|
-
<img src={settings} alt="Settings"/>Settings
|
|
59
|
-
</Link>
|
|
60
|
-
</div>
|
|
61
|
-
);
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export default Sidebar;
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
.sidebar {
|
|
2
|
-
min-width: 240px;
|
|
3
|
-
max-width: 240px;
|
|
4
|
-
padding-top: 30px;
|
|
5
|
-
box-sizing: border-box;
|
|
6
|
-
|
|
7
|
-
.collapsible-cont {
|
|
8
|
-
margin-bottom: 30px;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.collapsible-content-inner {
|
|
12
|
-
padding-left: 32px;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
a {
|
|
16
|
-
text-decoration: none;
|
|
17
|
-
color: @dark-1;
|
|
18
|
-
font-size: 18px;
|
|
19
|
-
font-weight: 400;
|
|
20
|
-
padding-top: 12px;
|
|
21
|
-
padding-bottom: 12px;
|
|
22
|
-
display: inline-block;
|
|
23
|
-
min-width: 100%;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.menu-item {
|
|
27
|
-
display: flex;
|
|
28
|
-
align-items: center;
|
|
29
|
-
gap: 10px;
|
|
30
|
-
padding-left: 16px;
|
|
31
|
-
padding-right: 16px;
|
|
32
|
-
transition: all 0.3s;
|
|
33
|
-
|
|
34
|
-
&.active {
|
|
35
|
-
color: @green-1;
|
|
36
|
-
padding-left: 30px;
|
|
37
|
-
|
|
38
|
-
img {
|
|
39
|
-
filter: none;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
img {
|
|
44
|
-
filter: grayscale(60%) brightness(0.5);
|
|
45
|
-
width: 35px;
|
|
46
|
-
height: 35px;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import React, { useEffect } from 'react';
|
|
2
|
-
import CustomSelect from '../../ui/customSelect/CustomSelect';
|
|
3
|
-
import Repeater from '../../ui/repeater/Repeater';
|
|
4
|
-
import PriceFormRow from '../priceFormRow/PriceFormRow';
|
|
5
|
-
import InventoryFormRow from '../inventoryFormRow/InventoryFormRow';
|
|
6
|
-
import AttributeFormRow from '../attributeFormRow/AttributeFormRow';
|
|
7
|
-
import { taxClasses } from '../../data/data';
|
|
8
|
-
import binWhite from '../../assets/bin-white.svg';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const Skus = ({ item, onChange, remove, showLabels }) => {
|
|
12
|
-
|
|
13
|
-
// useEffect(() => {
|
|
14
|
-
// console.log(item);
|
|
15
|
-
// }, [item]);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return (
|
|
19
|
-
<>
|
|
20
|
-
<div className='card'>
|
|
21
|
-
<div className='card-header'>
|
|
22
|
-
<h2>SKU: {item.sku || ''}</h2>
|
|
23
|
-
<button className="bin-icon white" onClick={remove}><img src={binWhite} alt="Remove" /></button>
|
|
24
|
-
</div>
|
|
25
|
-
<div className='card-content'>
|
|
26
|
-
<div>
|
|
27
|
-
<div className='form-cont'>
|
|
28
|
-
<h2>SKU</h2>
|
|
29
|
-
<div className='input-cont'>
|
|
30
|
-
<input
|
|
31
|
-
type="text"
|
|
32
|
-
name="skus"
|
|
33
|
-
value={item.sku || ''}
|
|
34
|
-
onChange={(e) => onChange('sku', e.target.value)}
|
|
35
|
-
required
|
|
36
|
-
/>
|
|
37
|
-
</div>
|
|
38
|
-
</div>
|
|
39
|
-
<div className='form-cont'>
|
|
40
|
-
<h2>Tax Class</h2>
|
|
41
|
-
<div className="tax-cont">
|
|
42
|
-
<CustomSelect
|
|
43
|
-
name="taxClass"
|
|
44
|
-
placeholder="Tax Class"
|
|
45
|
-
options={taxClasses}
|
|
46
|
-
labelKey="taxClass"
|
|
47
|
-
setSelectedOption={(selected) => onChange("taxClass", selected.id)}
|
|
48
|
-
selectedOption={taxClasses.find(tc => tc.id === item.taxClass) || null}
|
|
49
|
-
/>
|
|
50
|
-
</div>
|
|
51
|
-
</div>
|
|
52
|
-
</div>
|
|
53
|
-
{/* <h2>Attributes</h2>
|
|
54
|
-
<Repeater
|
|
55
|
-
items={attributes}
|
|
56
|
-
setItems={setAttributes}
|
|
57
|
-
defaultItem={{ name: '', value: '' }}
|
|
58
|
-
buttonText="Add new attribute"
|
|
59
|
-
renderRow={(item, index, updateItem, remove) => (
|
|
60
|
-
<AttributeFormRow
|
|
61
|
-
key={index}
|
|
62
|
-
item={item}
|
|
63
|
-
onChange={(field, value) => updateItem({ ...item, [field]: value })}
|
|
64
|
-
remove={remove}
|
|
65
|
-
product={product}
|
|
66
|
-
/>
|
|
67
|
-
)}
|
|
68
|
-
/> */}
|
|
69
|
-
|
|
70
|
-
<h2>Prices</h2>
|
|
71
|
-
<Repeater
|
|
72
|
-
items={item?.prices ?? [{}]}
|
|
73
|
-
setItems={(prices) => onChange('prices', prices)}
|
|
74
|
-
defaultItem={{ price: 0, currency: "GBP", type: "regular" }}
|
|
75
|
-
buttonText="Add new price list"
|
|
76
|
-
renderRow={(item, index, updateItem, remove) => (
|
|
77
|
-
<PriceFormRow
|
|
78
|
-
key={index}
|
|
79
|
-
item={item}
|
|
80
|
-
onChange={(field, value) => updateItem({ ...item, [field]: value })}
|
|
81
|
-
remove={remove}
|
|
82
|
-
showLabels={index === 0}
|
|
83
|
-
/>
|
|
84
|
-
)}
|
|
85
|
-
/>
|
|
86
|
-
|
|
87
|
-
{/* <h2>Inventory</h2>
|
|
88
|
-
<Repeater
|
|
89
|
-
items={inventories}
|
|
90
|
-
setItems={setInventories}
|
|
91
|
-
defaultItem={{ stock: 0, warehouse: "Main" }}
|
|
92
|
-
buttonText="Add new allocation"
|
|
93
|
-
renderRow={(item, index, updateItem, remove) => (
|
|
94
|
-
<InventoryFormRow
|
|
95
|
-
key={index}
|
|
96
|
-
item={item}
|
|
97
|
-
onChange={(field, value) => updateItem({ ...item, [field]: value })}
|
|
98
|
-
remove={remove}
|
|
99
|
-
product={product}
|
|
100
|
-
/>
|
|
101
|
-
)}
|
|
102
|
-
/> */}
|
|
103
|
-
</div>
|
|
104
|
-
</div>
|
|
105
|
-
</>
|
|
106
|
-
);
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
export default Skus;
|