mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 17:02:47 +00:00
adaptation mobile (#2938)
* adaptation mobile * improve style * repair naming bug
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component, Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import MediaQuery from 'react-responsive';
|
||||||
import { siteRoot } from '../../utils/constants';
|
import { siteRoot } from '../../utils/constants';
|
||||||
import SearchResultItem from './search-result-item';
|
import SearchResultItem from './search-result-item';
|
||||||
import editorUtilities from '../../utils/editor-utilties';
|
import editorUtilities from '../../utils/editor-utilties';
|
||||||
@@ -22,7 +23,8 @@ class Search extends Component {
|
|||||||
isMaskShow: false,
|
isMaskShow: false,
|
||||||
isResultShow: false,
|
isResultShow: false,
|
||||||
isResultGetted: false,
|
isResultGetted: false,
|
||||||
isCloseShow: false
|
isCloseShow: false,
|
||||||
|
isSearchInputShow: false, // for mobile
|
||||||
};
|
};
|
||||||
this.inputValue = '';
|
this.inputValue = '';
|
||||||
this.source = null; // used to cancel request;
|
this.source = null; // used to cancel request;
|
||||||
@@ -161,7 +163,8 @@ class Search extends Component {
|
|||||||
isCloseShow: false,
|
isCloseShow: false,
|
||||||
isResultShow: false,
|
isResultShow: false,
|
||||||
isResultGetted: false,
|
isResultGetted: false,
|
||||||
resultItems: []
|
resultItems: [],
|
||||||
|
isSearchInputShow: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,10 +215,19 @@ class Search extends Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSearchToggle = () => {
|
||||||
|
this.setState({
|
||||||
|
isSearchInputShow: !this.state.isSearchInputShow,
|
||||||
|
isMaskShow: !this.state.isMaskShow,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let width = this.state.width !== 'default' ? this.state.width : '';
|
let width = this.state.width !== 'default' ? this.state.width : '';
|
||||||
let style = {'width': width};
|
let style = {'width': width};
|
||||||
return (
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<MediaQuery query="(min-width: 768px)">
|
||||||
<div className="search">
|
<div className="search">
|
||||||
<div className={`search-mask ${this.state.isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
<div className={`search-mask ${this.state.isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
||||||
<div className="search-container">
|
<div className="search-container">
|
||||||
@@ -239,6 +251,38 @@ class Search extends Component {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery query="(max-width: 768px)">
|
||||||
|
<div className="search-icon-container">
|
||||||
|
<i className="search-icon fas fa-search" onClick={this.onSearchToggle}></i>
|
||||||
|
</div>
|
||||||
|
{this.state.isSearchInputShow &&
|
||||||
|
<div className="search">
|
||||||
|
<div className={`search-mask ${this.state.isMaskShow ? '' : 'hide'}`} onClick={this.onCloseHandler}></div>
|
||||||
|
<div className="search-container">
|
||||||
|
<div className="input-icon">
|
||||||
|
<i className="search-icon-left input-icon-addon fas fa-search"></i>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className="form-control search-input"
|
||||||
|
name="query"
|
||||||
|
placeholder={this.props.placeholder}
|
||||||
|
style={style}
|
||||||
|
value={this.state.value}
|
||||||
|
onFocus={this.onFocusHandler}
|
||||||
|
onChange={this.onChangeHandler}
|
||||||
|
autoComplete="off"
|
||||||
|
/>
|
||||||
|
{this.state.isCloseShow && <i className='search-icon-right input-icon-addon fas fa-times' onClick={this.onCloseHandler}></i>}
|
||||||
|
</div>
|
||||||
|
<div className="search-result-container">
|
||||||
|
{this.renderSearchResult()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</MediaQuery>
|
||||||
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import React, { Fragment } from 'react';
|
import React, { Fragment } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import MediaQuery from 'react-responsive';
|
||||||
import { Link } from '@reach/router';
|
import { Link } from '@reach/router';
|
||||||
import { siteRoot, gettext } from '../../utils/constants';
|
import { siteRoot, gettext } from '../../utils/constants';
|
||||||
import ModalPortal from '../modal-portal';
|
import ModalPortal from '../modal-portal';
|
||||||
@@ -41,6 +42,7 @@ class RepoViewToolbar extends React.Component {
|
|||||||
<Fragment>
|
<Fragment>
|
||||||
<div className="cur-view-toolbar border-left-show">
|
<div className="cur-view-toolbar border-left-show">
|
||||||
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
|
<span className="sf2-icon-menu side-nav-toggle hidden-md-up d-md-none" title="Side Nav Menu" onClick={this.props.onShowSidePanel}></span>
|
||||||
|
<MediaQuery query="(min-width: 768px)">
|
||||||
<div className="operation">
|
<div className="operation">
|
||||||
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateToggle}>
|
<button className="btn btn-secondary operation-item" title={gettext('New Library')} onClick={this.onCreateToggle}>
|
||||||
<i className="fas fa-plus-square text-secondary mr-1"></i>{gettext('New Library')}
|
<i className="fas fa-plus-square text-secondary mr-1"></i>{gettext('New Library')}
|
||||||
@@ -58,6 +60,10 @@ class RepoViewToolbar extends React.Component {
|
|||||||
</Dropdown>
|
</Dropdown>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</MediaQuery>
|
||||||
|
<MediaQuery query="(max-width: 768px)">
|
||||||
|
<span className="sf2-icon-plus mobile-toolbar-icon" title={gettext('New Library')} onClick={this.onCreateToggle}></span>
|
||||||
|
</MediaQuery>
|
||||||
</div>
|
</div>
|
||||||
{this.state.isCreateRepoDialogShow && (
|
{this.state.isCreateRepoDialogShow && (
|
||||||
<ModalPortal>
|
<ModalPortal>
|
||||||
|
@@ -53,6 +53,16 @@
|
|||||||
border-bottom: 1px solid #e8e8e8;
|
border-bottom: 1px solid #e8e8e8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.side-panel-north {
|
||||||
|
border-right: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.main-panel-north {
|
||||||
|
padding-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.side-panel-center,
|
.side-panel-center,
|
||||||
.main-panel-center {
|
.main-panel-center {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@@ -85,3 +85,45 @@
|
|||||||
.item-content .item-text b {
|
.item-content .item-text b {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.common-toolbar .search {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon-container {
|
||||||
|
display: flex;
|
||||||
|
width: 2rem;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
line-height: 1;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 2;
|
||||||
|
top: 5rem;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-input {
|
||||||
|
height: 2.5rem;
|
||||||
|
width: 20rem !important;
|
||||||
|
box-shadow: 5px 5px 5px #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-result-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 2.5rem;
|
||||||
|
left: auto;
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -241,11 +241,11 @@ class MylibRepoListItem extends React.Component {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{!this.state.isRenaming && repo.repo_name && (
|
{!this.state.isRenaming && repo.repo_name && (
|
||||||
<Link to={repoURL}>{repo.repo_name}</Link>
|
<div><Link to={repoURL}>{repo.repo_name}</Link></div>
|
||||||
)}
|
)}
|
||||||
{!this.state.isRenaming && !repo.repo_name &&
|
{!this.state.isRenaming && !repo.repo_name &&
|
||||||
(gettext('Broken (please contact your administrator to fix this library)'))
|
<div>(gettext('Broken (please contact your administrator to fix this library)'))</div>
|
||||||
}<br />
|
}
|
||||||
<span className="item-meta-info">{repo.size}</span>
|
<span className="item-meta-info">{repo.size}</span>
|
||||||
<span className="item-meta-info" title={moment(repo.last_modified).format('llll')}>{moment(repo.last_modified).fromNow()}</span>
|
<span className="item-meta-info" title={moment(repo.last_modified).format('llll')}>{moment(repo.last_modified).fromNow()}</span>
|
||||||
</td>
|
</td>
|
||||||
@@ -267,10 +267,10 @@ class MylibRepoListItem extends React.Component {
|
|||||||
let repo = this.props.repo;
|
let repo = this.props.repo;
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<MediaQuery query="(min-device-width: 768px)">
|
<MediaQuery query="(min-width: 768px)">
|
||||||
{this.renderPCUI()}
|
{this.renderPCUI()}
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
<MediaQuery query="(max-device-width: 768px)">
|
<MediaQuery query="(max-width: 768px)">
|
||||||
{this.renderMobileUI()}
|
{this.renderMobileUI()}
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
{this.state.isShareDialogShow && (
|
{this.state.isShareDialogShow && (
|
||||||
|
@@ -98,8 +98,8 @@ class MylibRepoListView extends React.Component {
|
|||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th width="18%"><span className="sr-only">{gettext('Library Type')}</span></th>
|
<th width="10%"><span className="sr-only">{gettext('Library Type')}</span></th>
|
||||||
<th width="76%">
|
<th width="84%">
|
||||||
{gettext('Sort:')}
|
{gettext('Sort:')}
|
||||||
<a className="table-sort-op" href="#" onClick={this.sortByName}>{gettext('name')} {this.props.sortBy === 'name' && sortIcon}</a>
|
<a className="table-sort-op" href="#" onClick={this.sortByName}>{gettext('name')} {this.props.sortBy === 'name' && sortIcon}</a>
|
||||||
<a className="table-sort-op" href="#" onClick={this.sortByTime}>{gettext('last update')} {this.props.sortBy === 'time' && sortIcon}</a>
|
<a className="table-sort-op" href="#" onClick={this.sortByTime}>{gettext('last update')} {this.props.sortBy === 'time' && sortIcon}</a>
|
||||||
@@ -117,10 +117,10 @@ class MylibRepoListView extends React.Component {
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<MediaQuery query="(min-device-width: 768px)">
|
<MediaQuery query="(min-width: 768px)">
|
||||||
{this.renderPCUI()}
|
{this.renderPCUI()}
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
<MediaQuery query="(max-device-width: 768px)">
|
<MediaQuery query="(max-width: 768px)">
|
||||||
{this.renderMobileUI()}
|
{this.renderMobileUI()}
|
||||||
</MediaQuery>
|
</MediaQuery>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@@ -140,7 +140,7 @@ class MylibRepoMenu extends React.Component {
|
|||||||
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
<Dropdown isOpen={this.state.isItemMenuShow} toggle={this.toggleOperationMenu}>
|
||||||
<DropdownToggle
|
<DropdownToggle
|
||||||
tag="i"
|
tag="i"
|
||||||
className="sf-dropdown-toggle sf2-icon-caret-down"
|
className="sf-dropdown-toggle sf2-icon-caret-down ml-0"
|
||||||
title={gettext('More Operations')}
|
title={gettext('More Operations')}
|
||||||
// onClick={this.clickOperationMenuToggle}
|
// onClick={this.clickOperationMenuToggle}
|
||||||
data-toggle="dropdown"
|
data-toggle="dropdown"
|
||||||
@@ -150,7 +150,7 @@ class MylibRepoMenu extends React.Component {
|
|||||||
<div className="mobile-operation-menu-bg-layer"></div>
|
<div className="mobile-operation-menu-bg-layer"></div>
|
||||||
<div className="mobile-operation-menu">
|
<div className="mobile-operation-menu">
|
||||||
{operations.map((item, index) => {
|
{operations.map((item, index) => {
|
||||||
return (<DropdownItem key={index} data-toggle={item} onClick={this.onMenuItemClick}>{this.translateOperations(item)}</DropdownItem>);
|
return (<DropdownItem key={index} className="mobile-menu-item" data-toggle={item} onClick={this.onMenuItemClick}>{this.translateOperations(item)}</DropdownItem>);
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -210,8 +210,6 @@ ul,ol,li {
|
|||||||
|
|
||||||
.side-nav-toggle { /* just for control side-panel */
|
.side-nav-toggle { /* just for control side-panel */
|
||||||
margin-right:0.9375rem;
|
margin-right:0.9375rem;
|
||||||
height: 1.875rem;
|
|
||||||
line-height: 1.875rem;
|
|
||||||
font-size:1.5rem;
|
font-size:1.5rem;
|
||||||
color:#999;
|
color:#999;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -325,14 +323,14 @@ ul,ol,li {
|
|||||||
|
|
||||||
.action-icon,
|
.action-icon,
|
||||||
.attr-action-icon {
|
.attr-action-icon {
|
||||||
color:#888;
|
color:#888 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-icon:focus,
|
.action-icon:focus,
|
||||||
.action-icon:hover,
|
.action-icon:hover,
|
||||||
.attr-action-icon:focus,
|
.attr-action-icon:focus,
|
||||||
.attr-action-icon:hover {
|
.attr-action-icon:hover {
|
||||||
color: #333;
|
color: #333 !important;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -785,11 +783,6 @@ a.sf-popover-item:hover {
|
|||||||
.side-panel-top {
|
.side-panel-top {
|
||||||
padding: .5rem 1rem;
|
padding: .5rem 1rem;
|
||||||
}
|
}
|
||||||
@media (max-width: 767px) {
|
|
||||||
.side-panel-top {
|
|
||||||
border-right: 1px solid #eee;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.side-panel-close {
|
.side-panel-close {
|
||||||
margin:10px 0 0 auto;
|
margin:10px 0 0 auto;
|
||||||
}
|
}
|
||||||
@@ -905,6 +898,12 @@ table td {
|
|||||||
color: green;
|
color: green;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
|
.rename-container input {
|
||||||
|
width: 10rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* table-item loading-more-data */
|
/* table-item loading-more-data */
|
||||||
.list-show-more {
|
.list-show-more {
|
||||||
padding: 0.25rem 0.75rem;
|
padding: 0.25rem 0.75rem;
|
||||||
@@ -1025,6 +1024,13 @@ a.table-sort-op:focus {
|
|||||||
margin-left: 0.5rem;
|
margin-left: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* thumbnail */
|
||||||
|
.thumbnail {
|
||||||
|
max-width: 24px;
|
||||||
|
max-height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 767px) {
|
||||||
/* mobile menu */
|
/* mobile menu */
|
||||||
.item-meta-info {
|
.item-meta-info {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@@ -1055,9 +1061,18 @@ a.table-sort-op:focus {
|
|||||||
z-index: 4;
|
z-index: 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* thumbnail */
|
/* toolbar icon */
|
||||||
.thumbnail {
|
.mobile-toolbar-icon {
|
||||||
max-width: 24px;
|
color: #999;
|
||||||
max-height: 24px;
|
font-size: 1.375rem;
|
||||||
|
margin-right: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mobile-menu-item {
|
||||||
|
color: #000;
|
||||||
|
line-height: 2rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user