Skip to content

Commit 6cf948a

Browse files
committed
ui: file share support
1 parent c809fd8 commit 6cf948a

File tree

8 files changed

+48
-26
lines changed

8 files changed

+48
-26
lines changed

web/src/App.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React from 'react';
22
import { Provider } from 'react-redux';
33
import {Fabric} from 'office-ui-fabric-react/lib/Fabric';
44
import { ConnectedRouter } from 'connected-react-router';
5-
import {BrowserRouter as Router, Switch, Route} from "react-router-dom";
5+
import {Switch, Route} from "react-router-dom";
66

77
import { configureStore } from './store';
88
import { history } from './store/configure';
@@ -18,14 +18,12 @@ function App() {
1818
<Provider store={store}>
1919
<ConnectedRouter history={history}>
2020
<Fabric className="App">
21-
<Router>
22-
<Switch>
23-
<Route
24-
path="/(snippet)?/:snippetID?"
25-
component={Playground}
26-
/>
27-
</Switch>
28-
</Router>
21+
<Switch>
22+
<Route
23+
path="/(snippet)?/:snippetID?"
24+
component={Playground}
25+
/>
26+
</Switch>
2927
</Fabric>
3028
</ConnectedRouter>
3129
</Provider>

web/src/Header.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
formatFileDispatcher,
99
runFileDispatcher,
1010
saveFileDispatcher,
11-
dispatchToggleTheme
11+
dispatchToggleTheme, shareSnippetDispatcher
1212
} from './store';
1313

1414
@Connect(s => ({darkMode: s.settings.darkMode, loading: s.status?.loading}))
@@ -62,7 +62,9 @@ export class Header extends React.Component<any> {
6262
text: 'Share',
6363
iconProps: {iconName: 'Share'},
6464
disabled: this.props.loading,
65-
onClick: () => alert('Work in progress 🐨')
65+
onClick: () => {
66+
this.props.dispatch(shareSnippetDispatcher);
67+
}
6668
},
6769
{
6870
key: 'download',

web/src/Playground.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import { connect } from 'react-redux';
99

1010
const Playground = connect()(function (props) {
1111
const {snippetID} = useParams();
12-
if (snippetID) {
13-
props.dispatch(newSnippetLoadDispatcher(snippetID));
14-
}
12+
props.dispatch(newSnippetLoadDispatcher(snippetID));
13+
1514
return <div className="playground">
1615
<Header />
1716
<CodeEditor />

web/src/editor/CodeEditor.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ import { DEFAULT_EDITOR_OPTIONS, LANGUAGE_GOLANG } from './props';
88

99
interface CodeEditorState {
1010
code?: string
11+
loading?:boolean
1112
}
1213

13-
@Connect(s => ({code: s.editor.code, darkMode: s.settings.darkMode}))
14+
@Connect(s => ({code: s.editor.code, darkMode: s.settings.darkMode, loading: s.status?.loading}))
1415
export default class CodeEditor extends React.Component<any, CodeEditorState> {
1516
editorDidMount(editor: editor.IStandaloneCodeEditor, monaco: any) {
1617
editor.focus();

web/src/services/api.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ const apiAddress = process.env['REACT_APP_LANG_SERVER'] ?? window.location.origi
66

77
let axiosClient = axios.default.create({baseURL: `${apiAddress}/api`});
88

9+
export interface ShareResponse {
10+
snippetID: string
11+
}
12+
913
export interface Snippet {
1014
fileName: string
1115
code: string
@@ -28,6 +32,7 @@ export interface IAPIClient {
2832
evaluateCode(code: string): Promise<CompilerResponse>
2933
formatCode(code: string): Promise<CompilerResponse>
3034
getSnippet(id: string): Promise<Snippet>
35+
shareSnippet(code: string): Promise<ShareResponse>
3136
}
3237

3338
class Client implements IAPIClient {
@@ -54,6 +59,10 @@ class Client implements IAPIClient {
5459
return this.get<Snippet>(`/snippet/${id}`);
5560
}
5661

62+
async shareSnippet(code: string): Promise<ShareResponse> {
63+
return this.post<ShareResponse>('/share', code);
64+
}
65+
5766
private async get<T>(uri: string): Promise<T> {
5867
try {
5968
const resp = await this.client.get<T>(uri);

web/src/store/actions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ export enum ActionType {
44
IMPORT_FILE = 'IMPORT_FILE',
55
FILE_CHANGE = 'FILE_CHANGE',
66
LOADING = 'LOADING',
7+
ERROR = 'ERROR',
78
COMPILE_RESULT = 'COMPILE_RESULT',
8-
COMPILE_FAIL = 'COMPILE_FAIL',
99
TOGGLE_THEME = 'TOGGLE_THEME'
1010
}
1111

@@ -37,9 +37,9 @@ export const newBuildResultAction = (resp: CompilerResponse) =>
3737
payload: resp,
3838
});
3939

40-
export const newBuildErrorAction = (err: string) =>
40+
export const newErrorAction = (err: string) =>
4141
({
42-
type: ActionType.COMPILE_FAIL,
42+
type: ActionType.ERROR,
4343
payload: err,
4444
});
4545

web/src/store/dispatch.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { saveAs } from 'file-saver';
2+
import { push } from 'connected-react-router';
23
import {
3-
newBuildErrorAction,
4+
newErrorAction,
45
newBuildResultAction,
56
newImportFileAction,
67
newLoadingAction,
@@ -37,23 +38,35 @@ export function newImportFileDispatcher(f: File): Dispatcher {
3738
}
3839

3940
export function newSnippetLoadDispatcher(snippetID: string): Dispatcher {
40-
return async(dispatch: DispatchFn, getState: StateProvider) => {
41-
console.log('load snippet %s', snippetID);
41+
return async(dispatch: DispatchFn, _: StateProvider) => {
4242
if (!snippetID) {
4343
dispatch(newImportFileAction('prog.go', DEMO_CODE));
4444
return;
4545
}
4646

4747
try {
48+
console.log('loading snippet %s', snippetID);
4849
const resp = await client.getSnippet(snippetID);
4950
const { fileName, code } = resp;
5051
dispatch(newImportFileAction(fileName, code));
5152
} catch(err) {
52-
dispatch(newBuildErrorAction(err.message));
53+
dispatch(newErrorAction(err.message));
5354
}
5455
}
5556
}
5657

58+
export const shareSnippetDispatcher: Dispatcher =
59+
async (dispatch: DispatchFn, getState: StateProvider) => {
60+
dispatch(newLoadingAction());
61+
try {
62+
const {code} = getState().editor;
63+
const res = await client.shareSnippet(code);
64+
dispatch(push(`/snippet/${res.snippetID}`));
65+
} catch (err) {
66+
dispatch(newErrorAction(err.message));
67+
}
68+
};
69+
5770
export const saveFileDispatcher: Dispatcher =
5871
(_: DispatchFn, getState: StateProvider) => {
5972
try {
@@ -74,7 +87,7 @@ export const runFileDispatcher: Dispatcher =
7487
const res = await client.evaluateCode(code);
7588
dispatch(newBuildResultAction(res));
7689
} catch (err) {
77-
dispatch(newBuildErrorAction(err.message));
90+
dispatch(newErrorAction(err.message));
7891
}
7992
};
8093

@@ -89,7 +102,7 @@ export const formatFileDispatcher: Dispatcher =
89102
dispatch(newBuildResultAction(res));
90103
}
91104
} catch (err) {
92-
dispatch(newBuildErrorAction(err.message));
105+
dispatch(newErrorAction(err.message));
93106
}
94107
};
95108

web/src/store/reducers.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ const reducers = {
3838
}
3939
},
4040
[ActionType.IMPORT_FILE]: (s: StatusState, a: Action<string>) => {
41-
return {...s, loading: false}
41+
return {...s, loading: false, lastError: null}
4242
},
43-
[ActionType.COMPILE_FAIL]: (s: StatusState, a: Action<string>) => {
43+
[ActionType.ERROR]: (s: StatusState, a: Action<string>) => {
4444
return {...s, loading: false, lastError: a.payload}
4545
},
4646
[ActionType.LOADING]: (s: StatusState, a: Action<string>) => {

0 commit comments

Comments
 (0)