Web: Files: Speeded up loading first page + refactoring
This commit is contained in:
parent
2f4a3141d5
commit
9623029d82
@ -29,12 +29,21 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<style type="text/css">
|
||||
body{height:100%;margin:0;padding:0;width:100%}body{font-family:'Open Sans',sans-serif;font-size:13px;-webkit-font-smoothing:antialiased}.ipl-progress-indicator.available{opacity:0}.ipl-progress-indicator{background-color:#f5f5f5;width:100%;height:100%;position:fixed;opacity:1;pointer-events:none;-webkit-transition:opacity cubic-bezier(.4,0,.2,1) 436ms;-moz-transition:opacity cubic-bezier(.4,0,.2,1) 436ms;transition:opacity cubic-bezier(.4,0,.2,1) 436ms;z-index:9999}.insp-logo-frame{display:-webkit-flex;display:-moz-flex;display:flex;-webkit-flex-direction:column;-moz-flex-direction:column;flex-direction:column;-webkit-justify-content:center;-moz-justify-content:center;justify-content:center;-webkit-animation:fadein 436ms;-moz-animation:fadein 436ms;animation:fadein 436ms;height:98%}.insp-logo-frame-img{width:112px;height:112px;-webkit-align-self:center;-moz-align-self:center;align-self:center;border-radius:50%}.ipl-progress-indicator-head{background-color:#c6dafc;height:4px;overflow:hidden;position:relative}.ipl-progress-indicator .first-indicator,.ipl-progress-indicator .second-indicator{background-color:#056d8b;bottom:0;left:0;right:0;top:0;position:absolute;-webkit-transform-origin:left center;-moz-transform-origin:left center;transform-origin:left center;-webkit-transform:scaleX(0);-moz-transform:scaleX(0);transform:scaleX(0)}.ipl-progress-indicator .first-indicator{-webkit-animation:first-indicator 2s linear infinite;-moz-animation:first-indicator 2s linear infinite;animation:first-indicator 2s linear infinite}.ipl-progress-indicator .second-indicator{-webkit-animation:second-indicator 2s linear infinite;-moz-animation:second-indicator 2s linear infinite;animation:second-indicator 2s linear infinite}.ipl-progress-indicator .insp-logo{animation:App-logo-spin infinite 20s linear;border-radius:50%;-webkit-align-self:center;-moz-align-self:center;align-self:center}@keyframes App-logo-spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}@-webkit-keyframes fadein{from{opacity:0}to{opacity:1}}@-moz-keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes fadein{from{opacity:0}to{opacity:1}}@keyframes first-indicator{0%{transform:translate(0) scaleX(0)}25%{transform:translate(0) scaleX(.5)}50%{transform:translate(25%) scaleX(.75)}75%{transform:translate(100%) scaleX(0)}100%{transform:translate(100%) scaleX(0)}}@keyframes second-indicator{0%{transform:translate(0) scaleX(0)}60%{transform:translate(0) scaleX(0)}80%{transform:translate(0) scaleX(.6)}100%{transform:translate(100%) scaleX(.1)}}
|
||||
</style>
|
||||
<title>ONLYOFFICE</title>
|
||||
</head>
|
||||
<body>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div class="ipl-progress-indicator" id="ipl-progress-indicator">
|
||||
<div class="ipl-progress-indicator-head">
|
||||
<div class="first-indicator"></div>
|
||||
<div class="second-indicator"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
|
@ -1,12 +1,21 @@
|
||||
import React, { Suspense } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import axios from "axios";
|
||||
import { Router, Switch, Redirect } from "react-router-dom";
|
||||
import { Loader } from "asc-web-components";
|
||||
import Home from "./components/pages/Home";
|
||||
import DocEditor from "./components/pages/DocEditor";
|
||||
import Settings from "./components/pages/Settings";
|
||||
import {
|
||||
fetchMyFolder,
|
||||
fetchTreeFolders,
|
||||
fetchFiles
|
||||
} from "./store/files/actions";
|
||||
import config from "../package.json";
|
||||
|
||||
import {
|
||||
store as commonStore,
|
||||
constants,
|
||||
history,
|
||||
PrivateRoute,
|
||||
PublicRoute,
|
||||
@ -14,9 +23,25 @@ import {
|
||||
Error404,
|
||||
Error520,
|
||||
StudioLayout,
|
||||
Offline
|
||||
Offline,
|
||||
api
|
||||
} from "asc-web-common";
|
||||
|
||||
import { getFilterByLocation } from "./helpers/converters";
|
||||
|
||||
const {
|
||||
setIsLoaded,
|
||||
getUser,
|
||||
getPortalSettings,
|
||||
getModules,
|
||||
setCurrentProductId,
|
||||
setCurrentProductHomePage,
|
||||
getPortalPasswordSettings,
|
||||
getPortalCultures
|
||||
} = commonStore.auth.actions;
|
||||
const { AUTH_KEY } = constants;
|
||||
const { FilesFilter } = api;
|
||||
|
||||
const VersionHistory = React.lazy(() =>
|
||||
import("./components/pages/VersionHistory")
|
||||
);
|
||||
@ -27,63 +52,218 @@ const withStudioLayout = Component => props => (
|
||||
</StudioLayout>
|
||||
);
|
||||
|
||||
const App = ({ settings }) => {
|
||||
const { homepage } = settings;
|
||||
class App extends React.Component {
|
||||
removeLoader = () => {
|
||||
const ele = document.getElementById("ipl-progress-indicator");
|
||||
if (ele) {
|
||||
// fade out
|
||||
ele.classList.add("available");
|
||||
setTimeout(() => {
|
||||
// remove from DOM
|
||||
ele.outerHTML = "";
|
||||
}, 2000);
|
||||
}
|
||||
};
|
||||
|
||||
return navigator.onLine ? (
|
||||
<Router history={history}>
|
||||
<Suspense
|
||||
fallback={<Loader className="pageLoader" type="rombs" size="40px" />}
|
||||
>
|
||||
<Switch>
|
||||
<Redirect exact from="/" to={`${homepage}`} />
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={[homepage, `${homepage}/filter`]}
|
||||
component={withStudioLayout(Home)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/settings/:setting`}
|
||||
component={withStudioLayout(Settings)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/doceditor`}
|
||||
component={DocEditor}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/:fileId/history`}
|
||||
component={withStudioLayout(VersionHistory)}
|
||||
/>
|
||||
<PublicRoute
|
||||
exact
|
||||
path={[
|
||||
"/login",
|
||||
"/login/error=:error",
|
||||
"/login/confirmed-email=:confirmedEmail"
|
||||
]}
|
||||
component={withStudioLayout(Login)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`/error=:error`}
|
||||
component={withStudioLayout(Error520)}
|
||||
/>
|
||||
<PrivateRoute component={withStudioLayout(Error404)} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</Router>
|
||||
) : (
|
||||
<Offline />
|
||||
);
|
||||
};
|
||||
componentDidMount() {
|
||||
const {
|
||||
getUser,
|
||||
getPortalSettings,
|
||||
getModules,
|
||||
getPortalPasswordSettings,
|
||||
getPortalCultures,
|
||||
fetchMyFolder,
|
||||
fetchTreeFolders,
|
||||
fetchFiles,
|
||||
finalize,
|
||||
setIsLoaded
|
||||
} = this.props;
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const token = localStorage.getItem(AUTH_KEY);
|
||||
|
||||
if (!token) {
|
||||
this.removeLoader();
|
||||
return setIsLoaded();
|
||||
}
|
||||
|
||||
const requests = [
|
||||
getUser(),
|
||||
getPortalSettings(),
|
||||
getModules(),
|
||||
getPortalPasswordSettings(),
|
||||
getPortalCultures(),
|
||||
fetchMyFolder(),
|
||||
fetchTreeFolders()
|
||||
];
|
||||
|
||||
axios
|
||||
.all(requests)
|
||||
.then(() => {
|
||||
const reg = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm"); //TODO: Always find?
|
||||
const match = window.location.pathname.match(reg);
|
||||
let filterObj = null;
|
||||
|
||||
if (match && match.length > 0) {
|
||||
filterObj = getFilterByLocation(window.location);
|
||||
|
||||
if (!filterObj) {
|
||||
filterObj = FilesFilter.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(filterObj);
|
||||
})
|
||||
.then(filter => {
|
||||
let dataObj = filter;
|
||||
|
||||
if (filter && filter.authorType) {
|
||||
const filterObj = filter;
|
||||
const authorType = filterObj.authorType;
|
||||
const indexOfUnderscore = authorType.indexOf("_");
|
||||
const type = authorType.slice(0, indexOfUnderscore);
|
||||
const itemId = authorType.slice(indexOfUnderscore + 1);
|
||||
|
||||
if (itemId) {
|
||||
dataObj = {
|
||||
type,
|
||||
itemId,
|
||||
filter: filterObj
|
||||
};
|
||||
} else {
|
||||
filterObj.authorType = null;
|
||||
dataObj = filterObj;
|
||||
}
|
||||
}
|
||||
return Promise.resolve(dataObj);
|
||||
})
|
||||
.then(data => {
|
||||
if (!data) return Promise.resolve();
|
||||
if (data instanceof FilesFilter) return Promise.resolve(data);
|
||||
|
||||
const { filter, itemId, type } = data;
|
||||
const newFilter = filter ? filter.clone() : FilesFilter.getDefault();
|
||||
|
||||
switch (type) {
|
||||
case "group":
|
||||
return Promise.all([api.groups.getGroup(itemId), newFilter]);
|
||||
case "user":
|
||||
return Promise.all([api.people.getUserById(itemId), newFilter]);
|
||||
default:
|
||||
return Promise.resolve(newFilter);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
Promise.resolve(FilesFilter.getDefault());
|
||||
console.warn("Filter restored by default", err);
|
||||
})
|
||||
.then(data => {
|
||||
if (!data) return Promise.resolve();
|
||||
if (data instanceof FilesFilter) return Promise.resolve(data);
|
||||
|
||||
const result = data[0];
|
||||
const filter = data[1];
|
||||
const type = result.displayName ? "user" : "group";
|
||||
const selectedItem = {
|
||||
key: result.id,
|
||||
label: type === "user" ? result.displayName : result.name,
|
||||
type
|
||||
};
|
||||
filter.selectedItem = selectedItem;
|
||||
|
||||
return Promise.resolve(filter);
|
||||
})
|
||||
.then(filter => {
|
||||
if (!filter) return Promise.resolve();
|
||||
|
||||
const folderId = filter.folder;
|
||||
return fetchFiles(folderId, filter);
|
||||
})
|
||||
.then(() => {
|
||||
this.removeLoader();
|
||||
finalize();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { homepage } = this.props.settings;
|
||||
|
||||
return navigator.onLine ? (
|
||||
<Router history={history}>
|
||||
<Suspense
|
||||
fallback={<Loader className="pageLoader" type="rombs" size="40px" />}
|
||||
>
|
||||
<Switch>
|
||||
<Redirect exact from="/" to={`${homepage}`} />
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={[homepage, `${homepage}/filter`]}
|
||||
component={withStudioLayout(Home)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/settings/:setting`}
|
||||
component={withStudioLayout(Settings)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/doceditor`}
|
||||
component={DocEditor}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`${homepage}/:fileId/history`}
|
||||
component={withStudioLayout(VersionHistory)}
|
||||
/>
|
||||
<PublicRoute
|
||||
exact
|
||||
path={[
|
||||
"/login",
|
||||
"/login/error=:error",
|
||||
"/login/confirmed-email=:confirmedEmail"
|
||||
]}
|
||||
component={withStudioLayout(Login)}
|
||||
/>
|
||||
<PrivateRoute
|
||||
exact
|
||||
path={`/error=:error`}
|
||||
component={withStudioLayout(Error520)}
|
||||
/>
|
||||
<PrivateRoute component={withStudioLayout(Error404)} />
|
||||
</Switch>
|
||||
</Suspense>
|
||||
</Router>
|
||||
) : (
|
||||
<Offline />
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
settings: state.auth.settings
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps)(App);
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
getUser: () => getUser(dispatch),
|
||||
getPortalSettings: () => getPortalSettings(dispatch),
|
||||
getModules: () => getModules(dispatch),
|
||||
getPortalPasswordSettings: () => getPortalPasswordSettings(dispatch),
|
||||
getPortalCultures: () => getPortalCultures(dispatch),
|
||||
fetchMyFolder: () => fetchMyFolder(dispatch),
|
||||
fetchTreeFolders: () => fetchTreeFolders(dispatch),
|
||||
fetchFiles: (folderId, filter) => fetchFiles(folderId, filter, dispatch),
|
||||
finalize: () => {
|
||||
dispatch(setCurrentProductHomePage(config.homepage));
|
||||
dispatch(setCurrentProductId("e67be73d-f9ae-4ce1-8fec-1880cb518cb4"));
|
||||
dispatch(setIsLoaded(true));
|
||||
},
|
||||
setIsLoaded: () => dispatch(setIsLoaded(true))
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
)(App);
|
||||
|
@ -1,145 +1,15 @@
|
||||
import "./wdyr";
|
||||
//import "./wdyr";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Provider } from "react-redux";
|
||||
import axios from "axios";
|
||||
|
||||
import store from "./store/store";
|
||||
import {
|
||||
fetchMyFolder,
|
||||
fetchTreeFolders,
|
||||
fetchFiles
|
||||
} from "./store/files/actions";
|
||||
import config from "../package.json";
|
||||
import "./custom.scss";
|
||||
import App from "./App";
|
||||
|
||||
import * as serviceWorker from "./serviceWorker";
|
||||
import {
|
||||
store as commonStore,
|
||||
constants,
|
||||
ErrorBoundary,
|
||||
api
|
||||
} from "asc-web-common";
|
||||
import { getFilterByLocation } from "./helpers/converters";
|
||||
const {
|
||||
setIsLoaded,
|
||||
getUser,
|
||||
getPortalSettings,
|
||||
getModules,
|
||||
setCurrentProductId,
|
||||
setCurrentProductHomePage,
|
||||
getPortalPasswordSettings,
|
||||
getPortalCultures
|
||||
} = commonStore.auth.actions;
|
||||
const { AUTH_KEY } = constants;
|
||||
const { FilesFilter } = api;
|
||||
|
||||
const token = localStorage.getItem(AUTH_KEY);
|
||||
|
||||
if (token) {
|
||||
const requests = [
|
||||
getUser(store.dispatch),
|
||||
getPortalSettings(store.dispatch),
|
||||
getModules(store.dispatch),
|
||||
getPortalPasswordSettings(store.dispatch),
|
||||
getPortalCultures(store.dispatch),
|
||||
fetchMyFolder(store.dispatch),
|
||||
fetchTreeFolders(store.dispatch)
|
||||
];
|
||||
|
||||
axios
|
||||
.all(requests)
|
||||
.then(() => {
|
||||
const reg = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm"); //TODO: Always find?
|
||||
const match = window.location.pathname.match(reg);
|
||||
let filterObj = null;
|
||||
|
||||
if (match && match.length > 0) {
|
||||
filterObj = getFilterByLocation(window.location);
|
||||
|
||||
if (!filterObj) {
|
||||
filterObj = FilesFilter.getDefault();
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.resolve(filterObj);
|
||||
})
|
||||
.then(filter => {
|
||||
let dataObj = filter;
|
||||
|
||||
if (filter && filter.authorType) {
|
||||
const filterObj = filter;
|
||||
const authorType = filterObj.authorType;
|
||||
const indexOfUnderscore = authorType.indexOf("_");
|
||||
const type = authorType.slice(0, indexOfUnderscore);
|
||||
const itemId = authorType.slice(indexOfUnderscore + 1);
|
||||
|
||||
if (itemId) {
|
||||
dataObj = {
|
||||
type,
|
||||
itemId,
|
||||
filter: filterObj
|
||||
};
|
||||
} else {
|
||||
filterObj.authorType = null;
|
||||
dataObj = filterObj;
|
||||
}
|
||||
}
|
||||
return Promise.resolve(dataObj);
|
||||
})
|
||||
.then(data => {
|
||||
if (!data) return Promise.resolve();
|
||||
if (data instanceof FilesFilter) return Promise.resolve(data);
|
||||
|
||||
const { filter, itemId, type } = data;
|
||||
const newFilter = filter ? filter.clone() : FilesFilter.getDefault();
|
||||
|
||||
switch (type) {
|
||||
case "group":
|
||||
return Promise.all([api.groups.getGroup(itemId), newFilter]);
|
||||
case "user":
|
||||
return Promise.all([api.people.getUserById(itemId), newFilter]);
|
||||
default:
|
||||
return Promise.resolve(newFilter);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
Promise.resolve(FilesFilter.getDefault());
|
||||
console.warn("Filter restored by default", err);
|
||||
})
|
||||
.then(data => {
|
||||
if (!data) return Promise.resolve();
|
||||
if (data instanceof FilesFilter) return Promise.resolve(data);
|
||||
|
||||
const result = data[0];
|
||||
const filter = data[1];
|
||||
const type = result.displayName ? "user" : "group";
|
||||
const selectedItem = {
|
||||
key: result.id,
|
||||
label: type === "user" ? result.displayName : result.name,
|
||||
type
|
||||
};
|
||||
filter.selectedItem = selectedItem;
|
||||
|
||||
return Promise.resolve(filter);
|
||||
})
|
||||
.then(filter => {
|
||||
if (!filter) return Promise.resolve();
|
||||
|
||||
const folderId = filter.folder;
|
||||
return fetchFiles(folderId, filter, store.dispatch);
|
||||
})
|
||||
.then(() => {
|
||||
store.dispatch(setCurrentProductHomePage(config.homepage));
|
||||
store.dispatch(
|
||||
setCurrentProductId("e67be73d-f9ae-4ce1-8fec-1880cb518cb4")
|
||||
);
|
||||
store.dispatch(setIsLoaded(true));
|
||||
});
|
||||
} else {
|
||||
store.dispatch(setIsLoaded(true));
|
||||
}
|
||||
import { ErrorBoundary } from "asc-web-common";
|
||||
|
||||
ReactDOM.render(
|
||||
<Provider store={store}>
|
||||
|
@ -67,25 +67,25 @@ class App extends React.Component {
|
||||
|
||||
const token = localStorage.getItem(AUTH_KEY);
|
||||
|
||||
if (token) {
|
||||
const requests = [
|
||||
getUser(),
|
||||
getPortalSettings(),
|
||||
getModules(),
|
||||
getPortalPasswordSettings(),
|
||||
getPortalCultures(),
|
||||
fetchGroups(),
|
||||
fetchPeople()
|
||||
];
|
||||
|
||||
axios.all(requests).then(() => {
|
||||
this.removeLoader();
|
||||
finalize();
|
||||
});
|
||||
} else {
|
||||
if (!token) {
|
||||
this.removeLoader();
|
||||
setIsLoaded();
|
||||
return setIsLoaded();
|
||||
}
|
||||
|
||||
const requests = [
|
||||
getUser(),
|
||||
getPortalSettings(),
|
||||
getModules(),
|
||||
getPortalPasswordSettings(),
|
||||
getPortalCultures(),
|
||||
fetchGroups(),
|
||||
fetchPeople()
|
||||
];
|
||||
|
||||
axios.all(requests).then(() => {
|
||||
this.removeLoader();
|
||||
finalize();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
|
Loading…
Reference in New Issue
Block a user