auto switch repo based on current language

pull/5237/head
drafish 2 months ago committed by yann300
parent e3c722ba48
commit 5aab313abd
  1. 30
      apps/learneth/src/App.tsx
  2. 2
      apps/learneth/src/components/LoadingScreen/index.tsx
  3. 19
      apps/learneth/src/components/RepoImporter/index.tsx
  4. 15
      apps/learneth/src/pages/Home/index.tsx
  5. 9
      apps/learneth/src/pages/Logo/index.tsx
  6. 1
      apps/learneth/src/redux/models/remixide.ts
  7. 41
      apps/learneth/src/redux/models/workshop.ts
  8. 13
      apps/learneth/src/redux/store.ts

@ -1,11 +1,14 @@
import React from 'react'
import {createHashRouter, RouterProvider} from 'react-router-dom'
import {ToastContainer} from 'react-toastify'
import React, { useEffect } from 'react'
import { createHashRouter, RouterProvider } from 'react-router-dom'
import { ToastContainer } from 'react-toastify'
import LoadingScreen from './components/LoadingScreen'
import LogoPage from './pages/Logo'
import HomePage from './pages/Home'
import StepListPage from './pages/StepList'
import StepDetailPage from './pages/StepDetail'
import remixClient from './remix-client'
import { repoMap } from './redux/models/workshop'
import { useAppDispatch } from './redux/hooks'
import 'react-toastify/dist/ReactToastify.css'
import './App.css'
@ -29,6 +32,27 @@ export const router = createHashRouter([
])
function App(): JSX.Element {
const dispatch = useAppDispatch()
useEffect(() => {
dispatch({
type: 'remixide/connect',
callback: () => {
// @ts-ignore
remixClient.on('locale', 'localeChanged', (locale: any) => {
dispatch({
type: 'remixide/save',
payload: { localeCode: locale.code },
})
dispatch({
type: 'workshop/loadRepo',
payload: repoMap[locale.code] || repoMap.en,
})
})
}
})
}, [])
return (
<>
<RouterProvider router={router} />

@ -1,7 +1,7 @@
import React from 'react'
import BounceLoader from 'react-spinners/BounceLoader'
import './index.css'
import {useAppSelector} from '../../redux/hooks'
import { useAppSelector } from '../../redux/hooks'
const LoadingScreen: React.FC = () => {
const loading = useAppSelector((state) => state.loading.screen)

@ -1,13 +1,14 @@
import React, {useState, useEffect} from 'react'
import {Button, Dropdown, Form, Tooltip, OverlayTrigger} from 'react-bootstrap'
import {useAppDispatch} from '../../redux/hooks'
import React, { useState, useEffect } from 'react'
import { Button, Dropdown, Form, Tooltip, OverlayTrigger } from 'react-bootstrap'
import { useAppDispatch, useAppSelector } from '../../redux/hooks'
import './index.css'
function RepoImporter({list, selectedRepo}: any): JSX.Element {
function RepoImporter({ list, selectedRepo }: any): JSX.Element {
const [open, setOpen] = useState(false)
const [name, setName] = useState('')
const [branch, setBranch] = useState('')
const dispatch = useAppDispatch()
const localeCode = useAppSelector((state) => state.remixide.localeCode)
useEffect(() => {
setName(selectedRepo.name)
@ -19,18 +20,18 @@ function RepoImporter({list, selectedRepo}: any): JSX.Element {
}
const selectRepo = (repo: {name: string; branch: string}) => {
dispatch({type: 'workshop/loadRepo', payload: repo});
dispatch({ type: 'workshop/loadRepo', payload: repo });
(window as any)._paq.push(['trackEvent', 'learneth', 'select_repo', `${name}/${branch}`])
}
const importRepo = (event: {preventDefault: () => void}) => {
event.preventDefault()
dispatch({type: 'workshop/loadRepo', payload: {name, branch}});
dispatch({ type: 'workshop/loadRepo', payload: { name, branch } });
(window as any)._paq.push(['trackEvent', 'learneth', 'import_repo', `${name}/${branch}`])
}
const resetAll = () => {
dispatch({type: 'workshop/resetAll'})
dispatch({ type: 'workshop/resetAll', payload: { code: localeCode } })
setName('')
setBranch('')
}
@ -45,7 +46,7 @@ function RepoImporter({list, selectedRepo}: any): JSX.Element {
</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">
<i className={`arrow-icon pt-1 fas fa-xs ${open ? 'fa-chevron-down' : 'fa-chevron-right'}`}></i>
</div>
@ -71,7 +72,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>

@ -1,9 +1,9 @@
import React, {useEffect} from 'react'
import {Link} from 'react-router-dom'
import React from 'react'
import { Link } from 'react-router-dom'
import Markdown from 'react-markdown'
import rehypeRaw from 'rehype-raw'
import remarkGfm from 'remark-gfm'
import {useAppDispatch, useAppSelector} from '../../redux/hooks'
import { useAppSelector } from '../../redux/hooks'
import RepoImporter from '../../components/RepoImporter'
import './index.css'
@ -15,8 +15,7 @@ function HomePage(): JSX.Element {
setOpenKeys(isOpen(key) ? openKeys.filter((item) => item !== key) : [...openKeys, key])
}
const dispatch = useAppDispatch()
const {list, detail, selectedId} = useAppSelector((state) => state.workshop)
const { list, detail, selectedId } = useAppSelector((state) => state.workshop)
const selectedRepo = detail[selectedId]
@ -26,12 +25,6 @@ function HomePage(): JSX.Element {
3: 'Advanced',
}
useEffect(() => {
dispatch({
type: 'workshop/init',
})
}, [])
return (
<div className="App">
<RepoImporter list={list} selectedRepo={selectedRepo || {}} />

@ -1,13 +1,6 @@
import React, {useEffect} from 'react'
import {useAppDispatch} from '../../redux/hooks'
import React from 'react'
const LogoPage: React.FC = () => {
const dispatch = useAppDispatch()
useEffect(() => {
dispatch({type: 'remixide/connect'})
}, [])
return (
<div>
<div>

@ -15,6 +15,7 @@ const Model: ModelType = {
success: false,
errorLoadingFile: false,
// theme: '',
localeCode: 'en'
},
reducers: {
save(state, { payload }) {

@ -3,12 +3,22 @@ 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'
export const repoMap = {
en: {
name: 'ethereum/remix-workshops',
branch: 'master',
},
zh: {
name: 'ethereum/remix-workshops',
branch: 'cn',
},
}
const Model: ModelType = {
namespace: 'workshop',
state: {
@ -22,26 +32,9 @@ const Model: ModelType = {
},
},
effects: {
*init(_, { put }) {
const cache = null // don't use cache because remote might change
if (cache) {
const workshopState = JSON.parse(cache)
yield put({
type: 'workshop/save',
payload: workshopState,
})
} else {
yield put({
type: 'workshop/loadRepo',
payload: {
name: 'ethereum/remix-workshops',
branch: 'master',
},
})
}
},
*loadRepo({ payload }, { put, select }) {
yield router.navigate('/home')
toast.info(`loading ${payload.name}/${payload.branch}`)
yield put({
@ -118,7 +111,6 @@ const Model: ModelType = {
type: 'workshop/save',
payload: workshopState,
})
localStorage.setItem('workshop.state', JSON.stringify(workshopState))
toast.dismiss()
yield put({
@ -141,7 +133,7 @@ const Model: ModelType = {
}
(<any>window)._paq.push(['trackEvent', 'learneth', 'load_repo', payload.name])
},
*resetAll(_, { put }) {
*resetAll({ payload }, { put }) {
yield put({
type: 'workshop/save',
payload: {
@ -151,10 +143,9 @@ const Model: ModelType = {
},
})
localStorage.removeItem('workshop.state')
yield put({
type: 'workshop/init',
type: 'workshop/loadRepo',
payload: repoMap[payload.code]
});
(<any>window)._paq.push(['trackEvent', 'learneth', 'reset_all'])
},

@ -46,19 +46,20 @@ 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) {
yield takeEvery(`${model.namespace}/${key}`, function* ({ callback, ...action }: {type: string; payload: any; callback?: any}) {
yield put({
type: 'loading/save',
payload: {
[`${model.namespace}/${key}`]: true,
},
})
yield effect(action, {
const result = yield effect(action, {
call,
put,
delay,
select,
})
callback && callback(result)
yield put({
type: 'loading/save',
payload: {
@ -82,7 +83,13 @@ const configureAppStore = (initialState = {}) => {
const store = configureStore({
reducer: rootReducer,
middleware: (gDM) => gDM().concat([...middleware]),
middleware: (gDM) =>
gDM({
serializableCheck: {
// Ignore these field paths in all actions
ignoredActionPaths: ['callback'],
},
}).concat([...middleware]),
preloadedState: initialState,
devTools: process.env.NODE_ENV !== 'production',
})

Loading…
Cancel
Save