Web: People: Speeded up loading first page + refactoring

This commit is contained in:
Alexey Safronov 2020-09-17 11:28:23 +03:00
parent c16659c322
commit 2f4a3141d5
4 changed files with 203 additions and 142 deletions

View File

@ -28,12 +28,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.

View File

@ -1,6 +1,7 @@
import React, { Suspense } from "react";
import { connect } from "react-redux";
import { Router, Switch, Redirect } from "react-router-dom";
import axios from "axios";
import { Loader } from "asc-web-components";
import Home from "./components/pages/Home";
import Profile from "./components/pages/Profile";
@ -17,80 +18,180 @@ import {
StudioLayout,
Offline
} from "asc-web-common";
import { store as commonStore, constants } from "asc-web-common";
import { getFilterByLocation } from "./helpers/converters";
import { getPortalInviteLinks } from "./store/portal/actions";
import { fetchGroups, fetchPeople } from "./store/people/actions";
import config from "../package.json";
const {
setIsLoaded,
getUser,
getPortalSettings,
getModules,
setCurrentProductId,
setCurrentProductHomePage,
getPortalPasswordSettings,
getPortalCultures
} = commonStore.auth.actions;
const { AUTH_KEY } = constants;
/*const Profile = lazy(() => import("./components/pages/Profile"));
const ProfileAction = lazy(() => import("./components/pages/ProfileAction"));
const GroupAction = lazy(() => import("./components/pages/GroupAction"));*/
const App = ({ settings }) => {
const { homepage } = settings;
return navigator.onLine ? (
<Router history={history}>
<StudioLayout>
<Suspense
fallback={<Loader className="pageLoader" type="rombs" size="40px" />}
>
<Switch>
<Redirect exact from="/" to={`${homepage}`} />
<PrivateRoute
exact
path={[homepage, `${homepage}/filter`]}
component={Home}
/>
<PrivateRoute
path={`${homepage}/view/:userId`}
component={Profile}
/>
<PrivateRoute
path={`${homepage}/edit/:userId`}
component={ProfileAction}
restricted
allowForMe
/>
<PrivateRoute
path={`${homepage}/create/:type`}
component={ProfileAction}
restricted
/>
<PrivateRoute
path={`${homepage}/group/edit/:groupId`}
component={GroupAction}
restricted
/>
<PrivateRoute
path={`${homepage}/group/create`}
component={GroupAction}
restricted
/>
<PrivateRoute
path={`${homepage}/reassign/:userId`}
component={Reassign}
restricted
/>
<PublicRoute
exact
path={[
"/login",
"/login/error=:error",
"/login/confirmed-email=:confirmedEmail"
]}
component={Login}
/>
<PrivateRoute exact path={`/error=:error`} component={Error520} />
<PrivateRoute component={Error404} />
</Switch>
</Suspense>
</StudioLayout>
</Router>
) : (
<Offline />
);
};
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);
}
};
componentDidMount() {
const {
getUser,
getPortalSettings,
getModules,
getPortalPasswordSettings,
getPortalCultures,
fetchGroups,
fetchPeople,
finalize,
setIsLoaded
} = this.props;
function mapStateToProps(state) {
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 {
this.removeLoader();
setIsLoaded();
}
}
render() {
const { homepage } = this.props.settings;
return navigator.onLine ? (
<Router history={history}>
<StudioLayout>
<Suspense
fallback={
<Loader className="pageLoader" type="rombs" size="40px" />
}
>
<Switch>
<Redirect exact from="/" to={`${homepage}`} />
<PrivateRoute
exact
path={[homepage, `${homepage}/filter`]}
component={Home}
/>
<PrivateRoute
path={`${homepage}/view/:userId`}
component={Profile}
/>
<PrivateRoute
path={`${homepage}/edit/:userId`}
component={ProfileAction}
restricted
allowForMe
/>
<PrivateRoute
path={`${homepage}/create/:type`}
component={ProfileAction}
restricted
/>
<PrivateRoute
path={`${homepage}/group/edit/:groupId`}
component={GroupAction}
restricted
/>
<PrivateRoute
path={`${homepage}/group/create`}
component={GroupAction}
restricted
/>
<PrivateRoute
path={`${homepage}/reassign/:userId`}
component={Reassign}
restricted
/>
<PublicRoute
exact
path={[
"/login",
"/login/error=:error",
"/login/confirmed-email=:confirmedEmail"
]}
component={Login}
/>
<PrivateRoute exact path={`/error=:error`} component={Error520} />
<PrivateRoute component={Error404} />
</Switch>
</Suspense>
</StudioLayout>
</Router>
) : (
<Offline />
);
}
}
const mapStateToProps = state => {
return {
settings: state.auth.settings
};
}
};
export default connect(mapStateToProps)(App);
const mapDispatchToProps = dispatch => {
return {
getUser: () =>
getUser(dispatch).then(() => dispatch(getPortalInviteLinks())), //TODO: Try simplify
getPortalSettings: () => getPortalSettings(dispatch),
getModules: () => getModules(dispatch),
getPortalPasswordSettings: () => getPortalPasswordSettings(dispatch),
getPortalCultures: () => getPortalCultures(dispatch),
fetchGroups: () => fetchGroups(dispatch),
fetchPeople: () => {
var re = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm");
const match = window.location.pathname.match(re);
if (match && match.length > 0) {
const newFilter = getFilterByLocation(window.location);
return fetchPeople(newFilter, dispatch);
}
return Promise.resolve();
},
finalize: () => {
dispatch(setCurrentProductHomePage(config.homepage));
dispatch(setCurrentProductId("f4d98afd-d336-4332-8778-3c6945c81ea0"));
dispatch(setIsLoaded(true));
},
setIsLoaded: () => dispatch(setIsLoaded(true))
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(App);

View File

@ -1,64 +1,13 @@
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import axios from "axios";
import store from "./store/store";
import { fetchGroups, fetchPeople } from "./store/people/actions";
import config from "../package.json";
import "./custom.scss";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import { store as commonStore, constants, ErrorBoundary } from "asc-web-common";
import { getFilterByLocation } from "./helpers/converters";
import { getPortalInviteLinks } from "./store/portal/actions";
const {
setIsLoaded,
getUser,
getPortalSettings,
getModules,
setCurrentProductId,
setCurrentProductHomePage,
getPortalPasswordSettings,
getPortalCultures
} = commonStore.auth.actions;
const { AUTH_KEY } = constants;
const token = localStorage.getItem(AUTH_KEY);
if (token) {
const requests = [
getUser(store.dispatch).then(() => store.dispatch(getPortalInviteLinks())), //TODO: Try simplify
getPortalSettings(store.dispatch),
getModules(store.dispatch),
getPortalPasswordSettings(store.dispatch),
getPortalCultures(store.dispatch),
fetchGroups(store.dispatch)
];
axios
.all(requests)
.then(() => {
var re = new RegExp(`${config.homepage}((/?)$|/filter)`, "gm");
const match = window.location.pathname.match(re);
if (match && match.length > 0) {
const newFilter = getFilterByLocation(window.location);
return fetchPeople(newFilter, store.dispatch);
}
return Promise.resolve();
})
.then(() => {
store.dispatch(setCurrentProductHomePage(config.homepage));
store.dispatch(
setCurrentProductId("f4d98afd-d336-4332-8778-3c6945c81ea0")
);
store.dispatch(setIsLoaded(true));
});
} else {
store.dispatch(setIsLoaded(true));
}
import { ErrorBoundary } from "asc-web-common";
ReactDOM.render(
<Provider store={store}>

View File

@ -31,6 +31,18 @@ const {
} = CommonStore.auth.actions;
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);
}
};
componentDidMount() {
const { getPortalSettings, getUser, getModules, setIsLoaded } = this.props;
@ -48,25 +60,15 @@ class App extends React.Component {
requests.push(getModules());
}
if (requests.length > 0) {
axios
.all(requests)
.catch(e => {
console.log("INIT REQUESTS FAILED", e);
})
.finally(() => {
const ele = document.getElementById("ipl-progress-indicator");
if (ele) {
// fade out
ele.classList.add("available");
setTimeout(() => {
// remove from DOM
ele.outerHTML = "";
}, 2000);
}
setIsLoaded(true);
});
}
axios
.all(requests)
.catch(e => {
console.log("INIT REQUESTS FAILED", e);
})
.finally(() => {
this.removeLoader();
setIsLoaded(true);
});
}
render() {