1
0
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:
杨顺强
2019-02-13 18:09:01 +08:00
committed by Daniel Pan
parent 0b00d00006
commit 2430b4fb4f
8 changed files with 210 additions and 93 deletions

View File

@@ -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>
); );
} }
} }

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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 && (

View File

@@ -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>

View File

@@ -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>

View File

@@ -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;
}
} }