devextreme-cli 1.3.3 → 1.4.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.
Files changed (25) hide show
  1. package/package.json +2 -2
  2. package/src/application.js +2 -2
  3. package/src/applications/application.angular.js +26 -41
  4. package/src/applications/application.react.js +0 -5
  5. package/src/templates/react/application/src/components/change-password-form/ChangePasswordForm.tsx +3 -2
  6. package/src/templates/react/application/src/components/create-account-form/CreateAccountForm.tsx +3 -2
  7. package/src/templates/react/application/src/components/login-form/LoginForm.tsx +1 -1
  8. package/src/templates/react/application/src/components/reset-password-form/ResetPasswordForm.tsx +1 -1
  9. package/src/templates/react/application/src/components/side-navigation-menu/SideNavigationMenu.tsx +2 -2
  10. package/src/templates/react/application/src/contexts/navigation.tsx +1 -1
  11. package/src/templates/react/application/src/dx-styles.scss +25 -13
  12. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +1 -16
  13. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.tsx +9 -7
  14. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +0 -9
  15. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.tsx +9 -7
  16. package/src/templates/react/application/src/types.tsx +4 -0
  17. package/src/templates/vue-v2/application/src/dx-styles.scss +12 -0
  18. package/src/templates/vue-v2/application/src/layouts/side-nav-inner-toolbar.vue +0 -15
  19. package/src/templates/vue-v2/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  20. package/src/templates/vue-v3/application/src/dx-styles.scss +12 -0
  21. package/src/templates/vue-v3/application/src/layouts/side-nav-inner-toolbar.vue +2 -17
  22. package/src/templates/vue-v3/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  23. package/src/themebuider.js +19 -4
  24. package/src/utility/latest-versions.js +3 -3
  25. 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.3",
3
+ "version": "1.4.0",
4
4
  "description": "DevExtreme CLI",
5
5
  "keywords": [
6
6
  "devexpress",
@@ -74,5 +74,5 @@
74
74
  "typescript": "^4.0.2",
75
75
  "typescript-eslint-parser": "^22.0.0"
76
76
  },
77
- "gitHead": "023ac50deaac92bd44a283079f55491f4db30049"
77
+ "gitHead": "555ce7269749c1c6586a09062044da0477505bc9"
78
78
  }
@@ -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 exec = require('child_process').exec;
8
- const minNgCliVersion = new semver('8.0.0');
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
- let globalNgCliVersion = '';
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, '--skipConfirmation=true'], evaluatingOptions);
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@13.3.7', 'ng'];
40
+ : ['-p', '@angular/cli', 'ng'];
40
41
 
41
42
  ngCommandArguments.push(...commandArguments);
42
43
  return runCommand(npmCommandName, ngCommandArguments, evaluatingOptions);
@@ -52,41 +53,21 @@ function localPackageExists(packageName) {
52
53
  return fs.existsSync(packageJsonPath);
53
54
  }
54
55
 
55
- function hasSutableNgCli() {
56
- return new Promise((resolve, reject) => {
57
- if(globalNgCliVersion !== '') {
58
- resolve(true);
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
- function parseNgCliVersion(stdout) {
85
- return new semver(/angular.cli:\s*(\S+)/ig.exec(stdout.toString())[1]);
86
- }
62
+ const isSupportVersion = localVersion.compare(minNgCliVersion) >= 0;
63
+ return isSupportVersion;
64
+ };
87
65
 
88
- const install = (options) => {
89
- runSchematicCommand('install', { ...options, globalNgCliVersion });
66
+ const install = async(options) => {
67
+ runSchematicCommand('install', {
68
+ ...options,
69
+ globalNgCliVersion: ngVersion.getNgCliVersion().version
70
+ });
90
71
  };
91
72
 
92
73
  const create = async(appName, options) => {
@@ -115,8 +96,12 @@ const create = async(appName, options) => {
115
96
  changeMainTs(appPath);
116
97
  };
117
98
 
118
- const addTemplate = (appName, options, evaluatingOptions) => {
119
- const schematicOptions = { ...(appName && { project: appName }), ...options };
99
+ const addTemplate = async(appName, options, evaluatingOptions) => {
100
+ const schematicOptions = {
101
+ ...(appName && { project: appName }),
102
+ ...options,
103
+ globalNgCliVersion: ngVersion.getNgCliVersion().version
104
+ };
120
105
  runSchematicCommand('add-app-template', schematicOptions, evaluatingOptions);
121
106
  };
122
107
 
@@ -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);
@@ -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
 
@@ -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);
@@ -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);
@@ -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<%=/isTypeScript%>) {
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
- .side-nav-outer-toolbar .dx-drawer {
11
- height: calc(100% - 56px)
12
- }
9
+ .content {
10
+ line-height: 1.5;
11
+ flex-grow: 1;
13
12
 
14
- .app .content {
15
- line-height: 1.5;
13
+ h2 {
14
+ font-size: 30px;
15
+ margin-top: 20px;
16
+ margin-bottom: 20px;
17
+ }
18
+ }
16
19
 
17
- h2 {
18
- font-size: 30px;
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
- .app .content-block {
25
- margin-left: 40px;
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.stopPropagation();
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: { path }, event, node }) => {
50
- if (menuStatus === MenuStatus.Closed || !path || node.selected) {
51
- event.preventDefault();
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.stopPropagation();
62
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
61
63
  }
62
64
  }, [navigate, menuStatus, isLarge]);
63
65
 
@@ -8,12 +8,3 @@
8
8
  .layout-header {
9
9
  z-index: 1501;
10
10
  }
11
-
12
- .layout-body {
13
- flex: 1;
14
- min-height: 0;
15
- }
16
-
17
- .content {
18
- flex-grow: 1;
19
- }
@@ -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.stopPropagation();
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: { path }, event, node }) => {
48
- if (menuStatus === MenuStatus.Closed || !path || node.selected) {
49
- event.preventDefault();
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.stopPropagation();
60
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
59
61
  }
60
62
  }, [navigate, menuStatus, isLarge]);
61
63
 
@@ -50,4 +50,8 @@ interface NavigationData {
50
50
  export type NavigationContextType = {
51
51
  setNavigationData?: ({ currentPath }: NavigationData) => void;
52
52
  navigationData: NavigationData;
53
+ }
54
+
55
+ export type ValidationType = {
56
+ value: string;
53
57
  }
@@ -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;
@@ -119,13 +119,4 @@ export default {
119
119
  .layout-header {
120
120
  z-index: 1501;
121
121
  }
122
-
123
- .layout-body {
124
- flex: 1;
125
- min-height: 0;
126
- }
127
-
128
- .content {
129
- flex-grow: 1;
130
- }
131
122
  </style>
@@ -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;
@@ -132,13 +132,4 @@ export default {
132
132
  .layout-header {
133
133
  z-index: 1501;
134
134
  }
135
-
136
- .layout-body {
137
- flex: 1;
138
- min-height: 0;
139
- }
140
-
141
- .content {
142
- flex-grow: 1;
143
- }
144
135
  </style>
@@ -14,7 +14,7 @@ const commands = {
14
14
 
15
15
  const themeBuilderPackagePath = path.join(process.cwd(), 'node_modules', 'devextreme-themebuilder');
16
16
 
17
- const scssCompiler = {
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 = scssCompiler;
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': '^21.2.4',
4
- 'devextreme-react': '^21.2.4',
5
- 'devextreme-vue': '^21.2.4',
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
+ };