Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[library] added new 'settings' dialog(includes setting panels for #7002

Merged
merged 1 commit into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions frontend/src/components/dialog/lib-settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import React, { Fragment, useCallback, useState } from 'react';
import PropTypes from 'prop-types';
import { Modal, ModalHeader, ModalBody, TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
import { gettext, enableRepoAutoDel } from '../../utils/constants';
import LibHistorySettingPanel from './lib-settings/lib-history-setting-panel';
import LibAutoDelSettingPanel from './lib-settings/lib-old-files-auto-del-setting-panel';
import {
MetadataStatusManagementDialog as LibExtendedPropertiesSettingPanel,
MetadataFaceRecognitionDialog as LibFaceRecognitionSettingPanel,
useMetadata
} from '../../metadata';

import '../../css/lib-settings.css';

const propTypes = {
toggleDialog: PropTypes.func.isRequired,
repoID: PropTypes.string.isRequired,
currentRepoInfo: PropTypes.object.isRequired
};

const LibSettingsDialog = ({ repoID, currentRepoInfo, toggleDialog, tab }) => {
let [activeTab, setActiveTab] = useState(tab || 'historySetting');

const toggleTab = useCallback((tab) => {
setActiveTab(tab);
}, []);

const onTabKeyDown = useCallback((e) => {
if (e.key == 'Enter' || e.key == 'Space') {
e.target.click();
}
}, []);

const { encrypted, is_admin } = currentRepoInfo;
const { enableMetadataManagement } = window.app.pageOptions;
const { enableMetadata, updateEnableMetadata, enableFaceRecognition, updateEnableFaceRecognition } = useMetadata();
const enableHistorySetting = is_admin; // repo owner, admin of the department which the repo belongs to, and ...
const enableAutoDelSetting = is_admin && enableRepoAutoDel;
const enableExtendedPropertiesSetting = !encrypted && is_admin && enableMetadataManagement;
const enableFaceRecognitionSetting = enableExtendedPropertiesSetting && enableMetadata;

return (
<div>
<Modal isOpen={true} className="lib-settings-dialog" toggle={toggleDialog}>
<ModalHeader toggle={toggleDialog}>
{gettext('Settings')}
</ModalHeader>
<ModalBody className="d-md-flex p-md-0" role="tablist">
<Fragment>
<div className="lib-setting-nav p-4">
<Nav pills className="flex-column">
{enableHistorySetting &&
<NavItem role="tab" aria-selected={activeTab === 'historySetting'} aria-controls="history-setting-panel">
<NavLink className={activeTab === 'historySetting' ? 'active' : ''} onClick={(toggleTab.bind(this, 'historySetting'))} tabIndex="0" onKeyDown={onTabKeyDown}>
{gettext('History')}
</NavLink>
</NavItem>
}
{enableAutoDelSetting &&
<NavItem role="tab" aria-selected={activeTab === 'autoDelSetting'} aria-controls="auto-del-setting-panel">
<NavLink className={activeTab === 'autoDelSetting' ? 'active' : ''} onClick={toggleTab.bind(this, 'autoDelSetting')} tabIndex="0" onKeyDown={onTabKeyDown}>
{gettext('Auto deletion')}
</NavLink>
</NavItem>
}
{enableExtendedPropertiesSetting &&
<NavItem role="tab" aria-selected={activeTab === 'extendedPropertiesSetting'} aria-controls="extended-properties-setting-panel">
<NavLink className={activeTab === 'extendedPropertiesSetting' ? 'active' : ''} onClick={toggleTab.bind(this, 'extendedPropertiesSetting')} tabIndex="0" onKeyDown={onTabKeyDown}>
{gettext('Extended properties')}
</NavLink>
</NavItem>
}
{enableFaceRecognitionSetting &&
<NavItem role="tab" aria-selected={activeTab === 'faceRecognitionSetting'} aria-controls="face-recognition-setting-panel">
<NavLink className={activeTab === 'faceRecognitionSetting' ? 'active' : ''} onClick={toggleTab.bind(this, 'faceRecognitionSetting')} tabIndex="0" onKeyDown={onTabKeyDown}>
{gettext('Face recognition')}
</NavLink>
</NavItem>
}
</Nav>
</div>
<TabContent activeTab={activeTab} className="flex-fill">
{(enableHistorySetting && activeTab === 'historySetting') &&
<TabPane tabId="historySetting" role="tabpanel" id="history-setting-panel">
<LibHistorySettingPanel
repoID={repoID}
toggleDialog={toggleDialog}
/>
</TabPane>
}
{(enableAutoDelSetting && activeTab === 'autoDelSetting') &&
<TabPane tabId="autoDelSetting" role="tabpanel" id="auto-del-setting-panel">
<LibAutoDelSettingPanel
repoID={repoID}
toggleDialog={toggleDialog}
/>
</TabPane>
}
{(enableExtendedPropertiesSetting && activeTab === 'extendedPropertiesSetting') &&
<TabPane tabId="extendedPropertiesSetting" role="tabpanel" id="extended-properties-setting-panel">
<LibExtendedPropertiesSettingPanel
repoID={repoID}
value={enableMetadata}
submit={(value) => { updateEnableMetadata(value); }}
toggleDialog={toggleDialog}
/>
</TabPane>
}
{(enableFaceRecognitionSetting && activeTab === 'faceRecognitionSetting') &&
<TabPane tabId="faceRecognitionSetting" role="tabpanel" id="face-recognition-setting-panel">
<LibFaceRecognitionSettingPanel
repoID={repoID}
value={enableFaceRecognition}
submit={(value) => { updateEnableFaceRecognition(true); }}
toggleDialog={toggleDialog}
/>
</TabPane>
}
</TabContent>
</Fragment>
</ModalBody>
</Modal>
</div>
);
};

LibSettingsDialog.propTypes = propTypes;

export default LibSettingsDialog;
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Alert } from 'reactstrap';
import { gettext, enableRepoHistorySetting } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import toaster from '../toast';
import { Button, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Alert } from 'reactstrap';
import { gettext, enableRepoHistorySetting } from '../../../utils/constants';
import { seafileAPI } from '../../../utils/seafile-api';
import { Utils } from '../../../utils/utils';
import toaster from '../../toast';

const propTypes = {
itemName: PropTypes.string.isRequired,
toggleDialog: PropTypes.func.isRequired,
repoID: PropTypes.string.isRequired,
};
Expand Down Expand Up @@ -108,14 +107,8 @@ class LibHistorySetting extends React.Component {
};

render() {
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 (
<Modal isOpen={true} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}>
<span dangerouslySetInnerHTML={{ __html: title }} className="d-flex mw-100"></span>
</ModalHeader>
<>
<ModalBody>
<Form>
{!enableRepoHistorySetting &&
Expand Down Expand Up @@ -151,7 +144,7 @@ class LibHistorySetting extends React.Component {
<Button color="secondary" onClick={this.props.toggleDialog}>{gettext('Cancel')}</Button>
<Button color="primary" onClick={this.submit}>{gettext('Submit')}</Button>
</ModalFooter>
</Modal>
</>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Alert } from 'reactstrap';
import { gettext } from '../../utils/constants';
import { seafileAPI } from '../../utils/seafile-api';
import { Utils } from '../../utils/utils';
import toaster from '../toast';
import { Button, ModalBody, ModalFooter, Form, FormGroup, Label, Input, Alert } from 'reactstrap';
import { gettext } from '../../../utils/constants';
import { seafileAPI } from '../../../utils/seafile-api';
import { Utils } from '../../../utils/utils';
import toaster from '../../toast';

const propTypes = {
toggleDialog: PropTypes.func.isRequired,
repoID: PropTypes.string.isRequired,
};

class LibOldFilesAutoDelDialog extends React.Component {
class LibOldFilesAutoDelSetting extends React.Component {

constructor(props) {
super(props);
Expand Down Expand Up @@ -93,10 +93,7 @@ class LibOldFilesAutoDelDialog extends React.Component {

render() {
return (
<Modal isOpen={true} toggle={this.props.toggleDialog}>
<ModalHeader toggle={this.props.toggleDialog}>
{gettext('Auto deletion')}
</ModalHeader>
<>
<ModalBody>
<Form>
<FormGroup check>
Expand All @@ -123,11 +120,11 @@ class LibOldFilesAutoDelDialog extends React.Component {
<Button color="secondary" onClick={this.props.toggleDialog}>{gettext('Cancel')}</Button>
<Button color="primary" onClick={this.submit}>{gettext('Submit')}</Button>
</ModalFooter>
</Modal>
</>
);
}
}

LibOldFilesAutoDelDialog.propTypes = propTypes;
LibOldFilesAutoDelSetting.propTypes = propTypes;

export default LibOldFilesAutoDelDialog;
export default LibOldFilesAutoDelSetting;
21 changes: 21 additions & 0 deletions frontend/src/components/dir-view-mode/dir-others.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@ import { gettext, siteRoot } from '../../utils/constants';
import { Utils } from '../../utils/utils';
import TreeSection from '../tree-section';
import TrashDialog from '../dialog/trash-dialog';
import LibSettingsDialog from '../dialog/lib-settings';

import './dir-others.css';

const DirOthers = ({ userPerm, repoID, currentRepoInfo }) => {
const showSettings = currentRepoInfo.is_admin; // repo owner, department admin, shared with 'Admin' permission
let [isSettingsDialogOpen, setSettingsDialogOpen] = useState(false);
const toggleSettingsDialog = () => {
setSettingsDialogOpen(!isSettingsDialogOpen);
};

const [showTrashDialog, setShowTrashDialog] = useState(false);
let trashUrl = null;
const historyUrl = siteRoot + 'repo/history/' + repoID + '/';
Expand All @@ -18,6 +26,12 @@ const DirOthers = ({ userPerm, repoID, currentRepoInfo }) => {
};
return (
<TreeSection title={gettext('Others')} className="dir-others">
{showSettings &&
<div className='dir-others-item text-nowrap' title={gettext('Settings')} onClick={toggleSettingsDialog}>
<span className="sf3-font-set-up sf3-font"></span>
<span className="dir-others-item-text">{gettext('Settings')}</span>
</div>
}
{trashUrl &&
<div className='dir-others-item text-nowrap' title={gettext('Trash')} onClick={toggleTrashDialog}>
<span className="sf3-font-trash sf3-font"></span>
Expand All @@ -38,6 +52,13 @@ const DirOthers = ({ userPerm, repoID, currentRepoInfo }) => {
toggleTrashDialog={toggleTrashDialog}
/>
)}
{isSettingsDialogOpen && (
<LibSettingsDialog
repoID={repoID}
currentRepoInfo={currentRepoInfo}
toggleDialog={toggleSettingsDialog}
/>
)}
</TreeSection>
);
};
Expand Down
77 changes: 14 additions & 63 deletions frontend/src/components/dir-view-mode/dir-views.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { gettext } from '../../utils/constants';
import TreeSection from '../tree-section';
import { MetadataStatusManagementDialog, MetadataFaceRecognitionDialog, MetadataTreeView, useMetadata } from '../../metadata';
import { MetadataTreeView, useMetadata } from '../../metadata';
import ExtensionPrompts from './extension-prompts';
import LibSettingsDialog from '../dialog/lib-settings';

const DirViews = ({ userPerm, repoID, currentPath, currentRepoInfo }) => {
const enableMetadataManagement = useMemo(() => {
Expand All @@ -12,53 +13,14 @@ const DirViews = ({ userPerm, repoID, currentPath, currentRepoInfo }) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [window.app.pageOptions.enableMetadataManagement, currentRepoInfo]);

const [showMetadataStatusManagementDialog, setShowMetadataStatusManagementDialog] = useState(false);
const [showMetadataFaceRecognitionDialog, setShowMetadataFaceRecognitionDialog] = useState(false);
const { enableMetadata, updateEnableMetadata, enableFaceRecognition, updateEnableFaceRecognition, navigation } = useMetadata();
const moreOperations = useMemo(() => {
if (!enableMetadataManagement || !currentRepoInfo.is_admin) return [];
let operations = [
{ key: 'extended-properties', value: gettext('Extended properties') }
];
if (enableMetadata) {
operations.push({ key: 'face-recognition', value: gettext('Face recognition') });
}
return operations;
}, [enableMetadataManagement, enableMetadata, currentRepoInfo]);

const moreOperationClick = useCallback((operationKey) => {
switch (operationKey) {
case 'extended-properties': {
setShowMetadataStatusManagementDialog(true);
break;
}
case 'face-recognition': {
setShowMetadataFaceRecognitionDialog(true);
break;
}
default:
break;
}
}, []);

const closeMetadataManagementDialog = useCallback(() => {
setShowMetadataStatusManagementDialog(false);
}, []);

const closeMetadataFaceRecognitionDialog = useCallback(() => {
setShowMetadataFaceRecognitionDialog(false);
}, []);

const openMetadataFaceRecognition = useCallback(() => {
updateEnableFaceRecognition(true);
}, [updateEnableFaceRecognition]);

const toggleMetadataStatus = useCallback((value) => {
updateEnableMetadata(value);
}, [updateEnableMetadata]);
const { enableMetadata, navigation } = useMetadata();

let [isSettingsDialogOpen, setSettingsDialogOpen] = useState(false);
const toggleSettingsDialog = () => {
setSettingsDialogOpen(!isSettingsDialogOpen);
};
const onExtendedProperties = useCallback(() => {
setShowMetadataStatusManagementDialog(true);
setSettingsDialogOpen(true);
}, []);

if (!enableMetadataManagement) return null;
Expand All @@ -67,30 +29,19 @@ const DirViews = ({ userPerm, repoID, currentPath, currentRepoInfo }) => {
<>
<TreeSection
title={gettext('Views')}
moreKey={{ name: 'views' }}
moreOperations={moreOperations}
moreOperationClick={moreOperationClick}
>
{!enableMetadata ? (
<ExtensionPrompts onExtendedProperties={onExtendedProperties} />
) : Array.isArray(navigation) && navigation.length > 0 ? (
<MetadataTreeView userPerm={userPerm} currentPath={currentPath} />
) : null}
</TreeSection>
{showMetadataStatusManagementDialog && (
<MetadataStatusManagementDialog
value={enableMetadata}
repoID={repoID}
toggle={closeMetadataManagementDialog}
submit={toggleMetadataStatus}
/>
)}
{showMetadataFaceRecognitionDialog && (
<MetadataFaceRecognitionDialog
value={enableFaceRecognition}
{isSettingsDialogOpen && (
<LibSettingsDialog
repoID={repoID}
toggle={closeMetadataFaceRecognitionDialog}
submit={openMetadataFaceRecognition}
currentRepoInfo={currentRepoInfo}
tab="extendedPropertiesSetting"
toggleDialog={toggleSettingsDialog}
/>
)}
</>
Expand All @@ -101,7 +52,7 @@ DirViews.propTypes = {
userPerm: PropTypes.string,
repoID: PropTypes.string,
currentPath: PropTypes.string,
onNodeClick: PropTypes.func,
currentRepoInfo: PropTypes.object.isRequired,
};

export default DirViews;
Loading
Loading