devextreme-cli 1.3.1 → 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 (70) hide show
  1. package/index.js +4 -2
  2. package/package.json +8 -3
  3. package/src/application.js +19 -19
  4. package/src/applications/application.angular.js +48 -46
  5. package/src/applications/application.react.js +76 -39
  6. package/src/applications/application.vue.js +71 -34
  7. package/src/commands.json +3 -0
  8. package/src/templates/react/application/src/{App.js → App.tsx} +0 -0
  9. package/src/templates/react/application/src/{Content.js → Content.tsx} +11 -9
  10. package/src/templates/react/application/src/UnauthenticatedContent.tsx +46 -0
  11. package/src/templates/react/application/src/api/{auth.js → auth.tsx} +4 -4
  12. package/src/templates/react/application/src/{app-info.js → app-info.tsx} +0 -0
  13. package/src/templates/react/application/src/{app-navigation.js → app-navigation.tsx} +0 -0
  14. package/src/templates/react/application/src/app-routes.tsx +24 -0
  15. package/src/templates/react/application/src/components/change-password-form/{change-password-form.js → ChangePasswordForm.tsx} +9 -8
  16. package/src/templates/react/application/src/components/create-account-form/{create-account-form.scss → CreateAccountForm.scss} +0 -0
  17. package/src/templates/react/application/src/components/create-account-form/{create-account-form.js → CreateAccountForm.tsx} +10 -9
  18. package/src/templates/react/application/src/components/footer/{footer.scss → Footer.scss} +0 -0
  19. package/src/templates/react/application/src/components/footer/{footer.js → Footer.tsx} +1 -1
  20. package/src/templates/react/application/src/components/header/{header.scss → Header.scss} +0 -0
  21. package/src/templates/react/application/src/components/header/{header.js → Header.tsx} +4 -3
  22. package/src/templates/react/application/src/components/index.tsx +7 -0
  23. package/src/templates/react/application/src/components/login-form/{login-form.scss → LoginForm.scss} +0 -0
  24. package/src/templates/react/application/src/components/login-form/{login-form.js → LoginForm.tsx} +7 -7
  25. package/src/templates/react/application/src/components/reset-password-form/{reset-password-form.scss → ResetPasswordForm.scss} +0 -0
  26. package/src/templates/react/application/src/components/reset-password-form/{reset-password-form.js → ResetPasswordForm.tsx} +8 -8
  27. package/src/templates/react/application/src/components/side-navigation-menu/{side-navigation-menu.scss → SideNavigationMenu.scss} +0 -0
  28. package/src/templates/react/application/src/components/side-navigation-menu/{side-navigation-menu.js → SideNavigationMenu.tsx} +10 -12
  29. package/src/templates/react/application/src/components/user-panel/{user-panel.scss → UserPanel.scss} +0 -0
  30. package/src/templates/react/application/src/components/user-panel/{user-panel.js → UserPanel.tsx} +8 -8
  31. package/src/templates/react/application/src/contexts/{auth.js → auth.tsx} +6 -5
  32. package/src/templates/react/application/src/contexts/navigation.tsx +35 -0
  33. package/src/templates/react/application/src/dx-styles.scss +25 -13
  34. package/src/templates/react/application/src/layouts/{index.js → index.tsx} +0 -0
  35. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/side-nav-inner-toolbar.scss +1 -16
  36. package/src/templates/react/application/src/layouts/side-nav-inner-toolbar/{side-nav-inner-toolbar.js → side-nav-inner-toolbar.tsx} +20 -15
  37. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/side-nav-outer-toolbar.scss +0 -9
  38. package/src/templates/react/application/src/layouts/side-nav-outer-toolbar/{side-nav-outer-toolbar.js → side-nav-outer-toolbar.tsx} +19 -16
  39. package/src/templates/react/application/src/layouts/single-card/{single-card.js → single-card.tsx} +2 -1
  40. package/src/templates/react/application/src/{polyfills.js → polyfills.tsx} +0 -0
  41. package/src/templates/react/application/src/types.tsx +57 -0
  42. package/src/templates/react/application/src/utils/{default-user.js → default-user.tsx} +0 -0
  43. package/src/templates/react/application/src/utils/{media-query.js → media-query.tsx} +4 -3
  44. package/src/templates/react/application/src/utils/{patches.js → patches.tsx} +1 -1
  45. package/src/templates/react/page/{page.js → page.tsx} +0 -0
  46. package/src/templates/react/sample-pages/home/{home.js → home.tsx} +0 -0
  47. package/src/templates/react/sample-pages/{index.js → index.tsx} +0 -0
  48. package/src/templates/react/sample-pages/profile/{profile.js → profile.tsx} +0 -0
  49. package/src/templates/react/sample-pages/tasks/{tasks.js → tasks.tsx} +1 -1
  50. package/src/templates/vue-v2/application/devextreme.json +2 -1
  51. package/src/templates/vue-v2/application/src/dx-styles.scss +12 -0
  52. package/src/templates/vue-v2/application/src/layouts/side-nav-inner-toolbar.vue +0 -15
  53. package/src/templates/vue-v2/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  54. package/src/templates/vue-v3/application/devextreme.json +2 -1
  55. package/src/templates/vue-v3/application/src/dx-styles.scss +12 -0
  56. package/src/templates/vue-v3/application/src/layouts/side-nav-inner-toolbar.vue +2 -17
  57. package/src/templates/vue-v3/application/src/layouts/side-nav-outer-toolbar.vue +0 -9
  58. package/src/themebuider.js +19 -4
  59. package/src/utility/latest-versions.js +3 -3
  60. package/src/utility/ng-version.js +35 -0
  61. package/src/utility/prompts/layout.js +9 -21
  62. package/src/utility/prompts/prompts.js +24 -8
  63. package/src/utility/prompts/typescript.js +18 -0
  64. package/src/utility/prompts/vue-version.js +9 -21
  65. package/src/utility/template-creator.js +11 -6
  66. package/src/utility/typescript-extension.js +24 -0
  67. package/src/templates/react/application/src/UnauthenticatedContent.js +0 -35
  68. package/src/templates/react/application/src/app-routes.js +0 -24
  69. package/src/templates/react/application/src/components/index.js +0 -7
  70. package/src/templates/react/application/src/contexts/navigation.js +0 -34
@@ -3,29 +3,32 @@ import Drawer from 'devextreme-react/drawer';
3
3
  import ScrollView from 'devextreme-react/scroll-view';
4
4
  import Toolbar, { Item } from 'devextreme-react/toolbar';
5
5
  import React, { useState, useCallback, useRef } from 'react';
6
- import { useHistory } from 'react-router';
6
+ import { useNavigate } from 'react-router';
7
7
  import { Header, SideNavigationMenu, Footer } from '../../components';
8
8
  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%>
13
+ <%=#isTypeScript%>import type { SideNavToolbarProps } from '../../types';<%=/isTypeScript%>
14
+ <%=#isTypeScript%>import { ClickEvent } from 'devextreme/ui/button';<%=/isTypeScript%>
12
15
 
13
- export default function SideNavInnerToolbar({ title, children }) {
14
- const scrollViewRef = useRef();
15
- const history = useHistory();
16
+ export default function SideNavInnerToolbar({ title, children }<%=#isTypeScript%>: React.PropsWithChildren<SideNavToolbarProps><%=/isTypeScript%>) {
17
+ const scrollViewRef = useRef<%=#isTypeScript%><ScrollView><%=/isTypeScript%>(null);
18
+ const navigate = useNavigate();
16
19
  const { isXSmall, isLarge } = useScreenSize();
17
20
  const [patchCssClass, onMenuReady] = useMenuPatch();
18
21
  const [menuStatus, setMenuStatus] = useState(
19
22
  isLarge ? MenuStatus.Opened : MenuStatus.Closed
20
23
  );
21
24
 
22
- const toggleMenu = useCallback(({ event }) => {
25
+ const toggleMenu = useCallback(({ event }<%=#isTypeScript%>: ClickEvent<%=/isTypeScript%>) => {
23
26
  setMenuStatus(
24
27
  prevMenuStatus => prevMenuStatus === MenuStatus.Closed
25
28
  ? MenuStatus.Opened
26
29
  : MenuStatus.Closed
27
30
  );
28
- event.stopPropagation();
31
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
29
32
  }, []);
30
33
 
31
34
  const temporaryOpenMenu = useCallback(() => {
@@ -42,22 +45,23 @@ export default function SideNavInnerToolbar({ title, children }) {
42
45
  ? MenuStatus.Closed
43
46
  : prevMenuStatus
44
47
  );
48
+ return true;
45
49
  }, [isLarge]);
46
50
 
47
- const onNavigationChanged = useCallback(({ itemData: { path }, event, node }) => {
48
- if (menuStatus === MenuStatus.Closed || !path || node.selected) {
49
- 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();
50
54
  return;
51
55
  }
52
56
 
53
- history.push(path);
54
- scrollViewRef.current.instance.scrollTo(0);
57
+ navigate(itemData.path);
58
+ scrollViewRef.current<%=#isTypeScript%>?<%=/isTypeScript%>.instance.scrollTo(0);
55
59
 
56
60
  if (!isLarge || menuStatus === MenuStatus.TemporaryOpened) {
57
61
  setMenuStatus(MenuStatus.Closed);
58
- event.stopPropagation();
62
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
59
63
  }
60
- }, [history, menuStatus, isLarge]);
64
+ }, [navigate, menuStatus, isLarge]);
61
65
 
62
66
  return (
63
67
  <div className={'side-nav-inner-toolbar'}>
@@ -80,12 +84,12 @@ export default function SideNavInnerToolbar({ title, children }) {
80
84
  />
81
85
  <ScrollView ref={scrollViewRef} className={'layout-body with-footer'}>
82
86
  <div className={'content'}>
83
- {React.Children.map(children, item => {
87
+ {React.Children.map(children, (item<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
84
88
  return item.type !== Footer && item;
85
89
  })}
86
90
  </div>
87
91
  <div className={'content-block'}>
88
- {React.Children.map(children, item => {
92
+ {React.Children.map(children, (item<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
89
93
  return item.type === Footer && item;
90
94
  })}
91
95
  </div>
@@ -122,3 +126,4 @@ const MenuStatus = {
122
126
  Opened: 2,
123
127
  TemporaryOpened: 3
124
128
  };
129
+
@@ -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
- }
@@ -1,29 +1,32 @@
1
1
  import Drawer from 'devextreme-react/drawer';
2
2
  import ScrollView from 'devextreme-react/scroll-view';
3
3
  import React, { useState, useCallback, useRef } from 'react';
4
- import { useHistory } from 'react-router';
4
+ import { useNavigate } from 'react-router';
5
5
  import { Header, SideNavigationMenu, Footer } from '../../components';
6
6
  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%>
12
+ <%=#isTypeScript%>import type { SideNavToolbarProps } from '../../types';<%=/isTypeScript%>
10
13
 
11
- export default function SideNavOuterToolbar({ title, children }) {
12
- const scrollViewRef = useRef();
13
- const history = useHistory();
14
+ export default function SideNavOuterToolbar({ title, children }<%=#isTypeScript%>: React.PropsWithChildren<SideNavToolbarProps><%=/isTypeScript%>) {
15
+ const scrollViewRef = useRef<%=#isTypeScript%><ScrollView><%=/isTypeScript%>(null);
16
+ const navigate = useNavigate();
14
17
  const { isXSmall, isLarge } = useScreenSize();
15
18
  const [patchCssClass, onMenuReady] = useMenuPatch();
16
19
  const [menuStatus, setMenuStatus] = useState(
17
20
  isLarge ? MenuStatus.Opened : MenuStatus.Closed
18
21
  );
19
22
 
20
- const toggleMenu = useCallback(({ event }) => {
23
+ const toggleMenu = useCallback(({ event }<%=#isTypeScript%>: ClickEvent<%=/isTypeScript%>) => {
21
24
  setMenuStatus(
22
25
  prevMenuStatus => prevMenuStatus === MenuStatus.Closed
23
26
  ? MenuStatus.Opened
24
27
  : MenuStatus.Closed
25
28
  );
26
- event.stopPropagation();
29
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
27
30
  }, []);
28
31
 
29
32
  const temporaryOpenMenu = useCallback(() => {
@@ -40,27 +43,27 @@ export default function SideNavOuterToolbar({ title, children }) {
40
43
  ? MenuStatus.Closed
41
44
  : prevMenuStatus
42
45
  );
46
+ return true;
43
47
  }, [isLarge]);
44
48
 
45
- const onNavigationChanged = useCallback(({ itemData: { path }, event, node }) => {
46
- if (menuStatus === MenuStatus.Closed || !path || node.selected) {
47
- 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();
48
52
  return;
49
53
  }
50
54
 
51
- history.push(path);
52
- scrollViewRef.current.instance.scrollTo(0);
55
+ navigate(itemData.path);
56
+ scrollViewRef.current<%=#isTypeScript%>?<%=/isTypeScript%>.instance.scrollTo(0);
53
57
 
54
58
  if (!isLarge || menuStatus === MenuStatus.TemporaryOpened) {
55
59
  setMenuStatus(MenuStatus.Closed);
56
- event.stopPropagation();
60
+ event<%=#isTypeScript%>?<%=/isTypeScript%>.stopPropagation();
57
61
  }
58
- }, [history, menuStatus, isLarge]);
62
+ }, [navigate, menuStatus, isLarge]);
59
63
 
60
64
  return (
61
65
  <div className={'side-nav-outer-toolbar'}>
62
66
  <Header
63
- className={'layout-header'}
64
67
  menuToggleEnabled
65
68
  toggleMenu={toggleMenu}
66
69
  title={title}
@@ -80,12 +83,12 @@ export default function SideNavOuterToolbar({ title, children }) {
80
83
  <div className={'container'}>
81
84
  <ScrollView ref={scrollViewRef} className={'layout-body with-footer'}>
82
85
  <div className={'content'}>
83
- {React.Children.map(children, item => {
86
+ {React.Children.map(children, (item<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
84
87
  return item.type !== Footer && item;
85
88
  })}
86
89
  </div>
87
90
  <div className={'content-block'}>
88
- {React.Children.map(children, item => {
91
+ {React.Children.map(children, (item<%=#isTypeScript%>: any<%=/isTypeScript%>) => {
89
92
  return item.type === Footer && item;
90
93
  })}
91
94
  </div>
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
2
  import ScrollView from 'devextreme-react/scroll-view';
3
3
  import './single-card.scss';
4
+ <%=#isTypeScript%>import type { SingleCardProps } from '../../types';<%=/isTypeScript%>
4
5
 
5
- export default function SingleCard({ title, description, children }) {
6
+ export default function SingleCard({ title, description, children }<%=#isTypeScript%>: React.PropsWithChildren<SingleCardProps><%=/isTypeScript%>) {
6
7
  return (
7
8
  <ScrollView height={'100%'} width={'100%'} className={'with-footer single-card'}>
8
9
  <div className={'dx-card content'}>
@@ -0,0 +1,57 @@
1
+ import dxTreeView, { ItemClickEvent } from 'devextreme/ui/tree_view';
2
+ import { ClickEvent } from 'devextreme/ui/button';
3
+ import { EventInfo } from 'devextreme/events';
4
+ import React from 'react';
5
+
6
+ export interface HeaderProps {
7
+ menuToggleEnabled: boolean;
8
+ title?: string;
9
+ toggleMenu: (e: ClickEvent) => void;
10
+ }
11
+
12
+ export interface SideNavigationMenuProps {
13
+ selectedItemChanged: (e: ItemClickEvent) => void;
14
+ openMenu: (e: React.PointerEvent) => void;
15
+ compactMode: boolean;
16
+ onMenuReady: (e: EventInfo<dxTreeView>) => void;
17
+ }
18
+
19
+ export interface UserPanelProps {
20
+ menuMode: 'context' | 'list';
21
+ }
22
+
23
+ export interface User {
24
+ email: string;
25
+ avatarUrl: string;
26
+ }
27
+
28
+ export type AuthContextType = {
29
+ user?: User;
30
+ signIn: (email: string, password: string) => Promise<{isOk: boolean, data?: User, message?: string}>;
31
+ signOut: () => void;
32
+ loading: boolean;
33
+ }
34
+
35
+ export interface SideNavToolbarProps {
36
+ title: string;
37
+ }
38
+
39
+ export interface SingleCardProps {
40
+ title?: string;
41
+ description?: string;
42
+ }
43
+
44
+ export type Handle = () => void;
45
+
46
+ interface NavigationData {
47
+ currentPath: string;
48
+ }
49
+
50
+ export type NavigationContextType = {
51
+ setNavigationData?: ({ currentPath }: NavigationData) => void;
52
+ navigationData: NavigationData;
53
+ }
54
+
55
+ export type ValidationType = {
56
+ value: string;
57
+ }
@@ -1,4 +1,5 @@
1
1
  import { useState, useCallback, useEffect } from 'react';
2
+ <%=#isTypeScript%>import type { Handle } from '../types';<%=/isTypeScript%>
2
3
 
3
4
  export const useScreenSize = () => {
4
5
  const [screenSize, setScreenSize] = useState(getScreenSize());
@@ -35,7 +36,7 @@ export const useScreenSizeClass = () => {
35
36
  return 'screen-x-small';
36
37
  }
37
38
 
38
- let handlers = [];
39
+ let handlers<%=#isTypeScript%>: Handle[]<%=/isTypeScript%> = [];
39
40
  const xSmallMedia = window.matchMedia('(max-width: 599.99px)');
40
41
  const smallMedia = window.matchMedia('(min-width: 600px) and (max-width: 959.99px)');
41
42
  const mediumMedia = window.matchMedia('(min-width: 960px) and (max-width: 1279.99px)');
@@ -47,9 +48,9 @@ const largeMedia = window.matchMedia('(min-width: 1280px)');
47
48
  });
48
49
  });
49
50
 
50
- const subscribe = handler => handlers.push(handler);
51
+ const subscribe = (handler<%=#isTypeScript%>: Handle<%=/isTypeScript%>) => handlers.push(handler);
51
52
 
52
- const unsubscribe = handler => {
53
+ const unsubscribe = (handler<%=#isTypeScript%>: Handle<%=/isTypeScript%>) => {
53
54
  handlers = handlers.filter(item => item !== handler);
54
55
  };
55
56
 
@@ -12,5 +12,5 @@ export function useMenuPatch() {
12
12
  setTimeout(() => setEnabled(false));
13
13
  }, [enabled]);
14
14
 
15
- return [enabled ? 'pre-init-blink-fix' : '', onMenuReady];
15
+ return [enabled ? 'pre-init-blink-fix' : '', onMenuReady]<%=#isTypeScript%> as [string, () => void]<%=/isTypeScript%>;
16
16
  }
File without changes
@@ -15,7 +15,7 @@ export default function Task() {
15
15
 
16
16
  <DataGrid
17
17
  className={'dx-card wide-card'}
18
- dataSource={dataSource}
18
+ dataSource={dataSource<%=#isTypeScript%> as any<%=/isTypeScript%>}
19
19
  showBorders={false}
20
20
  focusedRowEnabled={true}
21
21
  defaultFocusedRowIndex={0}
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "applicationEngine": "vue",
3
3
  "vue": {
4
- "version": 2
4
+ "version": 2,
5
+ "template": "javascript"
5
6
  },
6
7
  "build": {
7
8
  "commands": [
@@ -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,7 +1,8 @@
1
1
  {
2
2
  "applicationEngine": "vue",
3
3
  "vue": {
4
- "version": 3
4
+ "version": 3,
5
+ "template": "javascript"
5
6
  },
6
7
  "build": {
7
8
  "commands": [
@@ -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
+ };
@@ -1,29 +1,17 @@
1
- const runPrompts = require('./prompts');
2
- const layouts = [
1
+ const prompts = require('./prompts');
2
+
3
+ const choices = [
3
4
  { value: 'side-nav-outer-toolbar', title: 'Side navigation (outer toolbar)' },
4
5
  { value: 'side-nav-inner-toolbar', title: 'Side navigation (inner toolbar)' }
5
6
  ];
6
7
 
7
- const getValidLayoutName = (layoutName) => {
8
- if(!layoutName || !layouts.some((layout) => layoutName === layout.value)) {
9
- return;
10
- }
11
- return layoutName;
8
+ const question = {
9
+ message: 'Specify desired application layout:',
10
+ choices: choices
12
11
  };
13
12
 
14
- const getLayoutInfo = (layoutName) => {
15
- const questions = [
16
- {
17
- type: 'select',
18
- name: 'layout',
19
- message: 'Specify desired application layout:',
20
- choices: layouts
21
- }
22
- ];
23
-
24
- return runPrompts(questions, getValidLayoutName(layoutName));
13
+ const getLayoutInfo = async(defaultValue) => {
14
+ return await prompts(question, choices, defaultValue);
25
15
  };
26
16
 
27
- module.exports = {
28
- getLayoutInfo
29
- };
17
+ module.exports = getLayoutInfo;
@@ -1,16 +1,32 @@
1
1
  const prompts = require('prompts');
2
2
 
3
- const runPrompts = async(questions, validateValue) => {
3
+ const run = async(question, choices, defaultValue) => {
4
+ question = Object.assign({}, question, {
5
+ type: 'select',
6
+ name: 'answer',
7
+ });
8
+
9
+ const { answer } = await askQuestion(question, getDefaultValue(choices, defaultValue));
10
+
11
+ return answer;
12
+ };
13
+
14
+ const askQuestion = async(question, validateValue) => {
4
15
  if(validateValue) {
5
- const optionData = {
6
- [questions[0].name]: validateValue
16
+ return {
17
+ answer: validateValue
7
18
  };
8
- return new Promise((resolve, reject) => {
9
- resolve(optionData);
10
- });
11
19
  }
12
20
 
13
- return await prompts(questions);
21
+ return await prompts(question);
22
+ };
23
+
24
+ const getDefaultValue = (choices, answer) => {
25
+ if(!answer || !choices.some((choice) => answer === choice.value)) {
26
+ return;
27
+ }
28
+
29
+ return answer;
14
30
  };
15
31
 
16
- module.exports = runPrompts;
32
+ module.exports = run;