devextreme-cli 1.3.3 → 1.4.2
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 +6 -6
- package/src/application.js +2 -2
- package/src/applications/application.angular.js +25 -41
- package/src/applications/application.react.js +0 -5
- package/src/templates/react/application/src/App.test.tsx +12 -0
- package/src/templates/react/application/src/components/change-password-form/ChangePasswordForm.tsx +3 -2
- package/src/templates/react/application/src/components/create-account-form/CreateAccountForm.tsx +3 -2
- package/src/templates/react/application/src/components/login-form/LoginForm.tsx +1 -1
- package/src/templates/react/application/src/components/reset-password-form/ResetPasswordForm.tsx +1 -1
- package/src/templates/react/application/src/components/side-navigation-menu/SideNavigationMenu.tsx +2 -2
- package/src/templates/react/application/src/contexts/navigation.tsx +1 -1
- package/src/templates/react/application/src/dx-styles.scss +25 -13
- package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +1 -16
- package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.tsx +9 -7
- package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +0 -9
- package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.tsx +9 -7
- package/src/templates/react/application/src/matchMediaMock.tsx +14 -0
- package/src/templates/react/application/src/types.tsx +4 -0
- package/src/templates/vue-v2/application/src/dx-styles.scss +12 -0
- package/src/templates/vue-v2/application/src/layouts/side-nav-inner-toolbar.vue +0 -15
- package/src/templates/vue-v2/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
- package/src/templates/vue-v3/application/src/dx-styles.scss +12 -0
- package/src/templates/vue-v3/application/src/layouts/side-nav-inner-toolbar.vue +2 -17
- package/src/templates/vue-v3/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
- package/src/themebuider.js +19 -4
- package/src/utility/latest-versions.js +3 -3
- package/src/utility/ng-version.js +35 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "devextreme-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"description": "DevExtreme CLI",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"devexpress",
|
|
@@ -52,12 +52,12 @@
|
|
|
52
52
|
"@typescript-eslint/eslint-plugin": "^4.15.1",
|
|
53
53
|
"@typescript-eslint/parser": "^4.0.1",
|
|
54
54
|
"babel-eslint": "^10.1.0",
|
|
55
|
-
"cross-env": "^5.2.
|
|
56
|
-
"eslint": "^7.
|
|
55
|
+
"cross-env": "^5.2.1",
|
|
56
|
+
"eslint": "^7.32.0",
|
|
57
57
|
"eslint-config-angular": "^0.5.0",
|
|
58
58
|
"eslint-config-prettier": "^8.5.0",
|
|
59
|
-
"eslint-plugin-angular": "^4.0
|
|
60
|
-
"eslint-plugin-jest": "^22.
|
|
59
|
+
"eslint-plugin-angular": "^4.1.0",
|
|
60
|
+
"eslint-plugin-jest": "^22.21.0",
|
|
61
61
|
"eslint-plugin-prettier": "^4.0.0",
|
|
62
62
|
"eslint-plugin-react": "^7.20.6",
|
|
63
63
|
"eslint-plugin-react-hooks": "^4.1.0",
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"typescript": "^4.0.2",
|
|
75
75
|
"typescript-eslint-parser": "^22.0.0"
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "b48e36220ea219b061fb6db3aa58f48dbae70e5a"
|
|
78
78
|
}
|
package/src/application.js
CHANGED
|
@@ -35,7 +35,7 @@ const run = async(commands, options, devextremeConfig) => {
|
|
|
35
35
|
} else {
|
|
36
36
|
if(commands[0] === 'add') {
|
|
37
37
|
if(commands[1] === 'devextreme-angular') {
|
|
38
|
-
angularApplication.install(options);
|
|
38
|
+
await angularApplication.install(options);
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -50,7 +50,7 @@ const run = async(commands, options, devextremeConfig) => {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
if(commands[1] === 'angular-template') {
|
|
53
|
-
angularApplication.addTemplate(commands[2], options);
|
|
53
|
+
await angularApplication.addTemplate(commands[2], options);
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -4,11 +4,12 @@ const moduleWorker = require('../utility/module');
|
|
|
4
4
|
const runCommand = require('../utility/run-command');
|
|
5
5
|
const semver = require('semver').SemVer;
|
|
6
6
|
const fs = require('fs');
|
|
7
|
-
const
|
|
8
|
-
const
|
|
7
|
+
const dasherize = require('../utility/string').dasherize;
|
|
8
|
+
const ngVersion = require('../utility/ng-version');
|
|
9
9
|
const latestVersions = require('../utility/latest-versions');
|
|
10
10
|
const schematicsVersion = latestVersions['devextreme-schematics'] || 'latest';
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
const minNgCliVersion = new semver('12.0.0');
|
|
12
13
|
|
|
13
14
|
async function runSchematicCommand(schematicCommand, options, evaluatingOptions) {
|
|
14
15
|
const collectionName = 'devextreme-schematics';
|
|
@@ -20,12 +21,12 @@ async function runSchematicCommand(schematicCommand, options, evaluatingOptions)
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
if(!localPackageExists(collectionName)) {
|
|
23
|
-
await runNgCommand(['add', collectionPath, '--
|
|
24
|
+
await runNgCommand(['add', collectionPath, '--skip-confirmation=true'], evaluatingOptions);
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
const commandArguments = ['g', `${collectionName}:${schematicCommand}`];
|
|
27
28
|
for(let option in options) {
|
|
28
|
-
commandArguments.push(`--${option}=${options[option]}`);
|
|
29
|
+
commandArguments.push(`--${dasherize(option)}=${options[option]}`);
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
runNgCommand(commandArguments, evaluatingOptions);
|
|
@@ -36,7 +37,7 @@ async function runNgCommand(commandArguments, evaluatingOptions) {
|
|
|
36
37
|
const npmCommandName = hasNg ? 'ng' : 'npx';
|
|
37
38
|
const ngCommandArguments = hasNg
|
|
38
39
|
? []
|
|
39
|
-
: ['-p', '@angular/cli
|
|
40
|
+
: ['-p', '@angular/cli', 'ng'];
|
|
40
41
|
|
|
41
42
|
ngCommandArguments.push(...commandArguments);
|
|
42
43
|
return runCommand(npmCommandName, ngCommandArguments, evaluatingOptions);
|
|
@@ -52,41 +53,20 @@ function localPackageExists(packageName) {
|
|
|
52
53
|
return fs.existsSync(packageJsonPath);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
exec('ng v', (err, stdout, stderr) => {
|
|
62
|
-
if(!!err) {
|
|
63
|
-
resolve(false);
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const parsingResult = parseNgCliVersion(stdout);
|
|
68
|
-
if(!parsingResult) {
|
|
69
|
-
resolve(false);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const isSupportVersion = parsingResult.compare(minNgCliVersion) >= 0
|
|
73
|
-
&& parsingResult.compare(new semver('14.0.0')) < 0;
|
|
74
|
-
if(isSupportVersion) {
|
|
75
|
-
globalNgCliVersion = parsingResult.version;
|
|
76
|
-
resolve(true);
|
|
77
|
-
} else {
|
|
78
|
-
resolve(false);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
}
|
|
56
|
+
const hasSutableNgCli = async() => {
|
|
57
|
+
const localVersion = ngVersion.getLocalNgVersion();
|
|
58
|
+
if(!localVersion) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
83
61
|
|
|
84
|
-
|
|
85
|
-
return
|
|
86
|
-
}
|
|
62
|
+
const isSupportVersion = localVersion.compare(minNgCliVersion) >= 0;
|
|
63
|
+
return isSupportVersion;
|
|
64
|
+
};
|
|
87
65
|
|
|
88
|
-
const install = (options) => {
|
|
89
|
-
runSchematicCommand('install', {
|
|
66
|
+
const install = async(options) => {
|
|
67
|
+
runSchematicCommand('install', {
|
|
68
|
+
...options
|
|
69
|
+
});
|
|
90
70
|
};
|
|
91
71
|
|
|
92
72
|
const create = async(appName, options) => {
|
|
@@ -115,8 +95,12 @@ const create = async(appName, options) => {
|
|
|
115
95
|
changeMainTs(appPath);
|
|
116
96
|
};
|
|
117
97
|
|
|
118
|
-
const addTemplate = (appName, options, evaluatingOptions) => {
|
|
119
|
-
const schematicOptions = {
|
|
98
|
+
const addTemplate = async(appName, options, evaluatingOptions) => {
|
|
99
|
+
const schematicOptions = {
|
|
100
|
+
...(appName && { project: appName }),
|
|
101
|
+
...options,
|
|
102
|
+
globalNgCliVersion: ngVersion.getNgCliVersion().version
|
|
103
|
+
};
|
|
120
104
|
runSchematicCommand('add-app-template', schematicOptions, evaluatingOptions);
|
|
121
105
|
};
|
|
122
106
|
|
|
@@ -38,11 +38,6 @@ const preparePackageJsonForTemplate = (appPath, appName, isTypeScript) => {
|
|
|
38
38
|
{ name: 'postinstall', value: 'npm run build-themes' }
|
|
39
39
|
];
|
|
40
40
|
|
|
41
|
-
if(isTypeScript) {
|
|
42
|
-
dependencies.push({ name: '@types/react-router-dom', version: '^5.1.5' });
|
|
43
|
-
dependencies.push({ name: '@types/react', version: '^17.0.39' });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
41
|
packageJsonUtils.addDependencies(appPath, dependencies);
|
|
47
42
|
packageJsonUtils.updateScripts(appPath, scripts);
|
|
48
43
|
packageJsonUtils.updateName(appPath, appName);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import './matchMediaMock';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import App from './App';
|
|
4
|
+
import { act } from 'react-dom/test-utils';
|
|
5
|
+
|
|
6
|
+
describe("App", () => {
|
|
7
|
+
test('renders learn react link', async () => {
|
|
8
|
+
await act( async () => { render(<App/>) });
|
|
9
|
+
const linkElement = screen.getByText(/create react app/i);
|
|
10
|
+
expect(linkElement).toBeInTheDocument();
|
|
11
|
+
});
|
|
12
|
+
})
|
package/src/templates/react/application/src/components/change-password-form/ChangePasswordForm.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import Form, {
|
|
|
10
10
|
} from 'devextreme-react/form';
|
|
11
11
|
import LoadIndicator from 'devextreme-react/load-indicator';
|
|
12
12
|
import notify from 'devextreme/ui/notify';
|
|
13
|
+
<%=#isTypeScript%>import { ValidationType } from '../../types';<%=/isTypeScript%>
|
|
13
14
|
import { changePassword } from '../../api/auth';
|
|
14
15
|
|
|
15
16
|
export default function ChangePasswordForm() {
|
|
@@ -18,7 +19,7 @@ export default function ChangePasswordForm() {
|
|
|
18
19
|
const formData = useRef({ password: '' });
|
|
19
20
|
const { recoveryCode } = useParams();
|
|
20
21
|
|
|
21
|
-
const onSubmit = useCallback(async (e) => {
|
|
22
|
+
const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
|
|
22
23
|
e.preventDefault();
|
|
23
24
|
const { password } = formData.current;
|
|
24
25
|
setLoading(true);
|
|
@@ -34,7 +35,7 @@ export default function ChangePasswordForm() {
|
|
|
34
35
|
}, [navigate, recoveryCode]);
|
|
35
36
|
|
|
36
37
|
const confirmPassword = useCallback(
|
|
37
|
-
({ value }) => value === formData.current.password,
|
|
38
|
+
({ value }<%=#isTypeScript%>: ValidationType<%=/isTypeScript%>) => value === formData.current.password,
|
|
38
39
|
[]
|
|
39
40
|
);
|
|
40
41
|
|
package/src/templates/react/application/src/components/create-account-form/CreateAccountForm.tsx
CHANGED
|
@@ -12,6 +12,7 @@ import Form, {
|
|
|
12
12
|
import notify from 'devextreme/ui/notify';
|
|
13
13
|
import LoadIndicator from 'devextreme-react/load-indicator';
|
|
14
14
|
import { createAccount } from '../../api/auth';
|
|
15
|
+
<%=#isTypeScript%>import { ValidationType } from '../../types';<%=/isTypeScript%>
|
|
15
16
|
import './CreateAccountForm.scss';
|
|
16
17
|
|
|
17
18
|
export default function CreateAccountForm() {
|
|
@@ -19,7 +20,7 @@ export default function CreateAccountForm() {
|
|
|
19
20
|
const [loading, setLoading] = useState(false);
|
|
20
21
|
const formData = useRef({ email: '', password: '' });
|
|
21
22
|
|
|
22
|
-
const onSubmit = useCallback(async (e) => {
|
|
23
|
+
const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
|
|
23
24
|
e.preventDefault();
|
|
24
25
|
const { email, password } = formData.current;
|
|
25
26
|
setLoading(true);
|
|
@@ -35,7 +36,7 @@ export default function CreateAccountForm() {
|
|
|
35
36
|
}, [navigate]);
|
|
36
37
|
|
|
37
38
|
const confirmPassword = useCallback(
|
|
38
|
-
({ value }) => value === formData.current.password,
|
|
39
|
+
({ value }<%=#isTypeScript%>: ValidationType<%=/isTypeScript%>) => value === formData.current.password,
|
|
39
40
|
[]
|
|
40
41
|
);
|
|
41
42
|
|
|
@@ -20,7 +20,7 @@ export default function LoginForm() {
|
|
|
20
20
|
const [loading, setLoading] = useState(false);
|
|
21
21
|
const formData = useRef({ email: '', password: '' });
|
|
22
22
|
|
|
23
|
-
const onSubmit = useCallback(async (e) => {
|
|
23
|
+
const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
|
|
24
24
|
e.preventDefault();
|
|
25
25
|
const { email, password } = formData.current;
|
|
26
26
|
setLoading(true);
|
package/src/templates/react/application/src/components/reset-password-form/ResetPasswordForm.tsx
CHANGED
|
@@ -20,7 +20,7 @@ export default function ResetPasswordForm() {
|
|
|
20
20
|
const [loading, setLoading] = useState(false);
|
|
21
21
|
const formData = useRef({ email: '', password: '' });
|
|
22
22
|
|
|
23
|
-
const onSubmit = useCallback(async (e) => {
|
|
23
|
+
const onSubmit = useCallback(async (e<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
|
|
24
24
|
e.preventDefault();
|
|
25
25
|
const { email } = formData.current;
|
|
26
26
|
setLoading(true);
|
package/src/templates/react/application/src/components/side-navigation-menu/SideNavigationMenu.tsx
CHANGED
|
@@ -33,8 +33,8 @@ export default function SideNavigationMenu(props<%=#isTypeScript%>: React.PropsW
|
|
|
33
33
|
const { navigationData: { currentPath } } = useNavigation();
|
|
34
34
|
|
|
35
35
|
const treeViewRef = useRef<%=#isTypeScript%><TreeView><%=/isTypeScript%>(null);
|
|
36
|
-
const wrapperRef = useRef();
|
|
37
|
-
const getWrapperRef = useCallback((element) => {
|
|
36
|
+
const wrapperRef = useRef<%=#isTypeScript%><HTMLDivElement><%=/isTypeScript%>();
|
|
37
|
+
const getWrapperRef = useCallback((element<%=#isTypeScript%>: HTMLDivElement<%=/isTypeScript%>) => {
|
|
38
38
|
const prevElement = wrapperRef.current;
|
|
39
39
|
if (prevElement) {
|
|
40
40
|
events.off(prevElement, 'dxclick');
|
|
@@ -16,7 +16,7 @@ function NavigationProvider(props<%=#isTypeScript%>: React.PropsWithChildren<unk
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
function withNavigationWatcher(Component<%=#isTypeScript%>: React.ElementType<%=/isTypeScript%>, path<%=#isTypeScript%>: string<%=/isTypeScript%>) {
|
|
19
|
-
const WrappedComponent = function (props<%=#isTypeScript%>: unknown
|
|
19
|
+
const WrappedComponent = function (props<%=#isTypeScript%>: Record<string, unknown><%=/isTypeScript%>) {
|
|
20
20
|
const { setNavigationData } = useNavigation();
|
|
21
21
|
|
|
22
22
|
useEffect(() => {
|
|
@@ -5,26 +5,38 @@
|
|
|
5
5
|
display: flex;
|
|
6
6
|
height: 100%;
|
|
7
7
|
width: 100%;
|
|
8
|
-
}
|
|
9
8
|
|
|
10
|
-
.
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
.content {
|
|
10
|
+
line-height: 1.5;
|
|
11
|
+
flex-grow: 1;
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
h2 {
|
|
14
|
+
font-size: 30px;
|
|
15
|
+
margin-top: 20px;
|
|
16
|
+
margin-bottom: 20px;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
16
19
|
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
.container {
|
|
21
|
+
height: 100%;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
display: flex;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.layout-body {
|
|
27
|
+
flex: 1;
|
|
28
|
+
min-height: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.content-block {
|
|
32
|
+
margin-left: 40px;
|
|
33
|
+
margin-right: 40px;
|
|
19
34
|
margin-top: 20px;
|
|
20
|
-
margin-bottom: 20px;
|
|
21
35
|
}
|
|
22
36
|
}
|
|
23
37
|
|
|
24
|
-
.
|
|
25
|
-
|
|
26
|
-
margin-right: 40px;
|
|
27
|
-
margin-top: 20px;
|
|
38
|
+
.side-nav-outer-toolbar .dx-drawer {
|
|
39
|
+
height: calc(100% - 56px)
|
|
28
40
|
}
|
|
29
41
|
|
|
30
42
|
.screen-x-small .content-block {
|
|
@@ -2,21 +2,6 @@
|
|
|
2
2
|
width: 100%;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
-
.container {
|
|
6
|
-
height: 100%;
|
|
7
|
-
flex-direction: column;
|
|
8
|
-
display: flex;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
.layout-body {
|
|
12
|
-
flex: 1;
|
|
13
|
-
min-height: 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.content {
|
|
17
|
-
flex-grow: 1;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
5
|
#navigation-header {
|
|
21
6
|
@import "../../themes/generated/variables.additional.scss";
|
|
22
7
|
background-color: $base-accent;
|
|
@@ -29,7 +14,7 @@
|
|
|
29
14
|
.screen-x-small & {
|
|
30
15
|
padding-left: 20px;
|
|
31
16
|
}
|
|
32
|
-
|
|
17
|
+
|
|
33
18
|
.dx-theme-generic & {
|
|
34
19
|
padding-top: 10px;
|
|
35
20
|
padding-bottom: 10px;
|
|
@@ -9,7 +9,9 @@ import './side-nav-inner-toolbar.scss';
|
|
|
9
9
|
import { useScreenSize } from '../../utils/media-query';
|
|
10
10
|
import { Template } from 'devextreme-react/core/template';
|
|
11
11
|
import { useMenuPatch } from '../../utils/patches';
|
|
12
|
+
<%=#isTypeScript%>import { ItemClickEvent } from 'devextreme/ui/tree_view';<%=/isTypeScript%>
|
|
12
13
|
<%=#isTypeScript%>import type { SideNavToolbarProps } from '../../types';<%=/isTypeScript%>
|
|
14
|
+
<%=#isTypeScript%>import { ClickEvent } from 'devextreme/ui/button';<%=/isTypeScript%>
|
|
13
15
|
|
|
14
16
|
export default function SideNavInnerToolbar({ title, children }<%=#isTypeScript%>: React.PropsWithChildren<SideNavToolbarProps><%=/isTypeScript%>) {
|
|
15
17
|
const scrollViewRef = useRef<%=#isTypeScript%><ScrollView><%=/isTypeScript%>(null);
|
|
@@ -20,13 +22,13 @@ export default function SideNavInnerToolbar({ title, children }<%=#isTypeScript%
|
|
|
20
22
|
isLarge ? MenuStatus.Opened : MenuStatus.Closed
|
|
21
23
|
);
|
|
22
24
|
|
|
23
|
-
const toggleMenu = useCallback(({ event }) => {
|
|
25
|
+
const toggleMenu = useCallback(({ event }<%=#isTypeScript%>: ClickEvent<%=/isTypeScript%>) => {
|
|
24
26
|
setMenuStatus(
|
|
25
27
|
prevMenuStatus => prevMenuStatus === MenuStatus.Closed
|
|
26
28
|
? MenuStatus.Opened
|
|
27
29
|
: MenuStatus.Closed
|
|
28
30
|
);
|
|
29
|
-
event
|
|
31
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
|
|
30
32
|
}, []);
|
|
31
33
|
|
|
32
34
|
const temporaryOpenMenu = useCallback(() => {
|
|
@@ -46,18 +48,18 @@ export default function SideNavInnerToolbar({ title, children }<%=#isTypeScript%
|
|
|
46
48
|
return true;
|
|
47
49
|
}, [isLarge]);
|
|
48
50
|
|
|
49
|
-
const onNavigationChanged = useCallback(({ itemData
|
|
50
|
-
if (menuStatus === MenuStatus.Closed || !path || node
|
|
51
|
-
event
|
|
51
|
+
const onNavigationChanged = useCallback(({ itemData, event, node }<%=#isTypeScript%>: ItemClickEvent<%=/isTypeScript%>) => {
|
|
52
|
+
if (menuStatus === MenuStatus.Closed || !itemData<%=#isTypeScript%>?<%=/isTypeScript%>.path || node<%=#isTypeScript%>?<%=/isTypeScript%>.selected) {
|
|
53
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.preventDefault();
|
|
52
54
|
return;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
|
-
navigate(path);
|
|
57
|
+
navigate(itemData.path);
|
|
56
58
|
scrollViewRef.current<%=#isTypeScript%>?<%=/isTypeScript%>.instance.scrollTo(0);
|
|
57
59
|
|
|
58
60
|
if (!isLarge || menuStatus === MenuStatus.TemporaryOpened) {
|
|
59
61
|
setMenuStatus(MenuStatus.Closed);
|
|
60
|
-
event
|
|
62
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
|
|
61
63
|
}
|
|
62
64
|
}, [navigate, menuStatus, isLarge]);
|
|
63
65
|
|
|
@@ -7,6 +7,8 @@ import './side-nav-outer-toolbar.scss';
|
|
|
7
7
|
import { useScreenSize } from '../../utils/media-query';
|
|
8
8
|
import { Template } from 'devextreme-react/core/template';
|
|
9
9
|
import { useMenuPatch } from '../../utils/patches';
|
|
10
|
+
<%=#isTypeScript%>import { ClickEvent } from 'devextreme/ui/button';<%=/isTypeScript%>
|
|
11
|
+
<%=#isTypeScript%>import { ItemClickEvent } from 'devextreme/ui/tree_view';<%=/isTypeScript%>
|
|
10
12
|
<%=#isTypeScript%>import type { SideNavToolbarProps } from '../../types';<%=/isTypeScript%>
|
|
11
13
|
|
|
12
14
|
export default function SideNavOuterToolbar({ title, children }<%=#isTypeScript%>: React.PropsWithChildren<SideNavToolbarProps><%=/isTypeScript%>) {
|
|
@@ -18,13 +20,13 @@ export default function SideNavOuterToolbar({ title, children }<%=#isTypeScript%
|
|
|
18
20
|
isLarge ? MenuStatus.Opened : MenuStatus.Closed
|
|
19
21
|
);
|
|
20
22
|
|
|
21
|
-
const toggleMenu = useCallback(({ event }) => {
|
|
23
|
+
const toggleMenu = useCallback(({ event }<%=#isTypeScript%>: ClickEvent<%=/isTypeScript%>) => {
|
|
22
24
|
setMenuStatus(
|
|
23
25
|
prevMenuStatus => prevMenuStatus === MenuStatus.Closed
|
|
24
26
|
? MenuStatus.Opened
|
|
25
27
|
: MenuStatus.Closed
|
|
26
28
|
);
|
|
27
|
-
event
|
|
29
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
|
|
28
30
|
}, []);
|
|
29
31
|
|
|
30
32
|
const temporaryOpenMenu = useCallback(() => {
|
|
@@ -44,18 +46,18 @@ export default function SideNavOuterToolbar({ title, children }<%=#isTypeScript%
|
|
|
44
46
|
return true;
|
|
45
47
|
}, [isLarge]);
|
|
46
48
|
|
|
47
|
-
const onNavigationChanged = useCallback(({ itemData
|
|
48
|
-
if (menuStatus === MenuStatus.Closed || !path || node
|
|
49
|
-
event
|
|
49
|
+
const onNavigationChanged = useCallback(({ itemData, event, node }<%=#isTypeScript%>: ItemClickEvent<%=/isTypeScript%>) => {
|
|
50
|
+
if (menuStatus === MenuStatus.Closed || !itemData<%=#isTypeScript%>?<%=/isTypeScript%>.path || node<%=#isTypeScript%>?<%=/isTypeScript%>.selected) {
|
|
51
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.preventDefault();
|
|
50
52
|
return;
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
navigate(path);
|
|
55
|
+
navigate(itemData.path);
|
|
54
56
|
scrollViewRef.current<%=#isTypeScript%>?<%=/isTypeScript%>.instance.scrollTo(0);
|
|
55
57
|
|
|
56
58
|
if (!isLarge || menuStatus === MenuStatus.TemporaryOpened) {
|
|
57
59
|
setMenuStatus(MenuStatus.Closed);
|
|
58
|
-
event
|
|
60
|
+
event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
|
|
59
61
|
}
|
|
60
62
|
}, [navigate, menuStatus, isLarge]);
|
|
61
63
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Object.defineProperty(window, 'matchMedia', {
|
|
2
|
+
writable: true,
|
|
3
|
+
value: jest.fn().mockImplementation(query => ({
|
|
4
|
+
matches: false,
|
|
5
|
+
media: query,
|
|
6
|
+
onchange: null,
|
|
7
|
+
addListener: jest.fn(), // deprecated
|
|
8
|
+
removeListener: jest.fn(), // deprecated
|
|
9
|
+
addEventListener: jest.fn(),
|
|
10
|
+
removeEventListener: jest.fn(),
|
|
11
|
+
dispatchEvent: jest.fn(),
|
|
12
|
+
})),
|
|
13
|
+
});
|
|
14
|
+
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.content {
|
|
2
2
|
line-height: 1.5;
|
|
3
|
+
flex-grow: 1;
|
|
3
4
|
|
|
4
5
|
h2 {
|
|
5
6
|
font-size: 30px;
|
|
@@ -8,6 +9,17 @@
|
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
.container {
|
|
13
|
+
height: 100%;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
display: flex;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.layout-body {
|
|
19
|
+
flex: 1;
|
|
20
|
+
min-height: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
.side-nav-outer-toolbar .dx-drawer {
|
|
12
24
|
height: calc(100% - 56px)
|
|
13
25
|
}
|
|
@@ -137,21 +137,6 @@ export default {
|
|
|
137
137
|
width: 100%;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
.container {
|
|
141
|
-
height: 100%;
|
|
142
|
-
flex-direction: column;
|
|
143
|
-
display: flex;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
.layout-body {
|
|
147
|
-
flex: 1;
|
|
148
|
-
min-height: 0;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.content {
|
|
152
|
-
flex-grow: 1;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
140
|
#navigation-header {
|
|
156
141
|
@import "../themes/generated/variables.additional.scss";
|
|
157
142
|
background-color: $base-accent;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
.content {
|
|
2
2
|
line-height: 1.5;
|
|
3
|
+
flex-grow: 1;
|
|
3
4
|
|
|
4
5
|
h2 {
|
|
5
6
|
font-size: 30px;
|
|
@@ -8,6 +9,17 @@
|
|
|
8
9
|
}
|
|
9
10
|
}
|
|
10
11
|
|
|
12
|
+
.container {
|
|
13
|
+
height: 100%;
|
|
14
|
+
flex-direction: column;
|
|
15
|
+
display: flex;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.layout-body {
|
|
19
|
+
flex: 1;
|
|
20
|
+
min-height: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
.side-nav-outer-toolbar .dx-drawer {
|
|
12
24
|
height: calc(100% - 56px)
|
|
13
25
|
}
|
|
@@ -69,7 +69,7 @@ export default {
|
|
|
69
69
|
},
|
|
70
70
|
setup(props) {
|
|
71
71
|
const route = useRoute();
|
|
72
|
-
|
|
72
|
+
|
|
73
73
|
const scrollViewRef = ref(null);
|
|
74
74
|
const menuOpened = ref(props.isLarge);
|
|
75
75
|
const menuTemporaryOpened = ref(false);
|
|
@@ -117,7 +117,7 @@ export default {
|
|
|
117
117
|
}
|
|
118
118
|
}
|
|
119
119
|
);
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
watch(
|
|
122
122
|
() => route.path,
|
|
123
123
|
() => {
|
|
@@ -156,21 +156,6 @@ export default {
|
|
|
156
156
|
width: 100%;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
.container {
|
|
160
|
-
height: 100%;
|
|
161
|
-
flex-direction: column;
|
|
162
|
-
display: flex;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
.layout-body {
|
|
166
|
-
flex: 1;
|
|
167
|
-
min-height: 0;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
.content {
|
|
171
|
-
flex-grow: 1;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
159
|
#navigation-header {
|
|
175
160
|
@import "../themes/generated/variables.additional.scss";
|
|
176
161
|
background-color: $base-accent;
|
package/src/themebuider.js
CHANGED
|
@@ -14,7 +14,7 @@ const commands = {
|
|
|
14
14
|
|
|
15
15
|
const themeBuilderPackagePath = path.join(process.cwd(), 'node_modules', 'devextreme-themebuilder');
|
|
16
16
|
|
|
17
|
-
const
|
|
17
|
+
const scssCompilerDart = {
|
|
18
18
|
render: (scss) => {
|
|
19
19
|
return new Promise((resolve, reject) => {
|
|
20
20
|
require('dart-sass').render({
|
|
@@ -30,6 +30,16 @@ const scssCompiler = {
|
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
+
const scssCompiler = {
|
|
34
|
+
render: (scss) => {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
require('sass-embeded').compileStringAsync(scss)
|
|
37
|
+
.then((data) => resolve(data.css.toString()))
|
|
38
|
+
.catch((error) => reject(error.message));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
33
43
|
const createPath = filePath => {
|
|
34
44
|
const directoryName = path.dirname(filePath);
|
|
35
45
|
|
|
@@ -144,9 +154,16 @@ const getVarsFilter = (options) => {
|
|
|
144
154
|
|
|
145
155
|
const runThemeBuilder = async rawOptions => {
|
|
146
156
|
const options = await readInput(camelize(rawOptions));
|
|
157
|
+
const version = options.version || getInstalledPackageVersion('devextreme') || 'latest';
|
|
147
158
|
const initialItems = options.items ? [...options.items] : [];
|
|
159
|
+
|
|
148
160
|
options.reader = readFile;
|
|
149
|
-
options.sassCompiler =
|
|
161
|
+
options.sassCompiler = scssCompilerDart;
|
|
162
|
+
|
|
163
|
+
if(version === 'latest' || semver.gte(version, '22.1.3')) {
|
|
164
|
+
options.sassCompiler = scssCompiler;
|
|
165
|
+
}
|
|
166
|
+
|
|
150
167
|
options.lessCompiler = require('less/lib/less-node');
|
|
151
168
|
|
|
152
169
|
options.lessCompiler.options = options.lessCompiler.options || {};
|
|
@@ -157,8 +174,6 @@ const runThemeBuilder = async rawOptions => {
|
|
|
157
174
|
options.lessCompiler.options['rootpath'] = options.assetsBasePath;
|
|
158
175
|
}
|
|
159
176
|
|
|
160
|
-
const version = options.version || getInstalledPackageVersion('devextreme') || 'latest';
|
|
161
|
-
|
|
162
177
|
await lock.acquire();
|
|
163
178
|
|
|
164
179
|
try {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
const packageJson = require('../../package.json');
|
|
2
2
|
module.exports = {
|
|
3
|
-
'devextreme': '^
|
|
4
|
-
'devextreme-react': '^
|
|
5
|
-
'devextreme-vue': '^
|
|
3
|
+
'devextreme': '^22.1.3',
|
|
4
|
+
'devextreme-react': '^22.1.3',
|
|
5
|
+
'devextreme-vue': '^22.1.3',
|
|
6
6
|
'devextreme-cli': packageJson.version,
|
|
7
7
|
'devextreme-schematics': 'latest'
|
|
8
8
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const semver = require('semver').SemVer;
|
|
2
|
+
const execSync = require('child_process').execSync;
|
|
3
|
+
|
|
4
|
+
function parseNgCliVersion(stdout) {
|
|
5
|
+
return /angular.cli:\s*(\S+)/ig.exec(stdout)[1];
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const getLocalNgVersion = () => {
|
|
9
|
+
try {
|
|
10
|
+
const version = parseNgCliVersion(execSync('ng v').toString());
|
|
11
|
+
return new semver(version);
|
|
12
|
+
} catch(e) {
|
|
13
|
+
return '';
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const getPublicNgVersion = () => {
|
|
18
|
+
const version = execSync('npm view @angular/cli version').toString();
|
|
19
|
+
return new semver(version);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const getNgCliVersion = () => {
|
|
23
|
+
let ngCliVersion = getLocalNgVersion();
|
|
24
|
+
if(!ngCliVersion) {
|
|
25
|
+
ngCliVersion = getPublicNgVersion();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return ngCliVersion;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = {
|
|
32
|
+
getLocalNgVersion,
|
|
33
|
+
getPublicNgVersion,
|
|
34
|
+
getNgCliVersion
|
|
35
|
+
};
|