mirror of
https://github.com/cloudreve/frontend.git
synced 2025-12-25 19:52:48 +00:00
Refact: 分离viewe update reducer; 添加typescript (#24)
* 分离vieweupdate reducer; 添加typescript * Fix: Dispatch navigator actions * fix: dispatch change sub title
This commit is contained in:
parent
0e8e26e4de
commit
20e3b499cf
|
|
@ -21,3 +21,5 @@
|
|||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
dist/
|
||||
|
|
@ -8,6 +8,8 @@
|
|||
"@material-ui/icons": "^4.5.1",
|
||||
"@material-ui/lab": "^4.0.0-alpha.42",
|
||||
"@svgr/webpack": "4.3.2",
|
||||
"@types/invariant": "^2.2.32",
|
||||
"@types/react-dom": "^16.9.7",
|
||||
"@typescript-eslint/eslint-plugin": "^2.2.0",
|
||||
"@typescript-eslint/parser": "^2.2.0",
|
||||
"axios": "^0.19.0",
|
||||
|
|
@ -37,6 +39,7 @@
|
|||
"http-proxy-middleware": "^0.20.0",
|
||||
"husky": "^4.2.5",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"invariant": "^2.2.4",
|
||||
"is-wsl": "^1.1.0",
|
||||
"jest": "24.9.0",
|
||||
"jest-environment-jsdom-fourteen": "0.1.0",
|
||||
|
|
@ -74,6 +77,7 @@
|
|||
"react-router-dom": "^5.1.2",
|
||||
"recharts": "^2.0.0-beta.1",
|
||||
"redux": "^4.0.4",
|
||||
"redux-mock-store": "^1.5.4",
|
||||
"redux-thunk": "^2.3.0",
|
||||
"resolve": "1.12.0",
|
||||
"resolve-url-loader": "3.1.0",
|
||||
|
|
@ -83,6 +87,7 @@
|
|||
"terser-webpack-plugin": "1.4.1",
|
||||
"timeago-react": "^3.0.0",
|
||||
"ts-pnp": "1.1.4",
|
||||
"typescript": "^3.8.3",
|
||||
"url-loader": "2.1.0",
|
||||
"webpack": "4.41.0",
|
||||
"webpack-dev-server": "3.2.1",
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ export default function App() {
|
|||
},
|
||||
content: {
|
||||
flexGrow: 1,
|
||||
padding: theme.spacing.unit * 0,
|
||||
padding: theme.spacing(0),
|
||||
minWidth: 0
|
||||
},
|
||||
toolbar: theme.mixins.toolbar
|
||||
|
|
|
|||
|
|
@ -1,16 +1,30 @@
|
|||
export * from './explorer'
|
||||
|
||||
export const navigateTo = path => {
|
||||
return {
|
||||
type: "NAVIGATOR_TO",
|
||||
path: path
|
||||
};
|
||||
return (dispatch, getState) => {
|
||||
const state = getState()
|
||||
const navigatorLoading = path !== state.navigator.path
|
||||
return dispatch({
|
||||
type: "NAVIGATOR_TO",
|
||||
path: path,
|
||||
navigatorLoading,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export const navigateUp = () => {
|
||||
return {
|
||||
type: "NAVIGATOR_UP"
|
||||
};
|
||||
return (dispatch, getState) => {
|
||||
const state = getState()
|
||||
const pathSplit = state.navigator.path.split("/");
|
||||
pathSplit.pop();
|
||||
const newPath = pathSplit.length===1? "/":pathSplit.join("/");
|
||||
const navigatorLoading = newPath !== state.navigator.path
|
||||
return dispatch({
|
||||
type: "NAVIGATOR_UP",
|
||||
path: newPath,
|
||||
navigatorLoading
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
export const drawerToggleAction = open => {
|
||||
|
|
@ -35,13 +49,6 @@ export const changeViewMethod = method => {
|
|||
};
|
||||
};
|
||||
|
||||
export const changeSubTitle = title =>{
|
||||
return {
|
||||
type: "CHANGE_SUB_TITLE",
|
||||
title: title
|
||||
};
|
||||
};
|
||||
|
||||
export const toggleDaylightMode = ()=>{
|
||||
return {
|
||||
type: "TOGGLE_DAYLIGHT_MODE",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import React, { useCallback, useEffect, useState } from "react";
|
|||
import { useDispatch } from "react-redux";
|
||||
import { useHistory, useLocation } from "react-router";
|
||||
import { useRouteMatch } from "react-router-dom";
|
||||
import { changeSubTitle } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page";
|
||||
import UserAvatar from "../Navbar/UserAvatar";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { DndProvider } from 'react-dnd'
|
|||
import HTML5Backend from 'react-dnd-html5-backend'
|
||||
import { connect } from "react-redux"
|
||||
import { withRouter } from "react-router-dom"
|
||||
import { changeSubTitle, closeAllModals, navigateTo, setSelectedTarget, toggleSnackbar } from "../../actions"
|
||||
import { closeAllModals, navigateTo, setSelectedTarget, toggleSnackbar } from "../../actions"
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page"
|
||||
import DragLayer from "./DnD/DragLayer"
|
||||
import Explorer from "./Explorer"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ import React, { Suspense, useCallback, useEffect, useState } from "react";
|
|||
import PageLoading from "../Placeholder/PageLoading";
|
||||
import { useParams } from "react-router";
|
||||
import API from "../../middleware/Api";
|
||||
import { changeSubTitle, toggleSnackbar } from "../../actions";
|
||||
import { toggleSnackbar } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import { useDispatch } from "react-redux";
|
||||
import Notice from "./NotFound";
|
||||
import LockedFile from "./LockedFile";
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||
import { useLocation, useParams, useRouteMatch } from "react-router";
|
||||
import API from "../../middleware/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { changeSubTitle, toggleSnackbar } from "../../actions";
|
||||
import { toggleSnackbar } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page";
|
||||
import SaveButton from "../Dial/Save";
|
||||
import { codePreviewSuffix } from "../../config";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||
import {useLocation, useParams, useRouteMatch} from "react-router";
|
||||
import API from "../../middleware/Api";
|
||||
import {useDispatch} from "react-redux";
|
||||
import {changeSubTitle, toggleSnackbar} from "../../actions";
|
||||
import {toggleSnackbar} from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page";
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||
import { useLocation, useParams, useRouteMatch } from "react-router";
|
||||
import { getBaseURL } from "../../middleware/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { changeSubTitle, toggleSnackbar } from "../../actions";
|
||||
import { toggleSnackbar } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page";
|
||||
import TextLoading from "../Placeholder/TextLoading";
|
||||
pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`;
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||
import {useLocation, useParams, useRouteMatch} from "react-router";
|
||||
import API from "../../middleware/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { changeSubTitle, toggleSnackbar } from "../../actions";
|
||||
import { toggleSnackbar } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import Editor from 'for-editor'
|
||||
import SaveButton from "../Dial/Save";
|
||||
import pathHelper from "../../utils/page";
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { makeStyles } from "@material-ui/core/styles";
|
|||
import { useLocation, useParams, useRouteMatch } from "react-router";
|
||||
import { getBaseURL } from "../../middleware/Api";
|
||||
import { useDispatch } from "react-redux";
|
||||
import { changeSubTitle } from "../../actions";
|
||||
import { changeSubTitle } from "../../redux/viewUpdate/action";
|
||||
import pathHelper from "../../utils/page";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
|
|
|
|||
|
|
@ -1,19 +1,16 @@
|
|||
const Auth = {
|
||||
isAuthenticated: false,
|
||||
authenticate(cb) {
|
||||
authenticate(cb: any) {
|
||||
Auth.SetUser(cb);
|
||||
Auth.isAuthenticated = true;
|
||||
},
|
||||
GetUser(){
|
||||
return JSON.parse(localStorage.getItem("user"))
|
||||
},
|
||||
SetUser(newUser){
|
||||
SetUser(newUser: any){
|
||||
localStorage.setItem("user", JSON.stringify(newUser));
|
||||
},
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
Check() {
|
||||
Check(): boolean {
|
||||
if (Auth.isAuthenticated) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -29,16 +26,13 @@ const Auth = {
|
|||
oldUser.id = 0;
|
||||
localStorage.setItem("user", JSON.stringify(oldUser));
|
||||
},
|
||||
SetPreference(key,value){
|
||||
SetPreference(key: string,value: any){
|
||||
let preference = JSON.parse(localStorage.getItem("user_preference"));
|
||||
preference = (preference == null) ? {} : preference;
|
||||
preference[key] = value;
|
||||
localStorage.setItem("user_preference", JSON.stringify(preference));
|
||||
},
|
||||
/**
|
||||
* @return {null}
|
||||
*/
|
||||
GetPreference(key){
|
||||
GetPreference(key: string): any | null{
|
||||
let preference = JSON.parse(localStorage.getItem("user_preference"));
|
||||
if (preference && preference[key]){
|
||||
return preference[key];
|
||||
|
|
@ -15,8 +15,6 @@ export var InitSiteConfig = (rawStore) => {
|
|||
rawStore.navigator.path = c===null?"/":c;
|
||||
// 初始化用户个性配置
|
||||
rawStore.siteConfig = initUserConfig(rawStore.siteConfig);
|
||||
// 是否登录
|
||||
rawStore.viewUpdate.isLogin = Auth.Check();
|
||||
|
||||
// 更改站点标题
|
||||
document.title = rawStore.siteConfig.title;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
/* eslint-disable no-case-declarations */
|
||||
import { InitSiteConfig } from "../middleware/Init";
|
||||
import { combineReducers } from '../redux/combineReducers'
|
||||
import viewUpdate from '../redux/viewUpdate/reducer'
|
||||
|
||||
const checkSelectedProps = (state)=>{
|
||||
let isMultiple,withFolder,withFile=false;
|
||||
|
|
@ -15,17 +17,12 @@ const checkSelectedProps = (state)=>{
|
|||
return [isMultiple,withFolder,withFile];
|
||||
}
|
||||
|
||||
const doNavigate = (path,state)=>{
|
||||
const doNavigate = (path, state)=>{
|
||||
window.currntPath = path;
|
||||
return Object.assign({}, state, {
|
||||
navigator:Object.assign({}, state.navigator, {
|
||||
path: path
|
||||
}),
|
||||
viewUpdate:Object.assign({}, state.viewUpdate, {
|
||||
contextOpen:false,
|
||||
navigatorError:false,
|
||||
navigatorLoading:path !== state.navigator.path,
|
||||
}),
|
||||
explorer:Object.assign({}, state.explorer, {
|
||||
selected:[],
|
||||
selectProps: {
|
||||
|
|
@ -92,46 +89,6 @@ export const initState = {
|
|||
path: "/",
|
||||
refresh: true
|
||||
},
|
||||
viewUpdate: {
|
||||
isLogin:false,
|
||||
loadUploader:false,
|
||||
open: false,
|
||||
explorerViewMethod: "icon",
|
||||
sortMethod: "timePos",
|
||||
subTitle:null,
|
||||
contextType: "none",
|
||||
menuOpen: false,
|
||||
navigatorLoading: true,
|
||||
navigatorError: false,
|
||||
navigatorErrorMsg: null,
|
||||
modalsLoading: false,
|
||||
storageRefresh: false,
|
||||
userPopoverAnchorEl: null,
|
||||
shareUserPopoverAnchorEl: null,
|
||||
modals: {
|
||||
createNewFolder: false,
|
||||
createNewFile: false,
|
||||
rename: false,
|
||||
move: false,
|
||||
remove: false,
|
||||
share: false,
|
||||
music: false,
|
||||
remoteDownload: false,
|
||||
torrentDownload: false,
|
||||
getSource: false,
|
||||
copy:false,
|
||||
resave: false,
|
||||
compress:false,
|
||||
decompress:false,
|
||||
},
|
||||
snackbar: {
|
||||
toggle: false,
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "",
|
||||
color: ""
|
||||
}
|
||||
},
|
||||
explorer: {
|
||||
dndSignal:false,
|
||||
dndTarget:null,
|
||||
|
|
@ -162,18 +119,6 @@ const defaultStatus = InitSiteConfig(initState);
|
|||
// TODO: 将cloureveApp切分成小的reducer
|
||||
const cloudreveApp = (state = defaultStatus, action) => {
|
||||
switch (action.type) {
|
||||
case 'DRAWER_TOGGLE':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
open:action.open,
|
||||
}),
|
||||
});
|
||||
case 'CHANGE_VIEW_METHOD':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
explorerViewMethod:action.method,
|
||||
}),
|
||||
});
|
||||
case 'CHANGE_SORT_METHOD':
|
||||
let list = [...state.explorer.fileList,...state.explorer.dirList];
|
||||
// eslint-disable-next-line
|
||||
|
|
@ -203,24 +148,11 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
});
|
||||
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
sortMethod:action.method,
|
||||
}),
|
||||
explorer: Object.assign({}, state.explorer, {
|
||||
fileList: fileList,
|
||||
dirList: dirList,
|
||||
}),
|
||||
});
|
||||
case 'CHANGE_CONTEXT_MENU':
|
||||
if(state.viewUpdate.contextOpen && action.open){
|
||||
return Object.assign({}, state);
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
contextOpen: action.open,
|
||||
contextType:action.menuType,
|
||||
}),
|
||||
});
|
||||
case 'DRAG_AND_DROP':
|
||||
return Object.assign({}, state, {
|
||||
explorer: Object.assign({}, state.explorer, {
|
||||
|
|
@ -229,19 +161,6 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
dndSource:action.source,
|
||||
}),
|
||||
});
|
||||
case 'SET_NAVIGATOR_LOADING_STATUE':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
navigatorLoading:action.status,
|
||||
}),
|
||||
});
|
||||
case 'SET_NAVIGATOR_ERROR':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
navigatorError: action.status,
|
||||
navigatorErrorMsg: action.msg,
|
||||
}),
|
||||
});
|
||||
case 'UPDATE_FILE_LIST':
|
||||
// eslint-disable-next-line
|
||||
action.list.sort((a,b)=>{
|
||||
|
|
@ -379,224 +298,11 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
}
|
||||
break
|
||||
case 'NAVIGATOR_UP':
|
||||
var pathSplit = state.navigator.path.split("/");
|
||||
pathSplit.pop();
|
||||
var newPath = pathSplit.length===1?"/":pathSplit.join("/");
|
||||
return doNavigate(newPath,state);
|
||||
case 'OPEN_CREATE_FOLDER_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
createNewFolder:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_CREATE_FILE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
createNewFile:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_RENAME_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
rename:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_REMOVE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
remove:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_MOVE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
move:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_RESAVE_DIALOG':
|
||||
window.shareKey = action.key;
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
resave:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'SET_USER_POPOVER':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
userPopoverAnchorEl:action.anchor,
|
||||
}),
|
||||
});
|
||||
case 'SET_SHARE_USER_POPOVER':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
shareUserPopoverAnchorEl:action.anchor,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_SHARE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
share:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
return doNavigate(action.path, state);
|
||||
case 'SET_SITE_CONFIG':
|
||||
return Object.assign({}, state, {
|
||||
siteConfig: action.config,
|
||||
});
|
||||
case 'OPEN_MUSIC_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
music:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_REMOTE_DOWNLOAD_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
remoteDownload:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_TORRENT_DOWNLOAD_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
torrentDownload:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_DECOMPRESS_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
decompress:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_COMPRESS_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
compress:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_GET_SOURCE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
getSource:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_COPY_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
copy:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'OPEN_LOADING_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
loading:true,
|
||||
loadingText:action.text,
|
||||
}),
|
||||
contextOpen:false,
|
||||
}),
|
||||
});
|
||||
case 'CLOSE_ALL_MODALS':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modals: Object.assign({}, state.viewUpdate.modals, {
|
||||
createNewFolder:false,
|
||||
createNewFile:false,
|
||||
rename:false,
|
||||
move:false,
|
||||
remove:false,
|
||||
share:false,
|
||||
music:false,
|
||||
remoteDownload:false,
|
||||
torrentDownload:false,
|
||||
getSource:false,
|
||||
resave:false,
|
||||
copy:false,
|
||||
loading:false,
|
||||
compress:false,
|
||||
decompress:false,
|
||||
}),
|
||||
}),
|
||||
});
|
||||
case 'CHANGE_SUB_TITLE':
|
||||
document.title = (action.title === null || action.title === undefined) ? state.siteConfig.title : (action.title + " - " +state.siteConfig.title);
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
subTitle: action.title,
|
||||
}),
|
||||
});
|
||||
case 'TOGGLE_SNACKBAR':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
snackbar:{
|
||||
toggle:!state.viewUpdate.snackbar.toggle,
|
||||
vertical:action.vertical,
|
||||
horizontal:action.horizontal,
|
||||
msg:action.msg,
|
||||
color:action.color,
|
||||
},
|
||||
}),
|
||||
});
|
||||
case 'SET_MODALS_LOADING':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
modalsLoading:action.status,
|
||||
}),
|
||||
});
|
||||
case 'SET_SESSION_STATUS':
|
||||
return {
|
||||
...state,
|
||||
viewUpdate: {
|
||||
...state.viewUpdate,
|
||||
isLogin:action.status,
|
||||
}
|
||||
}
|
||||
case 'ENABLE_LOAD_UPLOADER':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate: Object.assign({}, state.viewUpdate, {
|
||||
loadUploader:true,
|
||||
}),
|
||||
});
|
||||
case 'REFRESH_FILE_LIST':
|
||||
return Object.assign({}, state, {
|
||||
navigator: Object.assign({}, state.navigator, {
|
||||
|
|
@ -617,11 +323,6 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
path: "/搜索结果",
|
||||
refresh:state.explorer.keywords === null? state.navigator.refresh:!state.navigator.refresh,
|
||||
}),
|
||||
viewUpdate:Object.assign({}, state.viewUpdate, {
|
||||
contextOpen:false,
|
||||
navigatorError:false,
|
||||
navigatorLoading:true,
|
||||
}),
|
||||
explorer:Object.assign({}, state.explorer, {
|
||||
selected:[],
|
||||
selectProps: {
|
||||
|
|
@ -641,12 +342,6 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
},
|
||||
}),
|
||||
});
|
||||
case 'REFRESH_STORAGE':
|
||||
return Object.assign({}, state, {
|
||||
viewUpdate:Object.assign({}, state.viewUpdate, {
|
||||
storageRefresh:!state.viewUpdate.storageRefresh,
|
||||
}),
|
||||
});
|
||||
case 'SAVE_FILE':
|
||||
return Object.assign({}, state, {
|
||||
explorer:Object.assign({}, state.explorer, {
|
||||
|
|
@ -679,4 +374,12 @@ const cloudreveApp = (state = defaultStatus, action) => {
|
|||
}
|
||||
}
|
||||
|
||||
export default cloudreveApp
|
||||
export default (state, action) => {
|
||||
const { viewUpdate: viewUpdateState } = state || {}
|
||||
const appState = cloudreveApp(state, action)
|
||||
const combinedState = combineReducers({ viewUpdate })({ viewUpdate: viewUpdateState }, action)
|
||||
return {
|
||||
...appState,
|
||||
...combinedState,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
import cloudreveApp, { initState } from './index'
|
||||
import configureMockStore from 'redux-mock-store'
|
||||
import thunk from 'redux-thunk'
|
||||
import cloudreveApp, { initState as cloudreveState } from './index'
|
||||
import { initState as viewUpdateState } from '../redux/viewUpdate/reducer'
|
||||
|
||||
import { setModalsLoading, openLoadingDialog, openGetSourceDialog,
|
||||
openShareDialog, openMoveDialog, navigateUp, navigateTo,
|
||||
drawerToggleAction, changeViewMethod, changeSortMethod,
|
||||
|
|
@ -10,13 +14,23 @@ import { setModalsLoading, openLoadingDialog, openGetSourceDialog,
|
|||
setShareUserPopover, setSiteConfig, openMusicDialog,
|
||||
openRemoteDownloadDialog, openTorrentDownloadDialog,
|
||||
openDecompressDialog, openCompressDialog, openCopyDialog,
|
||||
closeAllModals, changeSubTitle, toggleSnackbar, setSessionStatus,
|
||||
enableLoadUploader, refreshFileList, searchMyFile, showImgPreivew, refreshStorage, saveFile, setLastSelect, setShiftSelectedIds
|
||||
closeAllModals, toggleSnackbar, setSessionStatus,
|
||||
enableLoadUploader, refreshFileList, searchMyFile, showImgPreivew,
|
||||
refreshStorage, saveFile, setLastSelect, setShiftSelectedIds
|
||||
} from '../actions/index'
|
||||
import { changeSubTitle } from "../redux/viewUpdate/action"
|
||||
|
||||
|
||||
const initState = {
|
||||
...cloudreveState,
|
||||
viewUpdate: viewUpdateState,
|
||||
}
|
||||
const middlewares = [thunk]
|
||||
const mockStore = configureMockStore(middlewares)
|
||||
|
||||
describe('index reducer', () => {
|
||||
it('should return the initial state', () => {
|
||||
expect(cloudreveApp(undefined, {})).toEqual(initState)
|
||||
expect(cloudreveApp(undefined, { type: '@@INIT'})).toEqual(initState)
|
||||
})
|
||||
|
||||
it('should handle DRAWER_TOGGLE', () => {
|
||||
|
|
@ -593,9 +607,11 @@ describe('index reducer', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('should handle NAVIGATOR_TO', () => {
|
||||
it('should handle NAVIGATOR_TO', async () => {
|
||||
const store = mockStore(initState)
|
||||
const action = navigateTo('/somewhere')
|
||||
expect(cloudreveApp(initState, action)).toEqual({
|
||||
const navAction = await store.dispatch(action)
|
||||
expect(cloudreveApp(initState, navAction)).toEqual({
|
||||
...initState,
|
||||
navigator: {
|
||||
...initState.navigator,
|
||||
|
|
@ -621,8 +637,7 @@ describe('index reducer', () => {
|
|||
expect(window.currntPath).toEqual('/somewhere')
|
||||
})
|
||||
|
||||
it('should handle NAVIGATOR_UP', () => {
|
||||
const action = navigateUp('somewhere')
|
||||
it('should handle NAVIGATOR_UP', async () => {
|
||||
const navState = {
|
||||
...initState,
|
||||
navigator: {
|
||||
|
|
@ -630,7 +645,10 @@ describe('index reducer', () => {
|
|||
path: '/to/somewhere'
|
||||
}
|
||||
}
|
||||
expect(cloudreveApp(navState, action)).toEqual({
|
||||
const store = mockStore(navState)
|
||||
const action = navigateUp('somewhere')
|
||||
const navAction = await store.dispatch(action)
|
||||
expect(cloudreveApp(navState, navAction)).toEqual({
|
||||
...initState,
|
||||
navigator: {
|
||||
...initState.navigator,
|
||||
|
|
@ -993,15 +1011,18 @@ describe('index reducer', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('should handle CHANGE_SUB_TITLE', () => {
|
||||
it('should handle CHANGE_SUB_TITLE', async () => {
|
||||
const store = mockStore(initState)
|
||||
const action = changeSubTitle('test sub title')
|
||||
expect(cloudreveApp(initState, action)).toEqual({
|
||||
const changeSubtitleAction = await store.dispatch(action)
|
||||
expect(cloudreveApp(initState, changeSubtitleAction)).toEqual({
|
||||
...initState,
|
||||
viewUpdate: {
|
||||
...initState.viewUpdate,
|
||||
subTitle: 'test sub title',
|
||||
}
|
||||
})
|
||||
expect(document.title).toEqual('test sub title - Cloudreve')
|
||||
})
|
||||
|
||||
it('should handle TOGGLE_SNACKBAR', () => {
|
||||
|
|
|
|||
|
|
@ -1,38 +0,0 @@
|
|||
const viewUpdate = (state = [], action) => {
|
||||
switch (action.type) {
|
||||
case 'DRAWER_TOGGLE':
|
||||
return Object.assign({}, state, {
|
||||
open: action.open
|
||||
});
|
||||
case 'CHANGE_VIEW_METHOD':
|
||||
return Object.assign({}, state, {
|
||||
explorerViewMethod: action.method
|
||||
|
||||
});
|
||||
case 'CHANGE_SORT_METHOD':
|
||||
return Object.assign({}, state, {
|
||||
sortMethod: action.method
|
||||
});
|
||||
case 'CHANGE_CONTEXT_MENU':
|
||||
if(state.contextOpen && action.open){
|
||||
return Object.assign({}, state);
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
contextType: action.menuType,
|
||||
contextOpen: action.open,
|
||||
});
|
||||
case 'SET_NAVIGATOR_LOADING_STATUE':
|
||||
return Object.assign({}, state, {
|
||||
navigatorLoading: action.status
|
||||
});
|
||||
case 'SET_NAVIGATOR_ERROR':
|
||||
return Object.assign({}, state, {
|
||||
navigatorError: action.status,
|
||||
navigatorErrorMsg: action.msg,
|
||||
});
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export default viewUpdate
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
import { combineReducers as combine, ReducersMapObject, AnyAction } from 'redux'
|
||||
import invariant from 'invariant'
|
||||
|
||||
export const combineReducers = (reducers: ReducersMapObject) => {
|
||||
const combinedReducer = combine(reducers)
|
||||
// TODO: define state type
|
||||
return (state: any, action: AnyAction) => {
|
||||
if (action.type.split('/').length > 1) {
|
||||
const namespace = action.type.split('/')[0]
|
||||
const reducer = reducers[namespace]
|
||||
invariant(!!reducer, `reducer ${namespace} doesn't exist`)
|
||||
return reducer && reducer(state, action)
|
||||
}
|
||||
return combinedReducer(state, action)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
import { ThunkAction } from 'redux-thunk'
|
||||
|
||||
export interface ACTION_CHANGE_SUBTITLE {
|
||||
type: "CHANGE_SUB_TITLE",
|
||||
title: string,
|
||||
}
|
||||
|
||||
export const changeSubTitle = (title: string):
|
||||
ThunkAction<ACTION_CHANGE_SUBTITLE, any, any, any> => {
|
||||
return (dispatch, getState) => {
|
||||
const state = getState()
|
||||
document.title = (title === null || title === undefined) ? state.siteConfig.title : (title + " - " +state.siteConfig.title);
|
||||
return dispatch({
|
||||
type: "CHANGE_SUB_TITLE",
|
||||
title: title
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
import * as actions from './action'
|
||||
import * as reducers from './reducer'
|
||||
|
||||
export default {
|
||||
actions,
|
||||
reducers,
|
||||
}
|
||||
|
|
@ -0,0 +1,309 @@
|
|||
import { AnyAction } from "redux"
|
||||
import Auth from "../../middleware/Auth"
|
||||
|
||||
export interface ViewUpdateState {
|
||||
isLogin: boolean,
|
||||
loadUploader:boolean,
|
||||
open: boolean,
|
||||
explorerViewMethod: string,
|
||||
sortMethod: string,
|
||||
subTitle: string | null,
|
||||
contextType: string,
|
||||
contextOpen: boolean,
|
||||
menuOpen: boolean,
|
||||
navigatorLoading: boolean,
|
||||
navigatorError: boolean,
|
||||
navigatorErrorMsg: string | null,
|
||||
modalsLoading: boolean,
|
||||
storageRefresh: boolean,
|
||||
userPopoverAnchorEl: any,
|
||||
shareUserPopoverAnchorEl: any,
|
||||
modals: {
|
||||
createNewFolder: boolean,
|
||||
createNewFile: boolean,
|
||||
rename: boolean,
|
||||
move: boolean,
|
||||
remove: boolean,
|
||||
share: boolean,
|
||||
music: boolean,
|
||||
remoteDownload: boolean,
|
||||
torrentDownload: boolean,
|
||||
getSource: boolean,
|
||||
copy:boolean,
|
||||
resave: boolean,
|
||||
compress:boolean,
|
||||
decompress:boolean,
|
||||
},
|
||||
snackbar: {
|
||||
toggle: boolean,
|
||||
vertical: string,
|
||||
horizontal: string,
|
||||
msg: string,
|
||||
color: string
|
||||
}
|
||||
}
|
||||
export const initState: ViewUpdateState = {
|
||||
// 是否登录
|
||||
isLogin: Auth.Check(),
|
||||
loadUploader:false,
|
||||
open: false,
|
||||
explorerViewMethod: "icon",
|
||||
sortMethod: "timePos",
|
||||
subTitle: null,
|
||||
contextType: "none",
|
||||
contextOpen: false,
|
||||
menuOpen: false,
|
||||
navigatorLoading: true,
|
||||
navigatorError: false,
|
||||
navigatorErrorMsg: null,
|
||||
modalsLoading: false,
|
||||
storageRefresh: false,
|
||||
userPopoverAnchorEl: null,
|
||||
shareUserPopoverAnchorEl: null,
|
||||
modals: {
|
||||
createNewFolder: false,
|
||||
createNewFile: false,
|
||||
rename: false,
|
||||
move: false,
|
||||
remove: false,
|
||||
share: false,
|
||||
music: false,
|
||||
remoteDownload: false,
|
||||
torrentDownload: false,
|
||||
getSource: false,
|
||||
copy:false,
|
||||
resave: false,
|
||||
compress:false,
|
||||
decompress:false,
|
||||
},
|
||||
snackbar: {
|
||||
toggle: false,
|
||||
vertical: "top",
|
||||
horizontal: "center",
|
||||
msg: "",
|
||||
color: ""
|
||||
}
|
||||
}
|
||||
const viewUpdate = (state: ViewUpdateState = initState, action: AnyAction) => {
|
||||
switch (action.type) {
|
||||
case 'DRAWER_TOGGLE':
|
||||
return Object.assign({}, state, {
|
||||
open: action.open,
|
||||
});
|
||||
case 'CHANGE_VIEW_METHOD':
|
||||
return Object.assign({}, state, {
|
||||
explorerViewMethod: action.method,
|
||||
});
|
||||
case 'SET_NAVIGATOR_LOADING_STATUE':
|
||||
return Object.assign({}, state, {
|
||||
navigatorLoading:action.status,
|
||||
});
|
||||
case 'SET_NAVIGATOR_ERROR':
|
||||
return Object.assign({}, state, {
|
||||
navigatorError: action.status,
|
||||
navigatorErrorMsg: action.msg,
|
||||
})
|
||||
case 'OPEN_CREATE_FOLDER_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
createNewFolder:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_CREATE_FILE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
createNewFile:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_RENAME_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
rename:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_REMOVE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
remove:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_MOVE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
move:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_RESAVE_DIALOG':
|
||||
// window.shareKey = action.key;
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
resave:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'SET_USER_POPOVER':
|
||||
return Object.assign({}, state, {
|
||||
userPopoverAnchorEl:action.anchor,
|
||||
});
|
||||
case 'SET_SHARE_USER_POPOVER':
|
||||
return Object.assign({}, state, {
|
||||
shareUserPopoverAnchorEl:action.anchor,
|
||||
});
|
||||
case 'OPEN_SHARE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
share:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_MUSIC_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
music:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_REMOTE_DOWNLOAD_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
remoteDownload:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_TORRENT_DOWNLOAD_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
torrentDownload:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_DECOMPRESS_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
decompress:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_COMPRESS_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
compress:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_GET_SOURCE_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
getSource:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_COPY_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
copy:true,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'OPEN_LOADING_DIALOG':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
loading:true,
|
||||
loadingText:action.text,
|
||||
}),
|
||||
contextOpen:false,
|
||||
});
|
||||
case 'CLOSE_ALL_MODALS':
|
||||
return Object.assign({}, state, {
|
||||
modals: Object.assign({}, state.modals, {
|
||||
createNewFolder:false,
|
||||
createNewFile:false,
|
||||
rename:false,
|
||||
move:false,
|
||||
remove:false,
|
||||
share:false,
|
||||
music:false,
|
||||
remoteDownload:false,
|
||||
torrentDownload:false,
|
||||
getSource:false,
|
||||
resave:false,
|
||||
copy:false,
|
||||
loading:false,
|
||||
compress:false,
|
||||
decompress:false,
|
||||
}),
|
||||
});
|
||||
case 'TOGGLE_SNACKBAR':
|
||||
return Object.assign({}, state, {
|
||||
snackbar:{
|
||||
toggle:!state.snackbar.toggle,
|
||||
vertical:action.vertical,
|
||||
horizontal:action.horizontal,
|
||||
msg:action.msg,
|
||||
color:action.color,
|
||||
},
|
||||
});
|
||||
case 'SET_MODALS_LOADING':
|
||||
return Object.assign({}, state, {
|
||||
modalsLoading:action.status,
|
||||
});
|
||||
case 'SET_SESSION_STATUS':
|
||||
return {
|
||||
...state,
|
||||
isLogin: action.status,
|
||||
}
|
||||
case 'ENABLE_LOAD_UPLOADER':
|
||||
return Object.assign({}, state, {
|
||||
loadUploader:true,
|
||||
});
|
||||
case 'REFRESH_STORAGE':
|
||||
return Object.assign({}, state, {
|
||||
storageRefresh:!state.storageRefresh,
|
||||
});
|
||||
case 'SEARCH_MY_FILE':
|
||||
return Object.assign({}, state, {
|
||||
contextOpen:false,
|
||||
navigatorError:false,
|
||||
navigatorLoading:true,
|
||||
})
|
||||
case 'CHANGE_CONTEXT_MENU':
|
||||
if(state.contextOpen && action.open){
|
||||
return Object.assign({}, state);
|
||||
}
|
||||
return Object.assign({}, state, {
|
||||
contextOpen: action.open,
|
||||
contextType: action.menuType,
|
||||
});
|
||||
case 'CHANGE_SUB_TITLE':
|
||||
return Object.assign({}, state, {
|
||||
subTitle: action.title,
|
||||
});
|
||||
case 'CHANGE_SORT_METHOD':
|
||||
return {
|
||||
...state,
|
||||
sortMethod: action.method
|
||||
}
|
||||
case 'NAVIGATOR_TO':
|
||||
return {
|
||||
...state,
|
||||
contextOpen:false,
|
||||
navigatorError:false,
|
||||
navigatorLoading: action.navigatorLoading
|
||||
}
|
||||
// case 'NAVIGATOR_TO':
|
||||
// return Object.assign({}, state, {
|
||||
// contextOpen:false,
|
||||
// navigatorError:false,
|
||||
// navigatorLoading:true,
|
||||
// })
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
||||
|
||||
export default viewUpdate
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/",
|
||||
"sourceMap": true,
|
||||
"noImplicitAny": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "commonjs",
|
||||
"target": "es6",
|
||||
"jsx": "react"
|
||||
}
|
||||
}
|
||||
29
yarn.lock
29
yarn.lock
|
|
@ -1381,6 +1381,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.30.tgz#20efa342807606ada5483731a8137cb1561e5fe9"
|
||||
integrity sha512-98fB+yo7imSD2F7PF7GIpELNgtLNgo5wjivu0W5V4jx+KVVJxo6p/qN4zdzSTBWy4/sN3pPyXwnhRSD28QX+ag==
|
||||
|
||||
"@types/invariant@^2.2.32":
|
||||
version "2.2.32"
|
||||
resolved "https://registry.yarnpkg.com/@types/invariant/-/invariant-2.2.32.tgz#cf523a609062564e36e7a7dadb5089ed87da6382"
|
||||
integrity sha512-WjY4WVFaehHv+TOgm+dS3UI559NvsPGFz/C0nIo7KOOdC+HeC7Y3/yLzdJYQ3+oFQaTXrOVm7cNtIgMataIDVg==
|
||||
|
||||
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
|
||||
|
|
@ -1421,6 +1426,13 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8"
|
||||
integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==
|
||||
|
||||
"@types/react-dom@^16.9.7":
|
||||
version "16.9.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.7.tgz#60844d48ce252d7b2dccf0c7bb937130e27c0cd2"
|
||||
integrity sha512-GHTYhM8/OwUCf254WO5xqR/aqD3gC9kSTLpopWGpQLpnw23jk44RvMHsyUSEplvRJZdHxhJGMMLF0kCPYHPhQA==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-transition-group@^4.2.0":
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.2.3.tgz#4924133f7268694058e415bf7aea2d4c21131470"
|
||||
|
|
@ -6764,6 +6776,11 @@ lodash.debounce@^4.0.8:
|
|||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168=
|
||||
|
||||
lodash.isplainobject@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
|
||||
integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=
|
||||
|
||||
lodash.memoize@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
|
||||
|
|
@ -9465,6 +9482,13 @@ reduce-function-call@^1.0.1:
|
|||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
|
||||
redux-mock-store@^1.5.4:
|
||||
version "1.5.4"
|
||||
resolved "https://registry.yarnpkg.com/redux-mock-store/-/redux-mock-store-1.5.4.tgz#90d02495fd918ddbaa96b83aef626287c9ab5872"
|
||||
integrity sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==
|
||||
dependencies:
|
||||
lodash.isplainobject "^4.0.6"
|
||||
|
||||
redux-thunk@^2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
|
||||
|
|
@ -10946,6 +10970,11 @@ typedarray@^0.0.6:
|
|||
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
|
||||
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
|
||||
|
||||
typescript@^3.8.3:
|
||||
version "3.8.3"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061"
|
||||
integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==
|
||||
|
||||
ua-parser-js@^0.7.18:
|
||||
version "0.7.20"
|
||||
resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.20.tgz#7527178b82f6a62a0f243d1f94fd30e3e3c21098"
|
||||
|
|
|
|||
Loading…
Reference in New Issue