devextreme-cli 1.12.2 → 1.14.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "devextreme-cli",
3
- "version": "1.12.2",
3
+ "version": "1.14.0",
4
4
  "description": "DevExtreme CLI",
5
5
  "keywords": [
6
6
  "devexpress",
@@ -43,7 +43,7 @@
43
43
  "minimist": "^1.2.8",
44
44
  "mustache": "^3.2.1",
45
45
  "prompts": "^2.4.2",
46
- "sass": "^1.94.2",
46
+ "sass": "^1.97.3",
47
47
  "semver": "^5.7.2",
48
48
  "strip-bom": "^4.0.0"
49
49
  },
@@ -69,7 +69,7 @@
69
69
  "rimraf": "^2.7.1",
70
70
  "tree-kill": "^1.2.2",
71
71
  "tree-kill-promise": "^1.0.12",
72
- "typescript": "^4.0.2",
72
+ "typescript": "^4.9.5",
73
73
  "typescript-eslint-parser": "^22.0.0",
74
74
  "wait-on": "8.0.5"
75
75
  },
@@ -77,5 +77,5 @@
77
77
  "@babel/traverse@<7.23.2": ">=7.23.2",
78
78
  "braces@<3.0.3": ">=3.0.3"
79
79
  },
80
- "gitHead": "d8919cf6f14386254ace295b651ce3f532833ba8"
80
+ "gitHead": "fee8377b9b4ce9fb3939130e2be62a2671f0c399"
81
81
  }
@@ -79,6 +79,7 @@ const create = async(appName, options) => {
79
79
  '--src-dir',
80
80
  '--app',
81
81
  '--no-turbopack',
82
+ '--no-react-compiler',
82
83
  '--import-alias "@/*"',
83
84
  ];
84
85
 
@@ -82,7 +82,7 @@ const create = async(appName, options) => {
82
82
 
83
83
  const commandArguments = [`-p=create-vite@${depsVersionTag || latestVersions['create-vite']}`, 'create-vite', appName];
84
84
 
85
- commandArguments.push(`--template react${transpiler === 'swc' ? '-swc' : ''}${templateOptions.isTypeScript ? '-ts' : ''}`);
85
+ commandArguments.push(`--template react${transpiler === 'swc' ? '-swc' : ''}${templateOptions.isTypeScript ? '-ts' : ''} --no-rolldown --no-interactive`);
86
86
 
87
87
  await runCommand('npx', commandArguments);
88
88
 
@@ -17,15 +17,10 @@ const defaultStyles = [
17
17
  const preparePackageJsonForTemplate = (appPath, appName) => {
18
18
  const dependencies = [
19
19
  { name: 'sass-embedded', version: '^1.85.1' },
20
- { name: 'vue-router', version: '^3.0.1' },
20
+ { name: 'vue-router', version: '^4.0.1' },
21
21
  { name: 'devextreme-cli', version: latestVersions['devextreme-cli'], dev: true }
22
22
  ];
23
23
 
24
- const nameDepends = dependencies.map(d => d.name);
25
- const indexVueRouter = nameDepends.indexOf('vue-router');
26
-
27
- dependencies[indexVueRouter].version = '^4.0.1';
28
-
29
24
  const scripts = [
30
25
  { name: 'build-themes', value: 'devextreme build' },
31
26
  { name: 'postinstall', value: 'npm run build-themes' }
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
2
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import Form, {
5
5
  Item,
@@ -7,7 +7,8 @@ import Form, {
7
7
  ButtonItem,
8
8
  ButtonOptions,
9
9
  RequiredRule,
10
- CustomRule,
10
+ CustomRule,<%=#isTypeScript%>
11
+ type FormTypes,<%=/isTypeScript%>
11
12
  } from 'devextreme-react/form';
12
13
  import LoadIndicator from 'devextreme-react/load-indicator';
13
14
  import notify from 'devextreme/ui/notify';
@@ -17,11 +18,22 @@ import { changePassword } from '@/app/actions/auth';
17
18
  export default function ChangePasswordForm() {
18
19
  const router = useRouter();
19
20
  const [loading, setLoading] = useState(false);
20
- const formData = useRef({ password: '' });
21
+ const [formData, setFormData] = useState({ password: '' });
22
+
23
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
24
+ const { dataField, value } = e;
25
+
26
+ if (dataField) {
27
+ setFormData(formData => ({
28
+ ...formData,
29
+ [dataField]: value,
30
+ }));
31
+ }
32
+ }, []);
21
33
 
22
34
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
23
35
  e.preventDefault();
24
- const { password } = formData.current;
36
+ const { password } = formData;
25
37
  setLoading(true);
26
38
 
27
39
  const result = await changePassword(password);
@@ -32,16 +44,16 @@ export default function ChangePasswordForm() {
32
44
  } else {
33
45
  notify(result.message, 'error', 2000);
34
46
  }
35
- }, [router]);
47
+ }, [router, formData]);
36
48
 
37
49
  const confirmPassword = useCallback(
38
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
39
- []
50
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.password,
51
+ [formData]
40
52
  );
41
53
 
42
54
  return (
43
55
  <form onSubmit={onSubmit}>
44
- <Form formData={formData.current} disabled={loading}>
56
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
45
57
  <Item
46
58
  dataField={'password'}
47
59
  editorType={'dxTextBox'}
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
2
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import Link from 'next/link';
5
5
  import Form, {
@@ -9,7 +9,8 @@ import Form, {
9
9
  ButtonOptions,
10
10
  RequiredRule,
11
11
  CustomRule,
12
- EmailRule
12
+ EmailRule,<%=#isTypeScript%>
13
+ type FormTypes,<%=/isTypeScript%>
13
14
  } from 'devextreme-react/form';
14
15
  import notify from 'devextreme/ui/notify';
15
16
  import LoadIndicator from 'devextreme-react/load-indicator';
@@ -20,11 +21,22 @@ import './CreateAccountForm.scss';
20
21
  export default function CreateAccountForm() {
21
22
  const router = useRouter();
22
23
  const [loading, setLoading] = useState(false);
23
- const formData = useRef({ email: '', password: '' });
24
+ const [formData, setFormData] = useState({ email: '', password: '' });
25
+
26
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
27
+ const { dataField, value } = e;
28
+
29
+ if (dataField) {
30
+ setFormData(formData => ({
31
+ ...formData,
32
+ [dataField]: value,
33
+ }));
34
+ }
35
+ }, []);
24
36
 
25
37
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
26
38
  e.preventDefault();
27
- const { email, password } = formData.current;
39
+ const { email, password } = formData;
28
40
  setLoading(true);
29
41
 
30
42
  const result = await signUp(email, password);
@@ -35,16 +47,16 @@ export default function CreateAccountForm() {
35
47
  } else {
36
48
  notify(result.message, 'error', 2000);
37
49
  }
38
- }, [router]);
50
+ }, [router, formData]);
39
51
 
40
52
  const confirmPassword = useCallback(
41
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
42
- []
53
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.password,
54
+ [formData]
43
55
  );
44
56
 
45
57
  return (
46
58
  <form className={'create-account-form'} onSubmit={onSubmit}>
47
- <Form formData={formData.current} disabled={loading}>
59
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
48
60
  <Item
49
61
  dataField={'email'}
50
62
  editorType={'dxTextBox'}
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
2
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import Link from 'next/link';
5
5
  import Form, {
@@ -8,7 +8,8 @@ import Form, {
8
8
  ButtonItem,
9
9
  ButtonOptions,
10
10
  RequiredRule,
11
- EmailRule
11
+ EmailRule,<%=#isTypeScript%>
12
+ type FormTypes,<%=/isTypeScript%>
12
13
  } from 'devextreme-react/form';
13
14
  import LoadIndicator from 'devextreme-react/load-indicator';
14
15
  import Button from 'devextreme-react/button';
@@ -20,11 +21,22 @@ import './LoginForm.scss';
20
21
  export default function LoginForm() {
21
22
  const router = useRouter();
22
23
  const [loading, setLoading] = useState(false);
23
- const formData = useRef({ email: '', password: '' });
24
+ const [formData, setFormData] = useState({ email: '', password: '' });
25
+
26
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
27
+ const { dataField, value } = e;
28
+
29
+ if (dataField) {
30
+ setFormData(formData => ({
31
+ ...formData,
32
+ [dataField]: value,
33
+ }));
34
+ }
35
+ }, []);
24
36
 
25
37
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
26
38
  e.preventDefault();
27
- const { email, password } = formData.current;
39
+ const { email, password } = formData;
28
40
  setLoading(true);
29
41
 
30
42
  const result = await signIn(email, password);
@@ -34,7 +46,7 @@ export default function LoginForm() {
34
46
  } else {
35
47
  router.push('/');
36
48
  }
37
- }, [router]);
49
+ }, [router, formData]);
38
50
 
39
51
  const onCreateAccountClick = useCallback(() => {
40
52
  router.push('/auth/create-account');
@@ -42,7 +54,7 @@ export default function LoginForm() {
42
54
 
43
55
  return (
44
56
  <form className={'login-form'} onSubmit={onSubmit}>
45
- <Form formData={formData.current} disabled={loading}>
57
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
46
58
  <Item
47
59
  dataField={'email'}
48
60
  editorType={'dxTextBox'}
@@ -1,5 +1,5 @@
1
1
  'use client'
2
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
2
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
3
3
  import { useRouter } from 'next/navigation';
4
4
  import Link from 'next/link';
5
5
  import Form, {
@@ -8,7 +8,8 @@ import Form, {
8
8
  ButtonItem,
9
9
  ButtonOptions,
10
10
  RequiredRule,
11
- EmailRule
11
+ EmailRule,<%=#isTypeScript%>
12
+ type FormTypes,<%=/isTypeScript%>
12
13
  } from 'devextreme-react/form';
13
14
  import LoadIndicator from 'devextreme-react/load-indicator';
14
15
  import notify from 'devextreme/ui/notify';
@@ -20,11 +21,22 @@ const notificationText = 'We\'ve sent a link to reset your password. Check your
20
21
  export default function ResetPasswordForm() {
21
22
  const router = useRouter();
22
23
  const [loading, setLoading] = useState(false);
23
- const formData = useRef({ email: '', password: '' });
24
+ const [formData, setFormData] = useState({ email: '', password: '' });
25
+
26
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
27
+ const { dataField, value } = e;
28
+
29
+ if (dataField) {
30
+ setFormData(formData => ({
31
+ ...formData,
32
+ [dataField]: value,
33
+ }));
34
+ }
35
+ }, []);
24
36
 
25
37
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
26
38
  e.preventDefault();
27
- const { email } = formData.current;
39
+ const { email } = formData;
28
40
  setLoading(true);
29
41
 
30
42
  const result = await resetPassword(email);
@@ -36,11 +48,11 @@ export default function ResetPasswordForm() {
36
48
  } else {
37
49
  notify(result.message, 'error', 2000);
38
50
  }
39
- }, [router]);
51
+ }, [router, formData]);
40
52
 
41
53
  return (
42
54
  <form className={'reset-password-form'} onSubmit={onSubmit}>
43
- <Form formData={formData.current} disabled={loading}>
55
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
44
56
  <Item
45
57
  dataField={'email'}
46
58
  editorType={'dxTextBox'}
@@ -1,8 +1,5 @@
1
1
  body {
2
2
  margin: 0;
3
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
- sans-serif;
6
3
  -moz-osx-font-smoothing: grayscale;
7
4
  }
8
5
 
@@ -19,7 +19,7 @@ async function _DEMO_logIn() {
19
19
  // return NextResponse.redirect(new URL('/auth/login', req.nextUrl))
20
20
  }
21
21
 
22
- export default async function middleware(req<%=#isTypeScript%>: NextRequest<%=/isTypeScript%>) {
22
+ export default async function proxy(req<%=#isTypeScript%>: NextRequest<%=/isTypeScript%>) {
23
23
  const path = req.nextUrl.pathname;
24
24
 
25
25
  if (!isProtectedRoute(path)) {
@@ -1,12 +1,11 @@
1
1
  'use client'
2
2
  import React from 'react';
3
- import { DataSource } from 'devextreme-react/common/data';
3
+ import { CustomStore } from 'devextreme-react/common/data';
4
4
  import DataGrid, {
5
5
  Column,
6
6
  Pager,
7
7
  Paging,
8
8
  FilterRow,
9
- Lookup
10
9
  } from 'devextreme-react/data-grid';
11
10
  import './tasks.scss';
12
11
 
@@ -28,85 +27,61 @@ export default function Task() {
28
27
  <Pager showPageSizeSelector={true} showInfo={true} />
29
28
  <FilterRow visible={true} />
30
29
 
31
- <Column dataField={'Task_ID'} width={90} hidingPriority={2} />
30
+ <Column dataField={'id'} width={90} hidingPriority={1} />
32
31
  <Column
33
- dataField={'Task_Subject'}
32
+ dataField={'text'}
34
33
  width={190}
35
34
  caption={'Subject'}
36
- hidingPriority={8}
35
+ hidingPriority={6}
37
36
  />
38
37
  <Column
39
- dataField={'Task_Status'}
38
+ dataField={'status'}
40
39
  caption={'Status'}
41
- hidingPriority={6}
40
+ hidingPriority={4}
42
41
  />
43
42
  <Column
44
- dataField={'Task_Priority'}
45
- caption={'Priority'}
46
- hidingPriority={5}
47
- >
48
- <Lookup
49
- dataSource={priorities}
50
- valueExpr={'value'}
51
- displayExpr={'name'}
52
- />
53
- </Column>
54
- <Column
55
- dataField={'ResponsibleEmployee.Employee_Full_Name'}
43
+ dataField={'owner'}
56
44
  caption={'Assigned To'}
57
45
  allowSorting={false}
58
- hidingPriority={7}
46
+ hidingPriority={5}
59
47
  />
60
48
  <Column
61
- dataField={'Task_Start_Date'}
49
+ dataField={'startDate'}
62
50
  caption={'Start Date'}
63
51
  dataType={'date'}
64
- hidingPriority={3}
52
+ hidingPriority={2}
65
53
  />
66
54
  <Column
67
- dataField={'Task_Due_Date'}
55
+ dataField={'dueDate'}
68
56
  caption={'Due Date'}
69
57
  dataType={'date'}
70
- hidingPriority={4}
58
+ hidingPriority={3}
71
59
  />
72
60
  <Column
73
- dataField={'Task_Priority'}
61
+ dataField={'priority'}
74
62
  caption={'Priority'}
75
63
  name={'Priority'}
76
- hidingPriority={1}
77
- />
78
- <Column
79
- dataField={'Task_Completion'}
80
- caption={'Completion'}
81
64
  hidingPriority={0}
82
65
  />
83
66
  </DataGrid>
84
67
  </React.Fragment>
85
68
  )}
86
69
 
87
- const dataSource = new DataSource({
88
- store: {
89
- version: 2,
90
- type: 'odata',
91
- key: 'Task_ID',
92
- url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks'
93
- },
94
- expand: 'ResponsibleEmployee',
95
- select: [
96
- 'Task_ID',
97
- 'Task_Subject',
98
- 'Task_Start_Date',
99
- 'Task_Due_Date',
100
- 'Task_Status',
101
- 'Task_Priority',
102
- 'Task_Completion',
103
- 'ResponsibleEmployee/Employee_Full_Name'
104
- ]
105
- });
70
+ const dataSource = {
71
+ store: new CustomStore({
72
+ key: 'id',
73
+ async load() {
74
+ try {
75
+ const response = await fetch(`https://js.devexpress.com/Demos/RwaService/api/Employees/AllTasks`);
76
+
77
+ const result = await response.json();
106
78
 
107
- const priorities = [
108
- { name: 'High', value: 4 },
109
- { name: 'Urgent', value: 3 },
110
- { name: 'Normal', value: 2 },
111
- { name: 'Low', value: 1 }
112
- ];
79
+ return {
80
+ data: result,
81
+ };
82
+ } catch (err) {
83
+ throw new Error('Data Loading Error');
84
+ }
85
+ },
86
+ }),
87
+ };
@@ -1,4 +1,4 @@
1
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
1
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
2
2
  import { useNavigate, useParams } from 'react-router-dom';
3
3
  import Form, {
4
4
  Item,
@@ -6,7 +6,8 @@ import Form, {
6
6
  ButtonItem,
7
7
  ButtonOptions,
8
8
  RequiredRule,
9
- CustomRule,
9
+ CustomRule,<%=#isTypeScript%>
10
+ type FormTypes,<%=/isTypeScript%>
10
11
  } from 'devextreme-react/form';
11
12
  import LoadIndicator from 'devextreme-react/load-indicator';
12
13
  import notify from 'devextreme/ui/notify';
@@ -16,12 +17,23 @@ import { changePassword } from '../../api/auth';
16
17
  export default function ChangePasswordForm() {
17
18
  const navigate = useNavigate();
18
19
  const [loading, setLoading] = useState(false);
19
- const formData = useRef({ password: '' });
20
+ const [formData, setFormData] = useState({ password: '' });
20
21
  const { recoveryCode } = useParams();
21
22
 
23
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
24
+ const { dataField, value } = e;
25
+
26
+ if (dataField) {
27
+ setFormData(formData => ({
28
+ ...formData,
29
+ [dataField]: value,
30
+ }));
31
+ }
32
+ }, []);
33
+
22
34
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
23
35
  e.preventDefault();
24
- const { password } = formData.current;
36
+ const { password } = formData;
25
37
  setLoading(true);
26
38
 
27
39
  const result = await changePassword(password, recoveryCode);
@@ -32,16 +44,16 @@ export default function ChangePasswordForm() {
32
44
  } else {
33
45
  notify(result.message, 'error', 2000);
34
46
  }
35
- }, [navigate, recoveryCode]);
47
+ }, [navigate, recoveryCode, formData]);
36
48
 
37
49
  const confirmPassword = useCallback(
38
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
39
- []
50
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.password,
51
+ [formData]
40
52
  );
41
53
 
42
54
  return (
43
55
  <form onSubmit={onSubmit}>
44
- <Form formData={formData.current} disabled={loading}>
56
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
45
57
  <Item
46
58
  dataField={'password'}
47
59
  editorType={'dxTextBox'}
@@ -1,4 +1,4 @@
1
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
1
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
2
2
  import { Link, useNavigate } from 'react-router-dom';
3
3
  import Form, {
4
4
  Item,
@@ -7,7 +7,8 @@ import Form, {
7
7
  ButtonOptions,
8
8
  RequiredRule,
9
9
  CustomRule,
10
- EmailRule
10
+ EmailRule,<%=#isTypeScript%>
11
+ type FormTypes,<%=/isTypeScript%>
11
12
  } from 'devextreme-react/form';
12
13
  import notify from 'devextreme/ui/notify';
13
14
  import LoadIndicator from 'devextreme-react/load-indicator';
@@ -18,11 +19,22 @@ import './CreateAccountForm.scss';
18
19
  export default function CreateAccountForm() {
19
20
  const navigate = useNavigate();
20
21
  const [loading, setLoading] = useState(false);
21
- const formData = useRef({ email: '', password: '' });
22
+ const [formData, setFormData] = useState({ email: '', password: '' });
23
+
24
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
25
+ const { dataField, value } = e;
26
+
27
+ if (dataField) {
28
+ setFormData(formData => ({
29
+ ...formData,
30
+ [dataField]: value,
31
+ }));
32
+ }
33
+ }, []);
22
34
 
23
35
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
24
36
  e.preventDefault();
25
- const { email, password } = formData.current;
37
+ const { email, password } = formData;
26
38
  setLoading(true);
27
39
 
28
40
  const result = await createAccount(email, password);
@@ -33,16 +45,16 @@ export default function CreateAccountForm() {
33
45
  } else {
34
46
  notify(result.message, 'error', 2000);
35
47
  }
36
- }, [navigate]);
48
+ }, [navigate, formData]);
37
49
 
38
50
  const confirmPassword = useCallback(
39
- ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.current.password,
40
- []
51
+ ({ value }<%=#isTypeScript%>: ValidationCallbackData<%=/isTypeScript%>) => value === formData.password,
52
+ [formData]
41
53
  );
42
54
 
43
55
  return (
44
56
  <form className={'create-account-form'} onSubmit={onSubmit}>
45
- <Form formData={formData.current} disabled={loading}>
57
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
46
58
  <Item
47
59
  dataField={'email'}
48
60
  editorType={'dxTextBox'}
@@ -1,4 +1,4 @@
1
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
1
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
2
2
  import { Link, useNavigate } from 'react-router-dom';
3
3
  import Form, {
4
4
  Item,
@@ -6,7 +6,8 @@ import Form, {
6
6
  ButtonItem,
7
7
  ButtonOptions,
8
8
  RequiredRule,
9
- EmailRule
9
+ EmailRule,<%=#isTypeScript%>
10
+ type FormTypes,<%=/isTypeScript%>
10
11
  } from 'devextreme-react/form';
11
12
  import LoadIndicator from 'devextreme-react/load-indicator';
12
13
  import Button from 'devextreme-react/button';
@@ -19,11 +20,22 @@ export default function LoginForm() {
19
20
  const navigate = useNavigate();
20
21
  const { signIn } = useAuth();
21
22
  const [loading, setLoading] = useState(false);
22
- const formData = useRef({ email: '', password: '' });
23
+ const [formData, setFormData] = useState({ email: '', password: '' });
24
+
25
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
26
+ const { dataField, value } = e;
27
+
28
+ if (dataField) {
29
+ setFormData(formData => ({
30
+ ...formData,
31
+ [dataField]: value,
32
+ }));
33
+ }
34
+ }, []);
23
35
 
24
36
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
25
37
  e.preventDefault();
26
- const { email, password } = formData.current;
38
+ const { email, password } = formData;
27
39
  setLoading(true);
28
40
 
29
41
  const result = await signIn(email, password);
@@ -31,7 +43,7 @@ export default function LoginForm() {
31
43
  setLoading(false);
32
44
  notify(result.message, 'error', 2000);
33
45
  }
34
- }, [signIn]);
46
+ }, [signIn, formData]);
35
47
 
36
48
  const onCreateAccountClick = useCallback(() => {
37
49
  navigate('/create-account');
@@ -39,7 +51,7 @@ export default function LoginForm() {
39
51
 
40
52
  return (
41
53
  <form className={'login-form'} onSubmit={onSubmit}>
42
- <Form formData={formData.current} disabled={loading}>
54
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
43
55
  <Item
44
56
  dataField={'email'}
45
57
  editorType={'dxTextBox'}
@@ -1,4 +1,4 @@
1
- import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useRef, useCallback } from 'react';
1
+ import <%=#isTypeScript%>React, <%=/isTypeScript%>{ useState, useCallback } from 'react';
2
2
  import { Link, useNavigate } from "react-router-dom";
3
3
  import Form, {
4
4
  Item,
@@ -6,7 +6,8 @@ import Form, {
6
6
  ButtonItem,
7
7
  ButtonOptions,
8
8
  RequiredRule,
9
- EmailRule
9
+ EmailRule,<%=#isTypeScript%>
10
+ type FormTypes,<%=/isTypeScript%>
10
11
  } from 'devextreme-react/form';
11
12
  import LoadIndicator from 'devextreme-react/load-indicator';
12
13
  import notify from 'devextreme/ui/notify';
@@ -18,11 +19,22 @@ const notificationText = 'We\'ve sent a link to reset your password. Check your
18
19
  export default function ResetPasswordForm() {
19
20
  const navigate = useNavigate();
20
21
  const [loading, setLoading] = useState(false);
21
- const formData = useRef({ email: '', password: '' });
22
+ const [formData, setFormData] = useState({ email: '', password: '' });
23
+
24
+ const onFieldDataChanged = useCallback((e<%=#isTypeScript%>: FormTypes.FieldDataChangedEvent<%=/isTypeScript%>) => {
25
+ const { dataField, value } = e;
26
+
27
+ if (dataField) {
28
+ setFormData(formData => ({
29
+ ...formData,
30
+ [dataField]: value,
31
+ }));
32
+ }
33
+ }, []);
22
34
 
23
35
  const onSubmit = useCallback(async (e<%=#isTypeScript%>: React.FormEvent<HTMLFormElement><%=/isTypeScript%>) => {
24
36
  e.preventDefault();
25
- const { email } = formData.current;
37
+ const { email } = formData;
26
38
  setLoading(true);
27
39
 
28
40
  const result = await resetPassword(email);
@@ -34,11 +46,11 @@ export default function ResetPasswordForm() {
34
46
  } else {
35
47
  notify(result.message, 'error', 2000);
36
48
  }
37
- }, [navigate]);
49
+ }, [navigate, formData]);
38
50
 
39
51
  return (
40
52
  <form className={'reset-password-form'} onSubmit={onSubmit}>
41
- <Form formData={formData.current} disabled={loading}>
53
+ <Form formData={formData} disabled={loading} onFieldDataChanged={onFieldDataChanged}>
42
54
  <Item
43
55
  dataField={'email'}
44
56
  editorType={'dxTextBox'}
@@ -1,8 +1,5 @@
1
1
  body {
2
2
  margin: 0;
3
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4
- 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5
- sans-serif;
6
3
  -moz-osx-font-smoothing: grayscale;
7
4
  }
8
5
 
@@ -1,11 +1,10 @@
1
1
  import React from 'react';
2
- import { DataSource } from 'devextreme-react/common/data';
2
+ import { CustomStore } from 'devextreme-react/common/data';
3
3
  import DataGrid, {
4
4
  Column,
5
5
  Pager,
6
6
  Paging,
7
7
  FilterRow,
8
- Lookup
9
8
  } from 'devextreme-react/data-grid';
10
9
  import './tasks.scss';
11
10
 
@@ -27,85 +26,61 @@ export function Tasks() {
27
26
  <Pager showPageSizeSelector={true} showInfo={true} />
28
27
  <FilterRow visible={true} />
29
28
 
30
- <Column dataField={'Task_ID'} width={90} hidingPriority={2} />
29
+ <Column dataField={'id'} width={90} hidingPriority={1} />
31
30
  <Column
32
- dataField={'Task_Subject'}
31
+ dataField={'text'}
33
32
  width={190}
34
33
  caption={'Subject'}
35
- hidingPriority={8}
34
+ hidingPriority={6}
36
35
  />
37
36
  <Column
38
- dataField={'Task_Status'}
37
+ dataField={'status'}
39
38
  caption={'Status'}
40
- hidingPriority={6}
39
+ hidingPriority={4}
41
40
  />
42
41
  <Column
43
- dataField={'Task_Priority'}
44
- caption={'Priority'}
45
- hidingPriority={5}
46
- >
47
- <Lookup
48
- dataSource={priorities}
49
- valueExpr={'value'}
50
- displayExpr={'name'}
51
- />
52
- </Column>
53
- <Column
54
- dataField={'ResponsibleEmployee.Employee_Full_Name'}
42
+ dataField={'owner'}
55
43
  caption={'Assigned To'}
56
44
  allowSorting={false}
57
- hidingPriority={7}
45
+ hidingPriority={5}
58
46
  />
59
47
  <Column
60
- dataField={'Task_Start_Date'}
48
+ dataField={'startDate'}
61
49
  caption={'Start Date'}
62
50
  dataType={'date'}
63
- hidingPriority={3}
51
+ hidingPriority={2}
64
52
  />
65
53
  <Column
66
- dataField={'Task_Due_Date'}
54
+ dataField={'dueDate'}
67
55
  caption={'Due Date'}
68
56
  dataType={'date'}
69
- hidingPriority={4}
57
+ hidingPriority={3}
70
58
  />
71
59
  <Column
72
- dataField={'Task_Priority'}
60
+ dataField={'priority'}
73
61
  caption={'Priority'}
74
62
  name={'Priority'}
75
- hidingPriority={1}
76
- />
77
- <Column
78
- dataField={'Task_Completion'}
79
- caption={'Completion'}
80
63
  hidingPriority={0}
81
64
  />
82
65
  </DataGrid>
83
66
  </React.Fragment>
84
67
  )}
85
68
 
86
- const dataSource = new DataSource({
87
- store: {
88
- version: 2,
89
- type: 'odata',
90
- key: 'Task_ID',
91
- url: 'https://js.devexpress.com/Demos/DevAV/odata/Tasks'
92
- },
93
- expand: 'ResponsibleEmployee',
94
- select: [
95
- 'Task_ID',
96
- 'Task_Subject',
97
- 'Task_Start_Date',
98
- 'Task_Due_Date',
99
- 'Task_Status',
100
- 'Task_Priority',
101
- 'Task_Completion',
102
- 'ResponsibleEmployee/Employee_Full_Name'
103
- ]
104
- });
69
+ const dataSource = {
70
+ store: new CustomStore({
71
+ key: 'id',
72
+ async load() {
73
+ try {
74
+ const response = await fetch(`https://js.devexpress.com/Demos/RwaService/api/Employees/AllTasks`);
75
+
76
+ const result = await response.json();
105
77
 
106
- const priorities = [
107
- { name: 'High', value: 4 },
108
- { name: 'Urgent', value: 3 },
109
- { name: 'Normal', value: 2 },
110
- { name: 'Low', value: 1 }
111
- ];
78
+ return {
79
+ data: result,
80
+ };
81
+ } catch {
82
+ throw new Error(`Data Loading Error`);
83
+ }
84
+ },
85
+ })
86
+ };
@@ -15,64 +15,46 @@
15
15
  <dx-pager :show-page-size-selector="true" :show-info="true" />
16
16
  <dx-filter-row :visible="true" />
17
17
 
18
- <dx-column data-field="Task_ID" :width="90" :hiding-priority="2" />
18
+ <dx-column data-field="id" :width="90" :hiding-priority="1" />
19
19
 
20
20
  <dx-column
21
- data-field="Task_Subject"
21
+ data-field="text"
22
22
  caption="Subject"
23
23
  :width="190"
24
- :hiding-priority="8"
24
+ :hiding-priority="6"
25
25
  />
26
26
 
27
27
  <dx-column
28
- data-field="Task_Status"
28
+ data-field="status"
29
29
  caption="Status"
30
- :hiding-priority="6"
30
+ :hiding-priority="4"
31
31
  />
32
32
 
33
33
  <dx-column
34
- data-field="Task_Priority"
35
- caption="Priority"
36
- :hiding-priority="5"
37
- >
38
- <dx-lookup
39
- display-expr="name"
40
- value-expr="value"
41
- :data-source="priorities"
42
- />
43
- </dx-column>
44
-
45
- <dx-column
46
- data-field="ResponsibleEmployee.Employee_Full_Name"
34
+ data-field="owner"
47
35
  caption="Assigned To"
48
36
  :allow-sorting="false"
49
- :hiding-priority="7"
37
+ :hiding-priority="5"
50
38
  />
51
39
 
52
40
  <dx-column
53
- data-field="Task_Start_Date"
41
+ data-field="startDate"
54
42
  caption="Start Date"
55
43
  data-type="date"
56
- :hiding-priority="3"
44
+ :hiding-priority="2"
57
45
  />
58
46
 
59
47
  <dx-column
60
- data-field="Task_Due_Date"
48
+ data-field="dueDate"
61
49
  caption="Due Date"
62
50
  data-type="date"
63
- :hiding-priority="4"
51
+ :hiding-priority="3"
64
52
  />
65
53
 
66
54
  <dx-column
67
- data-field="Task_Priority"
55
+ data-field="priority"
68
56
  caption="Priority"
69
57
  name="Priority"
70
- :hiding-priority="1"
71
- />
72
-
73
- <dx-column
74
- data-field="Task_Completion"
75
- caption="Completion"
76
58
  :hiding-priority="0"
77
59
  />
78
60
  </dx-data-grid>
@@ -80,53 +62,42 @@
80
62
  </template>
81
63
 
82
64
  <script>
83
- import "devextreme-vue/common/data";
65
+ import { CustomStore } from 'devextreme-vue/common/data';
84
66
  import DxDataGrid, {
85
67
  DxColumn,
86
68
  DxFilterRow,
87
- DxLookup,
88
69
  DxPager,
89
70
  DxPaging
90
71
  } from "devextreme-vue/data-grid";
91
72
 
92
- const priorities = [
93
- { name: "High", value: 4 },
94
- { name: "Urgent", value: 3 },
95
- { name: "Normal", value: 2 },
96
- { name: "Low", value: 1 }
97
- ];
98
-
99
73
  export default {
100
74
  setup() {
101
75
  const dataSourceConfig = {
102
- store: {
103
- version: 2,
104
- type: "odata",
105
- key: "Task_ID",
106
- url: "https://js.devexpress.com/Demos/DevAV/odata/Tasks"
107
- },
108
- expand: "ResponsibleEmployee",
109
- select: [
110
- "Task_ID",
111
- "Task_Subject",
112
- "Task_Start_Date",
113
- "Task_Due_Date",
114
- "Task_Status",
115
- "Task_Priority",
116
- "Task_Completion",
117
- "ResponsibleEmployee/Employee_Full_Name"
118
- ]
76
+ store: new CustomStore({
77
+ key: 'id',
78
+ async load() {
79
+ try {
80
+ const response = await fetch(`https://js.devexpress.com/Demos/RwaService/api/Employees/AllTasks`);
81
+
82
+ const result = await response.json();
83
+
84
+ return {
85
+ data: result,
86
+ };
87
+ } catch (err) {
88
+ throw new Error('Data Loading Error');
89
+ }
90
+ },
91
+ }),
119
92
  };
120
93
  return {
121
94
  dataSourceConfig,
122
- priorities
123
95
  };
124
96
  },
125
97
  components: {
126
98
  DxDataGrid,
127
99
  DxColumn,
128
100
  DxFilterRow,
129
- DxLookup,
130
101
  DxPager,
131
102
  DxPaging
132
103
  }
@@ -1,12 +1,12 @@
1
1
  const packageJson = require('../../package.json');
2
2
  module.exports = {
3
- 'devextreme': '25.1.7',
4
- 'devextreme-react': '25.1.7',
5
- 'devextreme-vue': '25.1.7',
6
- 'create-vite': '7.0.0',
3
+ 'devextreme': '25.2.4',
4
+ 'devextreme-react': '25.2.4',
5
+ 'devextreme-vue': '25.2.4',
6
+ 'create-vite': '8.2.0',
7
7
  'create-vue': '3.17.0',
8
- 'create-next-app': '15.3.4',
9
- 'jose': '6.0.11',
8
+ 'create-next-app': '16.1.0',
9
+ 'jose': '6.1.3',
10
10
  'devextreme-cli': packageJson.version,
11
11
  'devextreme-schematics': 'latest'
12
12
  };