mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-16 07:08:55 +00:00
update org admin settings page (#5398)
This commit is contained in:
@@ -12,7 +12,7 @@ import OrgStatisticReport from './statistic/statistic-reports';
|
||||
import OrgDesktopDevices from './devices/desktop-devices.js';
|
||||
import OrgMobileDevices from './devices/mobile-devices.js';
|
||||
import OrgDevicesErrors from './devices/devices-errors.js';
|
||||
import WebSettings from './web-settings/web-settings';
|
||||
import OrgWebSettings from './web-settings/web-settings';
|
||||
import OrgUsers from './org-users-users';
|
||||
import OrgUsersSearchUsers from './org-users-search-users';
|
||||
import OrgAdmins from './org-users-admins';
|
||||
@@ -26,7 +26,6 @@ import OrgGroupRepos from './org-group-repos';
|
||||
import OrgGroupMembers from './org-group-members';
|
||||
import OrgLibraries from './org-libraries';
|
||||
import OrgInfo from './org-info';
|
||||
import OrgSettings from './org-web-settings';
|
||||
import OrgLinks from './org-links';
|
||||
import OrgDepartments from './org-departments';
|
||||
import OrgDepartmentsList from './org-departments-list';
|
||||
@@ -87,7 +86,6 @@ class Org extends React.Component {
|
||||
<div className="main-panel">
|
||||
<Router className="reach-router">
|
||||
<OrgInfo path={siteRoot + 'org/info/'} />
|
||||
<OrgSettings path={siteRoot + 'org/settings/'} />
|
||||
<OrgStatisticFile path={siteRoot + 'org/statistics-admin/file/'} />
|
||||
<OrgStatisticStorage path={siteRoot + 'org/statistics-admin/total-storage/'} />
|
||||
<OrgStatisticUsers path={siteRoot + 'org/statistics-admin/active-users/'} />
|
||||
@@ -96,7 +94,7 @@ class Org extends React.Component {
|
||||
<OrgDesktopDevices path={siteRoot + 'org/deviceadmin/desktop-devices/'} />
|
||||
<OrgMobileDevices path={siteRoot + 'org/deviceadmin/mobile-devices/'} />
|
||||
<OrgDevicesErrors path={siteRoot + 'org/deviceadmin/devices-errors/'} />
|
||||
<WebSettings path={siteRoot + 'org/web-settings'} />
|
||||
<OrgWebSettings path={siteRoot + 'org/web-settings'} />
|
||||
<OrgUsers path={siteRoot + 'org/useradmin'} />
|
||||
<OrgUsersSearchUsers path={siteRoot + 'org/useradmin/search-users'} />
|
||||
<OrgAdmins path={siteRoot + 'org/useradmin/admins/'} />
|
||||
|
@@ -38,12 +38,6 @@ class SidePanel extends React.Component {
|
||||
<span className="nav-text">{gettext('Info')}</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<Link className={`nav-link ellipsis ${this.getActiveClass('settings')}`} to={siteRoot + 'org/settings/'} onClick={() => this.tabItemClick('settings')} >
|
||||
<span className="sf2-icon-cog2"></span>
|
||||
<span className="nav-text">{gettext('Settings')}</span>
|
||||
</Link>
|
||||
</li>
|
||||
<li className="nav-item">
|
||||
<Link className={`nav-link ellipsis ${this.getActiveClass('statistics-admin')}`} to={siteRoot + 'org/statistics-admin/file/'} onClick={() => this.tabItemClick('statistics-admin')} >
|
||||
<span className="sf2-icon-histogram"></span>
|
||||
|
@@ -1,42 +0,0 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Row, Col, Label } from 'reactstrap';
|
||||
|
||||
const propTypes = {
|
||||
displayName: PropTypes.string.isRequired,
|
||||
helpTip: PropTypes.string,
|
||||
mainContent: PropTypes.object.isRequired,
|
||||
extraContent: PropTypes.object
|
||||
};
|
||||
|
||||
|
||||
class SettingItemBase extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { helpTip, displayName, mainContent, extraContent } = this.props;
|
||||
return (
|
||||
<Fragment>
|
||||
<Row className="my-4">
|
||||
<Col md="3">
|
||||
<Label className="web-setting-label">{displayName}</Label>
|
||||
</Col>
|
||||
<Col md="5">
|
||||
{mainContent}
|
||||
{helpTip && <p className="small text-secondary mt-1">{helpTip}</p>}
|
||||
</Col>
|
||||
<Col md="4">
|
||||
{extraContent}
|
||||
</Col>
|
||||
</Row>
|
||||
</Fragment>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SettingItemBase.propTypes = propTypes;
|
||||
|
||||
export default SettingItemBase;
|
@@ -1,76 +0,0 @@
|
||||
import React, { Component, Fragment } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Input, Button } from 'reactstrap';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import SettingItemBase from './web-setting-item-base';
|
||||
|
||||
const propTypes = {
|
||||
inputType: PropTypes.string,
|
||||
saveSetting: PropTypes.func.isRequired,
|
||||
keyText: PropTypes.string.isRequired,
|
||||
value: PropTypes.oneOfType([PropTypes.string,PropTypes.number]),
|
||||
helpTip: PropTypes.string.isRequired,
|
||||
displayName: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
class WebSettingInput extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isBtnsShown: false,
|
||||
value: this.props.value
|
||||
};
|
||||
}
|
||||
|
||||
toggleBtns = () => {
|
||||
this.setState({isBtnsShown: !this.state.isBtnsShown});
|
||||
}
|
||||
|
||||
hideBtns = (e) => {
|
||||
if (!this.state.isBtnsShown) {
|
||||
return;
|
||||
}
|
||||
if (this.props.value != this.state.value) {
|
||||
this.setState({value: this.props.value});
|
||||
}
|
||||
this.toggleBtns();
|
||||
}
|
||||
|
||||
onInputChange = (e) => {
|
||||
this.setState({ value: e.target.value });
|
||||
}
|
||||
|
||||
onSubmit = (e) => {
|
||||
const value = this.state.value.trim();
|
||||
if (value != this.props.value) {
|
||||
this.props.saveSetting(this.props.keyText, value);
|
||||
}
|
||||
this.toggleBtns();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { isBtnsShown, value } = this.state;
|
||||
const { helpTip, displayName, inputType } = this.props;
|
||||
return (
|
||||
<SettingItemBase
|
||||
displayName={displayName}
|
||||
helpTip={helpTip}
|
||||
mainContent={
|
||||
<Input type={inputType || 'text'} className={inputType == 'textarea' ? 'web-setting-textarea' : ''} onChange={this.onInputChange} onFocus={this.toggleBtns} onBlur={this.hideBtns} value={value} />
|
||||
}
|
||||
extraContent={
|
||||
isBtnsShown ?
|
||||
<Fragment>
|
||||
<Button className="sf2-icon-tick web-setting-icon-btn web-setting-icon-btn-submit" onMouseDown={this.onSubmit} title={gettext('Submit')}></Button>
|
||||
<Button className="ml-1 sf2-icon-x2 web-setting-icon-btn web-setting-icon-btn-cancel" title={gettext('Cancel')}></Button>
|
||||
</Fragment> : null
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
WebSettingInput.propTypes = propTypes;
|
||||
|
||||
export default WebSettingInput;
|
@@ -12,7 +12,7 @@ import CheckboxItem from './checkbox-item';
|
||||
|
||||
import '../../../css/system-admin-web-settings.css';
|
||||
|
||||
class WebSettings extends Component {
|
||||
class OrgWebSettings extends Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@@ -21,6 +21,7 @@ class WebSettings extends Component {
|
||||
errorMsg: '',
|
||||
config_dict: null,
|
||||
logoPath: mediaUrl + logoPath,
|
||||
file_ext_white_list: '',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -28,7 +29,8 @@ class WebSettings extends Component {
|
||||
seafileAPI.orgAdminGetOrgInfo().then((res) => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
config_dict: res.data
|
||||
config_dict: res.data,
|
||||
file_ext_white_list: res.data.file_ext_white_list
|
||||
});
|
||||
}).catch((error) => {
|
||||
this.setState({
|
||||
@@ -62,8 +64,20 @@ class WebSettings extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
updateFileExtWhiteList = (key, value) => {
|
||||
seafileAPI.orgAdminSetSysSettingInfo(orgID, key, value).then((res) => {
|
||||
this.setState({
|
||||
file_ext_white_list: res.data.file_ext_white_list
|
||||
});
|
||||
toaster.success(gettext('Success'));
|
||||
}).catch((error) => {
|
||||
let errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { loading, errorMsg, config_dict, logoPath } = this.state;
|
||||
const { loading, errorMsg, config_dict, logoPath, file_ext_white_list } = this.state;
|
||||
return (
|
||||
<Fragment>
|
||||
<MainPanelTopbar {...this.props} />
|
||||
@@ -101,6 +115,17 @@ class WebSettings extends Component {
|
||||
}
|
||||
</Fragment>
|
||||
</Section>
|
||||
<Section headingText={gettext('File Upload')}>
|
||||
<Fragment>
|
||||
<InputItem
|
||||
saveSetting={this.updateFileExtWhiteList}
|
||||
displayName='file_ext_white_list'
|
||||
keyText='file_ext_white_list'
|
||||
value={file_ext_white_list}
|
||||
helpTip={gettext('File upload format whitelist via web UI and API. For example: "md;txt;docx", empty means no limit.')}
|
||||
/>
|
||||
</Fragment>
|
||||
</Section>
|
||||
</Fragment>
|
||||
}
|
||||
</div>
|
||||
@@ -111,4 +136,4 @@ class WebSettings extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
export default WebSettings;
|
||||
export default OrgWebSettings;
|
||||
|
@@ -59,12 +59,15 @@ def get_org_info(request, org_id):
|
||||
member_usage = len(org_members)
|
||||
active_members = len([m for m in org_members if m.is_active])
|
||||
|
||||
file_ext_white_list = seafile_api.org_get_file_ext_white_list(org_id)
|
||||
|
||||
info = {}
|
||||
info['storage_quota'] = storage_quota
|
||||
info['storage_usage'] = storage_usage
|
||||
info['member_quota'] = member_quota
|
||||
info['member_usage'] = member_usage
|
||||
info['active_members'] = active_members
|
||||
info['file_ext_white_list'] = file_ext_white_list
|
||||
|
||||
return info
|
||||
|
||||
|
Reference in New Issue
Block a user