mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 00:43:53 +00:00
Change select style (#5645)
* 01 change css file path * 02 change Select style
This commit is contained in:
@@ -5,7 +5,7 @@ import { gettext } from '../../utils/constants';
|
||||
import NoticeItem from './notice-item';
|
||||
import UserNotificationsDialog from '../../user-notifications';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import './notification.css';
|
||||
import '../../css/notification.css';
|
||||
|
||||
class Notification extends React.Component {
|
||||
constructor(props) {
|
||||
|
5
frontend/src/components/common/select/index.js
Normal file
5
frontend/src/components/common/select/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
import SeahubSelect from './seahub-select';
|
||||
import { NoGroupMessage } from './no-group-message';
|
||||
import { MenuSelectStyle, UserSelectStyle } from './seahub-select-style';
|
||||
|
||||
export { SeahubSelect, NoGroupMessage, MenuSelectStyle, UserSelectStyle };
|
15
frontend/src/components/common/select/no-group-message.js
Normal file
15
frontend/src/components/common/select/no-group-message.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
|
||||
const NoGroupMessage = (props) => {
|
||||
return (
|
||||
<div {...props.innerProps} style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('Group not found')}</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoGroupMessage.propTypes = {
|
||||
innerProps: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
export { NoGroupMessage };
|
49
frontend/src/components/common/select/seahub-select-style.js
Normal file
49
frontend/src/components/common/select/seahub-select-style.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const MenuSelectStyle = {
|
||||
option: (provided, state) => {
|
||||
const { isDisabled, isSelected, isFocused } = state;
|
||||
return ({
|
||||
...provided,
|
||||
cursor: isDisabled ? 'default' : 'pointer',
|
||||
backgroundColor: isSelected ? '#20a0ff' : (isFocused ? '#f5f5f5' : '#fff'),
|
||||
'.header-icon .dtable-font': {
|
||||
color: isSelected ? '#fff' : '#aaa',
|
||||
},
|
||||
});
|
||||
},
|
||||
control: (provided) => ({
|
||||
...provided,
|
||||
fontSize: '14px',
|
||||
cursor: 'pointer',
|
||||
lineHeight: '1.5',
|
||||
}),
|
||||
menuPortal: base => ({ ...base, zIndex: 9999 }),
|
||||
indicatorSeparator: () => {},
|
||||
};
|
||||
|
||||
const UserSelectStyle = {
|
||||
option: (provided, state) => {
|
||||
const { isDisabled, isFocused } = state;
|
||||
return ({
|
||||
...provided,
|
||||
cursor: isDisabled ? 'default' : 'pointer',
|
||||
backgroundColor: isFocused ? '#f5f5f5' : '#fff',
|
||||
});
|
||||
},
|
||||
control: (provided) => ({
|
||||
...provided,
|
||||
fontSize: '14px',
|
||||
cursor: 'pointer',
|
||||
lineHeight: '1.5',
|
||||
}),
|
||||
indicatorSeparator: () => ({
|
||||
display: 'none',
|
||||
}),
|
||||
dropdownIndicator: () => ({
|
||||
display: 'none',
|
||||
}),
|
||||
clearIndicator: () => ({
|
||||
display: 'none',
|
||||
}),
|
||||
};
|
||||
|
||||
export { MenuSelectStyle, UserSelectStyle };
|
110
frontend/src/components/common/select/seahub-select.js
Normal file
110
frontend/src/components/common/select/seahub-select.js
Normal file
@@ -0,0 +1,110 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select, { components, createFilter } from 'react-select';
|
||||
import { MenuSelectStyle } from './seahub-select-style';
|
||||
|
||||
const ClearIndicator = ({ innerProps, ...props }) => {
|
||||
const onMouseDown = e => {
|
||||
e.nativeEvent.stopImmediatePropagation();
|
||||
innerProps.onMouseDown(e);
|
||||
};
|
||||
props.innerProps = { ...innerProps, onMouseDown };
|
||||
return <components.ClearIndicator {...props} />;
|
||||
};
|
||||
|
||||
ClearIndicator.propTypes = {
|
||||
innerProps: PropTypes.object,
|
||||
};
|
||||
|
||||
const MenuList = (props) => (
|
||||
<div onClick={e => e.nativeEvent.stopImmediatePropagation()} onMouseDown={e => e.nativeEvent.stopImmediatePropagation()} >
|
||||
<components.MenuList {...props}>{props.children}</components.MenuList>
|
||||
</div>
|
||||
);
|
||||
|
||||
MenuList.propTypes = {
|
||||
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
};
|
||||
|
||||
const Option = props => {
|
||||
return (
|
||||
<div style={props.data.style}>
|
||||
<components.Option {...props} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Option.propTypes = {
|
||||
data: PropTypes.shape({
|
||||
style: PropTypes.object,
|
||||
}),
|
||||
};
|
||||
|
||||
export default class SeahubSelect extends React.Component {
|
||||
|
||||
static propTypes = {
|
||||
isMulti: PropTypes.bool,
|
||||
options: PropTypes.array.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.string]),
|
||||
isSearchable: PropTypes.bool,
|
||||
isClearable: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
classNamePrefix: PropTypes.string,
|
||||
form: PropTypes.string,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
menuPortalTarget: PropTypes.string,
|
||||
menuPosition: PropTypes.string,
|
||||
noOptionsMessage: PropTypes.func,
|
||||
innerRef: PropTypes.object,
|
||||
isDisabled: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
options: [],
|
||||
value: {},
|
||||
isDisabled: false,
|
||||
isSearchable: false,
|
||||
isClearable: false,
|
||||
placeholder: '',
|
||||
isMulti: false,
|
||||
menuPortalTarget: '.modal',
|
||||
noOptionsMessage: () => {
|
||||
return null;
|
||||
},
|
||||
};
|
||||
|
||||
getMenuPortalTarget = () => {
|
||||
return document.querySelector(this.props.menuPortalTarget);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { options, onChange, value, isSearchable, placeholder, isMulti, menuPosition, isClearable, noOptionsMessage,
|
||||
classNamePrefix, innerRef, isDisabled, form } = this.props;
|
||||
return (
|
||||
<Select
|
||||
value={value}
|
||||
isDisabled={isDisabled}
|
||||
ref={innerRef}
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
isMulti={isMulti}
|
||||
classNamePrefix={classNamePrefix}
|
||||
styles={MenuSelectStyle}
|
||||
components={{ Option, MenuList, ClearIndicator }}
|
||||
filterOption={createFilter({
|
||||
matchFrom: 'any',
|
||||
stringify: option => `${option.data.labelValue}`,
|
||||
})}
|
||||
placeholder={placeholder}
|
||||
isSearchable={isSearchable}
|
||||
isClearable={isClearable}
|
||||
menuPosition={menuPosition || 'fixed'} // when use default menuPosition(absolute), menuPortalTarget is unnecessary.
|
||||
menuShouldScrollIntoView
|
||||
menuPortalTarget={this.getMenuPortalTarget()}
|
||||
captureMenuScroll={false}
|
||||
noOptionsMessage={noOptionsMessage}
|
||||
form={form}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Alert } from 'reactstrap';
|
||||
import { gettext, enableEncryptedLibrary, repoPasswordMinLength, storages, libraryTemplates } from '../../utils/constants';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
const propTypes = {
|
||||
libraryType: PropTypes.string.isRequired,
|
||||
@@ -189,9 +189,8 @@ class CreateRepoDialog extends React.Component {
|
||||
|
||||
{libraryTemplates.length > 0 && (
|
||||
<FormGroup>
|
||||
<Label for="library-template">{gettext('Template')}</Label>
|
||||
<Select
|
||||
id="library-template"
|
||||
<Label>{gettext('Template')}</Label>
|
||||
<SeahubSelect
|
||||
defaultValue={{value: libraryTemplates[0], label: libraryTemplates[0]}}
|
||||
options={libraryTemplates.map((item, index) => { return {value: item, label: item}; })}
|
||||
onChange={this.handlelibraryTemplatesInputChange}
|
||||
@@ -201,9 +200,8 @@ class CreateRepoDialog extends React.Component {
|
||||
|
||||
{storages.length > 0 && (
|
||||
<FormGroup>
|
||||
<Label for="storage-backend">{gettext('Storage Backend')}</Label>
|
||||
<Select
|
||||
id="storage-backend"
|
||||
<Label>{gettext('Storage Backend')}</Label>
|
||||
<SeahubSelect
|
||||
defaultValue={{value: storages[0].id, label: storages[0].name}}
|
||||
options={storages.map((item, index) => { return {value: item.id, label: item.name}; })}
|
||||
onChange={this.handleStorageInputChange}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap';
|
||||
import Select from 'react-select';
|
||||
import { gettext, isPro, siteRoot } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import SharePermissionEditor from '../select-editor/share-permission-editor';
|
||||
import FileChooser from '../file-chooser/file-chooser';
|
||||
import { SeahubSelect, NoGroupMessage } from '../common/select';
|
||||
|
||||
class GroupItem extends React.Component {
|
||||
|
||||
@@ -93,16 +93,6 @@ const propTypes = {
|
||||
folderPath: PropTypes.string,
|
||||
};
|
||||
|
||||
const NoOptionsMessage = (props) => {
|
||||
return (
|
||||
<div {...props.innerProps} style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('Group not found')}</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoOptionsMessage.propTypes = {
|
||||
innerProps: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
class LibSubFolderSerGroupPermissionDialog extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -306,14 +296,13 @@ class LibSubFolderSerGroupPermissionDialog extends React.Component {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Select
|
||||
<SeahubSelect
|
||||
onChange={this.handleSelectChange}
|
||||
options={this.options}
|
||||
placeholder={gettext('Select a group')}
|
||||
maxMenuHeight={200}
|
||||
inputId={'react-select-2-input'}
|
||||
value={this.state.selectedOption}
|
||||
components={{ NoOptionsMessage }}
|
||||
components={{ NoOptionsMessage: NoGroupMessage }}
|
||||
/>
|
||||
</td>
|
||||
{showPath &&
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'reactstrap';
|
||||
import Select from 'react-select';
|
||||
import { gettext, isPro, enableShareToDepartment } from '../../utils/constants';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import SharePermissionEditor from '../select-editor/share-permission-editor';
|
||||
import { SeahubSelect, NoGroupMessage } from '../common/select';
|
||||
|
||||
class GroupItem extends React.Component {
|
||||
|
||||
@@ -117,16 +117,6 @@ const propTypes = {
|
||||
onAddCustomPermissionToggle: PropTypes.func,
|
||||
};
|
||||
|
||||
const NoOptionsMessage = (props) => {
|
||||
return (
|
||||
<div {...props.innerProps} style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('Group not found')}</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoOptionsMessage.propTypes = {
|
||||
innerProps: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
class ShareToGroup extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -340,15 +330,13 @@ class ShareToGroup extends React.Component {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Select
|
||||
isMulti
|
||||
<SeahubSelect
|
||||
onChange={this.handleSelectChange}
|
||||
options={this.state.options}
|
||||
placeholder={gettext('Select groups...')}
|
||||
maxMenuHeight={200}
|
||||
inputId={'react-select-2-input'}
|
||||
value={this.state.selectedOption}
|
||||
components={{ NoOptionsMessage }}
|
||||
components={{ NoOptionsMessage: NoGroupMessage }}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
|
@@ -1,14 +1,13 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import Select from 'react-select';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext, ocmRemoteServers } from '../../utils/constants';
|
||||
import { Input } from 'reactstrap';
|
||||
import { Button } from 'reactstrap';
|
||||
import { Input, Button } from 'reactstrap';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import OpIcon from '../op-icon';
|
||||
import SharePermissionEditor from '../select-editor/share-permission-editor';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
class ShareItem extends React.Component {
|
||||
|
||||
@@ -228,7 +227,7 @@ class ShareToOtherServer extends React.Component {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Select
|
||||
<SeahubSelect
|
||||
placeholder={gettext('Select a server...')}
|
||||
value={selectedServer}
|
||||
options={ocmRemoteServers}
|
||||
|
@@ -1,12 +1,12 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button } from 'reactstrap';
|
||||
import Select from 'react-select';
|
||||
import { isPro, gettext } from '../../../utils/constants';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import toaster from '../../toast';
|
||||
import SharePermissionEditor from '../../select-editor/share-permission-editor';
|
||||
import { SeahubSelect, NoGroupMessage } from '../common/select';
|
||||
|
||||
class GroupItem extends React.Component {
|
||||
|
||||
@@ -109,16 +109,6 @@ const propTypes = {
|
||||
isRepoOwner: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
const NoOptionsMessage = (props) => {
|
||||
return (
|
||||
<div {...props.innerProps} style={{margin: '6px 10px', textAlign: 'center', color: 'hsl(0,0%,50%)'}}>{gettext('Group not found')}</div>
|
||||
);
|
||||
};
|
||||
|
||||
NoOptionsMessage.propTypes = {
|
||||
innerProps: PropTypes.any.isRequired,
|
||||
};
|
||||
|
||||
class SysAdminShareToGroup extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
@@ -257,15 +247,13 @@ class SysAdminShareToGroup extends React.Component {
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<Select
|
||||
isMulti
|
||||
<SeahubSelect
|
||||
onChange={this.handleSelectChange}
|
||||
options={this.options}
|
||||
placeholder={gettext('Select groups...')}
|
||||
maxMenuHeight={200}
|
||||
inputId={'react-select-2-input'}
|
||||
value={this.state.selectedOption}
|
||||
components={{ NoOptionsMessage }}
|
||||
components={{ NoOptionsMessage: NoGroupMessage }}
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
|
||||
import Select from 'react-select';
|
||||
import makeAnimated from 'react-select/animated';
|
||||
import { seafileAPI } from '../../utils/seafile-api';
|
||||
import { gettext, isPro } from '../../utils/constants';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import UserSelect from '../user-select';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
const propTypes = {
|
||||
itemName: PropTypes.string.isRequired,
|
||||
@@ -79,9 +79,8 @@ class TransferDialog extends React.Component {
|
||||
placeholder={gettext('Select a user')}
|
||||
onSelectChange={this.handleSelectChange}
|
||||
/> :
|
||||
<Select
|
||||
<SeahubSelect
|
||||
isClearable
|
||||
isMulti={false}
|
||||
maxMenuHeight={200}
|
||||
hideSelectedOptions={true}
|
||||
components={makeAnimated()}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Select from 'react-select';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import OpIcon from '../op-icon';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
const propTypes = {
|
||||
isTextMode: PropTypes.bool.isRequired,
|
||||
@@ -65,7 +65,7 @@ class RepoAPITokenPermissionEditor extends React.Component {
|
||||
}
|
||||
</Fragment>
|
||||
:
|
||||
<Select
|
||||
<SeahubSelect
|
||||
options={this.options}
|
||||
placeholder={optionTranslation}
|
||||
onChange={this.onPermissionChanged}
|
||||
|
@@ -2,6 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import Select from 'react-select';
|
||||
import { MenuSelectStyle } from '../common/select';
|
||||
import '../../css/select-editor.css';
|
||||
|
||||
const propTypes = {
|
||||
@@ -105,29 +106,6 @@ class SelectEditor extends React.Component {
|
||||
|
||||
render() {
|
||||
let { currentOption, isTextMode } = this.props;
|
||||
|
||||
const MenuSelectStyle = {
|
||||
option: (provided, state) => {
|
||||
const { isDisabled, isSelected } = state;
|
||||
return ({
|
||||
...provided,
|
||||
cursor: isDisabled ? 'default' : 'pointer',
|
||||
//backgroundColor: isSelected ? '#5A98F8' : (isFocused ? '#f5f5f5' : '#fff'),
|
||||
'.header-icon .dtable-font': {
|
||||
color: isSelected ? '#fff' : '#aaa',
|
||||
},
|
||||
});
|
||||
},
|
||||
control: (provided) => ({
|
||||
...provided,
|
||||
fontSize: '14px',
|
||||
cursor: 'pointer',
|
||||
lineHeight: '1.5',
|
||||
}),
|
||||
menuPortal: base => ({ ...base, zIndex: 9999 }),
|
||||
indicatorSeparator: () => {},
|
||||
};
|
||||
|
||||
// scence1: isTextMode (text)editor-icon --> select
|
||||
// scence2: !isTextMode select
|
||||
return (
|
||||
|
@@ -5,6 +5,7 @@ import { seafileAPI } from '../utils/seafile-api';
|
||||
import { gettext, enableShowContactEmailWhenSearchUser } from '../utils/constants';
|
||||
import { Utils } from '../utils/utils';
|
||||
import toaster from './toast';
|
||||
import { UserSelectStyle } from './common/select';
|
||||
|
||||
import '../css/user-select.css';
|
||||
|
||||
@@ -99,6 +100,7 @@ class UserSelect extends React.Component {
|
||||
className={`user-select ${this.props.className}`}
|
||||
value={this.props.value}
|
||||
ref="userSelect"
|
||||
styles={UserSelectStyle}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import Select from 'react-select';
|
||||
import { gettext, siteRoot } from '../../utils/constants';
|
||||
import { SeahubSelect } from '../common/select';
|
||||
|
||||
const {
|
||||
currentLang, langList
|
||||
@@ -28,7 +28,7 @@ class LanguageSetting extends React.Component {
|
||||
return (
|
||||
<div className="setting-item" id="lang-setting">
|
||||
<h3 className="setting-item-heading">{gettext('Language Setting')}</h3>
|
||||
<Select
|
||||
<SeahubSelect
|
||||
className='language-selector'
|
||||
defaultValue={{value: currentLang.langCode, label: currentLang.langName}}
|
||||
options={options}
|
||||
|
Reference in New Issue
Block a user