1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-03 16:10:26 +00:00

Change select style (#5645)

* 01 change css file path

* 02 change Select style
This commit is contained in:
Michael An
2023-09-18 10:01:30 +08:00
committed by GitHub
parent 8a09906cfb
commit f278cfd3bb
16 changed files with 206 additions and 86 deletions

View File

@@ -5,7 +5,7 @@ import { gettext } from '../../utils/constants';
import NoticeItem from './notice-item'; import NoticeItem from './notice-item';
import UserNotificationsDialog from '../../user-notifications'; import UserNotificationsDialog from '../../user-notifications';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import './notification.css'; import '../../css/notification.css';
class Notification extends React.Component { class Notification extends React.Component {
constructor(props) { constructor(props) {

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

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

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

View 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}
/>
);
}
}

View File

@@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Select from 'react-select';
import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Alert } from 'reactstrap'; import { Button, Modal, ModalHeader, Input, ModalBody, ModalFooter, Form, FormGroup, Label, Alert } from 'reactstrap';
import { gettext, enableEncryptedLibrary, repoPasswordMinLength, storages, libraryTemplates } from '../../utils/constants'; import { gettext, enableEncryptedLibrary, repoPasswordMinLength, storages, libraryTemplates } from '../../utils/constants';
import { SeahubSelect } from '../common/select';
const propTypes = { const propTypes = {
libraryType: PropTypes.string.isRequired, libraryType: PropTypes.string.isRequired,
@@ -189,9 +189,8 @@ class CreateRepoDialog extends React.Component {
{libraryTemplates.length > 0 && ( {libraryTemplates.length > 0 && (
<FormGroup> <FormGroup>
<Label for="library-template">{gettext('Template')}</Label> <Label>{gettext('Template')}</Label>
<Select <SeahubSelect
id="library-template"
defaultValue={{value: libraryTemplates[0], label: libraryTemplates[0]}} defaultValue={{value: libraryTemplates[0], label: libraryTemplates[0]}}
options={libraryTemplates.map((item, index) => { return {value: item, label: item}; })} options={libraryTemplates.map((item, index) => { return {value: item, label: item}; })}
onChange={this.handlelibraryTemplatesInputChange} onChange={this.handlelibraryTemplatesInputChange}
@@ -201,9 +200,8 @@ class CreateRepoDialog extends React.Component {
{storages.length > 0 && ( {storages.length > 0 && (
<FormGroup> <FormGroup>
<Label for="storage-backend">{gettext('Storage Backend')}</Label> <Label>{gettext('Storage Backend')}</Label>
<Select <SeahubSelect
id="storage-backend"
defaultValue={{value: storages[0].id, label: storages[0].name}} defaultValue={{value: storages[0].id, label: storages[0].name}}
options={storages.map((item, index) => { return {value: item.id, label: item.name}; })} options={storages.map((item, index) => { return {value: item.id, label: item.name}; })}
onChange={this.handleStorageInputChange} onChange={this.handleStorageInputChange}

View File

@@ -1,12 +1,12 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap'; import { Button, Input, InputGroup, InputGroupAddon } from 'reactstrap';
import Select from 'react-select';
import { gettext, isPro, siteRoot } from '../../utils/constants'; import { gettext, isPro, siteRoot } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import SharePermissionEditor from '../select-editor/share-permission-editor'; import SharePermissionEditor from '../select-editor/share-permission-editor';
import FileChooser from '../file-chooser/file-chooser'; import FileChooser from '../file-chooser/file-chooser';
import { SeahubSelect, NoGroupMessage } from '../common/select';
class GroupItem extends React.Component { class GroupItem extends React.Component {
@@ -93,16 +93,6 @@ const propTypes = {
folderPath: PropTypes.string, 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 { class LibSubFolderSerGroupPermissionDialog extends React.Component {
constructor(props) { constructor(props) {
@@ -306,14 +296,13 @@ class LibSubFolderSerGroupPermissionDialog extends React.Component {
<tbody> <tbody>
<tr> <tr>
<td> <td>
<Select <SeahubSelect
onChange={this.handleSelectChange} onChange={this.handleSelectChange}
options={this.options} options={this.options}
placeholder={gettext('Select a group')} placeholder={gettext('Select a group')}
maxMenuHeight={200} maxMenuHeight={200}
inputId={'react-select-2-input'}
value={this.state.selectedOption} value={this.state.selectedOption}
components={{ NoOptionsMessage }} components={{ NoOptionsMessage: NoGroupMessage }}
/> />
</td> </td>
{showPath && {showPath &&

View File

@@ -1,12 +1,12 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import Select from 'react-select';
import { gettext, isPro, enableShareToDepartment } from '../../utils/constants'; import { gettext, isPro, enableShareToDepartment } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import toaster from '../toast'; import toaster from '../toast';
import SharePermissionEditor from '../select-editor/share-permission-editor'; import SharePermissionEditor from '../select-editor/share-permission-editor';
import { SeahubSelect, NoGroupMessage } from '../common/select';
class GroupItem extends React.Component { class GroupItem extends React.Component {
@@ -117,16 +117,6 @@ const propTypes = {
onAddCustomPermissionToggle: PropTypes.func, 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 { class ShareToGroup extends React.Component {
constructor(props) { constructor(props) {
@@ -340,15 +330,13 @@ class ShareToGroup extends React.Component {
<tbody> <tbody>
<tr> <tr>
<td> <td>
<Select <SeahubSelect
isMulti
onChange={this.handleSelectChange} onChange={this.handleSelectChange}
options={this.state.options} options={this.state.options}
placeholder={gettext('Select groups...')} placeholder={gettext('Select groups...')}
maxMenuHeight={200} maxMenuHeight={200}
inputId={'react-select-2-input'}
value={this.state.selectedOption} value={this.state.selectedOption}
components={{ NoOptionsMessage }} components={{ NoOptionsMessage: NoGroupMessage }}
/> />
</td> </td>
<td> <td>

View File

@@ -1,14 +1,13 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import Select from 'react-select';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext, ocmRemoteServers } from '../../utils/constants'; import { gettext, ocmRemoteServers } from '../../utils/constants';
import { Input } from 'reactstrap'; import { Input, Button } from 'reactstrap';
import { Button } from 'reactstrap';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import toaster from '../toast'; import toaster from '../toast';
import OpIcon from '../op-icon'; import OpIcon from '../op-icon';
import SharePermissionEditor from '../select-editor/share-permission-editor'; import SharePermissionEditor from '../select-editor/share-permission-editor';
import { SeahubSelect } from '../common/select';
class ShareItem extends React.Component { class ShareItem extends React.Component {
@@ -228,7 +227,7 @@ class ShareToOtherServer extends React.Component {
<tbody> <tbody>
<tr> <tr>
<td> <td>
<Select <SeahubSelect
placeholder={gettext('Select a server...')} placeholder={gettext('Select a server...')}
value={selectedServer} value={selectedServer}
options={ocmRemoteServers} options={ocmRemoteServers}

View File

@@ -1,12 +1,12 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button } from 'reactstrap'; import { Button } from 'reactstrap';
import Select from 'react-select';
import { isPro, gettext } from '../../../utils/constants'; import { isPro, gettext } from '../../../utils/constants';
import { seafileAPI } from '../../../utils/seafile-api'; import { seafileAPI } from '../../../utils/seafile-api';
import { Utils } from '../../../utils/utils'; import { Utils } from '../../../utils/utils';
import toaster from '../../toast'; import toaster from '../../toast';
import SharePermissionEditor from '../../select-editor/share-permission-editor'; import SharePermissionEditor from '../../select-editor/share-permission-editor';
import { SeahubSelect, NoGroupMessage } from '../common/select';
class GroupItem extends React.Component { class GroupItem extends React.Component {
@@ -109,16 +109,6 @@ const propTypes = {
isRepoOwner: PropTypes.bool.isRequired, 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 { class SysAdminShareToGroup extends React.Component {
constructor(props) { constructor(props) {
@@ -257,15 +247,13 @@ class SysAdminShareToGroup extends React.Component {
<tbody> <tbody>
<tr> <tr>
<td> <td>
<Select <SeahubSelect
isMulti
onChange={this.handleSelectChange} onChange={this.handleSelectChange}
options={this.options} options={this.options}
placeholder={gettext('Select groups...')} placeholder={gettext('Select groups...')}
maxMenuHeight={200} maxMenuHeight={200}
inputId={'react-select-2-input'}
value={this.state.selectedOption} value={this.state.selectedOption}
components={{ NoOptionsMessage }} components={{ NoOptionsMessage: NoGroupMessage }}
/> />
</td> </td>
<td> <td>

View File

@@ -1,13 +1,13 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap'; import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Select from 'react-select';
import makeAnimated from 'react-select/animated'; import makeAnimated from 'react-select/animated';
import { seafileAPI } from '../../utils/seafile-api'; import { seafileAPI } from '../../utils/seafile-api';
import { gettext, isPro } from '../../utils/constants'; import { gettext, isPro } from '../../utils/constants';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import toaster from '../toast'; import toaster from '../toast';
import UserSelect from '../user-select'; import UserSelect from '../user-select';
import { SeahubSelect } from '../common/select';
const propTypes = { const propTypes = {
itemName: PropTypes.string.isRequired, itemName: PropTypes.string.isRequired,
@@ -79,9 +79,8 @@ class TransferDialog extends React.Component {
placeholder={gettext('Select a user')} placeholder={gettext('Select a user')}
onSelectChange={this.handleSelectChange} onSelectChange={this.handleSelectChange}
/> : /> :
<Select <SeahubSelect
isClearable isClearable
isMulti={false}
maxMenuHeight={200} maxMenuHeight={200}
hideSelectedOptions={true} hideSelectedOptions={true}
components={makeAnimated()} components={makeAnimated()}

View File

@@ -1,8 +1,8 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Select from 'react-select';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import OpIcon from '../op-icon'; import OpIcon from '../op-icon';
import { SeahubSelect } from '../common/select';
const propTypes = { const propTypes = {
isTextMode: PropTypes.bool.isRequired, isTextMode: PropTypes.bool.isRequired,
@@ -65,7 +65,7 @@ class RepoAPITokenPermissionEditor extends React.Component {
} }
</Fragment> </Fragment>
: :
<Select <SeahubSelect
options={this.options} options={this.options}
placeholder={optionTranslation} placeholder={optionTranslation}
onChange={this.onPermissionChanged} onChange={this.onPermissionChanged}

View File

@@ -2,6 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants'; import { gettext } from '../../utils/constants';
import Select from 'react-select'; import Select from 'react-select';
import { MenuSelectStyle } from '../common/select';
import '../../css/select-editor.css'; import '../../css/select-editor.css';
const propTypes = { const propTypes = {
@@ -105,29 +106,6 @@ class SelectEditor extends React.Component {
render() { render() {
let { currentOption, isTextMode } = this.props; 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 // scence1: isTextMode (text)editor-icon --> select
// scence2: !isTextMode select // scence2: !isTextMode select
return ( return (

View File

@@ -5,6 +5,7 @@ import { seafileAPI } from '../utils/seafile-api';
import { gettext, enableShowContactEmailWhenSearchUser } from '../utils/constants'; import { gettext, enableShowContactEmailWhenSearchUser } from '../utils/constants';
import { Utils } from '../utils/utils'; import { Utils } from '../utils/utils';
import toaster from './toast'; import toaster from './toast';
import { UserSelectStyle } from './common/select';
import '../css/user-select.css'; import '../css/user-select.css';
@@ -99,6 +100,7 @@ class UserSelect extends React.Component {
className={`user-select ${this.props.className}`} className={`user-select ${this.props.className}`}
value={this.props.value} value={this.props.value}
ref="userSelect" ref="userSelect"
styles={UserSelectStyle}
/> />
); );
} }

View File

@@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import Select from 'react-select';
import { gettext, siteRoot } from '../../utils/constants'; import { gettext, siteRoot } from '../../utils/constants';
import { SeahubSelect } from '../common/select';
const { const {
currentLang, langList currentLang, langList
@@ -28,7 +28,7 @@ class LanguageSetting extends React.Component {
return ( return (
<div className="setting-item" id="lang-setting"> <div className="setting-item" id="lang-setting">
<h3 className="setting-item-heading">{gettext('Language Setting')}</h3> <h3 className="setting-item-heading">{gettext('Language Setting')}</h3>
<Select <SeahubSelect
className='language-selector' className='language-selector'
defaultValue={{value: currentLang.langCode, label: currentLang.langName}} defaultValue={{value: currentLang.langCode, label: currentLang.langName}}
options={options} options={options}