@corva/create-app 0.106.1 → 0.108.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.
@@ -6,12 +6,12 @@ export const APP_RUNTIMES = {
6
6
  NODE18: 'nodejs18.x',
7
7
  NODE20: 'nodejs20.x',
8
8
  NODE22: 'nodejs22.x',
9
- PYTHON3_8: 'python3.8',
10
- PYTHON3_9: 'python3.9',
11
- PYTHON3_10: 'python3.10',
9
+ // PYTHON3_8: 'python3.8',
10
+ // PYTHON3_9: 'python3.9',
11
+ // PYTHON3_10: 'python3.10',
12
12
  PYTHON3_11: 'python3.11',
13
13
  PYTHON3_12: 'python3.12',
14
- // PYTHON3_13: 'python3.13',
14
+ PYTHON3_13: 'python3.13',
15
15
  };
16
16
 
17
17
  export const TEMPLATE_TYPES = {
@@ -38,6 +38,7 @@ export const defaultUIAppManifest = {
38
38
  initial_size: { w: 4, h: 10 },
39
39
  multi_rig: false,
40
40
  full_screen_report: false,
41
+ use_app_header_v3: true,
41
42
  },
42
43
  },
43
44
  settings: {
@@ -56,11 +56,15 @@ const corvaUiExtension = {
56
56
  scripts: {
57
57
  prepare: 'husky install',
58
58
  },
59
+ dependencies: {
60
+ '@tanstack/react-query': '4.35.3',
61
+ },
59
62
  devDependencies: {
60
63
  '@commitlint/cli': '^17.0.0',
61
64
  '@commitlint/config-conventional': '^17.0.0',
62
65
  'husky': '^8.0.0',
63
66
  'lint-staged': '^13.0.0',
67
+ '@tanstack/eslint-plugin-query': '4.34.1',
64
68
  },
65
69
  };
66
70
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@corva/create-app",
3
- "version": "0.106.1",
3
+ "version": "0.108.0",
4
4
  "private": false,
5
5
  "description": "Create an app to use it in CORVA.AI",
6
6
  "keywords": [
@@ -34,6 +34,8 @@
34
34
  "lint:fix": "eslint . --fix",
35
35
  "release": "git add -A && standard-version -a",
36
36
  "release-rc": "npm run release -- --prerelease",
37
+ "run:local-ui-ts-completion": "node ./bin/create-corva-app.cjs ../test-app-ui-ts-completions --appName 'TestAppUiTsCompletions' --segments 'completion' --category 'analytics' --appKey 'corva.testappuitscompletions.ui' --appType 'ui' --runtime 'ui' -t --extensions corva",
38
+ "run:local-ui-ts-drilling": "node ./bin/create-corva-app.cjs ../test-app-ui-ts-drilling --appName 'TestAppUiTsDrilling' --segments 'drilling' --category 'analytics' --appKey 'corva.testappuitsdrilling.ui' --appType 'ui' --runtime 'ui' -t --extensions corva",
37
39
  "test": "NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest"
38
40
  },
39
41
  "lint-staged": {
@@ -92,6 +94,7 @@
92
94
  "typescript": "^4.8.4",
93
95
  "zx": "^7.2.3"
94
96
  },
97
+ "packageManager": "yarn@1.22.19+sha512.ff4579ab459bb25aa7c0ff75b62acebe576f6084b36aa842971cf250a5d8c6cd3bc9420b22ce63c7f93a0857bc6ef29291db39c3e7a23aab5adfd5a4dd6c5d71",
95
98
  "engines": {
96
99
  "node": ">=18"
97
100
  },
@@ -99,6 +102,5 @@
99
102
  "skip": {
100
103
  "tag": true
101
104
  }
102
- },
103
- "packageManager": "yarn@1.22.19+sha512.ff4579ab459bb25aa7c0ff75b62acebe576f6084b36aa842971cf250a5d8c6cd3bc9420b22ce63c7f93a0857bc6ef29291db39c3e7a23aab5adfd5a4dd6c5d71"
105
+ }
104
106
  }
@@ -0,0 +1,32 @@
1
+ {
2
+ "root": true,
3
+ "parser": "@typescript-eslint/parser",
4
+ "parserOptions": {
5
+ "ecmaVersion": 2020,
6
+ "sourceType": "module",
7
+ "ecmaFeature": {
8
+ "jsx": true
9
+ }
10
+ },
11
+ "extends": ["@corva/eslint-config-browser"],
12
+ "overrides": [
13
+ {
14
+ "files": ["*.ts", "*.tsx"],
15
+ "extends": [
16
+ "@corva/eslint-config-browser",
17
+ "plugin:@typescript-eslint/recommended",
18
+ "plugin:@tanstack/eslint-plugin-query/recommended"
19
+ ],
20
+ "rules": {
21
+ "@typescript-eslint/no-explicit-any": 2,
22
+ "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx", ".ts", ".tsx"] }],
23
+ /* Turned off until adopted by @corva/eslint-config-browser */
24
+ "react/prop-types": 0,
25
+ "react/default-props-match-prop-types": 0,
26
+ "react/no-unused-prop-types": 0,
27
+ "react/require-default-props": 0
28
+ /* Turned off until adopted by @corva/eslint-config-browser */
29
+ }
30
+ }
31
+ ]
32
+ }
@@ -27,7 +27,7 @@ function App({
27
27
 
28
28
  return (
29
29
  <AppContainer header={<AppHeader />} testId={appKey}>
30
- <div>
30
+ <div className={styles.container}>
31
31
  <img src={logo} alt="logo" className={styles.logo} />
32
32
  <p>
33
33
  Edit <code>src/App.js</code> and save to reload.
@@ -37,7 +37,7 @@ function App({
37
37
  <p>
38
38
  Frac Fleet: <span data-testid="fracFleet">{fracFleet?.name || 'No Frac Fleet'}</span>
39
39
  <br />
40
- Wells: <span data-testid="wellsList">{wellsList.map(well => well.name).join(', ')}</span>
40
+ Wells: <span data-testid="wellsList">{wellsList.map(well => well?.name).join(', ')}</span>
41
41
  </p>
42
42
  <a
43
43
  className="App-link"
@@ -1,3 +1,7 @@
1
+ .container {
2
+ text-align: center;
3
+ }
4
+
1
5
  @keyframes App-logo-spin {
2
6
  from {
3
7
  transform: rotate(0deg);
@@ -17,7 +17,7 @@ function App({ isExampleCheckboxChecked = DEFAULT_SETTINGS.isExampleCheckboxChec
17
17
  const { appKey } = useAppCommons();
18
18
  return (
19
19
  <AppContainer header={<AppHeader />} testId={appKey}>
20
- <div>
20
+ <div className={styles.container}>
21
21
  <img src={logo} alt="logo" className={styles.logo} />
22
22
  <p>
23
23
  Edit <code>src/App.js</code> and save to reload.
@@ -25,9 +25,9 @@ function App({ isExampleCheckboxChecked = DEFAULT_SETTINGS.isExampleCheckboxChec
25
25
  <br />
26
26
  </p>
27
27
  <p>
28
- Rig: <span data-testid="rig">{rig.name}</span>
28
+ Rig: <span data-testid="rig">{rig?.name}</span>
29
29
  <br />
30
- Well: <span data-testid="well">{well.name}</span>
30
+ Well: <span data-testid="well">{well?.name}</span>
31
31
  </p>
32
32
  <a
33
33
  className="App-link"
@@ -2,23 +2,17 @@ import { AppContainer, AppHeader } from '@corva/ui/componentsV2';
2
2
  import { useAppCommons } from '@corva/ui/effects';
3
3
 
4
4
  import { DEFAULT_SETTINGS } from './constants';
5
+ import { AppProps, CustomAppSettings } from './types';
5
6
  import logo from './assets/logo.svg';
6
7
 
7
8
  import styles from './App.css';
8
9
 
9
- type AppProps = {
10
- isExampleCheckboxChecked?: boolean;
11
- fracFleet?: { name: string };
12
- well?: { name: string };
13
- wells?: { name: string }[];
14
- };
15
-
16
10
  function App({
17
11
  isExampleCheckboxChecked = DEFAULT_SETTINGS.isExampleCheckboxChecked,
18
12
  fracFleet,
19
13
  well,
20
14
  wells,
21
- }: AppProps): JSX.Element {
15
+ }: AppProps & CustomAppSettings): JSX.Element {
22
16
  const { appKey } = useAppCommons();
23
17
  // NOTE: On general type dashboard app receives wells array
24
18
  // on asset type dashboard app receives well object
@@ -26,7 +20,7 @@ function App({
26
20
 
27
21
  return (
28
22
  <AppContainer header={<AppHeader />} testId={appKey}>
29
- <div>
23
+ <div className={styles.container}>
30
24
  <img src={logo} alt="logo" className={styles.logo} />
31
25
  <p>
32
26
  Edit <code>src/App.js</code> and save to reload.
@@ -36,7 +30,7 @@ function App({
36
30
  <p>
37
31
  Frac Fleet: <span data-testid="fracFleet">{fracFleet?.name || 'No Frac Fleet'}</span>
38
32
  <br />
39
- Wells: <span data-testid="wellsList">{wellsList.map(well => well.name).join(', ')}</span>
33
+ Wells: <span data-testid="wellsList">{wellsList.map(well => well?.name).join(', ')}</span>
40
34
  </p>
41
35
  <a
42
36
  className="App-link"
@@ -1,3 +1,7 @@
1
+ .container {
2
+ text-align: center;
3
+ }
4
+
1
5
  @keyframes App-logo-spin {
2
6
  from {
3
7
  transform: rotate(0deg);
@@ -2,25 +2,20 @@ import { AppContainer, AppHeader } from '@corva/ui/componentsV2';
2
2
  import { useAppCommons } from '@corva/ui/effects';
3
3
 
4
4
  import { DEFAULT_SETTINGS } from './constants';
5
+ import { AppProps, CustomAppSettings } from './types';
5
6
  import logo from './assets/logo.svg';
6
7
 
7
8
  import styles from './App.css';
8
9
 
9
- type AppProps = {
10
- isExampleCheckboxChecked?: boolean;
11
- rig: { name: string };
12
- well: { name: string };
13
- };
14
-
15
10
  function App({
16
11
  isExampleCheckboxChecked = DEFAULT_SETTINGS.isExampleCheckboxChecked,
17
12
  rig,
18
13
  well,
19
- }: AppProps): JSX.Element {
14
+ }: AppProps & CustomAppSettings): JSX.Element {
20
15
  const { appKey } = useAppCommons();
21
16
  return (
22
17
  <AppContainer header={<AppHeader />} testId={appKey}>
23
- <div>
18
+ <div className={styles.container}>
24
19
  <img src={logo} alt="logo" className={styles.logo} />
25
20
  <p>
26
21
  Edit <code>src/App.js</code> and save to reload.
@@ -28,9 +23,9 @@ function App({
28
23
  <br />
29
24
  </p>
30
25
  <p>
31
- Rig: <span data-testid="rig">{rig.name}</span>
26
+ Rig: <span data-testid="rig">{rig?.name}</span>
32
27
  <br />
33
- Well: <span data-testid="well">{well.name}</span>
28
+ Well: <span data-testid="well">{well?.name}</span>
34
29
  </p>
35
30
  <a
36
31
  className="App-link"
@@ -1,19 +1,9 @@
1
1
  import { Checkbox, FormControlLabel } from '@material-ui/core';
2
2
 
3
3
  import { DEFAULT_SETTINGS } from './constants';
4
+ import { AppSettingsProps, CustomAppSettings } from './types';
4
5
 
5
- type AppSettingsProps = {
6
- app: { [key: string]: any };
7
- appData: { [key: string]: any };
8
- company: { [key: string]: any };
9
- onSettingChange: (key: string, value: any) => void;
10
- settings: {
11
- isExampleCheckboxChecked: boolean;
12
- };
13
- user: { [key: string]: any };
14
- };
15
-
16
- const AppSettings = (props: AppSettingsProps): JSX.Element => {
6
+ const AppSettings = (props: AppSettingsProps & CustomAppSettings): JSX.Element => {
17
7
  const { settings: apiSettings, onSettingChange } = props;
18
8
  const settings = { ...DEFAULT_SETTINGS, ...apiSettings };
19
9
 
@@ -0,0 +1,194 @@
1
+ import { AppInstance, AppInstanceData, User, AppHeaderData } from '../types';
2
+
3
+ export const mockApp: AppInstance = {
4
+ app: { app_key: 'test', platform: 'test' },
5
+ id: 1,
6
+ package: {
7
+ manifest: {
8
+ format: 1,
9
+ license: { type: 'test', url: 'test' },
10
+ developer: { name: 'test', identifier: 'test', authors: [] },
11
+ application: {
12
+ type: 'test',
13
+ key: 'test',
14
+ visibility: 'test',
15
+ name: 'test',
16
+ description: 'test',
17
+ summary: 'test',
18
+ category: 'test',
19
+ website: 'test',
20
+ segments: ['test'],
21
+ ui: {
22
+ initial_size: { w: 100, h: 100 },
23
+ multi_rig: false,
24
+ full_screen_report: false,
25
+ use_app_header_v3: false,
26
+ },
27
+ },
28
+ settings: {
29
+ entrypoint: { file: 'test', function: 'test' },
30
+ environment: {},
31
+ runtime: 'test',
32
+ app: { log_type: 'test' },
33
+ enable_isolation: false,
34
+ },
35
+ datasets: {},
36
+ },
37
+ build: 'test',
38
+ version: 'test',
39
+ },
40
+ segment: ['test'],
41
+ settings: {},
42
+ };
43
+
44
+ export const mockUser: User = {
45
+ id: 1,
46
+ company_id: 1,
47
+ first_name: 'Test',
48
+ last_name: 'User',
49
+ email: 'test@test.com',
50
+ mobile: '1234567890',
51
+ created_at: '2023-01-01',
52
+ terms_acceptance_at: '2023-01-01',
53
+ profile_photo: null,
54
+ recently_viewed_asset_ids: [],
55
+ unit_system: null,
56
+ custom_unit_system: null,
57
+ role: 'test',
58
+ title: null,
59
+ group: null,
60
+ favorite_asset_id: null,
61
+ current_segment: 'test',
62
+ theme: 'test',
63
+ messaging_id: 'test',
64
+ restricted_assets: [],
65
+ restricted_programs: [],
66
+ settings: {
67
+ favorites: [],
68
+ home_page: { selected_assets_tab: 'test' },
69
+ onboarded: false,
70
+ beta_2_158: {},
71
+ uiSettings: {},
72
+ singleAsset: {
73
+ padId: 1,
74
+ rigId: 1,
75
+ wellId: null,
76
+ rigAssetId: 1,
77
+ fracFleetId: 1,
78
+ wellAssetId: null,
79
+ drilloutUnitId: 1,
80
+ completionWellAssetId: 1,
81
+ },
82
+ feed_filters: {
83
+ company_id: null,
84
+ start_date: '2023-01-01',
85
+ content_types: [],
86
+ selected_rigs_ids: [],
87
+ selected_user_ids: [],
88
+ users_radio_value: 'test',
89
+ assets_radio_value: 'test',
90
+ date_range_radio_value: 'test',
91
+ },
92
+ sms_blacklisted: false,
93
+ favorit_asset_ids: [],
94
+ restricted_assets: [],
95
+ alerts_list_filters: {
96
+ end_date: '2023-01-01',
97
+ segments: [],
98
+ alert_name: 'test',
99
+ start_date: '2023-01-01',
100
+ validation: 'test',
101
+ alert_levels: [],
102
+ subscription: 'test',
103
+ classification: 'test',
104
+ assets_radio_value: 'test',
105
+ date_range_radio_value: 'test',
106
+ },
107
+ restricted_programs: [],
108
+ is_dnd_feature_shown: false,
109
+ last_new_alerts_check: '2023-01-01',
110
+ notifications_filters: {
111
+ end_date: '2023-01-01',
112
+ start_date: '2023-01-01',
113
+ content_types: [],
114
+ date_range_radio_value: 'test',
115
+ },
116
+ directional_app_settings: {
117
+ curve_to_lat_threshold: 0,
118
+ vert_to_curve_threshold: 0,
119
+ },
120
+ last_new_feed_items_check: '2023-01-01',
121
+ participates_in_beta_apps: false,
122
+ 'cross-plot__gradient-manager': [],
123
+ last_new_dashboard_shares_check: '2023-01-01',
124
+ formation_evaluation_lithology_types: {},
125
+ formation_evaluation_custom_gradients: [],
126
+ },
127
+ last_sign_in_at: '2023-01-01',
128
+ locked_access: false,
129
+ unit_ids: [],
130
+ intercom_admin_id: null,
131
+ resource: [],
132
+ consent_to_process_data: false,
133
+ identity_verification_enabled: null,
134
+ intercom_user_hash: 'test',
135
+ impersonating: false,
136
+ profile_groups: [],
137
+ preference: {
138
+ id: 1,
139
+ push_notifications_enabled: false,
140
+ emails_enabled: false,
141
+ sms_enabled: false,
142
+ alert_levels: [],
143
+ play_alerts_sound: false,
144
+ show_intercom_icon: false,
145
+ segment: [],
146
+ disable_create_dashboard: false,
147
+ disable_costs: false,
148
+ disable_documents: false,
149
+ realtime_operation_mode: false,
150
+ disable_file_upload: false,
151
+ stay_on_app_store: false,
152
+ new_navigation_beta: false,
153
+ new_mobile_app_enabled: false,
154
+ },
155
+ company: {
156
+ id: 1,
157
+ name: 'Test Company',
158
+ time_zone: 'UTC',
159
+ language: 'en',
160
+ provider: 'test',
161
+ unit_system: {},
162
+ custom_unit_system: {},
163
+ custom_units: {},
164
+ dev_center_enabled: false,
165
+ with_subscription: false,
166
+ competitor_analysis_enabled: false,
167
+ ai_model_scope: 'test',
168
+ },
169
+ groups: [],
170
+ };
171
+
172
+ export const mockAppData: AppInstanceData = {
173
+ id: 1,
174
+ rig: null,
175
+ well: null,
176
+ fracFleet: null,
177
+ program: {
178
+ id: null,
179
+ name: null,
180
+ },
181
+ wells: null,
182
+ isLoading: false,
183
+ appHash: 'test',
184
+ };
185
+
186
+ export const mockAppHeaderProps: AppHeaderData = {
187
+ app: mockApp,
188
+ appLastAnnotation: null,
189
+ appSettings: {},
190
+ coordinates: { w: 0, h: 0, x: 0, y: 0, pixelHeight: 0, pixelWidth: 0 },
191
+ currentUser: mockUser,
192
+ isMaximized: false,
193
+ layoutEnvironment: { type: 'test', pdfReportMode: false },
194
+ };
@@ -2,21 +2,47 @@ import { render, screen } from '@testing-library/react';
2
2
  import { AppTestWrapper } from '@corva/ui/testing';
3
3
 
4
4
  import App from '../App';
5
- import { mockAppProps } from '../__mocks__/mockAppProps';
5
+ import { mockApp, mockUser, mockAppHeaderProps } from '../__mocks__/mockData';
6
6
 
7
7
  describe('<App />', () => {
8
8
  it('should show correct layout', () => {
9
9
  render(
10
10
  <AppTestWrapper
11
- app={mockAppProps.app}
11
+ app={{}}
12
12
  appId={123}
13
13
  maximized={false}
14
- appSettings={mockAppProps.app.settings}
14
+ appSettings={{}}
15
15
  onSettingChange={() => {
16
16
  /* noop */
17
17
  }}
18
18
  >
19
- <App {...mockAppProps} />
19
+ <App
20
+ app={mockApp}
21
+ package="test"
22
+ coordinates={{ w: 0, h: 0, x: 0, y: 0, pixelHeight: 0, pixelWidth: 0 }}
23
+ currentUser={mockUser}
24
+ devCenterRouter={{ location: { pathname: '', query: {} } }}
25
+ segment="test"
26
+ appHeaderProps={mockAppHeaderProps}
27
+ isNative={false}
28
+ layoutEnvironment={{ type: 'test', pdfReportMode: false }}
29
+ onSettingChange={() => {
30
+ /* noop */
31
+ }}
32
+ onSettingsChange={() => {
33
+ /* noop */
34
+ }}
35
+ setIsFullscreenModalMode={() => Promise.resolve()}
36
+ setIsMaximized={() => {
37
+ /* noop */
38
+ }}
39
+ setMainMenuItems={() => {
40
+ /* noop */
41
+ }}
42
+ setSecondaryMenuItems={() => {
43
+ /* noop */
44
+ }}
45
+ />
20
46
  </AppTestWrapper>
21
47
  );
22
48
 
@@ -24,20 +50,43 @@ describe('<App />', () => {
24
50
  });
25
51
 
26
52
  it('should show correct layout when settings are not provided', () => {
27
- const propsWithoutSettings = mockAppProps;
28
- delete propsWithoutSettings.isExampleCheckboxChecked;
29
-
30
53
  render(
31
54
  <AppTestWrapper
32
- app={mockAppProps.app}
55
+ app={{}}
33
56
  appId={123}
34
57
  maximized={false}
35
- appSettings={mockAppProps.app.settings}
58
+ appSettings={{}}
36
59
  onSettingChange={() => {
37
60
  /* noop */
38
61
  }}
39
62
  >
40
- <App {...propsWithoutSettings} />
63
+ <App
64
+ app={mockApp}
65
+ package="test"
66
+ coordinates={{ w: 0, h: 0, x: 0, y: 0, pixelHeight: 0, pixelWidth: 0 }}
67
+ currentUser={mockUser}
68
+ devCenterRouter={{ location: { pathname: '', query: {} } }}
69
+ segment="test"
70
+ appHeaderProps={mockAppHeaderProps}
71
+ isNative={false}
72
+ layoutEnvironment={{ type: 'test', pdfReportMode: false }}
73
+ onSettingChange={() => {
74
+ /* noop */
75
+ }}
76
+ onSettingsChange={() => {
77
+ /* noop */
78
+ }}
79
+ setIsFullscreenModalMode={() => Promise.resolve()}
80
+ setIsMaximized={() => {
81
+ /* noop */
82
+ }}
83
+ setMainMenuItems={() => {
84
+ /* noop */
85
+ }}
86
+ setSecondaryMenuItems={() => {
87
+ /* noop */
88
+ }}
89
+ />
41
90
  </AppTestWrapper>
42
91
  );
43
92
 
@@ -2,15 +2,26 @@ import { render, screen, act } from '@testing-library/react';
2
2
  import userEvent from '@testing-library/user-event';
3
3
 
4
4
  import AppSettings from '../AppSettings';
5
- import { mockAppSettingsProps } from '../__mocks__/mockAppSettingsProps';
5
+ import { mockApp, mockUser, mockAppData } from '../__mocks__/mockData';
6
6
 
7
7
  describe('<AppSettings />', () => {
8
8
  it('should call onChange with a changed setting on settings change', async () => {
9
9
  const handleSettingsChange = jest.fn();
10
+ const handleSettingsChangeAll = jest.fn();
10
11
 
11
- render(<AppSettings {...mockAppSettingsProps} onSettingChange={handleSettingsChange} />);
12
+ render(
13
+ <AppSettings
14
+ app={mockApp}
15
+ appData={mockAppData}
16
+ settings={{ isExampleCheckboxChecked: true }}
17
+ layoutEnvironment={{ type: 'test', pdfReportMode: false }}
18
+ currentUser={mockUser}
19
+ onSettingChange={handleSettingsChange}
20
+ onSettingsChange={handleSettingsChangeAll}
21
+ />
22
+ );
12
23
 
13
- const exampleCheckbox = screen.getByTestId('exampleCheckbox').querySelector('input');
24
+ const exampleCheckbox = screen.getByRole('checkbox', { name: /example/i });
14
25
 
15
26
  await act(async () => {
16
27
  await userEvent.click(exampleCheckbox);