1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-01 23:20:51 +00:00

12.0 change app structure (#6335)

* 01 change app structure

* 02 change setting page

* 03 optimize header style

* 04 change app mobile side panel logo
This commit is contained in:
Michael An
2024-07-11 17:45:30 +08:00
committed by GitHub
parent 4e16703d33
commit c41407f783
38 changed files with 238 additions and 408 deletions

View File

@@ -6,8 +6,8 @@ import { Modal } from 'reactstrap';
import { siteRoot } from './utils/constants'; import { siteRoot } from './utils/constants';
import { Utils } from './utils/utils'; import { Utils } from './utils/utils';
import SystemNotification from './components/system-notification'; import SystemNotification from './components/system-notification';
//import Header from './components/header'; import EventBus from './components/common/event-bus';
import Logo from './components/logo'; import Header from './components/header';
import SidePanel from './components/side-panel'; import SidePanel from './components/side-panel';
import MainPanel from './components/main-panel'; import MainPanel from './components/main-panel';
import FilesActivities from './pages/dashboard/files-activities'; import FilesActivities from './pages/dashboard/files-activities';
@@ -30,22 +30,11 @@ import Group from './pages/groups/group-view';
import InvitationsView from './pages/invitations/invitations-view'; import InvitationsView from './pages/invitations/invitations-view';
import Wikis from './pages/wikis/wikis'; import Wikis from './pages/wikis/wikis';
import Libraries from './pages/libraries'; import Libraries from './pages/libraries';
import MainContentWrapper from './components/main-content-wrapper';
import './css/layout.css'; import './css/layout.css';
import './css/toolbar.css'; import './css/toolbar.css';
import './css/search.css'; import './css/search.css';
const FilesActivitiesWrapper = MainContentWrapper(FilesActivities);
const MyFileActivitiesWrapper = MainContentWrapper(MyFileActivities);
const StarredWrapper = MainContentWrapper(Starred);
const LinkedDevicesWrapper = MainContentWrapper(LinkedDevices);
const SharedLibrariesWrapper = MainContentWrapper(SharedLibraries);
const SharedWithOCMWrapper = MainContentWrapper(ShareWithOCM);
const OCMViaWebdavWrapper = MainContentWrapper(OCMViaWebdav);
const InvitationsViewWrapper = MainContentWrapper(InvitationsView);
const ShareAdminLibrariesWrapper = MainContentWrapper(ShareAdminLibraries);
const ShareAdminFoldersWrapper = MainContentWrapper(ShareAdminFolders);
class App extends Component { class App extends Component {
@@ -62,6 +51,8 @@ class App extends Component {
}; };
this.dirViewPanels = ['libraries', 'my-libs', 'shared-libs', 'org']; // and group this.dirViewPanels = ['libraries', 'my-libs', 'shared-libs', 'org']; // and group
window.onpopstate = this.onpopstate; window.onpopstate = this.onpopstate;
const eventBus = new EventBus();
this.eventBus = eventBus;
} }
onpopstate = (event) => { onpopstate = (event) => {
@@ -222,52 +213,55 @@ class App extends Component {
return ( return (
<React.Fragment> <React.Fragment>
<SystemNotification /> <SystemNotification />
{/*<Header <Header
isSidePanelClosed={isSidePanelClosed} isSidePanelClosed={isSidePanelClosed}
onCloseSidePanel={this.onCloseSidePanel} onCloseSidePanel={this.onCloseSidePanel}
onShowSidePanel={this.onShowSidePanel} onShowSidePanel={this.onShowSidePanel}
onSearchedClick={this.onSearchedClick} onSearchedClick={this.onSearchedClick}
eventBus={this.eventBus}
/> />
*/}
<div id="main" className="user-panel"> <div id="main" className="user-panel">
<Logo onCloseSidePanel={this.onCloseSidePanel} positioned={true} />
<SidePanel <SidePanel
isSidePanelClosed={isSidePanelClosed} isSidePanelClosed={isSidePanelClosed}
isSidePanelFolded={isSidePanelFolded} isSidePanelFolded={isSidePanelFolded}
onCloseSidePanel={this.onCloseSidePanel} onCloseSidePanel={this.onCloseSidePanel}
currentTab={currentTab} currentTab={currentTab}
tabItemClick={this.tabItemClick} tabItemClick={this.tabItemClick}
showLogoOnlyInMobile={true}
toggleFoldSideNav={this.toggleFoldSideNav} toggleFoldSideNav={this.toggleFoldSideNav}
/> />
<MainPanel> <MainPanel>
<Router className="reach-router"> <Router className="reach-router">
<Libraries path={ siteRoot } onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <Libraries path={siteRoot} />
<Libraries path={ siteRoot + 'libraries' } onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <Libraries path={siteRoot + 'libraries'} />
<FilesActivitiesWrapper path={siteRoot + 'dashboard'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <MyLibraries path={siteRoot + 'my-libs'} />
<MyFileActivitiesWrapper path={siteRoot + 'my-activities'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <MyLibDeleted path={siteRoot + 'my-libs/deleted/'} />
<StarredWrapper path={siteRoot + 'starred'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <ShareAdminShareLinks path={siteRoot + 'share-admin-share-links'} />
<LinkedDevicesWrapper path={siteRoot + 'linked-devices'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <ShareAdminUploadLinks path={siteRoot + 'share-admin-upload-links'} />
<ShareAdminLibrariesWrapper path={siteRoot + 'share-admin-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <PublicSharedView path={siteRoot + 'org/'} />
<ShareAdminFoldersWrapper path={siteRoot + 'share-admin-folders'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <Wikis path={siteRoot + 'published'} />
<ShareAdminShareLinks path={siteRoot + 'share-admin-share-links'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <Starred path={siteRoot + 'starred'} />
<ShareAdminUploadLinks path={siteRoot + 'share-admin-upload-links'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <InvitationsView path={siteRoot + 'invitations/'} />
<SharedLibrariesWrapper path={siteRoot + 'shared-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <FilesActivities path={siteRoot + 'dashboard'} />
<SharedWithOCMWrapper path={siteRoot + 'shared-with-ocm'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <MyFileActivities path={siteRoot + 'my-activities'} />
<OCMViaWebdavWrapper path={siteRoot + 'ocm-via-webdav'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <Group path={siteRoot + 'group/:groupID'} onGroupChanged={this.onGroupChanged} />
<MyLibraries path={siteRoot + 'my-libs'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} /> <LinkedDevices path={siteRoot + 'linked-devices'} />
<MyLibDeleted path={siteRoot + 'my-libs/deleted/'} onSearchedClick={this.onSearchedClick} /> <ShareAdminLibraries path={siteRoot + 'share-admin-libs'} />
<LibContentView path={siteRoot + 'library/:repoID/*'} pathPrefix={this.state.pathPrefix} isSidePanelFolded={isSidePanelFolded} onMenuClick={this.onShowSidePanel} onTabNavClick={this.tabItemClick}/> <ShareAdminFolders path={siteRoot + 'share-admin-folders'} />
<OCMRepoDir path={siteRoot + 'remote-library/:providerID/:repoID/*'} pathPrefix={this.state.pathPrefix} onMenuClick={this.onShowSidePanel} onTabNavClick={this.tabItemClick}/> <SharedLibraries path={siteRoot + 'shared-libs'} />
<Group <ShareWithOCM path={siteRoot + 'shared-with-ocm'} />
path={siteRoot + 'group/:groupID'} <OCMViaWebdav path={siteRoot + 'ocm-via-webdav'} />
onShowSidePanel={this.onShowSidePanel} <OCMRepoDir
onSearchedClick={this.onSearchedClick} path={siteRoot + 'remote-library/:providerID/:repoID/*'}
onGroupChanged={this.onGroupChanged} pathPrefix={this.state.pathPrefix}
onTabNavClick={this.tabItemClick}
/>
<LibContentView
path={siteRoot + 'library/:repoID/*'}
pathPrefix={this.state.pathPrefix}
isSidePanelFolded={isSidePanelFolded}
onTabNavClick={this.tabItemClick}
eventBus={this.eventBus}
/> />
<Wikis path={siteRoot + 'published'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick}/>
<PublicSharedView path={siteRoot + 'org/'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} onTabNavClick={this.tabItemClick}/>
<InvitationsViewWrapper path={siteRoot + 'invitations/'} onShowSidePanel={this.onShowSidePanel} onSearchedClick={this.onSearchedClick} />
</Router> </Router>
</MainPanel> </MainPanel>
<MediaQuery query="(max-width: 767.8px)"> <MediaQuery query="(max-width: 767.8px)">

View File

@@ -1,4 +1,5 @@
export const EVENT_BUS_TYPE = { export const EVENT_BUS_TYPE = {
// metadata
QUERY_COLLABORATORS: 'query-collaborators', QUERY_COLLABORATORS: 'query-collaborators',
QUERY_COLLABORATOR: 'query-collaborator', QUERY_COLLABORATOR: 'query-collaborator',
UPDATE_TABLE_ROWS: 'update-table-rows', UPDATE_TABLE_ROWS: 'update-table-rows',
@@ -34,4 +35,7 @@ export const EVENT_BUS_TYPE = {
// change // change
VIEW_CHANGED: 'view_changed', VIEW_CHANGED: 'view_changed',
// library
CURRENT_LIBRARY_CHANGED: 'current_library_changed',
}; };

View File

@@ -0,0 +1,5 @@
.top-header {
background-color: #f8fafd;
border-bottom: 1px solid #eee;
padding: .5rem 1rem;
}

View File

@@ -3,7 +3,11 @@ import PropTypes from 'prop-types';
import Logo from './logo'; import Logo from './logo';
import CommonToolbar from './toolbar/common-toolbar'; import CommonToolbar from './toolbar/common-toolbar';
import './header.css';
const propTypes = { const propTypes = {
children: PropTypes.object,
eventBus: PropTypes.object.isRequired,
isSidePanelClosed: PropTypes.bool, isSidePanelClosed: PropTypes.bool,
onCloseSidePanel: PropTypes.func, onCloseSidePanel: PropTypes.func,
onShowSidePanel: PropTypes.func, onShowSidePanel: PropTypes.func,
@@ -15,21 +19,23 @@ const propTypes = {
class Header extends React.Component { class Header extends React.Component {
render() { render() {
const { onShowSidePanel, onSearchedClick, showSearch } = this.props; const { onShowSidePanel, onSearchedClick, showSearch, children } = this.props;
return ( return (
<div id="header" className="d-flex justify-content-between py-2 px-4"> <div id="header" className="top-header d-flex justify-content-between flex-shrink-0">
<div className={'flex-shrink-0 d-none d-md-flex'}> <div className={'flex-shrink-0 d-none d-md-flex'}>
<Logo onCloseSidePanel={this.props.onCloseSidePanel} /> <Logo onCloseSidePanel={this.props.onCloseSidePanel} />
</div> </div>
<div className="flex-shrink-0 d-flex flex-fill"> <div className={`flex-shrink-0 d-flex flex-fill ${children ? 'border-left-show' : ''}`}>
<div className="cur-view-toolbar"> <div className="cur-view-toolbar">
<span title="Side Nav Menu" onClick={onShowSidePanel} className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none"> <span title="Side Nav Menu" onClick={onShowSidePanel} className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none">
</span> </span>
{children}
</div> </div>
<CommonToolbar <CommonToolbar
showSearch={showSearch} showSearch={showSearch}
searchPlaceholder={this.props.searchPlaceholder} searchPlaceholder={this.props.searchPlaceholder}
onSearchedClick={onSearchedClick} onSearchedClick={onSearchedClick}
eventBus={this.props.eventBus}
/> />
</div> </div>
</div> </div>

View File

@@ -1,13 +1,10 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from '../utils/constants'; import { siteRoot, mediaUrl, logoPath, logoWidth, logoHeight, siteTitle } from '../utils/constants';
import { Utils } from '../utils/utils';
const propTypes = { const propTypes = {
onCloseSidePanel: PropTypes.func, onCloseSidePanel: PropTypes.func,
showCloseSidePanelIcon: PropTypes.bool, showCloseSidePanelIcon: PropTypes.bool,
positioned: PropTypes.bool,
showLogoOnlyInMobile: PropTypes.bool
}; };
class Logo extends React.Component { class Logo extends React.Component {
@@ -17,14 +14,8 @@ class Logo extends React.Component {
}; };
render() { render() {
const { positioned, showLogoOnlyInMobile } = this.props;
if (showLogoOnlyInMobile && Utils.isDesktop()) {
return null;
}
return ( return (
<div className={`top-logo ${positioned ? 'd-none d-md-block positioned-top-logo' : ''}`}> <div className='top-logo'>
<a href={siteRoot} id="logo"> <a href={siteRoot} id="logo">
<img src={logoPath.indexOf('image-view') != -1 ? logoPath : mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" /> <img src={logoPath.indexOf('image-view') != -1 ? logoPath : mediaUrl + logoPath} height={logoHeight} width={logoWidth} title={siteTitle} alt="logo" />
</a> </a>

View File

@@ -1,22 +0,0 @@
import React, { Fragment } from 'react';
import GeneralToolBar from './toolbar/general-toolbar';
const MainContentWrapper = (WrapperedComponent) => {
return class Wrapper extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<Fragment>
<GeneralToolBar {...this.props} />
<WrapperedComponent {...this.props} />
</Fragment>
);
}
};
};
export default MainContentWrapper;

View File

@@ -1,6 +1,7 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import MediaQuery from 'react-responsive';
import Logo from './logo'; import Logo from './logo';
import MainSideNav from './main-side-nav'; import MainSideNav from './main-side-nav';
import { SIDE_PANEL_FOLDED_WIDTH } from '../constants'; import { SIDE_PANEL_FOLDED_WIDTH } from '../constants';
@@ -11,7 +12,6 @@ const propTypes = {
onCloseSidePanel: PropTypes.func, onCloseSidePanel: PropTypes.func,
tabItemClick: PropTypes.func, tabItemClick: PropTypes.func,
children: PropTypes.object, children: PropTypes.object,
showLogoOnlyInMobile: PropTypes.bool,
isSidePanelFolded: PropTypes.bool, isSidePanelFolded: PropTypes.bool,
toggleFoldSideNav: PropTypes.func toggleFoldSideNav: PropTypes.func
}; };
@@ -19,16 +19,15 @@ const propTypes = {
class SidePanel extends React.Component { class SidePanel extends React.Component {
render() { render() {
const { children, isSidePanelFolded, showLogoOnlyInMobile = false } = this.props; const { children, isSidePanelFolded } = this.props;
const style = isSidePanelFolded ? { flexBasis: SIDE_PANEL_FOLDED_WIDTH } : {}; const style = isSidePanelFolded ? { flexBasis: SIDE_PANEL_FOLDED_WIDTH } : {};
return ( return (
<div className={classnames('side-panel', { 'side-panel-folded': isSidePanelFolded, 'left-zero': !this.props.isSidePanelClosed })} style={style}> <div className={classnames('side-panel', { 'side-panel-folded': isSidePanelFolded, 'left-zero': !this.props.isSidePanelClosed })} style={style}>
<div className={'side-panel-north'}> <MediaQuery query="(max-width: 767.8px)">
<Logo <div className='side-panel-north'>
onCloseSidePanel={this.props.onCloseSidePanel} <Logo onCloseSidePanel={this.props.onCloseSidePanel} />
showLogoOnlyInMobile={showLogoOnlyInMobile} </div>
/> </MediaQuery>
</div>
<div className="side-panel-center"> <div className="side-panel-center">
{children ? children : ( {children ? children : (
<MainSideNav <MainSideNav

View File

@@ -7,6 +7,7 @@ import SearchByName from '../search/search-by-name';
import Notification from '../common/notification'; import Notification from '../common/notification';
import Account from '../common/account'; import Account from '../common/account';
import Logout from '../common/logout'; import Logout from '../common/logout';
import { EVENT_BUS_TYPE } from '../common/event-bus-type';
const propTypes = { const propTypes = {
repoID: PropTypes.string, repoID: PropTypes.string,
@@ -16,14 +17,41 @@ const propTypes = {
onSearchedClick: PropTypes.func, onSearchedClick: PropTypes.func,
searchPlaceholder: PropTypes.string, searchPlaceholder: PropTypes.string,
currentRepoInfo: PropTypes.object, currentRepoInfo: PropTypes.object,
eventBus: PropTypes.object,
isViewFile: PropTypes.bool, isViewFile: PropTypes.bool,
showSearch: PropTypes.bool showSearch: PropTypes.bool
}; };
class CommonToolbar extends React.Component { class CommonToolbar extends React.Component {
constructor(props) {
super(props);
this.state = {
repoID: props.repoID,
repoName: props.repoName,
isLibView: props.isLibView,
path: props.path,
isViewFile: props.isViewFile,
};
}
componentDidMount() {
if (this.props.eventBus) {
this.unsubscribeLibChange = this.props.eventBus.subscribe(EVENT_BUS_TYPE.CURRENT_LIBRARY_CHANGED, this.onRepoChange);
}
}
componentWillUnmount() {
this.unsubscribeLibChange && this.unsubscribeLibChange();
}
onRepoChange = ({ repoID, repoName, isLibView, path, isViewFile }) => {
this.setState({ repoID, repoName, isLibView, path, isViewFile });
};
renderSearch = () => { renderSearch = () => {
const { repoID, repoName, isLibView, searchPlaceholder, path, isViewFile } = this.props; const { repoID, repoName, isLibView, path, isViewFile } = this.state;
const { searchPlaceholder } = this.props;
const placeholder = searchPlaceholder || gettext('Search files'); const placeholder = searchPlaceholder || gettext('Search files');
if (isPro) { if (isPro) {

View File

@@ -1,36 +0,0 @@
import React from 'react';
import PropTypes from 'prop-types';
import CommonToolbar from './common-toolbar';
const propTypes = {
searchPlaceholder: PropTypes.string,
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
};
class GeneralToolbar extends React.Component {
render() {
// todo get repoID?
let { onShowSidePanel, onSearchedClick } = this.props;
return (
<div className="main-panel-north">
<div className="cur-view-toolbar">
<span
className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none"
title="Side Nav Menu"
onClick={onShowSidePanel}>
</span>
</div>
<CommonToolbar
searchPlaceholder={this.props.searchPlaceholder}
onSearchedClick={onSearchedClick}
/>
</div>
);
}
}
GeneralToolbar.propTypes = propTypes;
export default GeneralToolbar;

View File

@@ -0,0 +1,31 @@
import React from 'react';
import PropTypes from 'prop-types';
import Logo from '../logo';
import classnames from 'classnames';
import SideNav from './side-nav';
const propTypes = {
isSidePanelClosed: PropTypes.bool,
curItemID: PropTypes.string.isRequired,
data: PropTypes.array.isRequired,
onCloseSidePanel: PropTypes.func.isRequired,
};
class SettingSidePanel extends React.Component {
render() {
return (
<div className={classnames('side-panel', { 'left-zero': !this.props.isSidePanelClosed })}>
<div className="side-panel-north">
<Logo onCloseSidePanel={this.props.onCloseSidePanel}/>
</div>
<div className="side-panel-center">
<SideNav data={this.props.data} curItemID={this.props.curItemID} />
</div>
</div>
);
}
}
SettingSidePanel.propTypes = propTypes;
export default SettingSidePanel;

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import CommonToolbar from './common-toolbar'; import CommonToolbar from '../toolbar/common-toolbar';
const propTypes = { const propTypes = {
onShowSidePanel: PropTypes.func, onShowSidePanel: PropTypes.func,
@@ -10,7 +10,7 @@ const propTypes = {
showSearch: PropTypes.bool showSearch: PropTypes.bool
}; };
class TopToolbar extends React.Component { class SettingTopToolbar extends React.Component {
render() { render() {
const { onShowSidePanel, onSearchedClick, children, showSearch } = this.props; const { onShowSidePanel, onSearchedClick, children, showSearch } = this.props;
@@ -31,6 +31,6 @@ class TopToolbar extends React.Component {
} }
} }
TopToolbar.propTypes = propTypes; SettingTopToolbar.propTypes = propTypes;
export default TopToolbar; export default SettingTopToolbar;

View File

@@ -5,14 +5,6 @@
flex-direction: column; flex-direction: column;
} }
/* for top bottom layout*/
#header {
background: #fff;
border-bottom: 1px solid #eee;
box-shadow: 0 2px 4px rgba(0,0,0, 10%);
z-index: 100;
}
/* for left right layout */ /* for left right layout */
#main { #main {
flex: 1; flex: 1;
@@ -37,13 +29,6 @@
position: relative; position: relative;
} }
.positioned-top-logo {
position: absolute;
top: .5rem;
left: 1rem;
z-index: 101;
}
.main-panel { .main-panel {
flex: 1 0 78%; flex: 1 0 78%;
display: flex; display: flex;

View File

@@ -7,8 +7,8 @@ body {
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: .5rem 1rem; padding: .5rem 1rem;
flex-shrink: 0; flex-shrink: 0;
} }

View File

@@ -7,8 +7,8 @@ body {
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: .5rem 1rem; padding: .5rem 1rem;
flex-shrink: 0; flex-shrink: 0;
} }

View File

@@ -7,8 +7,8 @@ body {
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: .5rem 1rem; padding: .5rem 1rem;
flex-shrink: 0; flex-shrink: 0;
} }

View File

@@ -5,12 +5,12 @@
width: 100%; width: 100%;
height: 100%; height: 100%;
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
z-index: 1; z-index: 3;
} }
.search-container { .search-container {
position: relative; position: relative;
z-index: 2; z-index: 4;
} }
.search-container.show { .search-container.show {
@@ -298,7 +298,7 @@
.search-container { .search-container {
position: fixed; position: fixed;
z-index: 2; z-index: 4;
top: 5rem; top: 5rem;
left: 0; left: 0;
right: 0; right: 0;

View File

@@ -1,22 +1,26 @@
body { body {
overflow: hidden; overflow: hidden;
} }
#wrapper { #wrapper {
height: 100%; height: 100%;
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: 8px 16px 4px; padding: 8px 16px 4px;
height: 53px; height: 53px;
flex-shrink: 0; flex-shrink: 0;
} }
.shared-dir-view-main { .shared-dir-view-main {
width: calc(100% - 40px); width: calc(100% - 40px);
max-width: 950px; max-width: 950px;
padding: 15px 0 40px; padding: 15px 0 40px;
margin: 0 auto; margin: 0 auto;
} }
.op-bar { .op-bar {
padding: 9px 10px; padding: 9px 10px;
background: #f2f2f2; background: #f2f2f2;
@@ -34,18 +38,22 @@ body {
font-size: 18px; font-size: 18px;
border-radius: 2px; border-radius: 2px;
} }
.sf-view-mode-btn.current-mode { .sf-view-mode-btn.current-mode {
background-color: #ccc; background-color: #ccc;
color: #fff; color: #fff;
} }
.shared-dir-op-btn { .shared-dir-op-btn {
height: 30px; height: 30px;
line-height: 30px; line-height: 30px;
padding: 0 10px; padding: 0 10px;
} }
.shared-dir-upload-btn { .shared-dir-upload-btn {
border: 1px solid #ccc; border: 1px solid #ccc;
} }
.grid-item .action-icon { .grid-item .action-icon {
position: absolute; position: absolute;
top: 10px; top: 10px;

View File

@@ -1,15 +1,18 @@
body { body {
overflow: hidden; overflow: hidden;
} }
#wrapper { #wrapper {
height: 100%; height: 100%;
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: .5rem 1rem; padding: .5rem 1rem;
flex-shrink: 0; flex-shrink: 0;
} }
.content { .content {
max-width: 950px; max-width: 950px;
} }

View File

@@ -1,12 +1,14 @@
body { body {
overflow: hidden; overflow: hidden;
} }
#wrapper { #wrapper {
height: 100%; height: 100%;
} }
.top-header { .top-header {
background: #f4f4f7; background-color: #f8fafd;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid #eee;
padding: .5rem 1rem; padding: .5rem 1rem;
flex-shrink: 0; flex-shrink: 0;
} }
@@ -17,25 +19,30 @@ body {
border: 1px solid #ddd; border: 1px solid #ddd;
margin: 2em auto; margin: 2em auto;
} }
.shared-by .avatar { .shared-by .avatar {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
#upload-link-panel .warning-icon { #upload-link-panel .warning-icon {
color: #f25041; color: #f25041;
font-size: 48px; font-size: 48px;
} }
#upload-link-drop-zone { #upload-link-drop-zone {
background: rgba(255, 152, 0, 0.1); background: rgba(255, 152, 0, 0.1);
border: 2px dashed #ff9800; border: 2px dashed #ff9800;
border-radius: 4px; border-radius: 4px;
padding: 28px 0; padding: 28px 0;
} }
#upload-link-drop-zone .upload-icon { #upload-link-drop-zone .upload-icon {
color: rgba(240, 159, 63, 0.8); color: rgba(240, 159, 63, 0.8);
font-size: 60px; font-size: 60px;
line-height: 1; line-height: 1;
} }
.mh-2 { .mh-2 {
min-height: 2rem; min-height: 2rem;
} }

View File

@@ -15,7 +15,7 @@ import GroupbyService from '../../services/groupby-service';
import { isEsc } from '../../utils/hotkey'; import { isEsc } from '../../utils/hotkey';
import { getEventClassName } from '../../utils/utils'; import { getEventClassName } from '../../utils/utils';
import { generateDefaultGroupby, getDefaultCountType, getGroupbyColumns } from '../../../utils/groupby-utils'; import { generateDefaultGroupby, getDefaultCountType, getGroupbyColumns } from '../../../utils/groupby-utils';
import eventBus from '../../../utils/event-bus'; import eventBus from '../../../../../components/common/event-bus';
import { GROUPBY_ACTION_TYPE, GROUPBY_DATE_GRANULARITY_LIST, GROUPBY_GEOLOCATION_GRANULARITY_LIST } from '../../constants/groupby'; import { GROUPBY_ACTION_TYPE, GROUPBY_DATE_GRANULARITY_LIST, GROUPBY_GEOLOCATION_GRANULARITY_LIST } from '../../constants/groupby';
import { EVENT_BUS_TYPE } from '../../../constants'; import { EVENT_BUS_TYPE } from '../../../constants';
import { gettext } from '../../../utils'; import { gettext } from '../../../utils';

View File

@@ -1,5 +1,5 @@
import { CellType } from '../_basic'; import { CellType } from '../_basic';
import { EVENT_BUS_TYPE } from './event-bus-type'; import { EVENT_BUS_TYPE } from '../../../components/common/event-bus-type';
import TRANSFER_TYPES from './TransferTypes'; import TRANSFER_TYPES from './TransferTypes';
export const CELL_NAVIGATION_MODE = { export const CELL_NAVIGATION_MODE = {

View File

@@ -1,6 +1,6 @@
import metadataAPI from '../api'; import metadataAPI from '../api';
import { UserService, LocalStorage } from './_basic'; import { UserService, LocalStorage } from './_basic';
import EventBus from './utils/event-bus'; import EventBus from '../../components/common/event-bus';
import { username } from '../../utils/constants'; import { username } from '../../utils/constants';
class Context { class Context {

View File

@@ -10,7 +10,6 @@ import ModalPortal from '../../components/modal-portal';
import Group from '../../models/group'; import Group from '../../models/group';
import Repo from '../../models/repo'; import Repo from '../../models/repo';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import CommonToolbar from '../../components/toolbar/common-toolbar';
import CreateRepoDialog from '../../components/dialog/create-repo-dialog'; import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
import GroupMembersDialog from '../../components/dialog/group-members-dialog'; import GroupMembersDialog from '../../components/dialog/group-members-dialog';
import DismissGroupDialog from '../../components/dialog/dismiss-group-dialog'; import DismissGroupDialog from '../../components/dialog/dismiss-group-dialog';
@@ -26,8 +25,6 @@ import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-tool
import '../../css/group-view.css'; import '../../css/group-view.css';
const propTypes = { const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
onGroupChanged: PropTypes.func.isRequired, onGroupChanged: PropTypes.func.isRequired,
groupID: PropTypes.string, groupID: PropTypes.string,
}; };
@@ -430,12 +427,6 @@ class GroupView extends React.Component {
const opList = this.getOpList(); const opList = this.getOpList();
return ( return (
<Fragment> <Fragment>
<div className="main-panel-north border-left-show">
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
</div>
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">

View File

@@ -300,11 +300,4 @@ Content.propTypes = {
data: PropTypes.object.isRequired, data: PropTypes.object.isRequired,
}; };
const InvitationsViewPropTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
};
InvitationsView.propTypes = InvitationsViewPropTypes;
export default InvitationsView; export default InvitationsView;

View File

@@ -29,7 +29,6 @@ class LibContentToolbar extends React.Component {
repoName={this.props.repoName} repoName={this.props.repoName}
currentRepoInfo={this.props.currentRepoInfo} currentRepoInfo={this.props.currentRepoInfo}
onSearchedClick={this.props.onSearchedClick} onSearchedClick={this.props.onSearchedClick}
searchPlaceholder={gettext('Search files')}
/> />
</Fragment> </Fragment>
); );

View File

@@ -16,17 +16,17 @@ import treeHelper from '../../components/tree-view/tree-helper';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import LibDecryptDialog from '../../components/dialog/lib-decrypt-dialog'; import LibDecryptDialog from '../../components/dialog/lib-decrypt-dialog';
import LibContentToolbar from './lib-content-toolbar';
import LibContentContainer from './lib-content-container'; import LibContentContainer from './lib-content-container';
import FileUploader from '../../components/file-uploader/file-uploader'; import FileUploader from '../../components/file-uploader/file-uploader';
import CopyMoveDirentProgressDialog from '../../components/dialog/copy-move-dirent-progress-dialog'; import CopyMoveDirentProgressDialog from '../../components/dialog/copy-move-dirent-progress-dialog';
import DeleteFolderDialog from '../../components/dialog/delete-folder-dialog'; import DeleteFolderDialog from '../../components/dialog/delete-folder-dialog';
import { EVENT_BUS_TYPE } from '../../components/common/event-bus-type';
const propTypes = { const propTypes = {
eventBus: PropTypes.object,
isSidePanelFolded: PropTypes.bool, isSidePanelFolded: PropTypes.bool,
pathPrefix: PropTypes.array.isRequired, pathPrefix: PropTypes.array.isRequired,
onTabNavClick: PropTypes.func.isRequired, onTabNavClick: PropTypes.func.isRequired,
onMenuClick: PropTypes.func.isRequired,
repoID: PropTypes.string, repoID: PropTypes.string,
}; };
@@ -201,10 +201,24 @@ class LibContentView extends React.Component {
componentWillUnmount() { componentWillUnmount() {
window.onpopstate = this.oldonpopstate; window.onpopstate = this.oldonpopstate;
collabServer.unwatchRepo(this.props.repoID, this.onRepoUpdateEvent); collabServer.unwatchRepo(this.props.repoID, this.onRepoUpdateEvent);
this.props.eventBus.dispatch(EVENT_BUS_TYPE.CURRENT_LIBRARY_CHANGED, {
repoID: '',
repoName: '',
path: '',
isViewFile: false,
isLibView: false,
});
} }
componentDidUpdate() { componentDidUpdate() {
this.lastModifyTime = new Date(); this.lastModifyTime = new Date();
this.props.eventBus.dispatch(EVENT_BUS_TYPE.CURRENT_LIBRARY_CHANGED, {
repoID: this.props.repoID,
repoName: this.state.repoName,
path: this.state.path,
isViewFile: this.state.isViewFile,
isLibView: true,
});
} }
onpopstate = (event) => { onpopstate = (event) => {
@@ -2027,45 +2041,6 @@ class LibContentView extends React.Component {
return ( return (
<Fragment> <Fragment>
<div className="main-panel-north border-left-show">
<LibContentToolbar
isViewFile={this.state.isViewFile}
filePermission={this.state.filePermission}
fileTags={this.state.fileTags}
onFileTagChanged={this.onToolbarFileTagChanged}
onSideNavMenuClick={this.props.onMenuClick}
repoID={this.props.repoID}
path={this.state.path}
isDirentSelected={this.state.isDirentSelected}
selectedDirentList={this.state.selectedDirentList}
onItemsMove={this.onMoveItems}
onItemsCopy={this.onCopyItems}
onItemsDelete={this.onDeleteItems}
onItemRename={this.onMainPanelItemRename}
direntList={this.state.direntList}
repoName={this.state.repoName}
repoEncrypted={this.state.repoEncrypted}
isGroupOwnedRepo={this.state.isGroupOwnedRepo}
userPerm={this.state.userPerm}
showShareBtn={showShareBtn}
enableDirPrivateShare={enableDirPrivateShare}
onAddFile={this.onAddFile}
onAddFolder={this.onAddFolder}
onUploadFile={this.onUploadFile}
onUploadFolder={this.onUploadFolder}
currentMode={this.state.currentMode}
switchViewMode={this.switchViewMode}
onSearchedClick={this.onSearchedClick}
isRepoOwner={isRepoOwner}
currentRepoInfo={this.state.currentRepoInfo}
updateDirent={this.updateDirent}
onDirentSelected={this.onDirentSelected}
showDirentDetail={this.showDirentDetail}
unSelectDirent={this.unSelectDirent}
onFilesTagChanged={this.onFileTagChanged}
repoTags={this.state.repoTags}
/>
</div>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<LibContentContainer <LibContentContainer
isSidePanelFolded={this.props.isSidePanelFolded} isSidePanelFolded={this.props.isSidePanelFolded}

View File

@@ -1,5 +1,4 @@
import React, { Component, Fragment } from 'react'; import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cookie from 'react-cookies'; import cookie from 'react-cookies';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { gettext, canAddRepo, canViewOrg } from '../../utils/constants'; import { gettext, canAddRepo, canViewOrg } from '../../utils/constants';
@@ -10,7 +9,6 @@ import Group from '../../models/group';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import ViewModes from '../../components/view-modes'; import ViewModes from '../../components/view-modes';
import ReposSortMenu from '../../components/repos-sort-menu'; import ReposSortMenu from '../../components/repos-sort-menu';
import TopToolbar from '../../components/toolbar/top-toolbar';
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar'; import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
import SortOptionsDialog from '../../components/dialog/sort-options'; import SortOptionsDialog from '../../components/dialog/sort-options';
import GuideForNewDialog from '../../components/dialog/guide-for-new-dialog'; import GuideForNewDialog from '../../components/dialog/guide-for-new-dialog';
@@ -22,11 +20,6 @@ import GroupItem from '../../pages/groups/group-item';
import '../../css/files.css'; import '../../css/files.css';
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired
};
class Libraries extends Component { class Libraries extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -238,11 +231,7 @@ class Libraries extends Component {
}; };
}); });
return ( return (
<Fragment> <>
<TopToolbar
onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick}
/>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">
@@ -365,11 +354,9 @@ class Libraries extends Component {
/> />
)} )}
</div> </div>
</Fragment> </>
); );
} }
} }
Libraries.propTypes = propTypes;
export default Libraries; export default Libraries;

View File

@@ -8,7 +8,6 @@ import { Utils } from '../../utils/utils';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import EmptyTip from '../../components/empty-tip'; import EmptyTip from '../../components/empty-tip';
import CommonToolbar from '../../components/toolbar/common-toolbar';
moment.locale(lang); moment.locale(lang);
@@ -44,9 +43,6 @@ class MyLibsDeleted extends Component {
render() { render() {
return ( return (
<Fragment> <Fragment>
<div className="main-panel-north">
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">
@@ -187,8 +183,4 @@ DeletedRepoItem.propTypes = {
refreshDeletedRepoList: PropTypes.func.isRequired, refreshDeletedRepoList: PropTypes.func.isRequired,
}; };
MyLibsDeleted.propTypes = {
onSearchedClick: PropTypes.func.isRequired,
};
export default MyLibsDeleted; export default MyLibsDeleted;

View File

@@ -1,5 +1,4 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import cookie from 'react-cookies'; import cookie from 'react-cookies';
import { navigate } from '@gatsbyjs/reach-router'; import { navigate } from '@gatsbyjs/reach-router';
import { DropdownToggle, Dropdown, DropdownMenu, DropdownItem } from 'reactstrap'; import { DropdownToggle, Dropdown, DropdownMenu, DropdownItem } from 'reactstrap';
@@ -10,18 +9,12 @@ import toaster from '../../components/toast';
import Repo from '../../models/repo'; import Repo from '../../models/repo';
import Loading from '../../components/loading'; import Loading from '../../components/loading';
import EmptyTip from '../../components/empty-tip'; import EmptyTip from '../../components/empty-tip';
import TopToolbar from '../../components/toolbar/top-toolbar';
import MylibRepoListView from './mylib-repo-list-view'; import MylibRepoListView from './mylib-repo-list-view';
import SortOptionsDialog from '../../components/dialog/sort-options'; import SortOptionsDialog from '../../components/dialog/sort-options';
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar'; import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import CreateRepoDialog from '../../components/dialog/create-repo-dialog'; import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
};
class MyLibraries extends Component { class MyLibraries extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -156,11 +149,6 @@ class MyLibraries extends Component {
const { isDropdownMenuOpen } = this.state; const { isDropdownMenuOpen } = this.state;
return ( return (
<Fragment> <Fragment>
<TopToolbar
onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick}
>
</TopToolbar>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">
@@ -229,6 +217,4 @@ class MyLibraries extends Component {
} }
} }
MyLibraries.propTypes = propTypes;
export default MyLibraries; export default MyLibraries;

View File

@@ -14,7 +14,6 @@ import ShareLinkPermissionSelect from '../../components/dialog/share-link-permis
import ShareAdminLink from '../../components/dialog/share-admin-link'; import ShareAdminLink from '../../components/dialog/share-admin-link';
import SortOptionsDialog from '../../components/dialog/sort-options'; import SortOptionsDialog from '../../components/dialog/sort-options';
import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog'; import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog';
import TopToolbar from '../../components/toolbar/top-toolbar';
import Selector from '../../components/single-selector'; import Selector from '../../components/single-selector';
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar'; import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
@@ -363,11 +362,6 @@ class Item extends Component {
Item.propTypes = itemPropTypes; Item.propTypes = itemPropTypes;
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired
};
const PER_PAGE = 25; const PER_PAGE = 25;
class ShareAdminShareLinks extends Component { class ShareAdminShareLinks extends Component {
@@ -540,11 +534,6 @@ class ShareAdminShareLinks extends Component {
render() { render() {
return ( return (
<Fragment> <Fragment>
<TopToolbar
onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick}
>
</TopToolbar>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path share-upload-nav"> <div className="cur-view-path share-upload-nav">
@@ -600,6 +589,4 @@ class ShareAdminShareLinks extends Component {
} }
} }
ShareAdminShareLinks.propTypes = propTypes;
export default ShareAdminShareLinks; export default ShareAdminShareLinks;

View File

@@ -12,7 +12,6 @@ import EmptyTip from '../../components/empty-tip';
import UploadLink from '../../models/upload-link'; import UploadLink from '../../models/upload-link';
import ShareAdminLink from '../../components/dialog/share-admin-link'; import ShareAdminLink from '../../components/dialog/share-admin-link';
import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog'; import CommonOperationConfirmationDialog from '../../components/dialog/common-operation-confirmation-dialog';
import TopToolbar from '../../components/toolbar/top-toolbar';
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar'; import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
const contentPropTypes = { const contentPropTypes = {
@@ -203,11 +202,6 @@ class Item extends Component {
Item.propTypes = itemPropTypes; Item.propTypes = itemPropTypes;
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired
};
class ShareAdminUploadLinks extends Component { class ShareAdminUploadLinks extends Component {
constructor(props) { constructor(props) {
@@ -273,10 +267,6 @@ class ShareAdminUploadLinks extends Component {
render() { render() {
return ( return (
<Fragment> <Fragment>
<TopToolbar
onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick}
/>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path share-upload-nav"> <div className="cur-view-path share-upload-nav">
@@ -318,6 +308,4 @@ class ShareAdminUploadLinks extends Component {
} }
} }
ShareAdminUploadLinks.propTypes = propTypes;
export default ShareAdminUploadLinks; export default ShareAdminUploadLinks;

View File

@@ -1,30 +0,0 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Account from '../../components/common/account';
const propTypes = {
children: PropTypes.object
};
class MainPanelTopbar extends Component {
render() {
return (
<div className={`main-panel-north ${this.props.children ? 'border-left-show' : ''}`}>
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu"></span>
<div className="operation">
{this.props.children}
</div>
</div>
<div className="common-toolbar">
<Account isAdminPanel={false} />
</div>
</div>
);
}
}
MainPanelTopbar.propTypes = propTypes;
export default MainPanelTopbar;

View File

@@ -1,12 +1,10 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button } from 'reactstrap';
import axios from 'axios'; import axios from 'axios';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { siteRoot, gettext } from '../../utils/constants'; import { siteRoot } from '../../utils/constants';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import MainPanelTopbar from './remote-dir-topbar';
import DirPathBar from './remote-dir-path'; import DirPathBar from './remote-dir-path';
import DirContent from './remote-dir-content'; import DirContent from './remote-dir-content';
@@ -129,20 +127,15 @@ class DirView extends Component {
}; };
render() { render() {
const { loading, errorMsg, const { loading, errorMsg, repoName, direntList, path } = this.state;
repoName, direntList, path, userPerm } = this.state;
const { repoID } = this.props; const { repoID } = this.props;
return ( return (
<Fragment> <Fragment>
<MainPanelTopbar> {/*
<Fragment> <input className="d-none" type="file" onChange={this.onFileInputChange} ref={this.fileInput} />
<input className="d-none" type="file" onChange={this.onFileInputChange} ref={this.fileInput} /> {userPerm === 'rw' && <Button className="operation-item" onClick={this.openFileInput}>{gettext('Upload')}</Button>}
{userPerm === 'rw' && */}
<Button className="operation-item" onClick={this.openFileInput}>{gettext('Upload')}</Button>
}
</Fragment>
</MainPanelTopbar>
<div className="main-panel-center flex-row"> <div className="main-panel-center flex-row">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path align-items-center"> <div className="cur-view-path align-items-center">

View File

@@ -12,13 +12,10 @@ import SharedRepoListView from '../../components/shared-repo-list-view/shared-re
import SortOptionsDialog from '../../components/dialog/sort-options'; import SortOptionsDialog from '../../components/dialog/sort-options';
import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar'; import SingleDropdownToolbar from '../../components/toolbar/single-dropdown-toolbar';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import TopToolbar from '../../components/toolbar/top-toolbar';
import CreateRepoDialog from '../../components/dialog/create-repo-dialog'; import CreateRepoDialog from '../../components/dialog/create-repo-dialog';
import ShareRepoDialog from '../../components/dialog/share-repo-dialog'; import ShareRepoDialog from '../../components/dialog/share-repo-dialog';
const propTypes = { const propTypes = {
onShowSidePanel: PropTypes.func,
onSearchedClick: PropTypes.func,
currentViewMode: PropTypes.string, currentViewMode: PropTypes.string,
inAllLibs: PropTypes.bool, inAllLibs: PropTypes.bool,
repoList: PropTypes.array, repoList: PropTypes.array,
@@ -222,11 +219,6 @@ class PublicSharedView extends React.Component {
return ( return (
<Fragment> <Fragment>
<TopToolbar
onShowSidePanel={this.props.onShowSidePanel}
onSearchedClick={this.props.onSearchedClick}
>
</TopToolbar>
<div className="main-panel-center"> <div className="main-panel-center">
<div className="cur-view-container"> <div className="cur-view-container">
<div className="cur-view-path"> <div className="cur-view-path">

View File

@@ -1,21 +1,14 @@
import React, { Component, Fragment } from 'react'; import React, { Component, Fragment } from 'react';
import PropTypes from 'prop-types';
import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap'; import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
import { gettext, canPublishRepo } from '../../utils/constants'; import { gettext, canPublishRepo } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import toaster from '../../components/toast'; import toaster from '../../components/toast';
import ModalPortal from '../../components/modal-portal'; import ModalPortal from '../../components/modal-portal';
import EmptyTip from '../../components/empty-tip'; import EmptyTip from '../../components/empty-tip';
import CommonToolbar from '../../components/toolbar/common-toolbar';
import AddWikiDialog from '../../components/dialog/add-wiki-dialog'; import AddWikiDialog from '../../components/dialog/add-wiki-dialog';
import wikiAPI from '../../utils/wiki-api'; import wikiAPI from '../../utils/wiki-api';
import WikiCardView from '../../components/wiki-card-view/wiki-card-view'; import WikiCardView from '../../components/wiki-card-view/wiki-card-view';
const propTypes = {
onShowSidePanel: PropTypes.func.isRequired,
onSearchedClick: PropTypes.func.isRequired,
};
class Wikis extends Component { class Wikis extends Component {
constructor(props) { constructor(props) {
super(props); super(props);
@@ -177,12 +170,6 @@ class Wikis extends Component {
render() { render() {
return ( return (
<Fragment> <Fragment>
<div className="main-panel-north border-left-show">
<div className="cur-view-toolbar">
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
</div>
<CommonToolbar onSearchedClick={this.props.onSearchedClick} />
</div>
{this.state.isShowAddDialog && {this.state.isShowAddDialog &&
<ModalPortal> <ModalPortal>
<AddWikiDialog <AddWikiDialog
@@ -242,6 +229,4 @@ class Wikis extends Component {
} }
} }
Wikis.propTypes = propTypes;
export default Wikis; export default Wikis;

View File

@@ -6,10 +6,9 @@ import { Utils } from './utils/utils';
import { isPro, isDBSqlite3, gettext, siteRoot } from './utils/constants'; import { isPro, isDBSqlite3, gettext, siteRoot } from './utils/constants';
import { seafileAPI } from './utils/seafile-api'; import { seafileAPI } from './utils/seafile-api';
import toaster from './components/toast'; import toaster from './components/toast';
import SidePanel from './components/side-panel';
import MainPanel from './components/main-panel'; import MainPanel from './components/main-panel';
import TopToolbar from './components/toolbar/top-toolbar'; import SettingSidePanel from './components/user-settings/setting-side-panel';
import SideNav from './components/user-settings/side-nav'; import SettingTopToolbar from './components/user-settings/setting-top-toolbar';
import UserAvatarForm from './components/user-settings/user-avatar-form'; import UserAvatarForm from './components/user-settings/user-avatar-form';
import UserBasicInfoForm from './components/user-settings/user-basic-info-form'; import UserBasicInfoForm from './components/user-settings/user-basic-info-form';
import WebAPIAuthToken from './components/user-settings/web-api-auth-token'; import WebAPIAuthToken from './components/user-settings/web-api-auth-token';
@@ -124,60 +123,52 @@ class Settings extends React.Component {
render() { render() {
const { isSidePanelClosed } = this.state; const { isSidePanelClosed } = this.state;
return ( return (
<React.Fragment> <div id="main" className="h-100">
<div id="main" className="h-100"> <SettingSidePanel
<SidePanel isSidePanelClosed={isSidePanelClosed}
isSidePanelClosed={isSidePanelClosed} onCloseSidePanel={this.onCloseSidePanel}
onCloseSidePanel={this.onCloseSidePanel} data={this.sideNavItems}
> curItemID={this.state.curItemID}
<SideNav data={this.sideNavItems} curItemID={this.state.curItemID} /> />
</SidePanel> <MainPanel>
<MainPanel> <SettingTopToolbar onShowSidePanel={this.onShowSidePanel} showSearch={false} />
<> <div className="main-panel-center flex-row">
<TopToolbar <div className="cur-view-container">
onShowSidePanel={this.onShowSidePanel} <div className="cur-view-path">
showSearch={false} <h3 className="sf-heading m-0">{gettext('Settings')}</h3>
>
</TopToolbar>
<div className="main-panel-center flex-row">
<div className="cur-view-container">
<div className="cur-view-path">
<h3 className="sf-heading m-0">{gettext('Settings')}</h3>
</div>
<div className="cur-view-content content position-relative" onScroll={this.handleContentScroll}>
<div id="user-basic-info" className="setting-item">
<h3 className="setting-item-heading">{gettext('Profile Setting')}</h3>
<UserAvatarForm />
{this.state.userInfo && <UserBasicInfoForm userInfo={this.state.userInfo} updateUserInfo={this.updateUserInfo} />}
</div>
{canUpdatePassword &&
<div id="update-user-passwd" className="setting-item">
<h3 className="setting-item-heading">{gettext('Password')}</h3>
<a href={`${siteRoot}accounts/password/change/`} className="btn btn-outline-primary">{passwordOperationText}</a>
</div>
}
{enableGetAuthToken && <WebAPIAuthToken />}
{enableWebdavSecret && <WebdavPassword />}
{enableAddressBook && this.state.userInfo &&
<ListInAddressBook userInfo={this.state.userInfo} updateUserInfo={this.updateUserInfo} />}
<LanguageSetting />
{(isPro || !isDBSqlite3) && <EmailNotice />}
{twoFactorAuthEnabled && <TwoFactorAuthentication />}
{enableWechatWork && <SocialLogin />}
{enableDingtalk && <SocialLoginDingtalk />}
{(enableADFS || (enableMultiADFS && isOrgContext)) && <SocialLoginSAML />}
<LinkedDevices />
{enableDeleteAccount && <DeleteAccount />}
</div>
</div>
</div> </div>
</> <div className="cur-view-content content position-relative" onScroll={this.handleContentScroll}>
</MainPanel> <div id="user-basic-info" className="setting-item">
<MediaQuery query="(max-width: 767.8px)"> <h3 className="setting-item-heading">{gettext('Profile Setting')}</h3>
<Modal zIndex="1030" isOpen={!isSidePanelClosed} toggle={this.toggleSidePanel} contentClassName="d-none"></Modal> <UserAvatarForm />
</MediaQuery> {this.state.userInfo && <UserBasicInfoForm userInfo={this.state.userInfo} updateUserInfo={this.updateUserInfo} />}
</div> </div>
</React.Fragment> {canUpdatePassword &&
<div id="update-user-passwd" className="setting-item">
<h3 className="setting-item-heading">{gettext('Password')}</h3>
<a href={`${siteRoot}accounts/password/change/`} className="btn btn-outline-primary">{passwordOperationText}</a>
</div>
}
{enableGetAuthToken && <WebAPIAuthToken />}
{enableWebdavSecret && <WebdavPassword />}
{enableAddressBook && this.state.userInfo &&
<ListInAddressBook userInfo={this.state.userInfo} updateUserInfo={this.updateUserInfo} />}
<LanguageSetting />
{(isPro || !isDBSqlite3) && <EmailNotice />}
{twoFactorAuthEnabled && <TwoFactorAuthentication />}
{enableWechatWork && <SocialLogin />}
{enableDingtalk && <SocialLoginDingtalk />}
{(enableADFS || (enableMultiADFS && isOrgContext)) && <SocialLoginSAML />}
<LinkedDevices />
{enableDeleteAccount && <DeleteAccount />}
</div>
</div>
</div>
</MainPanel>
<MediaQuery query="(max-width: 767.8px)">
<Modal zIndex="1030" isOpen={!isSidePanelClosed} toggle={this.toggleSidePanel} contentClassName="d-none"></Modal>
</MediaQuery>
</div>
); );
} }
} }

View File

@@ -1188,15 +1188,13 @@ a.sf-popover-item {
} }
/********** Container ***********/ /********** Container ***********/
#header { #header {
background: #fff; background-color: #f8fafd;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
box-shadow: 0 2px 4px rgba(0,0,0, 10%);
z-index: 100; z-index: 100;
width: 100%; width: 100%;
height: 49px; height: 49px;
font-size: 14px; font-size: 14px;
padding: .5rem 1rem; padding: .5rem 1rem;
/*display:flex;*/
justify-content: space-between; justify-content: space-between;
flex-shrink: 0; flex-shrink: 0;
} }
@@ -1399,9 +1397,9 @@ a.sf-popover-item {
/*** separate pages ***/ /*** separate pages ***/
/* login */ /* login */
#lang { #lang {
font-weight:normal; font-weight: normal;
font-size:13px; font-size: 13px;
margin-top:12px; margin-top: 12px;
} }
#lang-context:hover { #lang-context:hover {
text-decoration:none; text-decoration:none;