Web: Files: Added default loader before react is ready

This commit is contained in:
Alexey Safronov 2020-09-23 17:20:51 +03:00
parent 0028707da6
commit 01abc6d4f1
2 changed files with 387 additions and 72 deletions

View File

@ -1,25 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no">
<meta name="theme-color" content="#000000">
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no"
/>
<meta name="theme-color" content="#000000" />
<base href="%PUBLIC_URL%/" />
<!--
manifest.json provides metadata used when your web app is added to the
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
-->
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!-- Tell the browser it's a PWA -->
<meta name="mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes" />
<!-- Tell iOS it's a PWA -->
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-icon" href="icon.png">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i' rel='stylesheet' type='text/css'></link>
<script type="text/javascript" src="https://dotnet.onlyoffice.com/ds-vpath/web-apps/apps/api/documents/api.js?ver=10.0.1.875"></script>
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="apple-touch-icon" href="icon.png" />
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
<link
href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,600,600i,700,700i"
rel="stylesheet"
type="text/css"
/>
<script
type="text/javascript"
src="https://dotnet.onlyoffice.com/ds-vpath/web-apps/apps/api/documents/api.js?ver=10.0.1.875"
></script>
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
@ -30,29 +40,328 @@
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:auto;position:absolute;/*top:55px;*/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)}}
/* .ksnrwP { -webkit-box-align: center; align-items: center; background-color: rgb(15, 64, 113); display: flex; -webkit-box-pack: center; justify-content: center; z-index: 185; position: absolute; width: calc(100vw - 64px); height: 56px; padding: 0px 32px; }.hMkrmf { -webkit-box-align: center; align-items: center; box-sizing: border-box; display: flex; -webkit-box-pack: justify; justify-content: space-between; outline: none; }.ksnrwP .header-items-wrapper { width: 960px; }.ksnrwP .header-logo-wrapper { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }.ksnrwP .header-logo-min_icon { display: none; cursor: pointer; width: 24px; height: 24px; }.ksnrwP .header-logo-icon { width: 146px; height: 24px; position: relative; padding: 4px 20px 0px 6px; cursor: pointer; }@media (max-width: 768px){.ksnrwP .header-items-wrapper { width: 475px; }}@media (max-width: 375px){.ksnrwP .header-items-wrapper { width: 311px; }} */
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: auto;
position: absolute;
opacity: 1;
pointer-events: none;
-webkit-transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 436ms;
-moz-transition: opacity cubic-bezier(0.4, 0, 0.2, 1) 436ms;
transition: opacity cubic-bezier(0.4, 0, 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(0.5);
}
50% {
transform: translate(25%) scaleX(0.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(0.6);
}
100% {
transform: translate(100%) scaleX(0.1);
}
}
.temp-header-container {
-webkit-box-align: center;
align-items: center;
background-color: rgb(15, 64, 113);
display: flex;
z-index: 185;
width: calc(100vw - 64px);
height: 56px;
padding: 0 32px;
}
.temp-header-container .header-items-wrapper {
width: 960px;
}
.temp-header-container .temp-header-logo-wrapper {
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
.temp-header-container .temp-header-logo-icon {
width: 146px;
height: 24px;
position: relative;
padding: 4px 20px 0 30px;
cursor: pointer;
}
.temp-content-loader {
padding: 16px;
height: calc(100vh - 91px);
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: calc(100vh - 91px);
grid-column-gap: 8px;
}
@media (max-width: 1024px) {
.temp-content-loader {
grid-template-columns: 1fr;
}
.temp-content__article {
display: none;
}
}
</style>
<title>ONLYOFFICE</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<!-- <header class="sc-cBssTz ksnrwP"><div class="sc-hJFzDP hMkrmf header-items-wrapper">
<div>
<a class="header-logo-wrapper" href="/">
<img class="header-logo-min_icon" src="images/nav.logo.react.svg">
<img class="header-logo-icon" src="images/nav.logo.opened.react.svg">
</a>
</div>
</header> -->
</head>
<body>
<noscript> 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="temp-content">
<header class="temp-header-container">
<a class="temp-header-logo-wrapper" href="/">
<img
class="temp-header-logo-icon"
src="images/nav.logo.opened.react.svg"
/>
</a>
</header>
<div class="temp-content-loader">
<div class="temp-content__article">
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria1"
preserveAspectRatio="none"
>
<title id="loading-aria1">Loading...</title>
<rect
x="0"
y="0"
width="100%"
height="100%"
clip-path="url(#clip-path1)"
style="fill: url('#fill1')"
></rect>
<defs>
<clipPath id="clip-path1">
<rect x="3" y="3" rx="5" ry="5" width="100%" />
</clipPath>
<linearGradient id="fill1">
<stop offset="0.599964" stop-color="#f3f3f3" stop-opacity="1">
<animate
attributeName="offset"
values="-2; -2; 1"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="1.59996" stop-color="#ecebeb" stop-opacity="1">
<animate
attributeName="offset"
values="-1; -1; 2"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="2.59996" stop-color="#f3f3f3" stop-opacity="1">
<animate
attributeName="offset"
values="0; 0; 3"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
</linearGradient>
</defs>
</svg>
</div>
<div>
<svg
role="img"
width="100%"
height="100%"
aria-labelledby="loading-aria2"
preserveAspectRatio="none"
>
<title id="loading-aria2">Loading...</title>
<rect
x="0"
y="0"
width="100%"
height="100%"
clip-path="url(#clip-path2)"
style="fill: url('#fill2')"
></rect>
<defs>
<clipPath id="clip-path2">
<rect x="3" y="3" rx="5" ry="5" width="100%" />
</clipPath>
<linearGradient id="fill2">
<stop offset="0.599964" stop-color="#f3f3f3" stop-opacity="1">
<animate
attributeName="offset"
values="-2; -2; 1"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="1.59996" stop-color="#ecebeb" stop-opacity="1">
<animate
attributeName="offset"
values="-1; -1; 2"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="2.59996" stop-color="#f3f3f3" stop-opacity="1">
<animate
attributeName="offset"
values="0; 0; 3"
keyTimes="0; 0.25; 1"
dur="2s"
repeatCount="indefinite"
></animate>
</stop>
</linearGradient>
</defs>
</svg>
</div>
</div>
</div>
<div id="root"></div>
<!--
This HTML file is a template.

View File

@ -9,13 +9,13 @@ import { withTranslation, I18nextProvider } from "react-i18next";
import {
ArticleBodyContent,
ArticleHeaderContent,
ArticleMainButtonContent
ArticleMainButtonContent,
} from "../../Article";
import {
SectionBodyContent,
SectionFilterContent,
SectionHeaderContent,
SectionPagingContent
SectionPagingContent,
} from "./Section";
import {
clearProgressData,
@ -31,11 +31,11 @@ import {
setSelected,
setTreeFolders,
setIsLoading,
setFirstLoad
setFirstLoad,
} from "../../../store/files/actions";
import {
loopTreeFolders,
checkFolderType
checkFolderType,
} from "../../../store/files/selectors";
import { ConvertDialog } from "../../dialogs";
@ -44,7 +44,7 @@ import { createI18N } from "../../../helpers/i18n";
import { getFilterByLocation } from "../../../helpers/converters";
const i18n = createI18N({
page: "Home",
localesPath: "pages/Home"
localesPath: "pages/Home",
});
const { changeLanguage } = utils;
const { FilesFilter } = api;
@ -68,11 +68,14 @@ class PureHome extends React.Component {
uploadStatus: null,
uploaded: true,
uploadToFolder: null
uploadToFolder: null,
};
}
componentDidMount() {
const tempElm = document.getElementById("temp-content");
if (tempElm) tempElm.outerHTML = "";
const { fetchFiles, homepage, setIsLoading, setFirstLoad } = this.props;
const reg = new RegExp(`${homepage}((/?)$|/filter)`, "gm"); //TODO: Always find?
@ -109,7 +112,7 @@ class PureHome extends React.Component {
dataObj = {
type,
itemId,
filter: filterObj
filter: filterObj,
};
} else {
filterObj.authorType = null;
@ -131,11 +134,11 @@ class PureHome extends React.Component {
setIsLoading(true);
Promise.all(requests)
.catch(err => {
.catch((err) => {
Promise.resolve(FilesFilter.getDefault());
console.warn("Filter restored by default", err);
})
.then(data => {
.then((data) => {
const filter = data[0];
const result = data[1];
if (result) {
@ -143,7 +146,7 @@ class PureHome extends React.Component {
const selectedItem = {
key: result.id,
label: type === "user" ? result.displayName : result.name,
type
type,
};
filter.selectedItem = selectedItem;
}
@ -195,11 +198,11 @@ class PureHome extends React.Component {
startUpload(files, folderId, t);
};
onSectionHeaderContentCheck = checked => {
onSectionHeaderContentCheck = (checked) => {
this.props.setSelected(checked ? "all" : "none");
};
onSectionHeaderContentSelect = selected => {
onSectionHeaderContentSelect = (selected) => {
this.props.setSelected(selected);
};
@ -219,7 +222,7 @@ class PureHome extends React.Component {
onChangeOriginalFormat = () =>
this.setState({
uploadOriginalFormatSetting: !this.state.uploadOriginalFormatSetting
uploadOriginalFormatSetting: !this.state.uploadOriginalFormatSetting,
});
onChangeWindowVisible = () =>
@ -229,7 +232,9 @@ class PureHome extends React.Component {
const { filter, selection, setFilter } = this.props;
const newFilter = filter.clone();
for (let item of selection) {
const expandedIndex = newFilter.treeFolders.findIndex(x => x == item.id);
const expandedIndex = newFilter.treeFolders.findIndex(
(x) => x == item.id
);
if (expandedIndex !== -1) {
newFilter.treeFolders.splice(expandedIndex, 1);
}
@ -249,17 +254,17 @@ class PureHome extends React.Component {
setNewTreeFilesBadge,
setProgressBarData,
treeFolders,
fetchFiles
fetchFiles,
} = this.props;
getProgress()
.then(res => {
const currentItem = res.find(x => x.id === id);
.then((res) => {
const currentItem = res.find((x) => x.id === id);
if (currentItem && currentItem.progress !== 100) {
setProgressBarData({
label: progressData.label,
percent: currentItem.progress,
visible: true
visible: true,
});
setTimeout(
() => this.loopFilesOperations(id, destFolderId, isCopy),
@ -269,10 +274,10 @@ class PureHome extends React.Component {
setProgressBarData({
label: progressData.label,
percent: 100,
visible: true
visible: true,
});
getFolder(destFolderId)
.then(data => {
.then((data) => {
let newTreeFolders = treeFolders;
let path = data.pathParts.slice(0);
let folders = data.folders;
@ -281,7 +286,7 @@ class PureHome extends React.Component {
if (!isCopy || destFolderId === currentFolderId) {
fetchFiles(currentFolderId, filter)
.then(data => {
.then((data) => {
if (!isRecycleBinFolder) {
newTreeFolders = treeFolders;
path = data.selectedFolder.pathParts.slice(0);
@ -298,7 +303,7 @@ class PureHome extends React.Component {
}
this.setNewFilter();
})
.catch(err => {
.catch((err) => {
toastr.error(err);
clearProgressData();
})
@ -307,33 +312,33 @@ class PureHome extends React.Component {
setProgressBarData({
label: progressData.label,
percent: 100,
visible: true
visible: true,
});
setTimeout(() => clearProgressData(), 5000);
setNewTreeFilesBadge(true);
setTreeFolders(newTreeFolders);
}
})
.catch(err => {
.catch((err) => {
toastr.error(err);
clearProgressData();
});
}
})
.catch(err => {
.catch((err) => {
toastr.error(err);
clearProgressData();
});
};
setSelections = items => {
setSelections = (items) => {
const {
selection,
folders,
files,
selectFile,
deselectFile,
fileActionId
fileActionId,
} = this.props;
if (selection.length > items.length) {
@ -346,10 +351,12 @@ class PureHome extends React.Component {
item = item.split("_");
if (item[0] === "folder") {
newFile = selection.find(
x => x.id === Number(item[1]) && !x.fileExst
(x) => x.id === Number(item[1]) && !x.fileExst
);
} else if (item[0] === "file") {
newFile = selection.find(x => x.id === Number(item[1]) && x.fileExst);
newFile = selection.find(
(x) => x.id === Number(item[1]) && x.fileExst
);
}
if (newFile) {
newSelection.push(newFile);
@ -358,7 +365,7 @@ class PureHome extends React.Component {
for (let item of selection) {
const element = newSelection.find(
x => x.id === item.id && x.fileExst === item.fileExst
(x) => x.id === item.id && x.fileExst === item.fileExst
);
if (!element) {
deselectFile(item);
@ -372,13 +379,15 @@ class PureHome extends React.Component {
let newFile = null;
item = item.split("_");
if (item[0] === "folder") {
newFile = folders.find(x => x.id === Number(item[1]) && !x.fileExst);
newFile = folders.find(
(x) => x.id === Number(item[1]) && !x.fileExst
);
} else if (item[0] === "file") {
newFile = files.find(x => x.id === Number(item[1]) && x.fileExst);
newFile = files.find((x) => x.id === Number(item[1]) && x.fileExst);
}
if (newFile && fileActionId !== newFile.id) {
const existItem = selection.find(
x => x.id === newFile.id && x.fileExst === newFile.fileExst
(x) => x.id === newFile.id && x.fileExst === newFile.fileExst
);
!existItem && selectFile(newFile);
}
@ -399,7 +408,7 @@ class PureHome extends React.Component {
isHeaderVisible,
isHeaderIndeterminate,
isHeaderChecked,
selected
selected,
// overwriteSetting,
// uploadOriginalFormatSetting,
// hideWindowSetting
@ -409,7 +418,7 @@ class PureHome extends React.Component {
progressData,
viewAs,
isLoading,
convertDialogVisible
convertDialogVisible,
} = this.props;
// const progressBarContent = (
@ -511,7 +520,7 @@ class PureHome extends React.Component {
const HomeContainer = withTranslation()(PureHome);
const Home = props => {
const Home = (props) => {
useEffect(() => {
changeLanguage(i18n);
}, []);
@ -525,7 +534,7 @@ const Home = props => {
Home.propTypes = {
files: PropTypes.array,
history: PropTypes.object.isRequired,
isLoaded: PropTypes.bool
isLoaded: PropTypes.bool,
};
function mapStateToProps(state) {
@ -542,7 +551,7 @@ function mapStateToProps(state) {
selection,
treeFolders,
viewAs,
isLoading
isLoading,
} = state.files;
const { id } = selectedFolder;
const indexOfTrash = 3;
@ -562,11 +571,11 @@ function mapStateToProps(state) {
treeFolders,
viewAs,
isLoading,
homepage
homepage,
};
}
const mapDispatchToProps = dispatch => {
const mapDispatchToProps = (dispatch) => {
return {
deselectFile,
getFolder,
@ -582,11 +591,8 @@ const mapDispatchToProps = dispatch => {
setIsLoading,
setFirstLoad,
fetchFiles: (folderId, filter) => fetchFiles(folderId, filter, dispatch),
clearProgressData: () => clearProgressData(dispatch)
clearProgressData: () => clearProgressData(dispatch),
};
};
export default connect(
mapStateToProps,
mapDispatchToProps
)(withRouter(Home));
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Home));