1
0
mirror of https://github.com/haiwen/seahub.git synced 2025-09-07 18:03:48 +00:00

feat: metadata filter (#6430)

Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
杨国璇
2024-07-26 17:15:52 +08:00
committed by GitHub
parent 3a06447faf
commit 1d2ee1ac52
33 changed files with 364 additions and 211 deletions

View File

@@ -18,7 +18,6 @@
"no-prototype-builtins": "off", "no-prototype-builtins": "off",
"no-restricted-globals": "off", "no-restricted-globals": "off",
"brace-style": "off", "brace-style": "off",
"no-console": "off",
"no-cond-assign": "off", "no-cond-assign": "off",
"no-var": "off", "no-var": "off",
"no-case-declarations": "off", "no-case-declarations": "off",

View File

@@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { SeafileMetadata } from '../../metadata'; import { SeafileMetadata } from '../../metadata';
import { Utils } from '../../utils/utils'; import { Utils } from '../../utils/utils';
import { gettext, siteRoot, lang, mediaUrl } from '../../utils/constants'; import { gettext, siteRoot, mediaUrl } from '../../utils/constants';
import SeafileMarkdownViewer from '../seafile-markdown-viewer'; import SeafileMarkdownViewer from '../seafile-markdown-viewer';
const propTypes = { const propTypes = {
@@ -54,13 +54,8 @@ class DirColumnFile extends React.Component {
if (this.props.content === '__sf-metadata') { if (this.props.content === '__sf-metadata') {
const { repoID, currentRepoInfo, metadataViewId } = this.props; const { repoID, currentRepoInfo, metadataViewId } = this.props;
window.sfMetadata = {
siteRoot,
lang,
mediaUrl,
};
return (<SeafileMetadata repoID={repoID} currentRepoInfo={currentRepoInfo} viewID={metadataViewId} />); return (<SeafileMetadata mediaUrl={mediaUrl} repoID={repoID} repoInfo={currentRepoInfo} viewID={metadataViewId} />);
} }
return ( return (

View File

@@ -27,7 +27,10 @@ export {
export { export {
PRIVATE_COLUMN_KEY, PRIVATE_COLUMN_KEY,
PRIVATE_COLUMN_KEYS PRIVATE_COLUMN_KEYS,
EDITABLE_PRIVATE_COLUMN_KEYS,
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
DELETABLE_PRIVATE_COLUMN_KEY,
} from './private'; } from './private';
export { export {

View File

@@ -46,3 +46,25 @@ export const PRIVATE_COLUMN_KEYS = [
PRIVATE_COLUMN_KEY.FILE_STATUS, PRIVATE_COLUMN_KEY.FILE_STATUS,
PRIVATE_COLUMN_KEY.LOCATION, PRIVATE_COLUMN_KEY.LOCATION,
]; ];
export const EDITABLE_PRIVATE_COLUMN_KEYS = [
PRIVATE_COLUMN_KEY.FILE_COLLABORATORS,
PRIVATE_COLUMN_KEY.FILE_EXPIRE_TIME,
PRIVATE_COLUMN_KEY.FILE_KEYWORDS,
PRIVATE_COLUMN_KEY.FILE_SUMMARY,
PRIVATE_COLUMN_KEY.FILE_EXPIRED,
PRIVATE_COLUMN_KEY.FILE_STATUS,
];
export const EDITABLE_DATA_PRIVATE_COLUMN_KEYS = [
];
export const DELETABLE_PRIVATE_COLUMN_KEY = [
PRIVATE_COLUMN_KEY.FILE_COLLABORATORS,
PRIVATE_COLUMN_KEY.FILE_EXPIRE_TIME,
PRIVATE_COLUMN_KEY.FILE_KEYWORDS,
PRIVATE_COLUMN_KEY.FILE_SUMMARY,
PRIVATE_COLUMN_KEY.FILE_EXPIRED,
PRIVATE_COLUMN_KEY.FILE_STATUS,
];

View File

@@ -24,6 +24,9 @@ export {
VIEW_NOT_DISPLAY_COLUMN_KEYS, VIEW_NOT_DISPLAY_COLUMN_KEYS,
PREDEFINED_COLUMN_KEYS, PREDEFINED_COLUMN_KEYS,
GEOLOCATION_FORMAT, GEOLOCATION_FORMAT,
EDITABLE_PRIVATE_COLUMN_KEYS,
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
DELETABLE_PRIVATE_COLUMN_KEY,
} from './column'; } from './column';
export { export {
FILTER_CONJUNCTION_TYPE, FILTER_CONJUNCTION_TYPE,

View File

@@ -50,6 +50,9 @@ export {
NOT_DISPLAY_COLUMN_KEYS, NOT_DISPLAY_COLUMN_KEYS,
VIEW_NOT_DISPLAY_COLUMN_KEYS, VIEW_NOT_DISPLAY_COLUMN_KEYS,
PREDEFINED_COLUMN_KEYS, PREDEFINED_COLUMN_KEYS,
EDITABLE_PRIVATE_COLUMN_KEYS,
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
DELETABLE_PRIVATE_COLUMN_KEY,
} from './constants'; } from './constants';
export { export {

View File

@@ -8,6 +8,7 @@ import {
FILTER_ERR_MSG, FILTER_ERR_MSG,
} from '../../constants/filter'; } from '../../constants/filter';
import { isDateColumn } from '../column/date'; import { isDateColumn } from '../column/date';
import { getColumnOptions } from '../column';
const TERM_TYPE_MAP = { const TERM_TYPE_MAP = {
NUMBER: 'number', NUMBER: 'number',
@@ -16,6 +17,11 @@ const TERM_TYPE_MAP = {
ARRAY: 'array', ARRAY: 'array',
}; };
const PREDICATES_REQUIRE_ARRAY_TERM = [
FILTER_PREDICATE_TYPE.IS_ANY_OF,
FILTER_PREDICATE_TYPE.IS_NONE_OF,
];
const TEXT_COLUMN_TYPES = [CellType.TEXT, CellType.FILE_NAME]; const TEXT_COLUMN_TYPES = [CellType.TEXT, CellType.FILE_NAME];
const CHECK_EMPTY_PREDICATES = [FILTER_PREDICATE_TYPE.EMPTY, FILTER_PREDICATE_TYPE.NOT_EMPTY]; const CHECK_EMPTY_PREDICATES = [FILTER_PREDICATE_TYPE.EMPTY, FILTER_PREDICATE_TYPE.NOT_EMPTY];
@@ -142,7 +148,7 @@ class ValidateFilter {
if (CHECK_EMPTY_PREDICATES.includes(predicate)) { if (CHECK_EMPTY_PREDICATES.includes(predicate)) {
return true; return true;
} }
if (array_type === CellType.SINGLE_SELECT || array_type === CellType.DEPARTMENT_SINGLE_SELECT) { if (array_type === CellType.SINGLE_SELECT) {
return this.validatePredicate(predicate, { type: CellType.MULTIPLE_SELECT }); return this.validatePredicate(predicate, { type: CellType.MULTIPLE_SELECT });
} }
if (COLLABORATOR_COLUMN_TYPES.includes(array_type)) { if (COLLABORATOR_COLUMN_TYPES.includes(array_type)) {
@@ -223,9 +229,13 @@ class ValidateFilter {
static isValidTerm(term, predicate, modifier, filterColumn) { static isValidTerm(term, predicate, modifier, filterColumn) {
switch (filterColumn.type) { switch (filterColumn.type) {
case CellType.TEXT: case CellType.TEXT:
case CellType.GEOLOCATION:
case CellType.FILE_NAME: { case CellType.FILE_NAME: {
return this.isValidTermType(term, TERM_TYPE_MAP.STRING); return this.isValidTermType(term, TERM_TYPE_MAP.STRING);
} }
case CellType.NUMBER: {
return this.isValidTermType(term, TERM_TYPE_MAP.NUMBER);
}
case CellType.CHECKBOX: case CellType.CHECKBOX:
case CellType.BOOL: { case CellType.BOOL: {
@@ -244,6 +254,24 @@ class ValidateFilter {
} }
return this.isValidTermType(term, TERM_TYPE_MAP.STRING); return this.isValidTermType(term, TERM_TYPE_MAP.STRING);
} }
case CellType.SINGLE_SELECT: {
const options = getColumnOptions(filterColumn);
if (PREDICATES_REQUIRE_ARRAY_TERM.includes(predicate)) {
if (!this.isValidTermType(term, TERM_TYPE_MAP.ARRAY)) {
return false;
}
// contains deleted option(s)
return this.isValidSelectedOptions(term, options);
}
if (!this.isValidTermType(term, TERM_TYPE_MAP.STRING)) {
return false;
}
// invalid filter_term if selected option is deleted
return !!options.find((option) => term === option.id);
}
default: { default: {
return false; return false;
} }

View File

@@ -57,7 +57,7 @@ const FileNameEditor = ({ column, record, onCommitCancel }) => {
if (fileType === 'image') { if (fileType === 'image') {
const fileExt = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase(); const fileExt = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase();
const isGIF = fileExt === 'gif'; const isGIF = fileExt === 'gif';
const useThumbnail = window.sfMetadataContext.getSetting('currentRepoInfo')?.encrypted; const useThumbnail = window.sfMetadataContext.getSetting('repoInfo')?.encrypted;
let src = ''; let src = '';
if (useThumbnail && !isGIF) { if (useThumbnail && !isGIF) {
src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`; src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`;

View File

@@ -2,7 +2,7 @@ import React, { useCallback, useMemo, useRef, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Button, UncontrolledPopover } from 'reactstrap'; import { Button, UncontrolledPopover } from 'reactstrap';
import classnames from 'classnames'; import classnames from 'classnames';
import { CellType, DEFAULT_DATE_FORMAT } from '../../../_basic'; import { CellType, DEFAULT_DATE_FORMAT, PRIVATE_COLUMN_KEY } from '../../../_basic';
import { gettext } from '../../../utils'; import { gettext } from '../../../utils';
import ObjectUtils from '../../../utils/object-utils'; import ObjectUtils from '../../../utils/object-utils';
import { ValidateColumnFormFields } from './utils'; import { ValidateColumnFormFields } from './utils';
@@ -11,6 +11,7 @@ import { useMetadata } from '../../../hooks';
import Name from './name'; import Name from './name';
import Type from './type'; import Type from './type';
import Data from './data'; import Data from './data';
import { getDefaultFileStatusOptions } from '../../../utils/column-utils';
import './index.css'; import './index.css';
@@ -73,6 +74,10 @@ const ColumnPopover = ({ target, onChange }) => {
} else if (column.type === CellType.DATE) { } else if (column.type === CellType.DATE) {
data = { format: DEFAULT_DATE_FORMAT }; data = { format: DEFAULT_DATE_FORMAT };
} }
} else {
if (column.type === CellType.SINGLE_SELECT && column.key === PRIVATE_COLUMN_KEY.FILE_STATUS) {
data = { options: getDefaultFileStatusOptions() };
}
} }
} }
onChange(columnName, column.type, { key: column.unique ? column.key : '', data }); onChange(columnName, column.type, { key: column.unique ? column.key : '', data });

View File

@@ -1,4 +1,4 @@
.filter-popover .popover { .sf-metadata-filter-popover .popover {
max-width: none; max-width: none;
min-width: 300px; min-width: 300px;
} }

View File

@@ -155,7 +155,7 @@ class FilterPopover extends Component {
target={target} target={target}
fade={false} fade={false}
hideArrow={true} hideArrow={true}
className="filter-popover" className="sf-metadata-filter-popover"
boundariesElement={document.body} boundariesElement={document.body}
> >
{({ scheduleUpdate }) => ( {({ scheduleUpdate }) => (
@@ -180,7 +180,7 @@ class FilterPopover extends Component {
addIconClassName="popover-add-icon" addIconClassName="popover-add-icon"
/> />
{this.isNeedSubmit() && ( {this.isNeedSubmit() && (
<div className='filter-popover-footer'> <div className='sf-metadata-filter-popover-footer'>
<Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button> <Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button>
<Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitFilters}>{gettext('Submit')}</Button> <Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitFilters}>{gettext('Submit')}</Button>
</div> </div>

View File

@@ -40,7 +40,7 @@ class FilterItemUtils {
<div className='select-option-name single-option-name'> <div className='select-option-name single-option-name'>
<div className="single-select-option" style={{ background: option.color, color: option.textColor || null }} title={option.name} aria-label={option.name}>{option.name}</div> <div className="single-select-option" style={{ background: option.color, color: option.textColor || null }} title={option.name} aria-label={option.name}>{option.name}</div>
<div className='single-check-icon'> <div className='single-check-icon'>
{selectedOption?.id === option.id && <i className="option-edit sf-metadata-font sf-metadata-icon-check-mark"></i>} {selectedOption?.id === option.id && (<Icon iconName="check-mark" />)}
</div> </div>
</div> </div>
) )
@@ -54,7 +54,7 @@ class FilterItemUtils {
<div className='select-option-name multiple-option-name'> <div className='select-option-name multiple-option-name'>
<div className="multiple-select-option" style={{ background: option.color, color: option.textColor }} title={option.name} aria-label={option.name}>{option.name}</div> <div className="multiple-select-option" style={{ background: option.color, color: option.textColor }} title={option.name} aria-label={option.name}>{option.name}</div>
<div className='multiple-check-icon'> <div className='multiple-check-icon'>
{filterTerm.indexOf(option.id) > -1 && <i className="option-edit sf-metadata-font sf-metadata-icon-check-mark"></i>} {filterTerm.indexOf(option.id) > -1 && (<Icon iconName="check-mark" />)}
</div> </div>
</div> </div>
) )

View File

@@ -0,0 +1,13 @@
.sf-metadata-selector-collaborator.sf-metadata-select .option {
line-height: 20px;
padding: 5px 10px 5px 10px !important;
}
.sf-metadata-selector-collaborator.sf-metadata-select .option:hover {
background-color: #f7f7f7;
color: #212529;
}
.sf-metadata-selector-collaborator.sf-metadata-select .selected-option-show {
text-overflow: clip;
}

View File

@@ -1,8 +1,10 @@
import React, { Fragment, useMemo } from 'react'; import React, { Fragment, useMemo } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { CustomizeSelect, Icon } from '@seafile/sf-metadata-ui-component'; import { CustomizeSelect, Icon } from '@seafile/sf-metadata-ui-component';
import { FILTER_PREDICATE_TYPE } from '../../../../_basic'; import { FILTER_PREDICATE_TYPE } from '../../../../../../_basic';
import { gettext } from '../../../../utils'; import { gettext } from '../../../../../../utils';
import './index.css';
const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators, placeholder, filter_predicate, onSelectCollaborator }) => { const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators, placeholder, filter_predicate, onSelectCollaborator }) => {
const supportMultipleSelectOptions = useMemo(() => { const supportMultipleSelectOptions = useMemo(() => {
@@ -73,7 +75,7 @@ const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators,
return ( return (
<CustomizeSelect <CustomizeSelect
className="selector-collaborator" className="sf-metadata-selector-collaborator"
value={selectValue ? { label: selectValue } : {}} value={selectValue ? { label: selectValue } : {}}
onSelectOption={onSelectCollaborator} onSelectOption={onSelectCollaborator}
options={options} options={options}

View File

@@ -0,0 +1,49 @@
.sf-metadata-selector-single-select .selected-option .single-select-option,
.sf-metadata-selector-multiple-select .selected-option .multiple-select-option {
display: inline-block;
margin: 0;
}
.sf-metadata-filters .filters-list .single-select-option,
.sf-metadata-filters .filters-list .multiple-select-option {
border-radius: 10px;
display: block;
font-size: 13px;
line-height: 20px;
margin: 0;
max-width: 150px;
overflow: hidden;
padding: 0 10px;
text-align: left;
text-overflow: ellipsis;
white-space: nowrap;
width: -webkit-min-content;
width: min-content;
}
.sf-metadata-selector-single-select .option,
.sf-metadata-selector-multiple-select .option {
height: 30px;
padding: 0 10px;
}
.sf-metadata-selector-single-select .option:hover,
.sf-metadata-selector-multiple-select .option:hover {
background-color: #f7f7f7;
color: #212529;
}
.sf-metadata-select .select-placeholder {
color: #868E96;
}
.sf-metadata-selector-multiple-select.sf-metadata-select .selected-option-show,
.sf-metadata-selector-single-select.sf-metadata-select .selected-option-show {
text-overflow: clip;
}
.sf-metadata-selector-single-select .select-option-name,
.sf-metadata-selector-multiple-select .select-option-name {
margin-top: 5px;
justify-content: space-between;
}

View File

@@ -9,17 +9,20 @@ import {
filterTermModifierIsWithin, filterTermModifierIsWithin,
isDateColumn, isDateColumn,
FILTER_ERR_MSG, FILTER_ERR_MSG,
} from '../../../../_basic'; getSelectColumnOptions,
} from '../../../../../_basic';
import CollaboratorFilter from './collaborator-filter'; import CollaboratorFilter from './collaborator-filter';
import FilterCalendar from './filter-calendar'; import FilterCalendar from '../filter-calendar';
import FilterItemUtils from './filter-item-utils'; import FilterItemUtils from '../filter-item-utils';
import { import {
getFilterByColumn, getUpdatedFilterBySelectSingle, getUpdatedFilterBySelectMultiple, getFilterByColumn, getUpdatedFilterBySelectSingle, getUpdatedFilterBySelectMultiple,
getUpdatedFilterByCreator, getUpdatedFilterByCollaborator, getColumnOptions, getUpdatedFilterByPredicate, getUpdatedFilterByCreator, getUpdatedFilterByCollaborator, getColumnOptions, getUpdatedFilterByPredicate,
} from '../../../../utils/filters-utils'; } from '../../../../../utils/filters-utils';
import { isCheckboxColumn } from '../../../../utils/column-utils'; import { isCheckboxColumn } from '../../../../../utils/column-utils';
import { gettext } from '../../../../utils'; import { gettext } from '../../../../../utils';
import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../../constants'; import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../../../constants';
import './index.css';
const propTypes = { const propTypes = {
index: PropTypes.number.isRequired, index: PropTypes.number.isRequired,
@@ -333,7 +336,7 @@ class FilterItem extends React.Component {
}); });
return ( return (
<CustomizeSelect <CustomizeSelect
className="selector-multiple-select" className="sf-metadata-selector-multiple-select"
value={selectedOptionNames} value={selectedOptionNames}
options={dataOptions} options={dataOptions}
onSelectOption={this.onSelectMultiple} onSelectOption={this.onSelectMultiple}
@@ -346,6 +349,12 @@ class FilterItem extends React.Component {
); );
}; };
getAllCollaborators = () => {
const collaborators = window.sfMetadata.collaborators;
const collaboratorsCache = window.sfMetadata.collaboratorsCache;
return [...collaborators, ...Object.values(collaboratorsCache)];
};
renderFilterTerm = (filterColumn) => { renderFilterTerm = (filterColumn) => {
const { index, filter, collaborators } = this.props; const { index, filter, collaborators } = this.props;
const { type } = filterColumn; const { type } = filterColumn;
@@ -410,6 +419,57 @@ class FilterItem extends React.Component {
case CellType.CHECKBOX: { case CellType.CHECKBOX: {
return this.getInputComponent('checkbox'); return this.getInputComponent('checkbox');
} }
case CellType.SINGLE_SELECT: {
// get options
const options = getSelectColumnOptions(filterColumn);
if ([FILTER_PREDICATE_TYPE.IS_ANY_OF, FILTER_PREDICATE_TYPE.IS_NONE_OF].includes(filter_predicate)) {
return this.renderMultipleSelectOption(options, filter_term);
}
let selectedOptionDom = { label: null };
if (filter_term) {
let selectedOption = options.find(option => option.id === filter_term);
const className = 'select-option-name single-select-option';
const style = selectedOption ?
{ background: selectedOption.color, color: selectedOption.textColor || null } :
{ background: DELETED_OPTION_BACKGROUND_COLOR };
const selectedOptionName = selectedOption ? selectedOption.name : gettext('deleted option');
selectedOptionDom = { label: (
<span className={className} style={style} title={selectedOptionName} aria-label={selectedOptionName}>{selectedOptionName}</span>
) };
}
let dataOptions = options.map(option => {
return FilterItemUtils.generatorSingleSelectOption(option);
});
return (
<CustomizeSelect
className="sf-metadata-selector-single-select"
value={selectedOptionDom}
options={dataOptions || []}
onSelectOption={this.onSelectSingle}
placeholder={gettext('Select an option')}
searchable={true}
searchPlaceholder={gettext('Search option')}
noOptionsPlaceholder={gettext('No options available')}
isInModal={this.props.isInModal}
/>
);
}
case CellType.COLLABORATOR: {
if (filter_predicate === FILTER_PREDICATE_TYPE.INCLUDE_ME) return null;
const allCollaborators = this.getAllCollaborators();
return (
<CollaboratorFilter
filterIndex={index}
filterTerm={filter_term || []}
filter_predicate={filter_predicate}
collaborators={allCollaborators}
placeholder={gettext('Select collaborators')}
onSelectCollaborator={this.onSelectCollaborator}
/>
);
}
default: { default: {
return null; return null;
} }

View File

@@ -226,8 +226,8 @@
.filters-list .multiple-check-icon .sf-metadata-icon-check-mark, .filters-list .multiple-check-icon .sf-metadata-icon-check-mark,
.filters-list .collaborator-check-icon .sf-metadata-icon-check-mark { .filters-list .collaborator-check-icon .sf-metadata-icon-check-mark {
fill: #798d99;
font-size: 12px; font-size: 12px;
color: #798d99;
} }
.user-select-item, .user-select-item,

View File

@@ -1,4 +1,4 @@
.filter-popover-footer { .sf-metadata-filter-popover-footer {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
@@ -25,6 +25,6 @@
fill: #c2c2c2; fill: #c2c2c2;
} }
.filter-popover .popover-add-tool.disabled { .sf-metadata-filter-popover .popover-add-tool.disabled {
color: #c2c2c2; color: #c2c2c2;
} }

View File

@@ -1,3 +1,9 @@
.sf-metadata-edit-column-options-popover .popover {
margin-left: -4px;
margin-top: 4px;
max-width: 600px;
}
.sf-metadata-edit-column-options-container { .sf-metadata-edit-column-options-container {
min-width: 400px; min-width: 400px;
height: auto; height: auto;
@@ -12,6 +18,13 @@
color: #212529; color: #212529;
} }
.sf-metadata-edit-column-options-container .none-search-result {
height: 100px;
opacity: .5;
padding: 10px;
width: 100%;
}
.sf-metadata-edit-column-options-container .sf-metadata-select-options-list { .sf-metadata-edit-column-options-container .sf-metadata-select-options-list {
margin-bottom: 0; margin-bottom: 0;
margin-top: 1rem; margin-top: 1rem;
@@ -19,3 +32,13 @@
overflow: auto; overflow: auto;
padding: 0; padding: 0;
} }
.sf-metadata-edit-column-options-container .sf-metadata-add-option {
border-top: none;
color: #666;
}
.sf-metadata-edit-column-options-container .sf-metadata-add-option .sf-metadata-add-option-icon {
fill: #666;
font-weight: 600;
}

View File

@@ -157,7 +157,7 @@ const OptionsPopover = ({ target, column, onToggle, onSubmit }) => {
<> <>
<CustomizePopover <CustomizePopover
target={target} target={target}
className="sf-metadata-edit-column-options" className="sf-metadata-edit-column-options-popover"
canHide={!deletingOptionId} canHide={!deletingOptionId}
hide={onToggle} hide={onToggle}
hideWithEsc={onToggle} hideWithEsc={onToggle}

View File

@@ -1,20 +1,20 @@
.sort-popover .popover { .sf-metadata-sort-popover .popover {
max-width: none; max-width: none;
min-width: 400px; min-width: 400px;
} }
.sort-popover .sorts-list { .sf-metadata-sort-popover .sorts-list {
min-height: 120px; min-height: 120px;
max-height: 100%; max-height: 100%;
padding: 15px; padding: 15px;
} }
.sort-popover .sorts-list .option-group { .sf-metadata-sort-popover .sorts-list .option-group {
overflow: auto; overflow: auto;
max-height: 360px; max-height: 360px;
} }
.sort-popover .empty-sorts-container { .sf-metadata-sort-popover .empty-sorts-container {
min-height: 80px; min-height: 80px;
padding: 16px; padding: 16px;
} }
@@ -51,7 +51,9 @@
} }
.sorts-list .empty-sorts-list { .sorts-list .empty-sorts-list {
color: #666666; color: #666;
font-size: 14px;
padding: 0.25rem 0.25rem 0.25rem 0;
} }
.delete-sort .sf-metadata-icon-fork-number { .delete-sort .sf-metadata-icon-fork-number {

View File

@@ -245,7 +245,7 @@ class SortPopover extends Component {
target={target} target={target}
fade={false} fade={false}
hideArrow={true} hideArrow={true}
className="sort-popover" className="sf-metadata-sort-popover"
boundariesElement={document.body} boundariesElement={document.body}
> >
<div ref={ref => this.sortPopoverRef = ref} onClick={this.onPopoverInsideClick}> <div ref={ref => this.sortPopoverRef = ref} onClick={this.onPopoverInsideClick}>
@@ -264,7 +264,7 @@ class SortPopover extends Component {
/> />
} }
{(this.isNeedSubmit() && !readonly) && ( {(this.isNeedSubmit() && !readonly) && (
<div className='sort-popover-footer'> <div className='sf-metadata-sort-popover-footer'>
<Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button> <Button className='mr-2' onClick={this.onClosePopover}>{gettext('Cancel')}</Button>
<Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitSorts}>{gettext('Submit')}</Button> <Button color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitSorts}>{gettext('Submit')}</Button>
</div> </div>

View File

@@ -49,122 +49,6 @@
box-shadow: inset 0 0 0 2px rgb(0 0 0 / 10%); box-shadow: inset 0 0 0 2px rgb(0 0 0 / 10%);
} }
.sf-metadata-wrapper .table-right-operations .new-record-btn button {
display: flex;
align-items: center;
justify-content: center;
height: 23px;
font-weight: 400;
border-color: rgba(0, 0, 0, 0.05);
}
.sf-metadata-wrapper .table-right-operations .more-operation-add-record {
padding: 0;
}
.sf-metadata-wrapper .table-right-operations .more-operation-add-record:not(:disabled):not(.disabled):active:focus {
box-shadow: none;
}
.sf-metadata-wrapper .table-right-operations .more-operation-add-record .dropdown {
display: inline-block;
width: 100%;
height: 100%;
}
.sf-metadata-wrapper .table-right-operations .add-record-dropdown-menu {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
width: 100%;
}
.sf-metadata-dropdown-menu.add-record {
margin-top: 4px;
}
.sf-metadata-wrapper .table-right-operations .more-operation-add-record .dropdown .sf-metadata-dropdown-menu {
margin-top: 2px;
}
.sf-metadata-wrapper .table-right-operations .more-operation-add-record .toggle-icon {
display: inline-block;
font-size: 12px;
transform: scale(0.8);
margin-top: 1px;
}
.sf-metadata-wrapper .table-right-operations .new-record {
font-size: 14px;
line-height: 1.5rem;
}
.sf-metadata-wrapper .table-right-operations .table-search-box .input-icon-addon.search-poll-button {
display: flex;
right: 25px;
height: 30px;
line-height: 30px;
left: auto;
text-align: center;
font-size: 12px;
min-width: 35px;
pointer-events: all;
}
.sf-metadata-wrapper .table-right-operations .table-search-box .search-poll-button .search-description {
height: 30px;
line-height: 30px;
color: #666666;
}
.search-poll-button .sf-metadata-font {
font-size: 12px;
cursor: pointer;
color: #212529;
}
.mobile-search-exchange-btn {
width: 30px;
height: 30px;
line-height: 30px;
background-color: #e5e5e5;
color: #212529;
display: block;
}
.mobile-search-exchange-btn:hover {
background-color: #ededed;
color: #666666;
}
.mobile-search-exchange-btn.mobile-search-upward {
border-radius: 2px 0 0 2px;
transform: scale(0.8, 0.8) translateX(8px);
}
.mobile-search-exchange-btn.mobile-search-backward {
border-radius: 0 2px 2px 0;
transform: scale(0.8, 0.8);
}
.search-text-clear {
cursor: pointer;
min-width: 25px;
pointer-events: all;
font-style: normal;
font-size: 18px;
font-weight: 700;
text-align: center;
line-height: 30px;
height: 30px;
color: #999;
}
.search-text-clear:hover {
color: #212529;
}
.sf-metadata-result.success { .sf-metadata-result.success {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View File

@@ -28,13 +28,12 @@ const Cell = React.memo(({
const className = useMemo(() => { const className = useMemo(() => {
const { type } = column; const { type } = column;
const canEditable = window.sfMetadataContext.canModifyCell(column); const canEditable = window.sfMetadataContext.canModifyCell(column);
return classnames('sf-metadata-result-table-cell', `sf-metadata-result-table-${type}-cell`, { return classnames('sf-metadata-result-table-cell', `sf-metadata-result-table-${type}-cell`, highlightClassName, {
'table-cell-uneditable': !canEditable || !TABLE_SUPPORT_EDIT_TYPE_MAP[type], 'table-cell-uneditable': !canEditable || !TABLE_SUPPORT_EDIT_TYPE_MAP[type],
[highlightClassName]: highlightClassName,
'last-cell': isLastCell, 'last-cell': isLastCell,
'table-last--frozen': isLastFrozenCell, 'table-last--frozen': isLastFrozenCell,
'cell-selected': isCellSelected, 'cell-selected': isCellSelected,
// 'draging-file-to-cell': , // 'dragging-file-to-cell': ,
// 'row-comment-cell': , // 'row-comment-cell': ,
}); });
}, [column, highlightClassName, isLastCell, isLastFrozenCell, isCellSelected]); }, [column, highlightClassName, isLastCell, isLastFrozenCell, isCellSelected]);

View File

@@ -1,18 +1,28 @@
import React, { useCallback } from 'react'; import React, { useCallback, useEffect, useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { UncontrolledTooltip, DropdownItem } from 'reactstrap'; import { UncontrolledTooltip, DropdownItem } from 'reactstrap';
import classnames from 'classnames'; import classnames from 'classnames';
import { Icon } from '@seafile/sf-metadata-ui-component'; import { Icon } from '@seafile/sf-metadata-ui-component';
const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className, onChange, onMouseEnter }) => { const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className, onChange, onMouseEnter }) => {
const [isShowToolTip, setToolTipShow] = useState(false);
useEffect(() => {
if (disabled) {
setToolTipShow(true);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const onClick = useCallback((event) => { const onClick = useCallback((event) => {
event.preventDefault(); event.preventDefault();
event.nativeEvent.stopImmediatePropagation();
event.stopPropagation();
}, []); }, []);
if (!disabled) { if (!disabled) {
return ( return (
<DropdownItem onClick={onChange} onMouseEnter={onMouseEnter} className={className}> <DropdownItem id={target} onClick={onChange} onMouseEnter={onMouseEnter} className={className}>
<Icon iconName={iconName} /> <Icon iconName={iconName} />
<span className="item-text">{title}</span> <span className="item-text">{title}</span>
</DropdownItem> </DropdownItem>
@@ -20,6 +30,7 @@ const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className,
} }
return ( return (
<>
<DropdownItem <DropdownItem
className={classnames('disabled', className)} className={classnames('disabled', className)}
toggle={true} toggle={true}
@@ -29,12 +40,13 @@ const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className,
> >
<Icon iconName={iconName} /> <Icon iconName={iconName} />
<span className="item-text">{title}</span> <span className="item-text">{title}</span>
{disabled && {isShowToolTip && (
<UncontrolledTooltip placement="right" target={target} fade={false} delay={{ show: 0, hide: 0 }}> <UncontrolledTooltip placement="right" target={target} fade={false} delay={{ show: 0, hide: 0 }}>
{tip} {tip}
</UncontrolledTooltip> </UncontrolledTooltip>
} )}
</DropdownItem> </DropdownItem>
</>
); );
}; };

View File

@@ -1,3 +1,7 @@
.sf-metadata-column-dropdown-menu {
margin-top: 20px;
}
.sf-metadata-column-dropdown-menu .dropdown-item .sf-metadata-icon { .sf-metadata-column-dropdown-menu .dropdown-item .sf-metadata-icon {
margin-right: 10px; margin-right: 10px;
font-size: 14px; font-size: 14px;
@@ -20,3 +24,18 @@
.sf-metadata-column-dropdown-menu .dropdown-toggle:hover::after { .sf-metadata-column-dropdown-menu .dropdown-toggle:hover::after {
color: #fff; color: #fff;
} }
.sf-metadata-column-dropdown-menu .dropdown-item.disabled,
.sf-metadata-column-dropdown-menu .dropdown-item:disabled {
pointer-events: unset !important;
}
.sf-metadata-column-dropdown-menu .disabled.dropdown-item:hover {
background-color: unset;
cursor: default;
color: #c2c2c2;
}
.sf-metadata-column-dropdown-menu .disabled.dropdown-item .sf-metadata-icon {
fill: #c2c2c2;
}

View File

@@ -4,7 +4,6 @@ import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem as DefaultDropdown
import classnames from 'classnames'; import classnames from 'classnames';
import { ModalPortal, Icon } from '@seafile/sf-metadata-ui-component'; import { ModalPortal, Icon } from '@seafile/sf-metadata-ui-component';
import { isMobile, gettext } from '../../../../../../../utils'; import { isMobile, gettext } from '../../../../../../../utils';
import { isFrozen } from '../../../../../../../utils/column-utils';
import DropdownItem from './dropdown-item'; import DropdownItem from './dropdown-item';
import { CellType, DEFAULT_DATE_FORMAT, getDateDisplayString } from '../../../../../../../_basic'; import { CellType, DEFAULT_DATE_FORMAT, getDateDisplayString } from '../../../../../../../_basic';
import { RenamePopover, OptionsPopover } from '../../../../../../popover'; import { RenamePopover, OptionsPopover } from '../../../../../../popover';
@@ -153,15 +152,12 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
}, [today, column, isMenuShow, isSubMenuShow, onChangeDateFormat, openSubMenu]); }, [today, column, isMenuShow, isSubMenuShow, onChangeDateFormat, openSubMenu]);
const renderDropdownMenu = useCallback(() => { const renderDropdownMenu = useCallback(() => {
let menuStyle = { transform: 'none' };
const { type } = column; const { type } = column;
if (!isFrozen(column)) { const canModifyColumnData = window.sfMetadataContext.canModifyColumnData(column);
menuStyle['top'] = -5; // - (container padding + menu margin) const canDeleteColumn = window.sfMetadataContext.canDeleteColumn(column);
menuStyle['left'] = - (column.width - 30); // column width - container width - padding const canRenameColumn = window.sfMetadataContext.canRenameColumn(column);
}
const canModifyColumnData = window.sfMetadataContext.canModifyColumn(column);
return ( return (
<DropdownMenu style={menuStyle} ref={menuRef} className="sf-metadata-column-dropdown-menu"> <DropdownMenu ref={menuRef} className="sf-metadata-column-dropdown-menu">
<div ref={dropdownDomRef}> <div ref={dropdownDomRef}>
{type === CellType.SINGLE_SELECT && ( {type === CellType.SINGLE_SELECT && (
<> <>
@@ -200,7 +196,7 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
<DefaultDropdownItem key="divider-item" divider /> <DefaultDropdownItem key="divider-item" divider />
)} )}
<DropdownItem <DropdownItem
disabled={!canModifyColumnData} disabled={!canRenameColumn}
target="sf-metadata-rename-column" target="sf-metadata-rename-column"
iconName="rename" iconName="rename"
title={gettext('Rename Column')} title={gettext('Rename Column')}
@@ -209,7 +205,7 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
onMouseEnter={hideSubMenu} onMouseEnter={hideSubMenu}
/> />
<DropdownItem <DropdownItem
disabled={!canModifyColumnData} disabled={!canDeleteColumn}
target="sf-metadata-delete-column" target="sf-metadata-delete-column"
iconName="delete" iconName="delete"
title={gettext('Delete Column')} title={gettext('Delete Column')}

View File

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import classnames from 'classnames'; import classnames from 'classnames';
import { UncontrolledTooltip } from 'reactstrap'; import { UncontrolledTooltip } from 'reactstrap';
import { Icon } from '@seafile/sf-metadata-ui-component'; import { Icon } from '@seafile/sf-metadata-ui-component';
import { COLUMNS_ICON_CONFIG, COLUMNS_ICON_NAME, PRIVATE_COLUMN_KEYS } from '../../../../../../_basic'; import { COLUMNS_ICON_CONFIG, COLUMNS_ICON_NAME } from '../../../../../../_basic';
import ResizeColumnHandle from './resize-column-handle'; import ResizeColumnHandle from './resize-column-handle';
import { EVENT_BUS_TYPE } from '../../../../../../constants'; import { EVENT_BUS_TYPE } from '../../../../../../constants';
import DropdownMenu from './dropdown-menu'; import DropdownMenu from './dropdown-menu';
@@ -28,7 +28,6 @@ const Cell = ({
const canEditColumnInfo = useMemo(() => { const canEditColumnInfo = useMemo(() => {
if (isHideTriangle) return false; if (isHideTriangle) return false;
if (PRIVATE_COLUMN_KEYS.includes(column.key)) return false;
return window.sfMetadataContext.canModifyColumn(column); return window.sfMetadataContext.canModifyColumn(column);
}, [isHideTriangle, column]); }, [isHideTriangle, column]);

View File

@@ -1,5 +1,6 @@
import metadataAPI from '../api'; import metadataAPI from '../api';
import { UserService, LocalStorage } from './_basic'; import { UserService, LocalStorage, PRIVATE_COLUMN_KEYS, EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
EDITABLE_PRIVATE_COLUMN_KEYS, PREDEFINED_COLUMN_KEYS } from './_basic';
import EventBus from '../../components/common/event-bus'; import EventBus from '../../components/common/event-bus';
import { username } from '../../utils/constants'; import { username } from '../../utils/constants';
@@ -12,6 +13,7 @@ class Context {
this.userService = null; this.userService = null;
this.eventBus = null; this.eventBus = null;
this.hasInit = false; this.hasInit = false;
this.permission = 'r';
} }
async init({ otherSettings }) { async init({ otherSettings }) {
@@ -21,7 +23,7 @@ class Context {
this.settings = otherSettings || {}; this.settings = otherSettings || {};
// init metadataAPI // init metadataAPI
const { mediaUrl } = this.settings; const { mediaUrl, repoInfo } = this.settings;
this.metadataAPI = metadataAPI; this.metadataAPI = metadataAPI;
// init localStorage // init localStorage
@@ -34,6 +36,8 @@ class Context {
const eventBus = new EventBus(); const eventBus = new EventBus();
this.eventBus = eventBus; this.eventBus = eventBus;
this.permission = repoInfo.permission !== 'admin' && repoInfo.permission !== 'rw' ? 'r' : 'rw';
this.hasInit = true; this.hasInit = true;
} }
@@ -44,6 +48,7 @@ class Context {
this.userService = null; this.userService = null;
this.eventBus = null; this.eventBus = null;
this.hasInit = false; this.hasInit = false;
this.permission = 'r';
}; };
getSetting = (key) => { getSetting = (key) => {
@@ -81,22 +86,46 @@ class Context {
return this.metadataAPI.getView(repoID, viewId); return this.metadataAPI.getView(repoID, viewId);
}; };
getPermission = () => {
return this.permission;
};
canModifyCell = (column) => { canModifyCell = (column) => {
if (this.permission === 'r') return false;
const { editable } = column; const { editable } = column;
if (!editable) return false; if (!editable) return false;
return true; return true;
}; };
canModifyRow = (row) => { canModifyRow = (row) => {
if (this.permission === 'r') return false;
return true; return true;
}; };
canModifyColumn = (column) => { canModifyColumn = (column) => {
if (this.permission === 'r') return false;
if (PRIVATE_COLUMN_KEYS.includes(column.key) && !EDITABLE_PRIVATE_COLUMN_KEYS.includes(column.key)) return false;
return true; return true;
}; };
getPermission = () => { canRenameColumn = (column) => {
return 'rw'; if (this.permission === 'r') return false;
if (PRIVATE_COLUMN_KEYS.includes(column.key)) return false;
return true;
};
canModifyColumnData = (column) => {
if (this.permission === 'r') return false;
const { key } = column;
if (PRIVATE_COLUMN_KEYS.includes(key)) return EDITABLE_DATA_PRIVATE_COLUMN_KEYS.includes(key);
return true;
};
canDeleteColumn = (column) => {
if (this.permission === 'r') return false;
const { key } = column;
if (PRIVATE_COLUMN_KEYS.includes(key)) return PREDEFINED_COLUMN_KEYS.includes(key);
return true;
}; };
getCollaboratorsFromCache = () => { getCollaboratorsFromCache = () => {

View File

@@ -19,6 +19,12 @@ export const CollaboratorsProvider = ({
setCollaborators(store?.collaborators || []); setCollaborators(store?.collaborators || []);
}, [store?.collaborators]); }, [store?.collaborators]);
useEffect(() => {
if (!window.sfMetadata) return;
window.sfMetadata.collaborators = collaborators;
window.sfMetadata.collaboratorsCache = collaboratorsCache;
}, [collaborators, collaboratorsCache]);
const updateCollaboratorsCache = useCallback((user) => { const updateCollaboratorsCache = useCallback((user) => {
const newCollaboratorsCache = { ...collaboratorsCacheRef.current, [user.email]: user }; const newCollaboratorsCache = { ...collaboratorsCacheRef.current, [user.email]: user };
collaboratorsCacheRef.current = newCollaboratorsCache; collaboratorsCacheRef.current = newCollaboratorsCache;

View File

@@ -12,7 +12,6 @@ export const MetadataProvider = ({
children, children,
repoID, repoID,
viewID, viewID,
currentRepoInfo,
...params ...params
}) => { }) => {
const [isLoading, setLoading] = useState(true); const [isLoading, setLoading] = useState(true);
@@ -37,11 +36,11 @@ export const MetadataProvider = ({
setLoading(true); setLoading(true);
// init context // init context
const context = new Context(); const context = new Context();
window.sfMetadata = {};
window.sfMetadataContext = context; window.sfMetadataContext = context;
window.sfMetadataContext.init({ otherSettings: params }); window.sfMetadataContext.init({ otherSettings: params });
window.sfMetadataContext.setSetting('viewID', viewID); window.sfMetadataContext.setSetting('viewID', viewID);
window.sfMetadataContext.setSetting('repoID', repoID); window.sfMetadataContext.setSetting('repoID', repoID);
window.sfMetadataContext.setSetting('currentRepoInfo', currentRepoInfo);
storeRef.current = new Store({ context: window.sfMetadataContext, repoId: repoID, viewId: viewID }); storeRef.current = new Store({ context: window.sfMetadataContext, repoId: repoID, viewId: viewID });
window.sfMetadataStore = storeRef.current; window.sfMetadataStore = storeRef.current;
storeRef.current.initStartIndex(); storeRef.current.initStartIndex();
@@ -59,6 +58,7 @@ export const MetadataProvider = ({
const unsubscribeUpdateRows = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.UPDATE_TABLE_ROWS, updateMetadata); const unsubscribeUpdateRows = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.UPDATE_TABLE_ROWS, updateMetadata);
return () => { return () => {
window.sfMetadata = {};
window.sfMetadataContext.destroy(); window.sfMetadataContext.destroy();
window.sfMetadataStore.destroy(); window.sfMetadataStore.destroy();
unsubscribeServerTableChanged(); unsubscribeServerTableChanged();
@@ -67,7 +67,7 @@ export const MetadataProvider = ({
unsubscribeUpdateRows(); unsubscribeUpdateRows();
}; };
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [repoID, viewID, currentRepoInfo]); }, [repoID, viewID]);
return ( return (
<MetadataContext.Provider value={{ isLoading, metadata, store: storeRef.current }}> <MetadataContext.Provider value={{ isLoading, metadata, store: storeRef.current }}>

View File

@@ -1,5 +1,5 @@
import { normalizeColumnData } from '../../utils/column-utils'; import { normalizeColumnData } from '../../utils/column-utils';
import { CellType } from '../../_basic'; import { CellType, PRIVATE_COLUMN_KEYS, EDITABLE_PRIVATE_COLUMN_KEYS } from '../../_basic';
class Column { class Column {
constructor(object) { constructor(object) {
@@ -8,10 +8,15 @@ class Column {
this.type = object.type || ''; this.type = object.type || '';
this.data = object.data || null; this.data = object.data || null;
this.width = object.width || 200; this.width = object.width || 200;
this.editable = object.editable || !this.key.startsWith('_') && this.type !== CellType.LONG_TEXT || false; this.editable = this.enable_edit(this.key, this.type);
this.data = normalizeColumnData(this); this.data = normalizeColumnData(this);
} }
enable_edit = (key, type) => {
if (PRIVATE_COLUMN_KEYS.includes(key)) return EDITABLE_PRIVATE_COLUMN_KEYS.includes(key);
return type !== CellType.LONG_TEXT;
};
} }
export default Column; export default Column;

View File

@@ -255,26 +255,25 @@ const getFileTypeColumnData = (column) => {
'_audio': { name: gettext('Audio'), color: '#FBD44A', textColor: '#FFFFFF', borderColor: '#E5C142', id: '_audio' }, '_audio': { name: gettext('Audio'), color: '#FBD44A', textColor: '#FFFFFF', borderColor: '#E5C142', id: '_audio' },
'_code': { name: gettext('Code'), color: '#4ad8fb', textColor: '#FFFFFF', borderColor: '#4283e5', id: '_code' }, '_code': { name: gettext('Code'), color: '#4ad8fb', textColor: '#FFFFFF', borderColor: '#4283e5', id: '_code' },
}; };
let newData = { ...data }; let newData = { ...data };
newData.options = Array.isArray(newData.options) ? newData.options.map(o => { newData.options = Array.isArray(data.options) ? data.options.map(o => {
return { ..._OPTIONS[o.name] }; return _OPTIONS[o.name];
}) : Object.keys(_OPTIONS); }) : Object.values(_OPTIONS);
return newData; return newData;
}; };
export const getDefaultFileStatusOptions = () => {
return [
{ name: gettext('Draft'), color: '#EED5FF', textColor: '#202428', id: '_draft' },
{ name: gettext('In review'), color: '#FFFDCF', textColor: '#202428', id: '_in_review' },
{ name: gettext('Done'), color: '#59CB74', textColor: '#FFFFFF', borderColor: '#844BD2', id: '_done' },
];
};
const getFileStatusColumnData = (column) => { const getFileStatusColumnData = (column) => {
const { data } = column; const { data } = column;
const _OPTIONS = {
'_draft': { name: gettext('Draft'), color: '#EED5FF', textColor: '#202428', id: '_draft' },
'_in_review': { name: gettext('In review'), color: '#FFFDCF', textColor: '#202428', id: '_in_review' },
'_done': { name: gettext('Done'), color: '#59CB74', textColor: '#FFFFFF', borderColor: '#844BD2', id: '_done' },
};
let newData = { ...data }; let newData = { ...data };
newData.options = Array.isArray(newData.options) ? newData.options.map(o => { newData.options = Array.isArray(data?.options) ? data.options : getDefaultFileStatusOptions();
return { ..._OPTIONS[o.name] };
}) : Object.keys(_OPTIONS);
return newData; return newData;
}; };
@@ -305,7 +304,6 @@ export const normalizeColumns = (columns) => {
type: columnType, type: columnType,
name: getColumnName(key, name), name: getColumnName(key, name),
width: columnsWidth[key] || 200, width: columnsWidth[key] || 200,
editable: !key.startsWith('_') && columnType !== CellType.LONG_TEXT
}; };
}).filter(column => !NOT_DISPLAY_COLUMN_KEYS.includes(column.key)); }).filter(column => !NOT_DISPLAY_COLUMN_KEYS.includes(column.key));
let displayColumns = []; let displayColumns = [];
@@ -332,7 +330,6 @@ export function canEdit(col, record, enableCellSelect) {
if (col.editable != null && typeof (col.editable) === 'function') { if (col.editable != null && typeof (col.editable) === 'function') {
return enableCellSelect === true && col.editable(record); return enableCellSelect === true && col.editable(record);
} }
console.log(col);
return enableCellSelect === true && !!col.editable; return enableCellSelect === true && !!col.editable;
} }