formate all files in learneth

pull/4466/head
drafish 10 months ago committed by yann300
parent 3586b42e20
commit 77a01a2ff9
  1. 4
      apps/learneth/src/components/BackButton/index.scss
  2. 16
      apps/learneth/src/components/LoadingScreen/index.tsx
  3. 123
      apps/learneth/src/components/RepoImporter/index.tsx
  4. 20
      apps/learneth/src/components/SlideIn/index.tsx
  5. 20
      apps/learneth/src/main.tsx
  6. 102
      apps/learneth/src/pages/Home/index.tsx
  7. 5
      apps/learneth/src/pages/StepDetail/index.scss
  8. 8
      apps/learneth/src/pages/StepList/index.scss
  9. 8
      apps/learneth/src/redux/hooks.ts
  10. 12
      apps/learneth/src/redux/models/loading.ts
  11. 123
      apps/learneth/src/redux/models/workshop.ts
  12. 100
      apps/learneth/src/redux/store.ts
  13. 26
      apps/learneth/src/remix-client.ts
  14. 54
      apps/learneth/webpack.config.js

@ -1,5 +1,4 @@
a {
.arrow {
display: inline-block;
opacity: 0;
@ -12,9 +11,6 @@ a {
transform: translateX(-0.875em); // size of icon
transition: transform 0.3s;
}
}
.workshoptitle{

@ -1,16 +1,16 @@
import React from 'react';
import BounceLoader from 'react-spinners/BounceLoader';
import './index.css';
import { useAppSelector } from '../../redux/hooks';
import React from 'react'
import BounceLoader from 'react-spinners/BounceLoader'
import './index.css'
import {useAppSelector} from '../../redux/hooks'
const LoadingScreen: React.FC = () => {
const loading = useAppSelector((state) => state.loading.screen);
const loading = useAppSelector((state) => state.loading.screen)
return loading ? (
<div className="spinnersOverlay">
<BounceLoader color="#a7b0ae" size={100} className="spinnersLoading" />
</div>
) : null;
};
) : null
}
export default LoadingScreen;
export default LoadingScreen

@ -1,50 +1,39 @@
import React, { useState, useEffect } from 'react';
import {
Button,
Dropdown,
Form,
Tooltip,
OverlayTrigger,
} from 'react-bootstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faQuestionCircle,
faInfoCircle,
faChevronRight,
faChevronDown,
} from '@fortawesome/free-solid-svg-icons';
import { useAppDispatch } from '../../redux/hooks';
import './index.css';
import React, {useState, useEffect} from 'react'
import {Button, Dropdown, Form, Tooltip, OverlayTrigger} from 'react-bootstrap'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {faQuestionCircle, faInfoCircle, faChevronRight, faChevronDown} from '@fortawesome/free-solid-svg-icons'
import {useAppDispatch} from '../../redux/hooks'
import './index.css'
function RepoImporter({ list, selectedRepo }: any): JSX.Element {
const [open, setOpen] = useState(false);
const [name, setName] = useState('');
const [branch, setBranch] = useState('');
const dispatch = useAppDispatch();
function RepoImporter({list, selectedRepo}: any): JSX.Element {
const [open, setOpen] = useState(false)
const [name, setName] = useState('')
const [branch, setBranch] = useState('')
const dispatch = useAppDispatch()
useEffect(() => {
setName(selectedRepo.name);
setBranch(selectedRepo.branch);
}, [selectedRepo]);
setName(selectedRepo.name)
setBranch(selectedRepo.branch)
}, [selectedRepo])
const panelChange = () => {
setOpen(!open);
};
setOpen(!open)
}
const selectRepo = (repo: { name: string; branch: string }) => {
dispatch({ type: 'workshop/loadRepo', payload: repo });
};
const selectRepo = (repo: {name: string; branch: string}) => {
dispatch({type: 'workshop/loadRepo', payload: repo})
}
const importRepo = (event: { preventDefault: () => void }) => {
event.preventDefault();
dispatch({ type: 'workshop/loadRepo', payload: { name, branch } });
};
const importRepo = (event: {preventDefault: () => void}) => {
event.preventDefault()
dispatch({type: 'workshop/loadRepo', payload: {name, branch}})
}
const resetAll = () => {
dispatch({ type: 'workshop/resetAll' });
setName('');
setBranch('');
};
dispatch({type: 'workshop/resetAll'})
setName('')
setBranch('')
}
return (
<>
@ -52,24 +41,13 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
<div className="container-fluid mb-3 small mt-3">
Tutorials from:
<h4 className="mb-1">{selectedRepo.name}</h4>
<span className="">
Date modified:{' '}
{new Date(selectedRepo.datemodified).toLocaleString()}
</span>
<span className="">Date modified: {new Date(selectedRepo.datemodified).toLocaleString()}</span>
</div>
)}
<div
onClick={panelChange}
style={{ cursor: 'pointer' }}
className="container-fluid d-flex mb-3 small"
>
<div onClick={panelChange} style={{cursor: 'pointer'}} className="container-fluid d-flex mb-3 small">
<div className="d-flex pr-2 pl-2">
<FontAwesomeIcon
className="arrow-icon pt-1"
size="xs"
icon={open ? faChevronDown : faChevronRight}
/>
<FontAwesomeIcon className="arrow-icon pt-1" size="xs" icon={open ? faChevronDown : faChevronRight} />
</div>
<div className="d-flex">Import another tutorial repo</div>
</div>
@ -77,10 +55,7 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
{open && (
<div className="container-fluid">
<Dropdown className="w-100">
<Dropdown.Toggle
className="btn btn-secondary w-100"
id="dropdownBasic1"
>
<Dropdown.Toggle className="btn btn-secondary w-100" id="dropdownBasic1">
Select a repo
</Dropdown.Toggle>
<Dropdown.Menu className="w-100">
@ -88,7 +63,7 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
<Dropdown.Item
key={`${item.name}/${item.branch}`}
onClick={() => {
selectRepo(item);
selectRepo(item)
}}
>
{item.name}-{item.branch}
@ -96,11 +71,7 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
))}
</Dropdown.Menu>
</Dropdown>
<div
onClick={resetAll}
className="small mb-3"
style={{ cursor: 'pointer' }}
>
<div onClick={resetAll} className="small mb-3" style={{cursor: 'pointer'}}>
reset list
</div>
</div>
@ -113,19 +84,14 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
<Form.Label className="mr-2" htmlFor="name">
REPO
</Form.Label>
<OverlayTrigger
placement="right"
overlay={
<Tooltip id="tooltip-right">ie username/repository</Tooltip>
}
>
<OverlayTrigger placement="right" overlay={<Tooltip id="tooltip-right">ie username/repository</Tooltip>}>
<FontAwesomeIcon icon={faQuestionCircle} />
</OverlayTrigger>
<Form.Control
id="name"
required
onChange={(e) => {
setName(e.target.value);
setName(e.target.value)
}}
value={name}
/>
@ -134,24 +100,15 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
id="branch"
required
onChange={(e) => {
setBranch(e.target.value);
setBranch(e.target.value)
}}
value={branch}
/>
</Form.Group>
<Button
className="btn btn-success start w-100"
type="submit"
disabled={!name || !branch}
>
<Button className="btn btn-success start w-100" type="submit" disabled={!name || !branch}>
Import {name}
</Button>
<a
href="https://github.com/bunsenstraat/remix-learneth-plugin/blob/master/README.md"
className="d-none"
target="_blank"
rel="noreferrer"
>
<a href="https://github.com/bunsenstraat/remix-learneth-plugin/blob/master/README.md" className="d-none" target="_blank" rel="noreferrer">
<FontAwesomeIcon icon={faInfoCircle} /> how to setup your repo
</a>
</Form>
@ -159,7 +116,7 @@ function RepoImporter({ list, selectedRepo }: any): JSX.Element {
<hr />
</div>
</>
);
)
}
export default RepoImporter;
export default RepoImporter

@ -1,18 +1,18 @@
import React, { type ReactNode, useEffect, useState } from 'react';
import { CSSTransition } from 'react-transition-group';
import './index.css';
import React, {type ReactNode, useEffect, useState} from 'react'
import {CSSTransition} from 'react-transition-group'
import './index.css'
const SlideIn: React.FC<{ children: ReactNode }> = ({ children }) => {
const [show, setShow] = useState(false);
const SlideIn: React.FC<{children: ReactNode}> = ({children}) => {
const [show, setShow] = useState(false)
useEffect(() => {
setShow(true);
}, []);
setShow(true)
}, [])
return (
<CSSTransition in={show} timeout={400} classNames="slide" unmountOnExit>
{children}
</CSSTransition>
);
};
)
}
export default SlideIn;
export default SlideIn

@ -1,15 +1,13 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import './index.css';
import App from './App';
import { store } from './redux/store';
import React from 'react'
import ReactDOM from 'react-dom/client'
import {Provider} from 'react-redux'
import './index.css'
import App from './App'
import {store} from './redux/store'
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(
<Provider store={store}>
<App />
</Provider>,
);
</Provider>
)

@ -1,48 +1,38 @@
import React, { useEffect } from 'react';
import { Link } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faChevronRight,
faChevronDown,
faPlayCircle,
} from '@fortawesome/free-solid-svg-icons';
import Markdown from 'react-markdown';
import rehypeRaw from 'rehype-raw';
import remarkGfm from 'remark-gfm';
import { useAppDispatch, useAppSelector } from '../../redux/hooks';
import RepoImporter from '../../components/RepoImporter';
import './index.css';
import React, {useEffect} from 'react'
import {Link} from 'react-router-dom'
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
import {faChevronRight, faChevronDown, faPlayCircle} from '@fortawesome/free-solid-svg-icons'
import Markdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import remarkGfm from 'remark-gfm'
import {useAppDispatch, useAppSelector} from '../../redux/hooks'
import RepoImporter from '../../components/RepoImporter'
import './index.css'
function HomePage(): JSX.Element {
const [openKeys, setOpenKeys] = React.useState<string[]>([]);
const [openKeys, setOpenKeys] = React.useState<string[]>([])
const isOpen = (key: string) => openKeys.includes(key);
const isOpen = (key: string) => openKeys.includes(key)
const handleClick = (key: string) => {
setOpenKeys(
isOpen(key)
? openKeys.filter((item) => item !== key)
: [...openKeys, key],
);
};
setOpenKeys(isOpen(key) ? openKeys.filter((item) => item !== key) : [...openKeys, key])
}
const dispatch = useAppDispatch();
const { list, detail, selectedId } = useAppSelector(
(state) => state.workshop,
);
const dispatch = useAppDispatch()
const {list, detail, selectedId} = useAppSelector((state) => state.workshop)
const selectedRepo = detail[selectedId];
const selectedRepo = detail[selectedId]
const levelMap: any = {
1: 'Beginner',
2: 'Intermediate',
3: 'Advanced',
};
}
useEffect(() => {
dispatch({
type: 'workshop/init',
});
}, []);
})
}, [])
return (
<div className="App">
@ -59,63 +49,37 @@ function HomePage(): JSX.Element {
href="#"
className="arrow-icon"
onClick={() => {
handleClick(item.id);
handleClick(item.id)
}}
>
<FontAwesomeIcon
size="xs"
icon={isOpen(item.id) ? faChevronDown : faChevronRight}
/>
<FontAwesomeIcon size="xs" icon={isOpen(item.id) ? faChevronDown : faChevronRight} />
</a>
<a
href="#"
className="workshop-link"
onClick={() => {
handleClick(item.id);
handleClick(item.id)
}}
>
{selectedRepo.entities[item.id].name}
</a>
<Link
to={`/list?id=${item.id}`}
className="text-decoration-none float-right"
>
<Link to={`/list?id=${item.id}`} className="text-decoration-none float-right">
<FontAwesomeIcon icon={faPlayCircle} size="lg" />
</Link>
</div>
<div
className={`container-fluid bg-light pt-3 mt-2 ${
isOpen(item.id) ? '' : 'description-collapsed'
}`}
>
{levelMap[level] && (
<p className="tag pt-2 pr-1 font-weight-bold small text-uppercase">
{levelMap[level]}
</p>
)}
<div className={`container-fluid bg-light pt-3 mt-2 ${isOpen(item.id) ? '' : 'description-collapsed'}`}>
{levelMap[level] && <p className="tag pt-2 pr-1 font-weight-bold small text-uppercase">{levelMap[level]}</p>}
{selectedRepo.entities[item.id].metadata.data.tags?.map(
(tag: string) => (
<p
key={tag}
className="tag pr-1 font-weight-bold small text-uppercase"
>
{selectedRepo.entities[item.id].metadata.data.tags?.map((tag: string) => (
<p key={tag} className="tag pr-1 font-weight-bold small text-uppercase">
{tag}
</p>
),
)}
))}
{selectedRepo.entities[item.id].steps && (
<div className="d-none">
{selectedRepo.entities[item.id].steps.length} step(s)
</div>
)}
{selectedRepo.entities[item.id].steps && <div className="d-none">{selectedRepo.entities[item.id].steps.length} step(s)</div>}
<div className="workshop-list_description pb-3 pt-3">
<Markdown
rehypePlugins={[rehypeRaw]}
remarkPlugins={[remarkGfm]}
>
<Markdown rehypePlugins={[rehypeRaw]} remarkPlugins={[remarkGfm]}>
{selectedRepo.entities[item.id].description?.content}
</Markdown>
</div>
@ -130,7 +94,7 @@ function HomePage(): JSX.Element {
</div>
)}
</div>
);
)
}
export default HomePage;
export default HomePage

@ -13,11 +13,6 @@ header, footer {
align-items: center;
}
.menuspacer{
// padding-top: 48px;
}
.errorloadingspacer{
padding-top: 44px;

@ -11,7 +11,6 @@ header {
.menuspacer{
margin-top: 52px;
}
.steplink {
@ -32,13 +31,6 @@ section {
display: flex;
flex-direction: column;
align-items: center;
.start {
padding: 5px 25px;
animation: jittery 2s 0.5s infinite;

@ -1,5 +1,5 @@
import { useDispatch, type TypedUseSelectorHook, useSelector } from 'react-redux';
import { type AppDispatch, type RootState } from './store';
import {useDispatch, type TypedUseSelectorHook, useSelector} from 'react-redux'
import {type AppDispatch, type RootState} from './store'
export const useAppDispatch: () => AppDispatch = useDispatch;
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
export const useAppDispatch: () => AppDispatch = useDispatch
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

@ -1,14 +1,14 @@
import { type ModelType } from '../store';
import {type ModelType} from '../store'
const Model: ModelType = {
namespace: 'loading',
state: { screen: true },
state: {screen: true},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
save(state, {payload}) {
return {...state, ...payload}
},
},
effects: {},
};
}
export default Model;
export default Model

@ -1,13 +1,13 @@
import axios from 'axios';
import { toast } from 'react-toastify';
import groupBy from 'lodash/groupBy';
import pick from 'lodash/pick';
import { type ModelType } from '../store';
import remixClient from '../../remix-client';
import { router } from '../../App';
import axios from 'axios'
import {toast} from 'react-toastify'
import groupBy from 'lodash/groupBy'
import pick from 'lodash/pick'
import {type ModelType} from '../store'
import remixClient from '../../remix-client'
import {router} from '../../App'
// const apiUrl = 'http://localhost:3001';
const apiUrl = 'https://static.220.14.12.49.clients.your-server.de:3000';
const apiUrl = 'https://static.220.14.12.49.clients.your-server.de:3000'
const Model: ModelType = {
namespace: 'workshop',
@ -17,20 +17,20 @@ const Model: ModelType = {
selectedId: '',
},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
save(state, {payload}) {
return {...state, ...payload}
},
},
effects: {
*init(_, { put }) {
const cache = localStorage.getItem('workshop.state');
*init(_, {put}) {
const cache = localStorage.getItem('workshop.state')
if (cache) {
const workshopState = JSON.parse(cache);
const workshopState = JSON.parse(cache)
yield put({
type: 'workshop/save',
payload: workshopState,
});
})
} else {
yield put({
type: 'workshop/loadRepo',
@ -38,80 +38,67 @@ const Model: ModelType = {
name: 'ethereum/remix-workshops',
branch: 'master',
},
});
})
}
},
*loadRepo({ payload }, { put, select }) {
toast.info(`loading ${payload.name}/${payload.branch}`);
*loadRepo({payload}, {put, select}) {
toast.info(`loading ${payload.name}/${payload.branch}`)
yield put({
type: 'loading/save',
payload: {
screen: true,
},
});
})
const { list, detail } = yield select((state) => state.workshop);
const {list, detail} = yield select((state) => state.workshop)
const url = `${apiUrl}/clone/${encodeURIComponent(payload.name)}/${
payload.branch
}?${Math.random()}`;
console.log('loading ', url);
const { data } = yield axios.get(url);
console.log(data);
const repoId = `${payload.name}-${payload.branch}`;
const url = `${apiUrl}/clone/${encodeURIComponent(payload.name)}/${payload.branch}?${Math.random()}`
console.log('loading ', url)
const {data} = yield axios.get(url)
console.log(data)
const repoId = `${payload.name}-${payload.branch}`
for (let i = 0; i < data.ids.length; i++) {
const {
steps,
metadata: {
data: { steps: metadataSteps },
data: {steps: metadataSteps},
},
} = data.entities[data.ids[i]];
} = data.entities[data.ids[i]]
let newSteps = [];
let newSteps = []
if (metadataSteps) {
newSteps = metadataSteps.map((step: any) => {
return {
...steps.find((item: any) => item.name === step.path),
name: step.name,
};
});
}
})
} else {
newSteps = steps.map((step: any) => ({
...step,
name: step.name.replace('_', ' '),
}));
}))
}
const stepKeysWithFile = [
'markdown',
'solidity',
'test',
'answer',
'js',
'vy',
];
const stepKeysWithFile = ['markdown', 'solidity', 'test', 'answer', 'js', 'vy']
for (let j = 0; j < newSteps.length; j++) {
const step = newSteps[j];
const step = newSteps[j]
for (let k = 0; k < stepKeysWithFile.length; k++) {
const key = stepKeysWithFile[k];
const key = stepKeysWithFile[k]
if (step[key]) {
try {
step[key].content = (yield remixClient.call(
'contentImport',
'resolve',
step[key].file,
)).content;
step[key].content = (yield remixClient.call('contentImport', 'resolve', step[key].file)).content
} catch (error) {
console.error(error);
console.error(error)
}
}
}
}
data.entities[data.ids[i]].steps = newSteps;
data.entities[data.ids[i]].steps = newSteps
}
const workshopState = {
@ -120,44 +107,42 @@ const Model: ModelType = {
[repoId]: {
...data,
group: groupBy(
data.ids.map((id: string) =>
pick(data.entities[id], ['level', 'id']),
),
(item: any) => item.level,
data.ids.map((id: string) => pick(data.entities[id], ['level', 'id'])),
(item: any) => item.level
),
...payload,
},
},
list: detail[repoId] ? list : [...list, payload],
selectedId: repoId,
};
}
yield put({
type: 'workshop/save',
payload: workshopState,
});
localStorage.setItem('workshop.state', JSON.stringify(workshopState));
})
localStorage.setItem('workshop.state', JSON.stringify(workshopState))
toast.dismiss();
toast.dismiss()
yield put({
type: 'loading/save',
payload: {
screen: false,
},
});
})
if (payload.id) {
const { detail, selectedId } = workshopState;
const { ids, entities } = detail[selectedId];
const {detail, selectedId} = workshopState
const {ids, entities} = detail[selectedId]
for (let i = 0; i < ids.length; i++) {
const entity = entities[ids[i]];
const entity = entities[ids[i]]
if (entity.metadata.data.id === payload.id || i + 1 === payload.id) {
yield router.navigate(`/list?id=${ids[i]}`);
break;
yield router.navigate(`/list?id=${ids[i]}`)
break
}
}
}
},
*resetAll(_, { put }) {
*resetAll(_, {put}) {
yield put({
type: 'workshop/save',
payload: {
@ -165,15 +150,15 @@ const Model: ModelType = {
detail: {},
selectedId: '',
},
});
})
localStorage.removeItem('workshop.state');
localStorage.removeItem('workshop.state')
yield put({
type: 'workshop/init',
});
})
},
},
};
}
export default Model;
export default Model

@ -1,117 +1,97 @@
import {
configureStore,
createSlice,
type PayloadAction,
type Reducer,
} from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import {
call,
put,
takeEvery,
delay,
select,
all,
fork,
type ForkEffect,
} from 'redux-saga/effects';
import {configureStore, createSlice, type PayloadAction, type Reducer} from '@reduxjs/toolkit'
import createSagaMiddleware from 'redux-saga'
import {call, put, takeEvery, delay, select, all, fork, type ForkEffect} from 'redux-saga/effects'
// @ts-expect-error
const context = require.context('./models', false, /\.ts$/);
const models = context.keys().map((key: any) => context(key).default);
const context = require.context('./models', false, /\.ts$/)
const models = context.keys().map((key: any) => context(key).default)
export type StateType = Record<string, any>;
export type StateType = Record<string, any>
export interface ModelType {
namespace: string;
state: StateType;
reducers: Record<
string,
(state: StateType, action: PayloadAction<any>) => StateType
>;
namespace: string
state: StateType
reducers: Record<string, (state: StateType, action: PayloadAction<any>) => StateType>
effects: Record<
string,
(
action: PayloadAction<any>,
effects: {
call: typeof call;
put: typeof put;
delay: typeof delay;
select: typeof select;
},
call: typeof call
put: typeof put
delay: typeof delay
select: typeof select
}
) => Generator<any, void, any>
>;
>
}
function createReducer(model: ModelType): Reducer {
const reducers = model.reducers;
const reducers = model.reducers
Object.keys(model.effects).forEach((key) => {
reducers[key] = (state: StateType, action: PayloadAction<any>) => state;
});
reducers[key] = (state: StateType, action: PayloadAction<any>) => state
})
const slice = createSlice({
name: model.namespace,
initialState: model.state,
reducers,
});
return slice.reducer;
})
return slice.reducer
}
const rootReducer = models.reduce((prev: any, model: ModelType) => {
return { ...prev, [model.namespace]: createReducer(model) };
}, {});
return {...prev, [model.namespace]: createReducer(model)}
}, {})
function watchEffects(model: ModelType): ForkEffect {
return fork(function* () {
for (const key in model.effects) {
const effect = model.effects[key];
yield takeEvery(
`${model.namespace}/${key}`,
function* (action: PayloadAction) {
const effect = model.effects[key]
yield takeEvery(`${model.namespace}/${key}`, function* (action: PayloadAction) {
yield put({
type: 'loading/save',
payload: {
[`${model.namespace}/${key}`]: true,
},
});
})
yield effect(action, {
call,
put,
delay,
select,
});
})
yield put({
type: 'loading/save',
payload: {
[`${model.namespace}/${key}`]: false,
},
});
},
);
})
})
}
});
})
}
function* rootSaga(): Generator {
yield all(models.map((model: ModelType) => watchEffects(model)));
yield all(models.map((model: ModelType) => watchEffects(model)))
}
const configureAppStore = (initialState = {}) => {
const reduxSagaMonitorOptions = {};
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions);
const reduxSagaMonitorOptions = {}
const sagaMiddleware = createSagaMiddleware(reduxSagaMonitorOptions)
const middleware = [sagaMiddleware];
const middleware = [sagaMiddleware]
const store = configureStore({
reducer: rootReducer,
middleware: (gDM) => gDM().concat([...middleware]),
preloadedState: initialState,
devTools: process.env.NODE_ENV !== 'production',
});
})
sagaMiddleware.run(rootSaga);
return store;
};
sagaMiddleware.run(rootSaga)
return store
}
export const store = configureAppStore();
export const store = configureAppStore()
export type AppDispatch = typeof store.dispatch;
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch
export type RootState = ReturnType<typeof store.getState>

@ -1,17 +1,17 @@
import { PluginClient } from '@remixproject/plugin';
import { createClient } from '@remixproject/plugin-webview';
import { store } from './redux/store';
import { router } from './App';
import {PluginClient} from '@remixproject/plugin'
import {createClient} from '@remixproject/plugin-webview'
import {store} from './redux/store'
import {router} from './App'
class RemixClient extends PluginClient {
constructor() {
super();
createClient(this);
super()
createClient(this)
}
startTutorial(name: any, branch: any, id: any): void {
console.log('start tutorial', name, branch, id);
void router.navigate('/home');
console.log('start tutorial', name, branch, id)
void router.navigate('/home')
store.dispatch({
type: 'workshop/loadRepo',
payload: {
@ -19,20 +19,20 @@ class RemixClient extends PluginClient {
branch,
id,
},
});
})
}
addRepository(name: any, branch: any) {
console.log('add repo', name, branch);
void router.navigate('/home');
console.log('add repo', name, branch)
void router.navigate('/home')
store.dispatch({
type: 'workshop/loadRepo',
payload: {
name,
branch,
},
});
})
}
}
export default new RemixClient();
export default new RemixClient()

@ -1,7 +1,7 @@
const { composePlugins, withNx } = require('@nrwl/webpack')
const {composePlugins, withNx} = require('@nrwl/webpack')
const webpack = require('webpack')
const TerserPlugin = require("terser-webpack-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const TerserPlugin = require('terser-webpack-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
// Nx plugins for webpack.
module.exports = composePlugins(withNx(), (config) => {
@ -10,26 +10,25 @@ module.exports = composePlugins(withNx(), (config) => {
// add fallback for node modules
config.resolve.fallback = {
...config.resolve.fallback,
"crypto": require.resolve("crypto-browserify"),
"stream": require.resolve("stream-browserify"),
"path": require.resolve("path-browserify"),
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"constants": require.resolve("constants-browserify"),
"os": false, //require.resolve("os-browserify/browser"),
"timers": false, // require.resolve("timers-browserify"),
"zlib": require.resolve("browserify-zlib"),
"fs": false,
"module": false,
"tls": false,
"net": false,
"readline": false,
"child_process": false,
"buffer": require.resolve("buffer/"),
"vm": require.resolve('vm-browserify'),
crypto: require.resolve('crypto-browserify'),
stream: require.resolve('stream-browserify'),
path: require.resolve('path-browserify'),
http: require.resolve('stream-http'),
https: require.resolve('https-browserify'),
constants: require.resolve('constants-browserify'),
os: false, //require.resolve("os-browserify/browser"),
timers: false, // require.resolve("timers-browserify"),
zlib: require.resolve('browserify-zlib'),
fs: false,
module: false,
tls: false,
net: false,
readline: false,
child_process: false,
buffer: require.resolve('buffer/'),
vm: require.resolve('vm-browserify'),
}
// add externals
config.externals = {
...config.externals,
@ -58,13 +57,12 @@ module.exports = composePlugins(withNx(), (config) => {
// souce-map loader
config.module.rules.push({
test: /\.js$/,
use: ["source-map-loader"],
enforce: "pre"
use: ['source-map-loader'],
enforce: 'pre',
})
config.ignoreWarnings = [/Failed to parse source map/] // ignore source-map-loader warnings
// set minimizer
config.optimization.minimizer = [
new TerserPlugin({
@ -80,13 +78,13 @@ module.exports = composePlugins(withNx(), (config) => {
extractComments: false,
}),
new CssMinimizerPlugin(),
];
]
config.watchOptions = {
ignored: /node_modules/
ignored: /node_modules/,
}
config.experiments.syncWebAssembly = true
return config;
});
return config
})

Loading…
Cancel
Save