1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-04 16:31:13 +00:00

feat: metadata view permission (#6500)

Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
杨国璇
2024-08-06 14:32:15 +08:00
committed by GitHub
parent fd12baeea1
commit 6d0713ef00
22 changed files with 121 additions and 63 deletions

View File

@@ -7,7 +7,9 @@ import { getValidFilters, CommonlyUsedHotkey } from '../../_basic';
import { gettext } from '../../../../utils/constants';
import { FilterPopover } from '../popover';
const FilterSetter = ({ columns,
const FilterSetter = ({
readOnly,
columns,
wrapperClass,
filters: propsFilters,
isNeedSubmit,
@@ -67,6 +69,7 @@ const FilterSetter = ({ columns,
placement="bottom-end"
filtersClassName={filtersClassName}
target={target}
readOnly={readOnly}
isNeedSubmit={isNeedSubmit}
columns={columns}
collaborators={collaborators}
@@ -83,6 +86,7 @@ const FilterSetter = ({ columns,
};
FilterSetter.propTypes = {
readOnly: PropTypes.bool,
wrapperClass: PropTypes.string,
filtersClassName: PropTypes.string,
target: PropTypes.string,

View File

@@ -6,7 +6,7 @@ import { CommonlyUsedHotkey, getValidGroupbys, SUPPORT_GROUP_COLUMN_TYPES } from
import { gettext } from '../../utils';
import { GroupbysPopover } from '../popover';
const GroupbySetter = ({ columns: allColumns, groupbys: propsGroupbys, wrapperClass, target, modifyGroupbys }) => {
const GroupbySetter = ({ columns: allColumns, readOnly, groupbys: propsGroupbys, wrapperClass, target, modifyGroupbys }) => {
const [isShowSetter, setShowSetter] = useState(false);
const columns = useMemo(() => {
@@ -56,6 +56,7 @@ const GroupbySetter = ({ columns: allColumns, groupbys: propsGroupbys, wrapperCl
/>
{isShowSetter && (
<GroupbysPopover
readOnly={readOnly}
groupbys={groupbys}
target={target}
placement="bottom-end"
@@ -75,6 +76,7 @@ GroupbySetter.defaultProps = {
};
GroupbySetter.propTypes = {
readOnly: PropTypes.bool,
wrapperClass: PropTypes.string,
columns: PropTypes.array,
groupbys: PropTypes.array, // valid groupbys

View File

@@ -6,7 +6,7 @@ import { CommonlyUsedHotkey } from '../../_basic';
import { gettext } from '../../utils';
import { HideColumnPopover } from '../popover';
const HideColumnSetter = ({ columns, wrapperClass, target, hiddenColumns, modifyHiddenColumns }) => {
const HideColumnSetter = ({ readOnly, columns, wrapperClass, target, hiddenColumns, modifyHiddenColumns }) => {
const [isShowSetter, setShowSetter] = useState(false);
const validHiddenColumns = useMemo(() => {
@@ -50,6 +50,7 @@ const HideColumnSetter = ({ columns, wrapperClass, target, hiddenColumns, modify
/>
{isShowSetter && (
<HideColumnPopover
readOnly={readOnly}
hiddenColumns={validHiddenColumns}
target={target}
placement="bottom-end"
@@ -63,6 +64,7 @@ const HideColumnSetter = ({ columns, wrapperClass, target, hiddenColumns, modify
};
HideColumnSetter.propTypes = {
readOnly: PropTypes.bool,
wrapperClass: PropTypes.string,
target: PropTypes.string,
hiddenColumns: PropTypes.array,

View File

@@ -6,7 +6,7 @@ import { getValidSorts, CommonlyUsedHotkey } from '../../_basic';
import { gettext } from '../../utils';
import { SortPopover } from '../popover';
const SortSetter = ({ target, sorts: propsSorts, columns, isNeedSubmit, wrapperClass, modifySorts }) => {
const SortSetter = ({ target, sorts: propsSorts, readOnly, columns, isNeedSubmit, wrapperClass, modifySorts }) => {
const [isShowSetter, setShowSetter] = useState(false);
const sorts = useMemo(() => {
@@ -53,6 +53,7 @@ const SortSetter = ({ target, sorts: propsSorts, columns, isNeedSubmit, wrapperC
{isShowSetter && (
<SortPopover
isNeedSubmit={isNeedSubmit}
readOnly={readOnly}
target={target}
columns={columns}
sorts={sorts}
@@ -67,6 +68,7 @@ const SortSetter = ({ target, sorts: propsSorts, columns, isNeedSubmit, wrapperC
const propTypes = {
readOnly: PropTypes.bool,
wrapperClass: PropTypes.string,
target: PropTypes.string,
isNeedSubmit: PropTypes.bool,

View File

@@ -145,7 +145,7 @@ class FilterPopover extends Component {
};
render() {
const { target, columns, placement } = this.props;
const { readOnly, target, columns, placement } = this.props;
const { filters, filterConjunction } = this.state;
const canAddFilter = columns.length > 0;
return (
@@ -169,17 +169,19 @@ class FilterPopover extends Component {
deleteFilter={this.deleteFilter}
updateFilterConjunction={this.updateFilterConjunction}
collaborators={this.props.collaborators}
readOnly={false}
readOnly={readOnly}
scheduleUpdate={scheduleUpdate}
isPre={this.props.isPre}
/>
<CustomizeAddTool
className={`popover-add-tool ${canAddFilter ? '' : 'disabled'}`}
callBack={canAddFilter ? () => this.addFilter(scheduleUpdate) : () => {}}
footerName={gettext('Add filter')}
addIconClassName="popover-add-icon"
/>
{this.isNeedSubmit() && (
{!readOnly && (
<CustomizeAddTool
className={`popover-add-tool ${canAddFilter ? '' : 'disabled'}`}
callBack={canAddFilter ? () => this.addFilter(scheduleUpdate) : () => {}}
footerName={gettext('Add filter')}
addIconClassName="popover-add-icon"
/>
)}
{!readOnly && this.isNeedSubmit() && (
<div className='sf-metadata-filter-popover-footer'>
<Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button>
<Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitFilters}>{gettext('Submit')}</Button>
@@ -197,7 +199,7 @@ FilterPopover.propTypes = {
filtersClassName: PropTypes.string,
target: PropTypes.string.isRequired,
isNeedSubmit: PropTypes.bool,
isLocked: PropTypes.bool,
readOnly: PropTypes.bool,
columns: PropTypes.array.isRequired,
filterConjunction: PropTypes.string,
filters: PropTypes.array,

View File

@@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
import { SfFilterCalendar } from '@seafile/sf-metadata-ui-component';
import { getDateColumnFormat } from '../../../../utils/column-utils';
const FilterCalendar = ({ value, filterColumn, isReadOnly, onChange }) => {
const FilterCalendar = ({ value, filterColumn, readOnly, onChange }) => {
const format = getDateColumnFormat(filterColumn).trim();
const lang = window.sfMetadataContext.getSetting('lang');
return (
<SfFilterCalendar
isReadOnly={isReadOnly}
isReadOnly={readOnly}
format={format}
lang={lang}
value={value}
@@ -22,7 +22,7 @@ FilterCalendar.propTypes = {
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
filterColumn: PropTypes.object.isRequired,
isReadOnly: PropTypes.bool,
readOnly: PropTypes.bool,
};
export default FilterCalendar;

View File

@@ -6,7 +6,7 @@ import { gettext } from '../../../../../../utils';
import './index.css';
const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators, placeholder, filter_predicate, onSelectCollaborator }) => {
const CollaboratorFilter = ({ readOnly, filterIndex, filterTerm, collaborators, placeholder, filter_predicate, onSelectCollaborator }) => {
const supportMultipleSelectOptions = useMemo(() => {
return [
FILTER_PREDICATE_TYPE.HAS_ANY_OF,
@@ -80,7 +80,7 @@ const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators,
onSelectOption={onSelectCollaborator}
options={options}
placeholder={placeholder}
isLocked={isLocked}
readOnly={readOnly}
supportMultipleSelect={isSupportMultipleSelect}
searchable={true}
searchPlaceholder={gettext('Search collaborator')}
@@ -96,7 +96,7 @@ CollaboratorFilter.propTypes = {
filter_predicate: PropTypes.string,
collaborators: PropTypes.array,
onSelectCollaborator: PropTypes.func,
isLocked: PropTypes.bool,
readOnly: PropTypes.bool,
placeholder: PropTypes.string,
};

View File

@@ -25,6 +25,7 @@ import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../.
import './index.css';
const propTypes = {
readOnly: PropTypes.bool,
index: PropTypes.number.isRequired,
filter: PropTypes.object.isRequired,
filterColumn: PropTypes.object.isRequired,
@@ -245,6 +246,7 @@ class FilterItem extends React.Component {
};
getInputComponent = (type) => {
const { readOnly } = this.props;
const { filterTerm } = this.state;
if (type === 'text') {
return (
@@ -252,13 +254,16 @@ class FilterItem extends React.Component {
value={filterTerm}
onChange={this.onFilterTermTextChanged}
autoFocus={false}
disabled={readOnly}
className='text-truncate'
/>
);
} else if (type === 'checkbox') {
const { readOnly } = this.props;
return (
<input
type="checkbox"
disabled={readOnly}
checked={filterTerm}
onChange={this.onFilterTermCheckboxChanged}
/>
@@ -267,7 +272,7 @@ class FilterItem extends React.Component {
};
renderConjunction = () => {
const { index, filterConjunction, conjunctionOptions } = this.props;
const { index, readOnly, filterConjunction, conjunctionOptions } = this.props;
switch (index) {
case 0: {
return null;
@@ -276,6 +281,7 @@ class FilterItem extends React.Component {
const activeConjunction = FilterItemUtils.getActiveConjunctionOption(filterConjunction);
return (
<CustomizeSelect
readOnly={readOnly}
value={activeConjunction}
options={conjunctionOptions}
onSelectOption={this.onSelectConjunction}
@@ -356,7 +362,7 @@ class FilterItem extends React.Component {
};
renderFilterTerm = (filterColumn) => {
const { index, filter, collaborators } = this.props;
const { index, filter, collaborators, readOnly } = this.props;
const { type } = filterColumn;
const { filter_term, filter_predicate, filter_term_modifier } = filter;
// predicate is empty or not empty
@@ -381,6 +387,7 @@ class FilterItem extends React.Component {
if (filter_term_modifier === 'exact_date') {
return (
<FilterCalendar
readOnly={readOnly}
onChange={this.onFilterExactDateChanged}
value={this.state.filterTerm}
filterColumn={filterColumn}
@@ -409,6 +416,7 @@ class FilterItem extends React.Component {
const creators = collaborators;
return (
<CollaboratorFilter
readOnly={readOnly}
filterIndex={index}
filterTerm={filter_term || []}
collaborators={creators}
@@ -444,6 +452,7 @@ class FilterItem extends React.Component {
return (
<CustomizeSelect
readOnly={readOnly}
className="sf-metadata-selector-single-select"
value={selectedOptionDom}
options={dataOptions || []}
@@ -461,6 +470,7 @@ class FilterItem extends React.Component {
const allCollaborators = this.getAllCollaborators();
return (
<CollaboratorFilter
readOnly={readOnly}
filterIndex={index}
filterTerm={filter_term || []}
filter_predicate={filter_predicate}
@@ -501,7 +511,7 @@ class FilterItem extends React.Component {
render() {
const { filterPredicateOptions, filterTermModifierOptions } = this;
const { filter, filterColumn, filterColumnOptions } = this.props;
const { filter, filterColumn, filterColumnOptions, readOnly } = this.props;
const { filter_predicate, filter_term_modifier } = filter;
const activeColumn = FilterItemUtils.generatorColumnOption(filterColumn);
const activePredicate = FilterItemUtils.generatorPredicateOption(filter_predicate);
@@ -521,9 +531,11 @@ class FilterItem extends React.Component {
return (
<div className="filter-item">
<div className="delete-filter" onClick={this.onDeleteFilter}>
<Icon iconName="fork-number"/>
</div>
{!readOnly && (
<div className="delete-filter" onClick={this.onDeleteFilter}>
<Icon iconName="fork-number"/>
</div>
)}
<div className="condition">
<div className="filter-conjunction">
{this.renderConjunction()}
@@ -531,6 +543,7 @@ class FilterItem extends React.Component {
<div className="filter-container">
<div className="filter-column">
<CustomizeSelect
readOnly={readOnly}
value={activeColumn}
options={filterColumnOptions}
onSelectOption={this.onSelectColumn}
@@ -541,6 +554,7 @@ class FilterItem extends React.Component {
</div>
<div className={`filter-predicate ml-2 ${_isCheckboxColumn ? 'filter-checkbox-predicate' : ''}`}>
<CustomizeSelect
readOnly={readOnly}
value={activePredicate}
options={filterPredicateOptions}
onSelectOption={this.onSelectPredicate}
@@ -549,6 +563,7 @@ class FilterItem extends React.Component {
{isDateColumn(filterColumn) && isNeedShowTermModifier && (
<div className="filter-term-modifier ml-2">
<CustomizeSelect
readOnly={readOnly}
value={activeTermModifier}
options={filterTermModifierOptions}
onSelectOption={this.onSelectTermModifier}

View File

@@ -67,6 +67,10 @@
line-height: 20px;
}
.filters-list .sf-metadata-select.disabled .selected-option-show {
width: 100%;
}
.filters-list .sf-metadata-select .selected-option {
width: auto;
overflow-x: auto;
@@ -147,7 +151,7 @@
border-color: rgb(179, 179, 179);
}
.filters-list .filter-term input.disabled:hover {
.filters-list .filter-term input:disabled:hover {
border-color: rgba(0, 40, 100, 0.12);
}

View File

@@ -12,7 +12,7 @@ import FilterItem from './filter-item';
import './index.css';
const propTypes = {
isLocked: PropTypes.bool,
readOnly: PropTypes.bool,
className: PropTypes.string,
filters: PropTypes.array,
columns: PropTypes.array.isRequired,
@@ -81,13 +81,13 @@ class FiltersList extends Component {
};
renderFilterItem = (filter, index, errMsg, filterColumn) => {
const { filterConjunction, value } = this.props;
const { readOnly, filterConjunction, value } = this.props;
const conjunctionOptions = this.getConjunctionOptions();
const columnOptions = this.getColumnOptions();
return (
<FilterItem
key={index}
isLocked={this.props.isLocked}
readOnly={readOnly}
index={index}
filter={filter}
errMsg={errMsg}

View File

@@ -60,7 +60,7 @@ const dropCollect = (connect, monitor) => ({
*/
const GroupbyItem = memo(({
isOver, isDragging, canDrop, connectDragSource, connectDragPreview, connectDropTarget,
showDragBtn, index, groupby, columns, onDelete, onUpdate
showDragBtn, index, readOnly, groupby, columns, onDelete, onUpdate
}) => {
const column = useMemo(() => {
return getColumnByKey(columns, groupby.column_key);
@@ -162,12 +162,15 @@ const GroupbyItem = memo(({
{ 'group-can-drop': isOver && canDrop && !isDragging }
)}
>
<div className="delete-groupby" onClick={deleteGroupby} aria-label={gettext('Delete')}>
<Icon iconName="fork-number"/>
</div>
{!readOnly && (
<div className="delete-groupby" onClick={deleteGroupby} aria-label={gettext('Delete')}>
<Icon iconName="fork-number"/>
</div>
)}
<div className="condition">
<div className="groupby-column">
<CustomizeSelect
readOnly={readOnly}
value={selectedColumn}
options={columnsOptions}
onSelectOption={selectColumn}
@@ -179,6 +182,7 @@ const GroupbyItem = memo(({
{isShowGroupCountType(column) && (
<div className="groupby-count-type">
<CustomizeSelect
readOnly={readOnly}
value={selectedCountType}
onSelectOption={selectCountType}
options={countTypeOptions}
@@ -188,6 +192,7 @@ const GroupbyItem = memo(({
<div className="groupby-predicate">
{(!column.key || SORT_COLUMN_OPTIONS.includes(column.type)) && (
<CustomizeSelect
readOnly={readOnly}
value={selectedSortType}
options={sortOptions}
onSelectOption={selectSortType}
@@ -195,7 +200,7 @@ const GroupbyItem = memo(({
)}
</div>
</div>
{showDragBtn && connectDragSource(
{!readOnly && showDragBtn && connectDragSource(
<div className="groupby-drag">
<Icon iconName="drag" />
</div>
@@ -217,6 +222,7 @@ const GroupbyItem = memo(({
GroupbyItem.propTypes = {
index: PropTypes.number,
readOnly: PropTypes.bool,
groupby: PropTypes.object,
columns: PropTypes.array,
onDelete: PropTypes.func,

View File

@@ -6,15 +6,16 @@ import html5DragDropContext from '../../../../../../pages/wiki2/wiki-nav/html5Dr
import { gettext } from '../../../../utils';
import GroupbyItem from './groupby-item';
const Groupbys = ({ groupbys, columns, onDelete, onUpdate, onMove }) => {
const Groupbys = ({ readOnly, groupbys, columns, onDelete, onUpdate, onMove }) => {
const isEmpty = useMemo(() => {
if (!Array.isArray(groupbys) || groupbys.length === 0) return true;
return false;
}, [groupbys]);
const showDragBtn = useMemo(() => {
if (readOnly) return false;
if (!Array.isArray(groupbys) || groupbys.length === 0) return false;
return groupbys.length > 1;
}, [groupbys]);
}, [readOnly, groupbys]);
return (
<div className={classnames('groupbys-list', { 'empty-groupbys-container': isEmpty })}>
@@ -24,6 +25,7 @@ const Groupbys = ({ groupbys, columns, onDelete, onUpdate, onMove }) => {
<GroupbyItem
key={index}
index={index}
readOnly={readOnly}
showDragBtn={showDragBtn}
groupby={groupby}
columns={columns}

View File

@@ -13,7 +13,7 @@ import Groupbys from './groupbys';
import './index.css';
const GroupbysPopover = ({ groupbys: propsGroupBys, hidePopover, onChange, target, placement, columns }) => {
const GroupbysPopover = ({ groupbys: propsGroupBys, readOnly, hidePopover, onChange, target, placement, columns }) => {
const [groupbys, setGroupbys] = useState(propsGroupBys);
const isSelectOpenRef = useState(false);
const popoverRef = useRef(null);
@@ -107,8 +107,8 @@ const GroupbysPopover = ({ groupbys: propsGroupBys, hidePopover, onChange, targe
boundariesElement={document.body}
>
<div ref={popoverRef} onClick={onPopoverInsideClick} className="sf-metadata-groupbys">
<Groupbys groupbys={groupbys} columns={columns} onDelete={deleteGroup} onUpdate={updateGroup} onMove={moveGroupbys} />
{(groupbys.length < MAX_GROUP_LEVEL) && (
<Groupbys readOnly={readOnly} groupbys={groupbys} columns={columns} onDelete={deleteGroup} onUpdate={updateGroup} onMove={moveGroupbys} />
{!readOnly && (groupbys.length < MAX_GROUP_LEVEL) && (
<CustomizeAddTool
className="popover-add-tool"
callBack={addGroupby}
@@ -128,6 +128,7 @@ const GroupbysPopover = ({ groupbys: propsGroupBys, hidePopover, onChange, targe
};
GroupbysPopover.propTypes = {
readOnly: PropTypes.bool,
target: PropTypes.oneOfType([PropTypes.string, PropTypes.object, PropTypes.node]),
groupbys: PropTypes.array,
columns: PropTypes.array,

View File

@@ -2,16 +2,19 @@ import React, { useCallback } from 'react';
import PropTypes from 'prop-types';
import { Icon, Switch } from '@seafile/sf-metadata-ui-component';
import { COLUMNS_ICON_CONFIG } from '../../../../_basic';
import classNames from 'classnames';
const HideColumnItem = ({ column, isHidden, onChange }) => {
const HideColumnItem = ({ readOnly, column, isHidden, onChange }) => {
const update = useCallback(() => {
if (readOnly) return;
onChange(column.key);
}, [column, onChange]);
}, [readOnly, column, onChange]);
return (
<div className="hide-column-item">
<div className={classNames('hide-column-item', { 'disabled': readOnly })}>
<Switch
disabled={readOnly}
checked={isHidden}
placeholder={(
<>
@@ -27,6 +30,7 @@ const HideColumnItem = ({ column, isHidden, onChange }) => {
};
HideColumnItem.propTypes = {
readOnly: PropTypes.bool,
isHidden: PropTypes.bool,
column: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,

View File

@@ -4,7 +4,7 @@ import classnames from 'classnames';
import { gettext } from '../../../../utils';
import HideColumn from './hide-column';
const HiddenColumns = ({ columns, hiddenColumns, onChange }) => {
const HiddenColumns = ({ readOnly, columns, hiddenColumns, onChange }) => {
const isEmpty = useMemo(() => {
if (!Array.isArray(columns) || columns.length === 0) return true;
return false;
@@ -17,6 +17,7 @@ const HiddenColumns = ({ columns, hiddenColumns, onChange }) => {
return (
<HideColumn
key={column.key}
readOnly={readOnly}
isHidden={hiddenColumns.includes(column.key)}
column={column}
onChange={onChange}
@@ -28,6 +29,7 @@ const HiddenColumns = ({ columns, hiddenColumns, onChange }) => {
};
HiddenColumns.propTypes = {
readOnly: PropTypes.bool,
hiddenColumns: PropTypes.array,
columns: PropTypes.array,
onChange: PropTypes.func,

View File

@@ -57,10 +57,10 @@
.sf-metadata-hide-columns-popover .hide-columns-list .hide-column-item:hover {
background: #f5f5f5;
cursor: pointer;
}
.sf-metadata-hide-columns-popover .hide-columns-list .hide-column-item:hover * {
.sf-metadata-hide-columns-popover .hide-columns-list .hide-column-item:not(.disabled):hover
.sf-metadata-hide-columns-popover .hide-columns-list .hide-column-item:not(.disabled):hover * {
cursor: pointer;
}

View File

@@ -9,7 +9,7 @@ import { getEventClassName, gettext } from '../../../utils';
import './index.css';
const HideColumnPopover = ({ hidePopover, onChange, target, placement, columns, hiddenColumns: oldHiddenColumns }) => {
const HideColumnPopover = ({ hidePopover, onChange, readOnly, target, placement, columns, hiddenColumns: oldHiddenColumns }) => {
const [searchValue, setSearchValue] = useState('');
const [hiddenColumns, setHiddenColumns] = useState(oldHiddenColumns);
const displayColumns = useMemo(() => {
@@ -104,8 +104,8 @@ const HideColumnPopover = ({ hidePopover, onChange, target, placement, columns,
<div className="sf-metadata-hide-columns-search-container">
<SearchInput placeholder={gettext('Search column')} onKeyDown={onKeyDown} onChange={onChangeSearch} autoFocus={true}/>
</div>
<HiddenColumns columns={displayColumns} hiddenColumns={hiddenColumns} onChange={hideColumn} />
{!searchValue && (
<HiddenColumns readOnly={readOnly} columns={displayColumns} hiddenColumns={hiddenColumns} onChange={hideColumn} />
{!readOnly && !searchValue && (
<div className="sf-metadata-hide-columns-operations">
<div className="sf-metadata-hide-columns-operation px-2" onClick={hideAll} aria-label={gettext('Hide all')}>{gettext('Hide all')}</div>
<div className="sf-metadata-hide-columns-operation px-2" onClick={showAll} aria-label={gettext('Show all')}>{gettext('Show all')}</div>
@@ -118,6 +118,7 @@ const HideColumnPopover = ({ hidePopover, onChange, target, placement, columns,
};
HideColumnPopover.propTypes = {
readOnly: PropTypes.bool,
placement: PropTypes.string.isRequired,
target: PropTypes.string.isRequired,
hiddenColumns: PropTypes.array.isRequired,

View File

@@ -18,19 +18,19 @@ import './index.css';
const SORT_TYPES = [SORT_TYPE.UP, SORT_TYPE.DOWN];
const propTypes = {
readOnly: PropTypes.bool,
target: PropTypes.string.isRequired,
isNeedSubmit: PropTypes.bool,
sorts: PropTypes.array,
columns: PropTypes.array.isRequired,
onSortComponentToggle: PropTypes.func,
update: PropTypes.func,
readonly: PropTypes.bool,
};
class SortPopover extends Component {
static defaultProps = {
readonly: false,
readOnly: false,
};
constructor(props) {
@@ -183,7 +183,7 @@ class SortPopover extends Component {
renderSortItem = (column, sort, index) => {
let { name, type } = column;
const { readonly } = this.props;
const { readOnly } = this.props;
let selectedColumn = {
label: (
<Fragment>
@@ -200,7 +200,7 @@ class SortPopover extends Component {
return (
<div key={'sort-item-' + index} className="sort-item">
{!readonly &&
{!readOnly &&
<div className="delete-sort" onClick={(event) => this.deleteSort(event, index)}>
<Icon iconName="fork-number"/>
</div>
@@ -208,7 +208,7 @@ class SortPopover extends Component {
<div className="condition">
<div className="sort-column">
<CustomizeSelect
isLocked={readonly}
readOnly={readOnly}
value={selectedColumn}
onSelectOption={(value) => this.onSelectColumn(value, index)}
options={this.columnsOptions}
@@ -219,7 +219,7 @@ class SortPopover extends Component {
</div>
<div className="sort-predicate ml-2">
<CustomizeSelect
isLocked={readonly}
readOnly={readOnly}
value={selectedSortType}
onSelectOption={(value) => this.onSelectSortType(value, index)}
options={this.sortTypeOptions}
@@ -235,7 +235,7 @@ class SortPopover extends Component {
};
render() {
const { target, readonly } = this.props;
const { target, readOnly } = this.props;
const { sorts } = this.state;
const isEmpty = isSortsEmpty(sorts);
return (
@@ -255,7 +255,7 @@ class SortPopover extends Component {
this.renderSortsList()
}
</div>
{!readonly &&
{!readOnly &&
<CustomizeAddTool
callBack={this.addSort}
footerName={gettext('Add sort')}
@@ -263,7 +263,7 @@ class SortPopover extends Component {
addIconClassName="popover-add-icon"
/>
}
{(this.isNeedSubmit() && !readonly) && (
{(this.isNeedSubmit() && !readOnly) && (
<div className='sf-metadata-sort-popover-footer'>
<Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button>
<Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitSorts}>{gettext('Submit')}</Button>

View File

@@ -63,6 +63,8 @@ const ViewToolBar = ({ metadataViewId }) => {
if (!view) return null;
const readOnly = !window.sfMetadataContext.canModifyView(view);
return (
<div
className="sf-metadata-tool"
@@ -73,6 +75,7 @@ const ViewToolBar = ({ metadataViewId }) => {
wrapperClass="sf-metadata-view-tool-operation-btn sf-metadata-view-tool-filter"
filtersClassName="sf-metadata-filters"
target="sf-metadata-filter-popover"
readOnly={readOnly}
filterConjunction={view.filter_conjunction}
filters={view.filters}
columns={availableColumns}
@@ -82,6 +85,7 @@ const ViewToolBar = ({ metadataViewId }) => {
<SortSetter
wrapperClass="sf-metadata-view-tool-operation-btn sf-metadata-view-tool-sort"
target="sf-metadata-sort-popover"
readOnly={readOnly}
sorts={view.sorts}
columns={viewColumns}
modifySorts={modifySorts}
@@ -89,6 +93,7 @@ const ViewToolBar = ({ metadataViewId }) => {
<GroupbySetter
wrapperClass="sf-metadata-view-tool-operation-btn sf-metadata-view-tool-groupby"
target="sf-metadata-groupby-popover"
readOnly={readOnly}
columns={viewColumns}
groupbys={view.groupbys}
modifyGroupbys={modifyGroupbys}
@@ -96,6 +101,7 @@ const ViewToolBar = ({ metadataViewId }) => {
<HideColumnSetter
wrapperClass="sf-metadata-view-tool-operation-btn sf-metadata-view-tool-hide-column"
target="sf-metadata-hide-column-popover"
readOnly={readOnly}
columns={viewColumns.slice(1)}
hiddenColumns={view.hidden_columns || []}
modifyHiddenColumns={modifyHiddenColumns}

View File

@@ -130,6 +130,11 @@ class Context {
return true;
};
canModifyView = (view) => {
if (this.permission === 'r') return false;
return true;
};
getCollaboratorFromCache(email) {
return this.collaboratorsCache[email];
}