1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-15 06:44:16 +00:00

Fix mobile UI in wiki trash dialog and share dialog (#7612)

* 01 change mobile wiki trash dialog

* 02 share dialog support mobile use

* 03 fix share to group click outside
This commit is contained in:
Michael An
2025-03-15 10:02:56 +08:00
committed by GitHub
parent f46070e76d
commit f1050952dd
4 changed files with 172 additions and 39 deletions

View File

@@ -2,7 +2,6 @@ import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import SearchInput from '../../search-input';
import ClickOutside from '../../click-outside';
import Option from './option';
import KeyCodes from '../../../constants/keyCodes';
@@ -26,6 +25,7 @@ class SelectOptionGroup extends Component {
componentDidMount() {
window.addEventListener('keydown', this.onHotKey);
document.addEventListener('mousedown', this.handleDocumentClick);
setTimeout(() => {
this.resetMenuStyle();
}, 1);
@@ -35,8 +35,13 @@ class SelectOptionGroup extends Component {
this.filterOptions = null;
this.timer && clearTimeout(this.timer);
window.removeEventListener('keydown', this.onHotKey);
document.removeEventListener('mousedown', this.handleDocumentClick);
}
handleDocumentClick = (e) => {
this.props.onClickOutside(e);
};
resetMenuStyle = () => {
const { isInModal, position } = this.props;
const { top, height } = this.optionGroupRef.getBoundingClientRect();
@@ -170,7 +175,6 @@ class SelectOptionGroup extends Component {
};
}
return (
<ClickOutside onClickOutside={this.props.onClickOutside}>
<div
className={classnames('pt-0 option-group', className ? 'option-group-' + className : '')}
ref={(ref) => this.optionGroupRef = ref}
@@ -190,7 +194,6 @@ class SelectOptionGroup extends Component {
{this.renderOptGroup(searchVal)}
</div>
</div>
</ClickOutside>
);
}
}

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { Button } from 'reactstrap';
import { gettext, isPro, enableShareToDepartment } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import { Utils, isMobile } from '../../utils/utils';
import toaster from '../toast';
import SharePermissionEditor from '../select-editor/share-permission-editor';
import EventBus from '../common/event-bus';
@@ -40,6 +40,36 @@ class GroupItem extends React.Component {
render() {
let item = this.props.item;
let currentPermission = Utils.getSharedPermission(item);
if (isMobile) {
return (
<tr>
<td className='name'>{item.group_info.name}</td>
<td>
<SharePermissionEditor
repoID={this.props.repoID}
isTextMode={true}
autoFocus={true}
isEditIconShow={this.state.isOperationShow}
currentPermission={currentPermission}
permissions={this.props.permissions}
onPermissionChanged={this.onChangeUserPermission}
/>
</td>
<td>
<span
tabIndex="0"
role="button"
className='sf2-icon-x3 action-icon'
onClick={this.deleteShareItem}
onKeyDown={Utils.onKeyDown}
title={gettext('Delete')}
aria-label={gettext('Delete')}
>
</span>
</td>
</tr>
);
}
return (
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} tabIndex="0" onFocus={this.onMouseEnter}>
<td className='name'>{item.group_info.name}</td>
@@ -352,7 +382,7 @@ class ShareToGroup extends React.Component {
};
render() {
const thead = (
let thead = (
<thead>
<tr>
<th width="47%">{gettext('Group')}</th>
@@ -361,9 +391,20 @@ class ShareToGroup extends React.Component {
</tr>
</thead>
);
if (isMobile) {
thead = (
<thead>
<tr>
<th width="43%">{gettext('Group')}</th>
<th width="35%">{gettext('Permission')}</th>
<th width="22%"></th>
</tr>
</thead>
);
}
return (
<Fragment>
<table className="w-xs-200">
<table>
{thead}
<tbody>
<tr>
@@ -392,7 +433,7 @@ class ShareToGroup extends React.Component {
/>
</td>
<td>
<Button color="primary" onClick={this.shareToGroup}>{gettext('Submit')}</Button>
<Button color="primary" onClick={this.shareToGroup} size={isMobile ? 'sm' : 'md'}>{gettext('Submit')}</Button>
</td>
</tr>
{this.state.errorMsg.length > 0 &&
@@ -408,7 +449,7 @@ class ShareToGroup extends React.Component {
</tbody>
</table>
<div className="share-list-container">
<table className="table-thead-hidden w-xs-200">
<table className="table-thead-hidden">
{thead}
<GroupList
repoID={this.props.repoID}

View File

@@ -4,7 +4,7 @@ import classnames from 'classnames';
import { gettext, isPro, cloudMode, isOrgContext } from '../../utils/constants';
import { Button } from 'reactstrap';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import { Utils, isMobile } from '../../utils/utils';
import toaster from '../toast';
import UserSelect from '../user-select';
import SharePermissionEditor from '../select-editor/share-permission-editor';
@@ -52,6 +52,65 @@ class UserItem extends React.Component {
let item = this.props.item;
let currentPermission = Utils.getSharedPermission(item);
const { isUserDetailsPopoverOpen } = this.state;
if (isMobile) {
return (
<tr>
<td className="name">
<div className="position-relative d-flex align-items-center">
<img
src={item.user_info.avatar_url}
width="24"
alt={item.user_info.nickname}
className="rounded-circle mr-2 cursor-pointer"
onMouseEnter={this.userAvatarOnMouseEnter}
onMouseLeave={this.userAvatarOnMouseLeave}
/>
<span>{item.user_info.nickname}</span>
{isUserDetailsPopoverOpen && (
<div className="user-details-popover p-4 position-absolute w-100 mt-1">
<div className="user-details-main pb-3">
<img
src={item.user_info.avatar_url}
width="40"
alt={item.user_info.nickname}
className="rounded-circle mr-2"
/>
<span className="user-details-name">{item.user_info.nickname}</span>
</div>
<dl className="m-0 mt-3 d-flex">
<dt className="m-0 mr-3">{gettext('Email')}</dt>
<dd className="m-0">{item.user_info.contact_email}</dd>
</dl>
</div>
)}
</div>
</td>
<td>
<SharePermissionEditor
repoID={this.props.repoID}
isTextMode={true}
autoFocus={true}
isEditIconShow={true}
currentPermission={currentPermission}
permissions={this.props.permissions}
onPermissionChanged={this.onChangeUserPermission}
/>
</td>
<td>
<span
tabIndex="0"
role="button"
className='sf2-icon-x3 action-icon'
onClick={this.deleteShareItem}
onKeyDown={Utils.onKeyDown}
title={gettext('Delete')}
aria-label={gettext('Delete')}
>
</span>
</td>
</tr>
);
}
return (
<tr onMouseEnter={this.onMouseEnter} onMouseLeave={this.onMouseLeave} tabIndex="0" onFocus={this.onMouseEnter}>
<td className="name">
@@ -438,7 +497,7 @@ class ShareToUser extends React.Component {
showDeptBtn = false;
}
let { sharedItems } = this.state;
const thead = (
let thead = (
<thead>
<tr>
<th width="47%">{gettext('User')}</th>
@@ -447,9 +506,20 @@ class ShareToUser extends React.Component {
</tr>
</thead>
);
if (isMobile) {
thead = (
<thead>
<tr>
<th width="43%">{gettext('User')}</th>
<th width="35%">{gettext('Permission')}</th>
<th width="22%"></th>
</tr>
</thead>
);
}
return (
<div className="share-link-container">
<table className="w-xs-200">
<table>
{thead}
<tbody>
<tr>
@@ -485,7 +555,7 @@ class ShareToUser extends React.Component {
/>
</td>
<td>
<Button color="primary" onClick={this.shareToUser}>{gettext('Submit')}</Button>
<Button color="primary" onClick={this.shareToUser} size={isMobile ? 'sm' : 'md'}>{gettext('Submit')}</Button>
</td>
</tr>
{this.state.errorMsg.length > 0 &&
@@ -506,7 +576,7 @@ class ShareToUser extends React.Component {
</tbody>
</table>
<div className="share-list-container">
<table className="table-thead-hidden w-xs-200">
<table className="table-thead-hidden">
{thead}
<UserList
repoID={this.props.repoID}

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';
import { Modal, ModalBody, ModalHeader } from 'reactstrap';
import dayjs from 'dayjs';
import { Utils } from '../../utils/utils';
import { Utils, isMobile } from '../../utils/utils';
import { gettext, wikiId } from '../../utils/constants';
import wikiAPI from '../../utils/wiki-api';
import ModalPortal from '../../components/modal-portal';
@@ -137,6 +137,14 @@ class Content extends React.Component {
constructor(props) {
super(props);
if (isMobile) {
this.theadData = [
{ width: '30%', text: gettext('Name') },
{ width: '20%', text: gettext('Size') },
{ width: '30%', text: gettext('Delete Time') },
{ width: '20%', text: '' }
];
} else {
this.theadData = [
{ width: '5%', text: gettext('Name') },
{ width: '20%', text: '' },
@@ -145,6 +153,7 @@ class Content extends React.Component {
{ width: '10%', text: '' }
];
}
}
getPreviousPage = () => {
this.props.getListByPage(this.props.currentPage - 1);
@@ -251,6 +260,16 @@ class Item extends React.Component {
return null;
}
const { isAdmin } = window.wiki.config;
if (isMobile) {
return (
<tr>
<td>{item.name}</td>
<td>{Utils.bytesToSize(item.size)}</td>
<td title={dayjs(item.deleted_time).format('dddd, MMMM D, YYYY h:mm:ss A')}>{dayjs(item.deleted_time).format('YYYY-MM-DD')}</td>
<td>{isAdmin && <a href="#" onClick={this.restoreItem} role="button">{gettext('Restore')}</a>}</td>
</tr>
);
}
return (
<tr onMouseOver={this.handleMouseOver} onMouseOut={this.handleMouseOut} onFocus={this.handleMouseOver}>
<td><NavItemIcon symbol={'file'} disable={true} /></td>