devextreme-cli 1.6.4 → 1.6.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 (40) hide show
  1. package/package.json +3 -3
  2. package/src/applications/application.vue.js +16 -67
  3. package/src/commands.json +0 -3
  4. package/src/templates/react/application/src/components/change-password-form/ChangePasswordForm.tsx +86 -86
  5. package/src/templates/react/application/src/components/create-account-form/CreateAccountForm.tsx +107 -107
  6. package/src/templates/react/application/src/components/side-navigation-menu/SideNavigationMenu.scss +1 -1
  7. package/src/templates/react/application/src/dx-styles.scss +17 -0
  8. package/src/templates/react/application/src/types.tsx +55 -55
  9. package/src/templates/react/sample-pages/tasks/tasks.tsx +1 -0
  10. package/src/templates/vue-v3/application/src/components/side-nav-menu.vue +1 -1
  11. package/src/templates/vue-v3/sample-pages/tasks-page.vue +1 -0
  12. package/src/utility/latest-versions.js +3 -3
  13. package/src/templates/vue-v2/application/devextreme.json +0 -39
  14. package/src/templates/vue-v2/application/src/App.vue +0 -91
  15. package/src/templates/vue-v2/application/src/app-info.js +0 -3
  16. package/src/templates/vue-v2/application/src/app-navigation.js +0 -21
  17. package/src/templates/vue-v2/application/src/auth.js +0 -101
  18. package/src/templates/vue-v2/application/src/components/app-footer.vue +0 -21
  19. package/src/templates/vue-v2/application/src/components/header-toolbar.vue +0 -157
  20. package/src/templates/vue-v2/application/src/components/side-nav-menu.vue +0 -190
  21. package/src/templates/vue-v2/application/src/components/user-panel.vue +0 -114
  22. package/src/templates/vue-v2/application/src/dx-styles.scss +0 -65
  23. package/src/templates/vue-v2/application/src/layouts/side-nav-inner-toolbar.vue +0 -158
  24. package/src/templates/vue-v2/application/src/layouts/side-nav-outer-toolbar.vue +0 -122
  25. package/src/templates/vue-v2/application/src/layouts/single-card.vue +0 -67
  26. package/src/templates/vue-v2/application/src/main.js +0 -16
  27. package/src/templates/vue-v2/application/src/router.js +0 -149
  28. package/src/templates/vue-v2/application/src/themes/metadata.additional.json +0 -11
  29. package/src/templates/vue-v2/application/src/themes/metadata.base.json +0 -7
  30. package/src/templates/vue-v2/application/src/utils/media-query.js +0 -33
  31. package/src/templates/vue-v2/application/src/views/change-password-form.vue +0 -105
  32. package/src/templates/vue-v2/application/src/views/create-account-form.vue +0 -143
  33. package/src/templates/vue-v2/application/src/views/login-form.vue +0 -133
  34. package/src/templates/vue-v2/application/src/views/reset-password-form.vue +0 -108
  35. package/src/templates/vue-v2/application/vue.config.js +0 -1
  36. package/src/templates/vue-v2/page/page.vue +0 -13
  37. package/src/templates/vue-v2/sample-pages/home-page.vue +0 -173
  38. package/src/templates/vue-v2/sample-pages/profile-page.vue +0 -84
  39. package/src/templates/vue-v2/sample-pages/tasks-page.vue +0 -134
  40. package/src/utility/prompts/vue-version.js +0 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devextreme-cli",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "DevExtreme CLI",
5
5
  "keywords": [
6
6
  "devexpress",
@@ -65,7 +65,7 @@
65
65
  "eslint-plugin-vue": "^7.20.0",
66
66
  "eslint-stylish": "^0.2.0",
67
67
  "jest": "^29.7.0",
68
- "jest-image-snapshot": "^6.3.0",
68
+ "jest-image-snapshot": "^6.4.0",
69
69
  "prettier": "^2.8.8",
70
70
  "rimraf": "^2.7.1",
71
71
  "tree-kill": "^1.2.2",
@@ -73,5 +73,5 @@
73
73
  "typescript": "^4.0.2",
74
74
  "typescript-eslint-parser": "^22.0.0"
75
75
  },
76
- "gitHead": "d66609dcd9396442ea85c700c4f58c53b83d388a"
76
+ "gitHead": "ba5f2db7dea0fb8fbf7d77050e305356309f790f"
77
77
  }
@@ -1,7 +1,6 @@
1
1
  const path = require('path');
2
2
  const fs = require('fs');
3
3
  const getLayoutInfo = require('../utility/prompts/layout');
4
- const getVersionInfo = require('../utility/prompts/vue-version');
5
4
  const templateCreator = require('../utility/template-creator');
6
5
  const packageManager = require('../utility/package-manager');
7
6
  const packageJsonUtils = require('../utility/package-json-utils');
@@ -14,21 +13,8 @@ const { toolingVersionOptionName, extractToolingVersion } = require('../utility/
14
13
  const defaultStyles = [
15
14
  'devextreme/dist/css/dx.light.css'
16
15
  ];
17
- const defaultVueVersion = 'v3';
18
-
19
- const getVueVersion = () => {
20
- const devextremeConfig = require('../utility/devextreme-config').read();
21
-
22
- return devextremeConfig.vue
23
- ? `v${devextremeConfig.vue.version}`
24
- : defaultVueVersion;
25
- };
26
-
27
- const preparePackageJsonForTemplate = (appPath, appName, version) => {
28
- if(!version) {
29
- version = getVueVersion();
30
- }
31
16
 
17
+ const preparePackageJsonForTemplate = (appPath, appName) => {
32
18
  const dependencies = [
33
19
  { name: 'sass', version: '^1.34.1' },
34
20
  { name: 'vue-router', version: '^3.0.1' },
@@ -36,12 +22,10 @@ const preparePackageJsonForTemplate = (appPath, appName, version) => {
36
22
  { name: 'sass-loader', version: '^10', dev: true }
37
23
  ];
38
24
 
39
- if(version === 'v3') {
40
- const nameDepends = dependencies.map(d => d.name);
41
- const indexVueRouter = nameDepends.indexOf('vue-router');
25
+ const nameDepends = dependencies.map(d => d.name);
26
+ const indexVueRouter = nameDepends.indexOf('vue-router');
42
27
 
43
- dependencies[indexVueRouter].version = '^4.0.1';
44
- }
28
+ dependencies[indexVueRouter].version = '^4.0.1';
45
29
 
46
30
  const scripts = [
47
31
  { name: 'build-themes', value: 'devextreme build' },
@@ -54,27 +38,18 @@ const preparePackageJsonForTemplate = (appPath, appName, version) => {
54
38
  };
55
39
 
56
40
  async function createVueApp(name, templateOptions) {
57
- const { version } = templateOptions;
58
41
  const toolingVersion = extractToolingVersion(templateOptions);
59
- const argList = ['-p', `@vue/cli${toolingVersion}`, 'vue', 'create', name, '--registry', 'https://registry.npmjs.org/'];
60
-
61
- if(version === 'v2') {
62
- argList.push('-p "Default (Vue 2)"');
63
- } else {
64
- argList.push('-p "Default (Vue 3)"');
65
- }
42
+ const argList = ['-p', `@vue/cli${toolingVersion}`, 'vue', 'create', name, '--registry', 'https://registry.npmjs.org/', '-p "Default (Vue 3)"'];
66
43
 
67
44
  return runCommand('npx', argList);
68
45
  }
69
46
 
70
47
  const create = async(appName, options) => {
71
- const version = await getVersionInfo(options.version);
72
48
  const layout = await getLayoutInfo(options.layout);
73
49
 
74
50
  const templateOptions = {
75
51
  project: stringUtils.humanize(appName),
76
52
  layout: layout,
77
- version: version,
78
53
  [toolingVersionOptionName]: options[toolingVersionOptionName]
79
54
  };
80
55
 
@@ -99,13 +74,7 @@ const getCorrectPath = (extension, pathToApp) => {
99
74
  };
100
75
 
101
76
  const addTemplate = (appPath, appName, templateOptions) => {
102
- let { version } = templateOptions;
103
-
104
- if(!version) {
105
- version = getVueVersion();
106
- }
107
-
108
- const applicationTemplatePath = path.join(templateCreator.getTempaltePath(`vue-${version}`), 'application');
77
+ const applicationTemplatePath = path.join(templateCreator.getTempaltePath('vue-v3'), 'application');
109
78
  const styles = [
110
79
  './themes/generated/theme.additional.css',
111
80
  './themes/generated/theme.base.css',
@@ -116,7 +85,7 @@ const addTemplate = (appPath, appName, templateOptions) => {
116
85
  if(!templateOptions.empty) {
117
86
  addSamplePages(appPath, templateOptions);
118
87
  }
119
- preparePackageJsonForTemplate(appPath, appName, version);
88
+ preparePackageJsonForTemplate(appPath, appName);
120
89
  install({}, appPath, styles);
121
90
  };
122
91
 
@@ -136,14 +105,8 @@ const addStylesToApp = (appPath, styles) => {
136
105
  });
137
106
  };
138
107
 
139
- const addSamplePages = (appPath, templateOptions) => {
140
- let { version } = templateOptions;
141
-
142
- if(!version) {
143
- version = getVueVersion();
144
- }
145
-
146
- const samplePageTemplatePath = path.join(templateCreator.getTempaltePath(`vue-${version}`), 'sample-pages');
108
+ const addSamplePages = (appPath) => {
109
+ const samplePageTemplatePath = path.join(templateCreator.getTempaltePath('vue-v3'), 'sample-pages');
147
110
  const pagesPath = createPathToPage(appPath);
148
111
  templateCreator.moveTemplateFilesToProject(samplePageTemplatePath, pagesPath, {}, getCorrectPath);
149
112
  };
@@ -152,35 +115,23 @@ const getComponentPageName = (viewName) => {
152
115
  return `${stringUtils.classify(viewName)}`;
153
116
  };
154
117
 
155
- const getVueRoute = (viewName, componentName, pagePath, version) => {
156
- if(!version) {
157
- version = getVueVersion();
158
- }
159
-
118
+ const getVueRoute = (viewName, componentName, pagePath) => {
160
119
  const path = `path: "/${pagePath}"`;
161
120
  const name = `name: "${stringUtils.dasherize(viewName)}"`;
162
121
 
163
- const metaPart = version === 'v2'
164
- ? 'meta: { requiresAuth: true }'
165
- : 'meta: {\n requiresAuth: true,\n layout: defaultLayout\n }';
122
+ const metaPart = 'meta: {\n requiresAuth: true,\n layout: defaultLayout\n }';
166
123
 
167
- const componentPart = version === 'v2'
168
- ? `components:\n {\n layout: defaultLayout,\n content: ${componentName}\n }`
169
- : `component: ${componentName}`;
124
+ const componentPart = `component: ${componentName}`;
170
125
 
171
126
  const commonPart = `\n {\n ${path},\n ${name},\n ${metaPart},\n ${componentPart}\n }`;
172
127
 
173
128
  return commonPart;
174
129
  };
175
130
 
176
- const getNavigationData = (viewName, componentName, icon, version) => {
177
- if(!version) {
178
- version = getVueVersion();
179
- }
180
-
131
+ const getNavigationData = (viewName, componentName, icon) => {
181
132
  const pagePath = stringUtils.dasherize(viewName);
182
133
  return {
183
- route: getVueRoute(viewName, componentName, pagePath, version),
134
+ route: getVueRoute(viewName, componentName, pagePath),
184
135
  navigation: `\n {\n text: \'${stringUtils.humanize(viewName)}\',\n path: \'/${pagePath}\',\n icon: \'${icon}\'\n }`
185
136
  };
186
137
  };
@@ -196,15 +147,13 @@ const createPathToPage = (appPath) => {
196
147
  };
197
148
 
198
149
  const addView = (pageName, options) => {
199
- const version = getVueVersion();
200
-
201
- const pageTemplatePath = path.join(templateCreator.getTempaltePath(`vue-${version}`), 'page');
150
+ const pageTemplatePath = path.join(templateCreator.getTempaltePath('vue-v3'), 'page');
202
151
 
203
152
  const componentName = getComponentPageName(pageName);
204
153
  const pathToPage = createPathToPage(process.cwd());
205
154
  const routingModulePath = path.join(process.cwd(), 'src', 'router.js');
206
155
  const navigationModulePath = path.join(process.cwd(), 'src', 'app-navigation.js');
207
- const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder', version);
156
+ const navigationData = getNavigationData(pageName, componentName, options && options.icon || 'folder');
208
157
  const getCorrectExtension = (fileExtension) => fileExtension;
209
158
  templateCreator.addPageToApp(pageName, pathToPage, pageTemplatePath, getCorrectExtension);
210
159
  moduleUtils.insertImport(routingModulePath, `./views/${pageName}`, componentName, true);
package/src/commands.json CHANGED
@@ -15,9 +15,6 @@
15
15
  }, {
16
16
  "name": "--empty",
17
17
  "description": "Skips sample view generation (default: false)"
18
- }, {
19
- "name": "--version",
20
- "description": "Specifies whether to generate a Vue 2 or Vue 3 application. Available values: 2 (default) and 3"
21
18
  }, {
22
19
  "name": "--template",
23
20
  "description": "Create template with typescsript support. Specifies for React & Vue application"
@@ -1,86 +1,86 @@
1
- import React, { useState, useRef, useCallback } from 'react';
2
- import { useNavigate, useParams } from 'react-router-dom';
3
- import Form, {
4
- Item,
5
- Label,
6
- ButtonItem,
7
- ButtonOptions,
8
- RequiredRule,
9
- CustomRule,
10
- } from 'devextreme-react/form';
11
- import LoadIndicator from 'devextreme-react/load-indicator';
12
- import notify from 'devextreme/ui/notify';
13
- <%=#isTypeScript%>import { ValidationCallbackData } from 'devextreme-react/common';<%=/isTypeScript%>
14
- import { changePassword } from '../../api/auth';
15
-
16
- export default function ChangePasswordForm() {
17
- const navigate = useNavigate();
18
- const [loading, setLoading] = useState(false);
19
- const formData = useRef({ password: '' });
20
- const { recoveryCode } = useParams();
21
-
22
- const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
23
- e.preventDefault();
24
- const { password } = formData.current;
25
- setLoading(true);
26
-
27
- const result = await changePassword(password, recoveryCode);
28
- setLoading(false);
29
-
30
- if (result.isOk) {
31
- navigate('/login');
32
- } else {
33
- notify(result.message, 'error', 2000);
34
- }
35
- }, [navigate, recoveryCode]);
36
-
37
- const confirmPassword = useCallback(
38
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
39
- []
40
- );
41
-
42
- return (
43
- <form onSubmit={onSubmit}>
44
- <Form formData={formData.current} disabled={loading}>
45
- <Item
46
- dataField={'password'}
47
- editorType={'dxTextBox'}
48
- editorOptions={passwordEditorOptions}
49
- >
50
- <RequiredRule message="Password is required" />
51
- <Label visible={false} />
52
- </Item>
53
- <Item
54
- dataField={'confirmedPassword'}
55
- editorType={'dxTextBox'}
56
- editorOptions={confirmedPasswordEditorOptions}
57
- >
58
- <RequiredRule message="Password is required" />
59
- <CustomRule
60
- message={'Passwords do not match'}
61
- validationCallback={confirmPassword}
62
- />
63
- <Label visible={false} />
64
- </Item>
65
- <ButtonItem>
66
- <ButtonOptions
67
- width={'100%'}
68
- type={'default'}
69
- useSubmitBehavior={true}
70
- >
71
- <span className="dx-button-text">
72
- {
73
- loading
74
- ? <LoadIndicator width={'24px'} height={'24px'} visible={true} />
75
- : 'Continue'
76
- }
77
- </span>
78
- </ButtonOptions>
79
- </ButtonItem>
80
- </Form>
81
- </form>
82
- );
83
- }
84
-
85
- const passwordEditorOptions = { stylingMode: 'filled', placeholder: 'Password', mode: 'password' };
86
- const confirmedPasswordEditorOptions = { stylingMode: 'filled', placeholder: 'Confirm Password', mode: 'password' };
1
+ import React, { useState, useRef, useCallback } from 'react';
2
+ import { useNavigate, useParams } from 'react-router-dom';
3
+ import Form, {
4
+ Item,
5
+ Label,
6
+ ButtonItem,
7
+ ButtonOptions,
8
+ RequiredRule,
9
+ CustomRule,
10
+ } from 'devextreme-react/form';
11
+ import LoadIndicator from 'devextreme-react/load-indicator';
12
+ import notify from 'devextreme/ui/notify';
13
+ <%=#isTypeScript%>import { ValidationCallbackData } from 'devextreme-react/common';<%=/isTypeScript%>
14
+ import { changePassword } from '../../api/auth';
15
+
16
+ export default function ChangePasswordForm() {
17
+ const navigate = useNavigate();
18
+ const [loading, setLoading] = useState(false);
19
+ const formData = useRef({ password: '' });
20
+ const { recoveryCode } = useParams();
21
+
22
+ const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
23
+ e.preventDefault();
24
+ const { password } = formData.current;
25
+ setLoading(true);
26
+
27
+ const result = await changePassword(password, recoveryCode);
28
+ setLoading(false);
29
+
30
+ if (result.isOk) {
31
+ navigate('/login');
32
+ } else {
33
+ notify(result.message, 'error', 2000);
34
+ }
35
+ }, [navigate, recoveryCode]);
36
+
37
+ const confirmPassword = useCallback(
38
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
39
+ []
40
+ );
41
+
42
+ return (
43
+ <form onSubmit={onSubmit}>
44
+ <Form formData={formData.current} disabled={loading}>
45
+ <Item
46
+ dataField={'password'}
47
+ editorType={'dxTextBox'}
48
+ editorOptions={passwordEditorOptions}
49
+ >
50
+ <RequiredRule message="Password is required" />
51
+ <Label visible={false} />
52
+ </Item>
53
+ <Item
54
+ dataField={'confirmedPassword'}
55
+ editorType={'dxTextBox'}
56
+ editorOptions={confirmedPasswordEditorOptions}
57
+ >
58
+ <RequiredRule message="Password is required" />
59
+ <CustomRule
60
+ message={'Passwords do not match'}
61
+ validationCallback={confirmPassword}
62
+ />
63
+ <Label visible={false} />
64
+ </Item>
65
+ <ButtonItem>
66
+ <ButtonOptions
67
+ width={'100%'}
68
+ type={'default'}
69
+ useSubmitBehavior={true}
70
+ >
71
+ <span className="dx-button-text">
72
+ {
73
+ loading
74
+ ? <LoadIndicator width={'24px'} height={'24px'} visible={true} />
75
+ : 'Continue'
76
+ }
77
+ </span>
78
+ </ButtonOptions>
79
+ </ButtonItem>
80
+ </Form>
81
+ </form>
82
+ );
83
+ }
84
+
85
+ const passwordEditorOptions = { stylingMode: 'filled', placeholder: 'Password', mode: 'password' };
86
+ const confirmedPasswordEditorOptions = { stylingMode: 'filled', placeholder: 'Confirm Password', mode: 'password' };
@@ -1,107 +1,107 @@
1
- import React, { useState, useRef, useCallback } from 'react';
2
- import { Link, useNavigate } from 'react-router-dom';
3
- import Form, {
4
- Item,
5
- Label,
6
- ButtonItem,
7
- ButtonOptions,
8
- RequiredRule,
9
- CustomRule,
10
- EmailRule
11
- } from 'devextreme-react/form';
12
- import notify from 'devextreme/ui/notify';
13
- import LoadIndicator from 'devextreme-react/load-indicator';
14
- import { createAccount } from '../../api/auth';
15
- <%=#isTypeScript%>import { ValidationCallbackData } from 'devextreme-react/common';<%=/isTypeScript%>
16
- import './CreateAccountForm.scss';
17
-
18
- export default function CreateAccountForm() {
19
- const navigate = useNavigate();
20
- const [loading, setLoading] = useState(false);
21
- const formData = useRef({ email: '', password: '' });
22
-
23
- const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
24
- e.preventDefault();
25
- const { email, password } = formData.current;
26
- setLoading(true);
27
-
28
- const result = await createAccount(email, password);
29
- setLoading(false);
30
-
31
- if (result.isOk) {
32
- navigate('/login');
33
- } else {
34
- notify(result.message, 'error', 2000);
35
- }
36
- }, [navigate]);
37
-
38
- const confirmPassword = useCallback(
39
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
40
- []
41
- );
42
-
43
- return (
44
- <form className={'create-account-form'} onSubmit={onSubmit}>
45
- <Form formData={formData.current} disabled={loading}>
46
- <Item
47
- dataField={'email'}
48
- editorType={'dxTextBox'}
49
- editorOptions={emailEditorOptions}
50
- >
51
- <RequiredRule message="Email is required" />
52
- <EmailRule message="Email is invalid" />
53
- <Label visible={false} />
54
- </Item>
55
- <Item
56
- dataField={'password'}
57
- editorType={'dxTextBox'}
58
- editorOptions={passwordEditorOptions}
59
- >
60
- <RequiredRule message="Password is required" />
61
- <Label visible={false} />
62
- </Item>
63
- <Item
64
- dataField={'confirmedPassword'}
65
- editorType={'dxTextBox'}
66
- editorOptions={confirmedPasswordEditorOptions}
67
- >
68
- <RequiredRule message="Password is required" />
69
- <CustomRule
70
- message={'Passwords do not match'}
71
- validationCallback={confirmPassword}
72
- />
73
- <Label visible={false} />
74
- </Item>
75
- <Item>
76
- <div className='policy-info'>
77
- By creating an account, you agree to the <Link to="#">Terms of Service</Link> and <Link to="#">Privacy Policy</Link>
78
- </div>
79
- </Item>
80
- <ButtonItem>
81
- <ButtonOptions
82
- width={'100%'}
83
- type={'default'}
84
- useSubmitBehavior={true}
85
- >
86
- <span className="dx-button-text">
87
- {
88
- loading
89
- ? <LoadIndicator width={'24px'} height={'24px'} visible={true} />
90
- : 'Create a new account'
91
- }
92
- </span>
93
- </ButtonOptions>
94
- </ButtonItem>
95
- <Item>
96
- <div className={'login-link'}>
97
- Have an account? <Link to={'/login'}>Sign In</Link>
98
- </div>
99
- </Item>
100
- </Form>
101
- </form>
102
- );
103
- }
104
-
105
- const emailEditorOptions = { stylingMode: 'filled', placeholder: 'Email', mode: 'email' };
106
- const passwordEditorOptions = { stylingMode: 'filled', placeholder: 'Password', mode: 'password' };
107
- const confirmedPasswordEditorOptions = { stylingMode: 'filled', placeholder: 'Confirm Password', mode: 'password' };
1
+ import React, { useState, useRef, useCallback } from 'react';
2
+ import { Link, useNavigate } from 'react-router-dom';
3
+ import Form, {
4
+ Item,
5
+ Label,
6
+ ButtonItem,
7
+ ButtonOptions,
8
+ RequiredRule,
9
+ CustomRule,
10
+ EmailRule
11
+ } from 'devextreme-react/form';
12
+ import notify from 'devextreme/ui/notify';
13
+ import LoadIndicator from 'devextreme-react/load-indicator';
14
+ import { createAccount } from '../../api/auth';
15
+ <%=#isTypeScript%>import { ValidationCallbackData } from 'devextreme-react/common';<%=/isTypeScript%>
16
+ import './CreateAccountForm.scss';
17
+
18
+ export default function CreateAccountForm() {
19
+ const navigate = useNavigate();
20
+ const [loading, setLoading] = useState(false);
21
+ const formData = useRef({ email: '', password: '' });
22
+
23
+ const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
24
+ e.preventDefault();
25
+ const { email, password } = formData.current;
26
+ setLoading(true);
27
+
28
+ const result = await createAccount(email, password);
29
+ setLoading(false);
30
+
31
+ if (result.isOk) {
32
+ navigate('/login');
33
+ } else {
34
+ notify(result.message, 'error', 2000);
35
+ }
36
+ }, [navigate]);
37
+
38
+ const confirmPassword = useCallback(
39
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
40
+ []
41
+ );
42
+
43
+ return (
44
+ <form className={'create-account-form'} onSubmit={onSubmit}>
45
+ <Form formData={formData.current} disabled={loading}>
46
+ <Item
47
+ dataField={'email'}
48
+ editorType={'dxTextBox'}
49
+ editorOptions={emailEditorOptions}
50
+ >
51
+ <RequiredRule message="Email is required" />
52
+ <EmailRule message="Email is invalid" />
53
+ <Label visible={false} />
54
+ </Item>
55
+ <Item
56
+ dataField={'password'}
57
+ editorType={'dxTextBox'}
58
+ editorOptions={passwordEditorOptions}
59
+ >
60
+ <RequiredRule message="Password is required" />
61
+ <Label visible={false} />
62
+ </Item>
63
+ <Item
64
+ dataField={'confirmedPassword'}
65
+ editorType={'dxTextBox'}
66
+ editorOptions={confirmedPasswordEditorOptions}
67
+ >
68
+ <RequiredRule message="Password is required" />
69
+ <CustomRule
70
+ message={'Passwords do not match'}
71
+ validationCallback={confirmPassword}
72
+ />
73
+ <Label visible={false} />
74
+ </Item>
75
+ <Item>
76
+ <div className='policy-info'>
77
+ By creating an account, you agree to the <Link to="#">Terms of Service</Link> and <Link to="#">Privacy Policy</Link>
78
+ </div>
79
+ </Item>
80
+ <ButtonItem>
81
+ <ButtonOptions
82
+ width={'100%'}
83
+ type={'default'}
84
+ useSubmitBehavior={true}
85
+ >
86
+ <span className="dx-button-text">
87
+ {
88
+ loading
89
+ ? <LoadIndicator width={'24px'} height={'24px'} visible={true} />
90
+ : 'Create a new account'
91
+ }
92
+ </span>
93
+ </ButtonOptions>
94
+ </ButtonItem>
95
+ <Item>
96
+ <div className={'login-link'}>
97
+ Have an account? <Link to={'/login'}>Sign In</Link>
98
+ </div>
99
+ </Item>
100
+ </Form>
101
+ </form>
102
+ );
103
+ }
104
+
105
+ const emailEditorOptions = { stylingMode: 'filled', placeholder: 'Email', mode: 'email' };
106
+ const passwordEditorOptions = { stylingMode: 'filled', placeholder: 'Password', mode: 'password' };
107
+ const confirmedPasswordEditorOptions = { stylingMode: 'filled', placeholder: 'Confirm Password', mode: 'password' };
@@ -21,7 +21,7 @@
21
21
  // ## Icon width customization
22
22
  .dx-treeview-item {
23
23
  padding-left: 0;
24
- padding-right: 0;
24
+ flex-direction: row-reverse;
25
25
 
26
26
  .dx-icon {
27
27
  width: $side-panel-min-width !important;
@@ -1,5 +1,22 @@
1
1
  @import "./themes/generated/variables.base.scss";
2
2
 
3
+ body {
4
+ font-family:
5
+ -apple-system,
6
+ BlinkMacSystemFont,
7
+ 'Segoe UI',
8
+ 'Roboto',
9
+ 'Oxygen',
10
+ 'Ubuntu',
11
+ 'Cantarell',
12
+ 'Fira Sans',
13
+ 'Droid Sans',
14
+ 'Helvetica Neue',
15
+ sans-serif;
16
+ -webkit-font-smoothing: antialiased;
17
+ -moz-osx-font-smoothing: grayscale;
18
+ }
19
+
3
20
  .app {
4
21
  background-color: darken($base-bg, 5.00);
5
22
  display: flex;