Skip to content

Commit 78c794b

Browse files
committedFeb 26, 2021
Add Support page in the configurator with help resources. Added an a ability to clear platformio source core_dir
1 parent 112274d commit 78c794b

File tree

13 files changed

+387
-13
lines changed

13 files changed

+387
-13
lines changed
 

‎graphql.schema.json

+55
Original file line numberDiff line numberDiff line change
@@ -669,6 +669,22 @@
669669
},
670670
"isDeprecated": false,
671671
"deprecationReason": null
672+
},
673+
{
674+
"name": "clearPlatformioCoreDir",
675+
"description": null,
676+
"args": [],
677+
"type": {
678+
"kind": "NON_NULL",
679+
"name": null,
680+
"ofType": {
681+
"kind": "OBJECT",
682+
"name": "ClearPlatformioCoreDirResult",
683+
"ofType": null
684+
}
685+
},
686+
"isDeprecated": false,
687+
"deprecationReason": null
672688
}
673689
],
674690
"inputFields": null,
@@ -1108,6 +1124,45 @@
11081124
"enumValues": null,
11091125
"possibleTypes": null
11101126
},
1127+
{
1128+
"kind": "OBJECT",
1129+
"name": "ClearPlatformioCoreDirResult",
1130+
"description": null,
1131+
"fields": [
1132+
{
1133+
"name": "success",
1134+
"description": null,
1135+
"args": [],
1136+
"type": {
1137+
"kind": "NON_NULL",
1138+
"name": null,
1139+
"ofType": {
1140+
"kind": "SCALAR",
1141+
"name": "Boolean",
1142+
"ofType": null
1143+
}
1144+
},
1145+
"isDeprecated": false,
1146+
"deprecationReason": null
1147+
},
1148+
{
1149+
"name": "message",
1150+
"description": null,
1151+
"args": [],
1152+
"type": {
1153+
"kind": "SCALAR",
1154+
"name": "String",
1155+
"ofType": null
1156+
},
1157+
"isDeprecated": false,
1158+
"deprecationReason": null
1159+
}
1160+
],
1161+
"inputFields": null,
1162+
"interfaces": [],
1163+
"enumValues": null,
1164+
"possibleTypes": null
1165+
},
11111166
{
11121167
"kind": "OBJECT",
11131168
"name": "Subscription",

‎package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@
223223
"@types/react-dom": "^17.0.0",
224224
"@types/react-router-dom": "^5.1.7",
225225
"@types/react-test-renderer": "^17.0.0",
226+
"@types/rimraf": "^3.0.0",
226227
"@types/uuid": "^8.3.0",
227228
"@types/webpack-env": "^1.16.0",
228229
"@typescript-eslint/eslint-plugin": "^4.15.0",
@@ -274,7 +275,7 @@
274275
"prettier": "^2.2.1",
275276
"react-refresh": "^0.9.0",
276277
"react-test-renderer": "^17.0.1",
277-
"rimraf": "^3.0.0",
278+
"rimraf": "^3.0.2",
278279
"sass-loader": "^10.1.1",
279280
"style-loader": "^2.0.0",
280281
"terser-webpack-plugin": "^5.1.1",

‎src/api/src/graphql/resolvers/Firmware.resolver.ts

+14
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import BuildProgressNotification from '../../models/BuildProgressNotification';
2020
import PubSubTopic from '../../pubsub/enum/PubSubTopic';
2121
import BuildLogUpdate from '../../models/BuildLogUpdate';
2222
import { ConfigToken, IConfig } from '../../config';
23+
import ClearPlatformioCoreDirResult from '../../models/ClearPlatformioCoreDirResult';
2324

2425
@Service()
2526
@Resolver()
@@ -48,6 +49,19 @@ export default class FirmwareResolver {
4849
return this.firmwareService.buildFlashFirmware(input, this.config.git);
4950
}
5051

52+
@Mutation(() => ClearPlatformioCoreDirResult)
53+
async clearPlatformioCoreDir(): Promise<ClearPlatformioCoreDirResult> {
54+
try {
55+
await this.firmwareService.clearPlatformioCoreDir();
56+
return new ClearPlatformioCoreDirResult(true);
57+
} catch (e) {
58+
return new ClearPlatformioCoreDirResult(
59+
false,
60+
`Failed to clear platformio state: ${e}`
61+
);
62+
}
63+
}
64+
5165
@Subscription(() => BuildProgressNotification, {
5266
topics: [PubSubTopic.BuildProgressNotification],
5367
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Field, ObjectType } from 'type-graphql';
2+
3+
@ObjectType('ClearPlatformioCoreDirResult')
4+
export default class ClearPlatformioCoreDirResult {
5+
@Field()
6+
success: boolean;
7+
8+
@Field({ nullable: true })
9+
message?: string;
10+
11+
constructor(success: boolean, message?: string) {
12+
this.success = success;
13+
this.message = message;
14+
}
15+
}

‎src/api/src/services/Firmware/index.ts

+28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { Service } from 'typedi';
22
import { PubSubEngine } from 'graphql-subscriptions';
33
import * as os from 'os';
4+
import * as fs from 'fs';
5+
import rimraf from 'rimraf';
46
import BuildJobType from '../../models/enum/BuildJobType';
57
import DeviceTarget from '../../library/FirmwareBuilder/Enum/DeviceTarget';
68
import UserDefinesMode from '../../models/enum/UserDefinesMode';
@@ -392,4 +394,30 @@ export default class FirmwareService {
392394
this.mutex.unlock();
393395
}
394396
}
397+
398+
async clearPlatformioCoreDir(): Promise<void> {
399+
const platformioStateJson = await this.platformio.getPlatformioState();
400+
if (
401+
platformioStateJson.core_dir === undefined ||
402+
platformioStateJson.core_dir.length === 0 ||
403+
platformioStateJson.core_dir.indexOf('.platformio') === -1
404+
) {
405+
throw new Error(`core_dir is invalid: ${platformioStateJson.core_dir}`);
406+
}
407+
408+
const statResult = await fs.promises.lstat(platformioStateJson.core_dir);
409+
if (!statResult.isDirectory()) {
410+
throw new Error(`core_dir is invalid: ${platformioStateJson.core_dir}`);
411+
}
412+
413+
return new Promise((resolve, reject) => {
414+
rimraf(platformioStateJson.core_dir, (err) => {
415+
if (err) {
416+
reject();
417+
} else {
418+
resolve();
419+
}
420+
});
421+
});
422+
}
395423
}

‎src/ui/App.tsx

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import client from './gql';
1010
import ConfiguratorView from './views/ConfiguratorView';
1111
import SettingsView from './views/SettingsView';
1212
import LogsView from './views/LogsView';
13+
import SupportView from './views/SupportView';
1314

1415
export default function App() {
1516
return (
@@ -24,6 +25,7 @@ export default function App() {
2425
<Route path="/configurator" component={ConfiguratorView} />
2526
<Route path="/settings" component={SettingsView} />
2627
<Route path="/logs" component={LogsView} />
28+
<Route path="/support" component={SupportView} />
2729
</Switch>
2830
</HashRouter>
2931
</ApolloProvider>

‎src/ui/components/Sidebar/index.tsx

+16
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
Toolbar,
1212
} from '@material-ui/core';
1313
import BuildIcon from '@material-ui/icons/Build';
14+
import HelpIcon from '@material-ui/icons/Help';
1415
// import SettingsIcon from '@material-ui/icons/Settings';
1516
import ListIcon from '@material-ui/icons/List';
1617
import { matchPath, useLocation, Link } from 'react-router-dom';
@@ -44,6 +45,7 @@ const Sidebar: FunctionComponent<SidebarProps> = ({ navigationEnabled }) => {
4445
matchPath(location.pathname, '/configurator') !== null;
4546
// const settingsActive = matchPath(location.pathname, '/settings') !== null;
4647
const logsActive = matchPath(location.pathname, '/logs') !== null;
48+
const supportActive = matchPath(location.pathname, '/support') !== null;
4749

4850
return (
4951
<Drawer
@@ -97,6 +99,20 @@ const Sidebar: FunctionComponent<SidebarProps> = ({ navigationEnabled }) => {
9799
</ListItemIcon>
98100
<ListItemText primary="Logs" />
99101
</ListItem>
102+
103+
<ListItem
104+
component={Link}
105+
to="/support"
106+
selected={supportActive}
107+
className={styles.menuItem}
108+
button
109+
disabled={!navigationEnabled}
110+
>
111+
<ListItemIcon>
112+
<HelpIcon />
113+
</ListItemIcon>
114+
<ListItemText primary="Support" />
115+
</ListItem>
100116
</List>
101117
</div>
102118
</Drawer>

‎src/ui/gql/generated/types.ts

+68
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export enum UserDefineKey {
110110
export type Mutation = {
111111
readonly __typename?: 'Mutation';
112112
readonly buildFlashFirmware: BuildFlashFirmwareResult;
113+
readonly clearPlatformioCoreDir: ClearPlatformioCoreDirResult;
113114
};
114115

115116
export type MutationBuildFlashFirmwareArgs = {
@@ -175,6 +176,12 @@ export type UserDefineInput = {
175176
readonly value?: Maybe<Scalars['String']>;
176177
};
177178

179+
export type ClearPlatformioCoreDirResult = {
180+
readonly __typename?: 'ClearPlatformioCoreDirResult';
181+
readonly success: Scalars['Boolean'];
182+
readonly message?: Maybe<Scalars['String']>;
183+
};
184+
178185
export type Subscription = {
179186
readonly __typename?: 'Subscription';
180187
readonly buildProgressNotifications: BuildProgressNotification;
@@ -255,6 +262,18 @@ export type BuildProgressNotificationsSubscription = {
255262
} & Pick<BuildProgressNotification, 'type' | 'step' | 'message'>;
256263
};
257264

265+
export type ClearPlatformioCoreDirMutationVariables = Exact<{
266+
[key: string]: never;
267+
}>;
268+
269+
export type ClearPlatformioCoreDirMutation = {
270+
readonly __typename?: 'Mutation';
271+
} & {
272+
readonly clearPlatformioCoreDir: {
273+
readonly __typename?: 'ClearPlatformioCoreDirResult';
274+
} & Pick<ClearPlatformioCoreDirResult, 'success' | 'message'>;
275+
};
276+
258277
export type TargetDeviceOptionsQueryVariables = Exact<{
259278
target: DeviceTarget;
260279
}>;
@@ -469,6 +488,55 @@ export type BuildProgressNotificationsSubscriptionHookResult = ReturnType<
469488
typeof useBuildProgressNotificationsSubscription
470489
>;
471490
export type BuildProgressNotificationsSubscriptionResult = Apollo.SubscriptionResult<BuildProgressNotificationsSubscription>;
491+
export const ClearPlatformioCoreDirDocument = gql`
492+
mutation clearPlatformioCoreDir {
493+
clearPlatformioCoreDir {
494+
success
495+
message
496+
}
497+
}
498+
`;
499+
export type ClearPlatformioCoreDirMutationFn = Apollo.MutationFunction<
500+
ClearPlatformioCoreDirMutation,
501+
ClearPlatformioCoreDirMutationVariables
502+
>;
503+
504+
/**
505+
* __useClearPlatformioCoreDirMutation__
506+
*
507+
* To run a mutation, you first call `useClearPlatformioCoreDirMutation` within a React component and pass it any options that fit your needs.
508+
* When your component renders, `useClearPlatformioCoreDirMutation` returns a tuple that includes:
509+
* - A mutate function that you can call at any time to execute the mutation
510+
* - An object with fields that represent the current status of the mutation's execution
511+
*
512+
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
513+
*
514+
* @example
515+
* const [clearPlatformioCoreDirMutation, { data, loading, error }] = useClearPlatformioCoreDirMutation({
516+
* variables: {
517+
* },
518+
* });
519+
*/
520+
export function useClearPlatformioCoreDirMutation(
521+
baseOptions?: Apollo.MutationHookOptions<
522+
ClearPlatformioCoreDirMutation,
523+
ClearPlatformioCoreDirMutationVariables
524+
>
525+
) {
526+
return Apollo.useMutation<
527+
ClearPlatformioCoreDirMutation,
528+
ClearPlatformioCoreDirMutationVariables
529+
>(ClearPlatformioCoreDirDocument, baseOptions);
530+
}
531+
532+
export type ClearPlatformioCoreDirMutationHookResult = ReturnType<
533+
typeof useClearPlatformioCoreDirMutation
534+
>;
535+
export type ClearPlatformioCoreDirMutationResult = Apollo.MutationResult<ClearPlatformioCoreDirMutation>;
536+
export type ClearPlatformioCoreDirMutationOptions = Apollo.BaseMutationOptions<
537+
ClearPlatformioCoreDirMutation,
538+
ClearPlatformioCoreDirMutationVariables
539+
>;
472540
export const TargetDeviceOptionsDocument = gql`
473541
query targetDeviceOptions($target: DeviceTarget!) {
474542
targetDeviceOptions(target: $target) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mutation clearPlatformioCoreDir {
2+
clearPlatformioCoreDir {
3+
success
4+
message
5+
}
6+
}

‎src/ui/views/SettingsView/index.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@ const SettingsView: FunctionComponent = () => {
4141
<ul>
4242
<li>Display configurator version</li>
4343
<li>Language selector</li>
44-
<li>Git exec location</li>
45-
<li>Python location</li>
46-
<li>Platformio location</li>
4744
</ul>
4845
</CardContent>
4946
</Card>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React, { FunctionComponent } from 'react';
2+
import { Button, makeStyles, Typography } from '@material-ui/core';
3+
import { useClearPlatformioCoreDirMutation } from '../../../../gql/generated/types';
4+
import Loader from '../../../../components/Loader';
5+
import ShowAlerts from '../../../../components/ShowAlerts';
6+
7+
const useStyles = makeStyles((theme) => ({
8+
actions: {
9+
marginBottom: theme.spacing(2),
10+
},
11+
}));
12+
13+
const ClearPlatformioDependencies: FunctionComponent = () => {
14+
const styles = useStyles();
15+
const [
16+
clearPlatformioCoreDirMutation,
17+
{ loading, data, error },
18+
] = useClearPlatformioCoreDirMutation();
19+
const onClearPlatformioDependencies = () => {
20+
clearPlatformioCoreDirMutation().catch((err) => {
21+
console.error('clearPlatformioCoreDirMutation err: ', err);
22+
});
23+
};
24+
return (
25+
<div>
26+
<Typography variant="h6">Corrupted platformio dependencies</Typography>
27+
<p>
28+
If you close the Configurator while platformio installs the required
29+
dependencies their state might get corrupted. You can manually clear all
30+
dependencies and start the build process again.
31+
</p>
32+
<div className={styles.actions}>
33+
<Button variant="contained" onClick={onClearPlatformioDependencies}>
34+
Clear platformio dependencies
35+
</Button>
36+
</div>
37+
<Loader loading={loading} />
38+
<ShowAlerts severity="error" messages={error} />
39+
{data?.clearPlatformioCoreDir?.success === true && (
40+
<ShowAlerts
41+
severity="success"
42+
messages="Corrupted platformio dependencies were deleted. Try building again."
43+
/>
44+
)}
45+
{data?.clearPlatformioCoreDir?.success === false && (
46+
<ShowAlerts
47+
severity="error"
48+
messages={data?.clearPlatformioCoreDir?.message}
49+
/>
50+
)}
51+
</div>
52+
);
53+
};
54+
export default ClearPlatformioDependencies;

0 commit comments

Comments
 (0)
Please sign in to comment.