1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-05 08:53:14 +00:00

[long name] fixup for UIs with long library/folder/file names (#5971)

* [long name] fixup for UIs with long library/folder/file names

* fixed code indentation
This commit is contained in:
llj
2024-03-07 15:37:09 +08:00
committed by GitHub
parent 9281a14634
commit 046aa47022
24 changed files with 112 additions and 84 deletions

View File

@@ -95,12 +95,13 @@ class ChangeRepoPasswordDialog extends React.Component {
render() { render() {
const { repoName, toggleDialog } = this.props; const { repoName, toggleDialog } = this.props;
let title = gettext('Change Password of Library {placeholder}');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<Modal isOpen={true} style={{height: 'auto'}} toggle={toggleDialog}> <Modal isOpen={true} style={{height: 'auto'}} toggle={toggleDialog}>
<ModalHeader toggle={toggleDialog}> <ModalHeader toggle={toggleDialog}>
<span> <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
{Utils.generateDialogTitle(gettext('Change Password of Library {placeholder}'), repoName)}
</span>
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<form id="repo-change-passwd-form" action="" method="post"> <form id="repo-change-passwd-form" action="" method="post">

View File

@@ -91,7 +91,7 @@ class Content extends React.Component {
<ul> <ul>
{ {
data[item.type].map((item, index) => { data[item.type].map((item, index) => {
return <li key={index} dangerouslySetInnerHTML={{__html: item}} className="commit-detail-item"></li>; return <li key={index} dangerouslySetInnerHTML={{__html: item}} className="commit-detail-item text-truncate"></li>;
}) })
} }
</ul> </ul>

View File

@@ -140,14 +140,17 @@ class CopyDirent extends React.Component {
render() { render() {
let title = gettext('Copy {placeholder} to'); let title = gettext('Copy {placeholder} to');
if (!this.props.isMutipleOperation) { if (!this.props.isMutipleOperation) {
title = title.replace('{placeholder}', '<span class="op-target">' + Utils.HTMLescape(this.props.dirent.name) + '</span>'); title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(this.props.dirent.name) + '</span>');
} else { } else {
title = gettext('Copy selected item(s) to:'); title = gettext('Copy selected item(s) to:');
} }
let mode = 'current_repo_and_other_repos'; let mode = 'current_repo_and_other_repos';
const { isMutipleOperation } = this.props;
return ( return (
<Modal isOpen={true} toggle={this.toggle}> <Modal isOpen={true} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}><div dangerouslySetInnerHTML={{__html: title}}></div></ModalHeader> <ModalHeader toggle={this.toggle}>
{isMutipleOperation ? title : <div dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></div>}
</ModalHeader>
<ModalBody> <ModalBody>
<FileChooser <FileChooser
repoID={this.props.repoID} repoID={this.props.repoID}

View File

@@ -108,12 +108,13 @@ class LibHistorySetting extends React.Component {
}; };
render() { render() {
const itemName = this.props.itemName; const { itemName: repoName } = this.props;
let title = gettext('{placeholder} History Setting');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<Modal isOpen={true} toggle={this.props.toggleDialog}> <Modal isOpen={true} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}> <ModalHeader toggle={this.props.toggleDialog}>
<span className="op-target" title={itemName}>{itemName}</span>{' '} <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
{gettext('History Setting')}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<Form> <Form>

View File

@@ -66,11 +66,13 @@ class LibSubFolderPermissionDialog extends React.Component {
render() { render() {
const { repoName, folderName } = this.props; const { repoName, folderName } = this.props;
let title = repoName ? gettext('{placeholder} Folder Permission') : gettext('Set permission of {placeholder}');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName || folderName) + '</span>');
return ( return (
<div> <div>
<Modal isOpen={true} style={{maxWidth: '980px'}} className="share-dialog" toggle={this.props.toggleDialog}> <Modal isOpen={true} style={{maxWidth: '980px'}} className="share-dialog" toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}> <ModalHeader toggle={this.props.toggleDialog}>
<span>{repoName ? Utils.generateDialogTitle(gettext('{placeholder} Folder Permission'), repoName) : Utils.generateDialogTitle(gettext('Set {placeholder}\'s permission'), folderName)}</span> <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
</ModalHeader> </ModalHeader>
<ModalBody className="dialog-list-container share-dialog-content" role="tablist"> <ModalBody className="dialog-list-container share-dialog-content" role="tablist">
{this.renderContent()} {this.renderContent()}

View File

@@ -90,7 +90,7 @@ const propTypes = {
repoID: PropTypes.string.isRequired, repoID: PropTypes.string.isRequired,
isDepartmentRepo: PropTypes.bool, isDepartmentRepo: PropTypes.bool,
folderPath: PropTypes.string.isRequired, folderPath: PropTypes.string.isRequired,
repoName: PropTypes.string.isRequired, repoName: PropTypes.string,
}; };

View File

@@ -154,12 +154,12 @@ class MoveDirent extends React.Component {
render() { render() {
let title = gettext('Move {placeholder} to'); let title = gettext('Move {placeholder} to');
if (!this.props.isMutipleOperation) { if (!this.props.isMutipleOperation) {
title = title.replace('{placeholder}', '<span class="op-target">' + Utils.HTMLescape(this.props.dirent.name) + '</span>'); title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(this.props.dirent.name) + '</span>');
} else { } else {
title = gettext('Move selected item(s) to:'); title = gettext('Move selected item(s) to:');
} }
let mode = 'current_repo_and_other_repos'; let mode = 'current_repo_and_other_repos';
const { dirent, selectedDirentList } = this.props; const { dirent, selectedDirentList, isMutipleOperation } = this.props;
const movedDirent = dirent ? dirent : selectedDirentList[0]; const movedDirent = dirent ? dirent : selectedDirentList[0];
const { permission } = movedDirent; const { permission } = movedDirent;
const { isCustomPermission } = Utils.getUserPermission(permission); const { isCustomPermission } = Utils.getUserPermission(permission);
@@ -168,7 +168,9 @@ class MoveDirent extends React.Component {
} }
return ( return (
<Modal isOpen={true} toggle={this.toggle}> <Modal isOpen={true} toggle={this.toggle}>
<ModalHeader toggle={this.toggle}><div dangerouslySetInnerHTML={{__html: title}}></div></ModalHeader> <ModalHeader toggle={this.toggle}>
{isMutipleOperation ? title : <div dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></div>}
</ModalHeader>
<ModalBody> <ModalBody>
<FileChooser <FileChooser
repoID={this.props.repoID} repoID={this.props.repoID}

View File

@@ -281,7 +281,7 @@ class RepoAPITokenDialog extends React.Component {
render() { render() {
let repo = this.repo; let repo = this.repo;
const itemName = '<span class="op-target">' + Utils.HTMLescape(repo.repo_name) + '</span>'; const itemName = '<span class="op-target text-truncate mr-1">' + Utils.HTMLescape(repo.repo_name) + '</span>';
const title = gettext('{placeholder} API Token').replace('{placeholder}', itemName); const title = gettext('{placeholder} API Token').replace('{placeholder}', itemName);
return ( return (
<Modal <Modal
@@ -289,7 +289,7 @@ class RepoAPITokenDialog extends React.Component {
toggle={this.props.onRepoAPITokenToggle} toggle={this.props.onRepoAPITokenToggle}
> >
<ModalHeader toggle={this.props.onRepoAPITokenToggle}> <ModalHeader toggle={this.props.onRepoAPITokenToggle}>
<p dangerouslySetInnerHTML={{__html: title}} className="m-0"></p> <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<div className="o-auto"> <div className="o-auto">

View File

@@ -2,6 +2,7 @@ import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap'; import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import { gettext, canGenerateShareLink, canGenerateUploadLink } from '../../utils/constants'; import { gettext, canGenerateShareLink, canGenerateUploadLink } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import RepoShareAdminShareLinks from './repo-share-admin/share-links'; import RepoShareAdminShareLinks from './repo-share-admin/share-links';
import RepoShareAdminUploadLinks from './repo-share-admin/upload-links'; import RepoShareAdminUploadLinks from './repo-share-admin/upload-links';
import RepoShareAdminUserShares from './repo-share-admin/user-shares'; import RepoShareAdminUserShares from './repo-share-admin/user-shares';
@@ -48,12 +49,13 @@ class RepoShareAdminDialog extends React.Component {
render() { render() {
const { activeTab } = this.state; const { activeTab } = this.state;
const { repo_name: repoName } = this.props.repo; const { repo_name: repoName } = this.props.repo;
let title = gettext('{placeholder} Share Admin');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<div> <div>
<Modal isOpen={true} style={{maxWidth: '760px'}} className="share-dialog" toggle={this.props.toggleDialog}> <Modal isOpen={true} style={{maxWidth: '760px'}} className="share-dialog" toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}> <ModalHeader toggle={this.props.toggleDialog}>
<span className="op-target" title={repoName}>{repoName}</span> {gettext('Share Admin')} <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
</ModalHeader> </ModalHeader>
<ModalBody className="dialog-list-container share-dialog-content" role="tablist"> <ModalBody className="dialog-list-container share-dialog-content" role="tablist">
<Fragment> <Fragment>

View File

@@ -106,12 +106,13 @@ class SysAdminLibHistorySettingDialog extends React.Component {
}; };
render() { render() {
const itemName = this.props.itemName; const { itemName: repoName } = this.props;
let title = gettext('{placeholder} History Setting');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<Modal isOpen={true} toggle={this.props.toggleDialog}> <Modal isOpen={true} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}> <ModalHeader toggle={this.props.toggleDialog}>
<span className="op-target" title={itemName}>{itemName}</span>{' '} <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
{gettext('History Setting')}
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
<Form> <Form>

View File

@@ -60,15 +60,19 @@ class TransferDialog extends React.Component {
}; };
render() { render() {
const itemName = this.props.itemName;
let canTransferToDept = true; let canTransferToDept = true;
if (this.props.canTransferToDept != undefined) { if (this.props.canTransferToDept != undefined) {
canTransferToDept = this.props.canTransferToDept; canTransferToDept = this.props.canTransferToDept;
} }
const { itemName: repoName } = this.props;
let title = gettext('Transfer Library {library_name}');
title = title.replace('{library_name}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<Modal isOpen={true} toggle={this.props.toggleDialog}> <Modal isOpen={true} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}> <ModalHeader toggle={this.props.toggleDialog}>
<span>{gettext('Transfer Library {library_name}').replace('{library_name}', itemName)}</span> <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
</ModalHeader> </ModalHeader>
<ModalBody> <ModalBody>
{this.state.transferToUser ? {this.state.transferToUser ?

View File

@@ -82,7 +82,7 @@ class RepoListItem extends React.Component {
let errMessage = Utils.getErrorMsg(error); let errMessage = Utils.getErrorMsg(error);
toaster.danger(errMessage); toaster.danger(errMessage);
}); });
} };
addResponseListToNode = (list, node) => { addResponseListToNode = (list, node) => {
node.isLoaded = true; node.isLoaded = true;

View File

@@ -30,9 +30,9 @@ class FileInfo extends React.PureComponent {
const starredText = isStarred ? gettext('starred') : gettext('unstarred'); const starredText = isStarred ? gettext('starred') : gettext('unstarred');
const lockedText = gettext('locked'); const lockedText = gettext('locked');
return ( return (
<div> <div className="text-truncate">
<h2 className="file-title d-flex align-items-center"> <h2 className="file-title d-flex align-items-center">
<span className="file-name">{fileName}</span> <span className="file-name text-truncate" title={fileName}>{fileName}</span>
<a className={`file-star ${isStarred ? 'fa' : 'far'} fa-star`} <a className={`file-star ${isStarred ? 'fa' : 'far'} fa-star`}
href="#" href="#"
title={starredText} title={starredText}

View File

@@ -113,7 +113,7 @@ class FileToolbar extends React.Component {
return ( return (
<Fragment> <Fragment>
<ButtonGroup className="d-none d-md-block"> <ButtonGroup className="d-none d-md-block flex-shrink-0 ml-4">
{fileType == 'PDF' && ( {fileType == 'PDF' && (
<IconButton <IconButton
id="seafile-pdf-print" id="seafile-pdf-print"
@@ -202,7 +202,7 @@ class FileToolbar extends React.Component {
</ButtonDropdown> </ButtonDropdown>
</ButtonGroup> </ButtonGroup>
<Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle} className="d-block d-md-none"> <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle} className="d-block d-md-none flex-shrink-0 ml-4">
<ButtonGroup > <ButtonGroup >
{(canEditFile && fileType != 'SDoc' && !err) && {(canEditFile && fileType != 'SDoc' && !err) &&
(this.props.isSaving ? (this.props.isSaving ?

View File

@@ -7,7 +7,7 @@ const {
function Download() { function Download() {
return ( return (
<a href={`${siteRoot}repo/${repoID}/${objID}/download/?file_name=${encodeURIComponent(fileName)}&p=${encodeURIComponent(path)}`} className="btn btn-secondary">{gettext('Download')}</a> <a href={`${siteRoot}repo/${repoID}/${objID}/download/?file_name=${encodeURIComponent(fileName)}&p=${encodeURIComponent(path)}`} className="btn btn-secondary flex-shrink-0">{gettext('Download')}</a>
); );
} }

View File

@@ -26,10 +26,10 @@ class FileView extends React.Component {
render() { render() {
return ( return (
<div className="h-100 d-flex flex-column flex-1"> <div className="h-100 d-flex flex-column flex-1 mw-100">
<div className="file-view-header d-flex justify-content-between align-items-center"> <div className="file-view-header d-flex justify-content-between align-items-center">
<div> <div className="text-truncate mr-4">
<h2 className="file-title">{fileName}</h2> <h2 className="file-title text-truncate" title={fileName}>{fileName}</h2>
<p className="meta-info m-0">{fromTrash ? `${gettext('Current Path: ')}${gettext('Trash')}`: commitTime}</p> <p className="meta-info m-0">{fromTrash ? `${gettext('Current Path: ')}${gettext('Trash')}`: commitTime}</p>
</div> </div>
{canDownloadFile && <Download />} {canDownloadFile && <Download />}

View File

@@ -116,14 +116,14 @@ class SharedFileView extends React.Component {
</div> </div>
<div className="shared-file-view-md-main"> <div className="shared-file-view-md-main">
<div className={`shared-file-view-head ${(fileType == 'md' || fileType == 'pdf') ? 'w-100 px-4' : ''}`}> <div className={`shared-file-view-head ${(fileType == 'md' || fileType == 'pdf') ? 'w-100 px-4' : ''}`}>
<div className="float-left"> <div className="text-truncate">
<h2 className="ellipsis" title={fileName}>{fileName}</h2> <h2 className="ellipsis" title={fileName}>{fileName}</h2>
{zipped ? {zipped ?
<p className="m-0">{gettext('Current path: ')}{this.renderPath()}</p> : <p className="m-0">{gettext('Current path: ')}{this.renderPath()}</p> :
<p className="share-by ellipsis">{gettext('Shared by:')}{' '}{sharedBy}</p> <p className="share-by ellipsis">{gettext('Shared by:')}{' '}{sharedBy}</p>
} }
</div> </div>
<div className="float-right"> <div className="flex-shrink-0 ml-4">
{(canDownload && loginUser && (loginUser !== sharedBy)) && {(canDownload && loginUser && (loginUser !== sharedBy)) &&
<Button color="secondary" id="save" <Button color="secondary" id="save"
onClick={this.handleSaveSharedFileDialog}>{gettext('Save as ...')} onClick={this.handleSaveSharedFileDialog}>{gettext('Save as ...')}

View File

@@ -48,13 +48,13 @@ class FileHistory extends React.Component {
render() { render() {
return ( return (
<div className="history-content flex-fill d-flex h-100"> <div className="history-content flex-fill d-flex h-100">
<div className="flex-fill d-flex flex-column"> <div className="flex-fill d-flex flex-column text-truncate">
<div className="history-header file-history-header flex-shrink-0"> <div className="history-header file-history-header flex-shrink-0">
<div className="title"> <div className="title d-flex mw-100">
<a href="#" className="go-back" title="Back" onClick={this.onBackClick}> <a href="#" className="go-back" title="Back" onClick={this.onBackClick}>
<span className="fas fa-chevron-left"></span> <span className="fas fa-chevron-left"></span>
</a> </a>
<span className="name">{fileName}</span> <span className="name text-truncate" title={fileName}>{fileName}</span>
</div> </div>
</div> </div>
<MainPanel <MainPanel

View File

@@ -16,32 +16,30 @@ class FileInfo extends React.PureComponent {
const lockedText = gettext('locked'); const lockedText = gettext('locked');
return ( return (
<div className="file-info-wrapper"> <div className="topbar-file-info text-truncate ml-0 mr-4">
<div className="topbar-file-info"> <div className="file-title">
<div className="file-title"> <span className='file-name text-truncate'>{fileInfo.name}</span>
<span className='file-name'>{fileInfo.name}</span> <span className="file-star" title={starTitle}>
<span className="file-star" title={starTitle}> <i className={starIconClass} onClick={this.props.toggleStar}/>
<i className={starIconClass} onClick={this.props.toggleStar}/> </span>
</span> <InternalLinkOperation path={filePath} repoID={repoID} />
<InternalLinkOperation path={filePath} repoID={repoID} /> {(isPro && isLocked) && (
{(isPro && isLocked) && ( <img
<img className="file-locked-icon mx-2"
className="file-locked-icon mx-2" width="16"
width="16" src={`${mediaUrl}img/file-locked-32.png`}
src={`${mediaUrl}img/file-locked-32.png`} alt={lockedText}
alt={lockedText} title={lockedText}
title={lockedText} aria-label={lockedText}
aria-label={lockedText} />
/> )}
)} </div>
</div> <div className="file-state">
<div className="file-state"> <span className={'file-modifier-name'}>{fileInfo.lastModifier}</span>
<span className={'file-modifier-name'}>{fileInfo.lastModifier}</span> <span className={'file-modifier-time'}>{modifyTime}</span>
<span className={'file-modifier-time'}>{modifyTime}</span> {this.props.showDraftSaved && (
{this.props.showDraftSaved && ( <span className={'file-modifier-savedraft'}>{gettext('Local draft saved')}</span>
<span className={'file-modifier-savedraft'}>{gettext('Local draft saved')}</span> )}
)}
</div>
</div> </div>
</div> </div>
); );

View File

@@ -63,7 +63,7 @@ class HeaderToolbar extends React.Component {
if (this.props.editorMode === 'rich') { if (this.props.editorMode === 'rich') {
return ( return (
<div className="sf-md-viewer-topbar"> <div className="sf-md-viewer-topbar">
<div className="sf-md-viewer-topbar-first d-flex justify-content-between"> <div className="sf-md-viewer-topbar-first d-flex justify-content-between mw-100">
<FileInfo <FileInfo
toggleStar={this.props.toggleStar} toggleStar={this.props.toggleStar}
editorApi={this.props.editorApi} editorApi={this.props.editorApi}

View File

@@ -160,21 +160,21 @@ class RepoFolderTrash extends React.Component {
const pathList = this.state.folderPath.split('/'); const pathList = this.state.folderPath.split('/');
return ( return (
<React.Fragment> <React.Fragment>
<a href="#" onClick={this.clickRoot}>{repoFolderName}</a> <a href="#" onClick={this.clickRoot} className="text-truncate" title={repoFolderName}>{repoFolderName}</a>
<span> / </span> <span className="mx-1">/</span>
{pathList.map((item, index) => { {pathList.map((item, index) => {
if (index > 0 && index != pathList.length - 1) { if (index > 0 && index != pathList.length - 1) {
return ( return (
<React.Fragment key={index}> <React.Fragment key={index}>
<a href="#" onClick={this.clickFolderPath.bind(this, pathList.slice(0, index+1).join('/'))}>{pathList[index]}</a> <a className="text-truncate" href="#" onClick={this.clickFolderPath.bind(this, pathList.slice(0, index+1).join('/'))} title={pathList[index]}>{pathList[index]}</a>
<span> / </span> <span className="mx-1">/</span>
</React.Fragment> </React.Fragment>
); );
} }
return null; return null;
} }
)} )}
{pathList[pathList.length - 1]} <span className="text-truncate" title={pathList[pathList.length - 1]}>{pathList[pathList.length - 1]}</span>
</React.Fragment> </React.Fragment>
); );
}; };
@@ -182,6 +182,9 @@ class RepoFolderTrash extends React.Component {
render() { render() {
const { isCleanTrashDialogOpen, showFolder } = this.state; const { isCleanTrashDialogOpen, showFolder } = this.state;
let title = gettext('{placeholder} Trash');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoFolderName) + '</span>');
return ( return (
<React.Fragment> <React.Fragment>
<div className="h-100 d-flex flex-column"> <div className="h-100 d-flex flex-column">
@@ -194,14 +197,14 @@ class RepoFolderTrash extends React.Component {
<div className="flex-auto container-fluid pt-4 pb-6 o-auto"> <div className="flex-auto container-fluid pt-4 pb-6 o-auto">
<div className="row"> <div className="row">
<div className="col-md-10 offset-md-1"> <div className="col-md-10 offset-md-1">
<h2>{Utils.generateDialogTitle(gettext('{placeholder} Trash'), repoFolderName)}</h2> <h2 dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></h2>
<a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role={gettext('Back')}> <a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role={gettext('Back')}>
<span className="fas fa-chevron-left"></span> <span className="fas fa-chevron-left"></span>
</a> </a>
<div className="d-flex justify-content-between align-items-center op-bar"> <div className="d-flex justify-content-between align-items-center op-bar">
<p className="m-0">{gettext('Current path: ')}{showFolder ? this.renderFolderPath() : repoFolderName}</p> <p className="m-0 text-truncate d-flex"><span className="mr-1">{gettext('Current path: ')}</span>{showFolder ? this.renderFolderPath() : <span className="text-truncate" title={repoFolderName}>{repoFolderName}</span>}</p>
{(path == '/' && enableClean && !showFolder) && {(path == '/' && enableClean && !showFolder) &&
<button className="btn btn-secondary clean" onClick={this.cleanTrash}>{gettext('Clean')}</button> <button className="btn btn-secondary clean flex-shrink-0 ml-4" onClick={this.cleanTrash}>{gettext('Clean')}</button>
} }
</div> </div>
<Content <Content

View File

@@ -93,6 +93,9 @@ class RepoHistory extends React.Component {
}; };
render() { render() {
let title = gettext('{placeholder} Modification History');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<React.Fragment> <React.Fragment>
<div className="h-100 d-flex flex-column"> <div className="h-100 d-flex flex-column">
@@ -105,7 +108,7 @@ class RepoHistory extends React.Component {
<div className="flex-auto container-fluid pt-4 pb-6 o-auto"> <div className="flex-auto container-fluid pt-4 pb-6 o-auto">
<div className="row"> <div className="row">
<div className="col-md-10 offset-md-1"> <div className="col-md-10 offset-md-1">
<h2>{Utils.generateDialogTitle(gettext('{placeholder} Modification History'), repoName)}</h2> <h2 dangerouslySetInnerHTML={{__html: title}} className="d-flex text-nowrap"></h2>
<a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role="button" aria-label={gettext('Back')}> <a href="#" className="go-back" title={gettext('Back')} onClick={this.goBack} role="button" aria-label={gettext('Back')}>
<span className="fas fa-chevron-left"></span> <span className="fas fa-chevron-left"></span>
</a> </a>

View File

@@ -91,26 +91,26 @@ class RepoSnapshot extends React.Component {
const pathList = path.split('/'); const pathList = path.split('/');
if (path == '/') { if (path == '/') {
return repoName; return <span className="text-truncate" title={repoName}>{repoName}</span>;
} }
return ( return (
<React.Fragment> <React.Fragment>
<a href="#" onClick={this.clickFolderPath.bind(this, '/')}>{repoName}</a> <a href="#" onClick={this.clickFolderPath.bind(this, '/')} className="text-truncate" title={repoName}>{repoName}</a>
<span> / </span> <span className="mx-1">/</span>
{pathList.map((item, index) => { {pathList.map((item, index) => {
if (index > 0 && index != pathList.length - 1) { if (index > 0 && index != pathList.length - 1) {
return ( return (
<React.Fragment key={index}> <React.Fragment key={index}>
<a href="#" onClick={this.clickFolderPath.bind(this, pathList.slice(0, index+1).join('/'))}>{pathList[index]}</a> <a href="#" onClick={this.clickFolderPath.bind(this, pathList.slice(0, index+1).join('/'))} className="text-truncate" title={pathList[index]}>{pathList[index]}</a>
<span> / </span> <span className="mx-1">/</span>
</React.Fragment> </React.Fragment>
); );
} }
return null; return null;
} }
)} )}
{pathList[pathList.length - 1]} <span className="text-truncate" title={pathList[pathList.length - 1]}>{pathList[pathList.length - 1]}</span>
</React.Fragment> </React.Fragment>
); );
}; };
@@ -129,6 +129,8 @@ class RepoSnapshot extends React.Component {
render() { render() {
const { isConfirmDialogOpen, folderPath } = this.state; const { isConfirmDialogOpen, folderPath } = this.state;
let title = gettext('{placeholder} Snapshot');
title = title.replace('{placeholder}', '<span class="op-target text-truncate mx-1">' + Utils.HTMLescape(repoName) + '</span>');
return ( return (
<React.Fragment> <React.Fragment>
<div className="h-100 d-flex flex-column"> <div className="h-100 d-flex flex-column">
@@ -142,7 +144,7 @@ class RepoSnapshot extends React.Component {
<div className="row"> <div className="row">
<div className="col-md-10 offset-md-1"> <div className="col-md-10 offset-md-1">
<h2> <h2>
<span>{Utils.generateDialogTitle(gettext('{placeholder} Snapshot'), repoName)}</span> <span dangerouslySetInnerHTML={{__html: title}} className="d-flex mw-100"></span>
<span className="heading-commit-time ml-1">({commitTime})</span> <span className="heading-commit-time ml-1">({commitTime})</span>
</h2> </h2>
<a href="#" className="go-back" title={gettext('Back')} role="button" aria-label={gettext('Back')} onClick={this.goBack}> <a href="#" className="go-back" title={gettext('Back')} role="button" aria-label={gettext('Back')} onClick={this.goBack}>
@@ -150,8 +152,8 @@ class RepoSnapshot extends React.Component {
</a> </a>
{folderPath == '/' && ( {folderPath == '/' && (
<div className="d-flex mb-2 align-items-center"> <div className="d-flex mb-2 align-items-center">
<p className="m-0">{commitDesc}</p> <p className="m-0 text-truncate" title={commitDesc}>{commitDesc}</p>
<div className="ml-4 border-left pl-4 d-flex align-items-center"> <div className="ml-4 border-left pl-4 d-flex align-items-center flex-shrink-0">
{showAuthor ? ( {showAuthor ? (
<React.Fragment> <React.Fragment>
<img src={authorAvatarURL} width="20" height="20" alt="" className="rounded mr-1" /> <img src={authorAvatarURL} width="20" height="20" alt="" className="rounded mr-1" />
@@ -163,9 +165,9 @@ class RepoSnapshot extends React.Component {
</div> </div>
)} )}
<div className="d-flex justify-content-between align-items-center op-bar"> <div className="d-flex justify-content-between align-items-center op-bar">
<p className="m-0">{gettext('Current path: ')}{this.renderPath()}</p> <p className="m-0 text-truncate d-flex"><span className="mr-1">{gettext('Current path: ')}</span>{this.renderPath()}</p>
{(folderPath == '/' && canRestoreRepo) && {(folderPath == '/' && canRestoreRepo) &&
<button className="btn btn-secondary op-bar-btn" onClick={this.toggleDialog}>{gettext('Restore')}</button> <button className="btn btn-secondary op-bar-btn flex-shrink-0 ml-4" onClick={this.toggleDialog}>{gettext('Restore')}</button>
} }
</div> </div>
<Content <Content

View File

@@ -1260,3 +1260,9 @@ a.table-sort-op:hover {
#wiki-file-content .seafile-markdown-outline .seafile-markdown-outline:hover { #wiki-file-content .seafile-markdown-outline .seafile-markdown-outline:hover {
overflow-y: auto; overflow-y: auto;
} }
.modal-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}