mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-05 00:43:53 +00:00
feat: metadata filter (#6430)
Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
@@ -18,7 +18,6 @@
|
||||
"no-prototype-builtins": "off",
|
||||
"no-restricted-globals": "off",
|
||||
"brace-style": "off",
|
||||
"no-console": "off",
|
||||
"no-cond-assign": "off",
|
||||
"no-var": "off",
|
||||
"no-case-declarations": "off",
|
||||
|
@@ -2,7 +2,7 @@ import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { SeafileMetadata } from '../../metadata';
|
||||
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';
|
||||
|
||||
const propTypes = {
|
||||
@@ -54,13 +54,8 @@ class DirColumnFile extends React.Component {
|
||||
|
||||
if (this.props.content === '__sf-metadata') {
|
||||
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 (
|
||||
|
@@ -27,7 +27,10 @@ export {
|
||||
|
||||
export {
|
||||
PRIVATE_COLUMN_KEY,
|
||||
PRIVATE_COLUMN_KEYS
|
||||
PRIVATE_COLUMN_KEYS,
|
||||
EDITABLE_PRIVATE_COLUMN_KEYS,
|
||||
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
|
||||
DELETABLE_PRIVATE_COLUMN_KEY,
|
||||
} from './private';
|
||||
|
||||
export {
|
||||
|
@@ -46,3 +46,25 @@ export const PRIVATE_COLUMN_KEYS = [
|
||||
PRIVATE_COLUMN_KEY.FILE_STATUS,
|
||||
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,
|
||||
];
|
||||
|
@@ -24,6 +24,9 @@ export {
|
||||
VIEW_NOT_DISPLAY_COLUMN_KEYS,
|
||||
PREDEFINED_COLUMN_KEYS,
|
||||
GEOLOCATION_FORMAT,
|
||||
EDITABLE_PRIVATE_COLUMN_KEYS,
|
||||
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
|
||||
DELETABLE_PRIVATE_COLUMN_KEY,
|
||||
} from './column';
|
||||
export {
|
||||
FILTER_CONJUNCTION_TYPE,
|
||||
|
@@ -50,6 +50,9 @@ export {
|
||||
NOT_DISPLAY_COLUMN_KEYS,
|
||||
VIEW_NOT_DISPLAY_COLUMN_KEYS,
|
||||
PREDEFINED_COLUMN_KEYS,
|
||||
EDITABLE_PRIVATE_COLUMN_KEYS,
|
||||
EDITABLE_DATA_PRIVATE_COLUMN_KEYS,
|
||||
DELETABLE_PRIVATE_COLUMN_KEY,
|
||||
} from './constants';
|
||||
|
||||
export {
|
||||
|
@@ -8,6 +8,7 @@ import {
|
||||
FILTER_ERR_MSG,
|
||||
} from '../../constants/filter';
|
||||
import { isDateColumn } from '../column/date';
|
||||
import { getColumnOptions } from '../column';
|
||||
|
||||
const TERM_TYPE_MAP = {
|
||||
NUMBER: 'number',
|
||||
@@ -16,6 +17,11 @@ const TERM_TYPE_MAP = {
|
||||
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 CHECK_EMPTY_PREDICATES = [FILTER_PREDICATE_TYPE.EMPTY, FILTER_PREDICATE_TYPE.NOT_EMPTY];
|
||||
@@ -142,7 +148,7 @@ class ValidateFilter {
|
||||
if (CHECK_EMPTY_PREDICATES.includes(predicate)) {
|
||||
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 });
|
||||
}
|
||||
if (COLLABORATOR_COLUMN_TYPES.includes(array_type)) {
|
||||
@@ -223,9 +229,13 @@ class ValidateFilter {
|
||||
static isValidTerm(term, predicate, modifier, filterColumn) {
|
||||
switch (filterColumn.type) {
|
||||
case CellType.TEXT:
|
||||
case CellType.GEOLOCATION:
|
||||
case CellType.FILE_NAME: {
|
||||
return this.isValidTermType(term, TERM_TYPE_MAP.STRING);
|
||||
}
|
||||
case CellType.NUMBER: {
|
||||
return this.isValidTermType(term, TERM_TYPE_MAP.NUMBER);
|
||||
}
|
||||
|
||||
case CellType.CHECKBOX:
|
||||
case CellType.BOOL: {
|
||||
@@ -244,6 +254,24 @@ class ValidateFilter {
|
||||
}
|
||||
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: {
|
||||
return false;
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ const FileNameEditor = ({ column, record, onCommitCancel }) => {
|
||||
if (fileType === 'image') {
|
||||
const fileExt = fileName.substr(fileName.lastIndexOf('.') + 1).toLowerCase();
|
||||
const isGIF = fileExt === 'gif';
|
||||
const useThumbnail = window.sfMetadataContext.getSetting('currentRepoInfo')?.encrypted;
|
||||
const useThumbnail = window.sfMetadataContext.getSetting('repoInfo')?.encrypted;
|
||||
let src = '';
|
||||
if (useThumbnail && !isGIF) {
|
||||
src = `${siteRoot}thumbnail/${repoID}/${thumbnailSizeForOriginal}${path}`;
|
||||
|
@@ -2,7 +2,7 @@ import React, { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Button, UncontrolledPopover } from 'reactstrap';
|
||||
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 ObjectUtils from '../../../utils/object-utils';
|
||||
import { ValidateColumnFormFields } from './utils';
|
||||
@@ -11,6 +11,7 @@ import { useMetadata } from '../../../hooks';
|
||||
import Name from './name';
|
||||
import Type from './type';
|
||||
import Data from './data';
|
||||
import { getDefaultFileStatusOptions } from '../../../utils/column-utils';
|
||||
|
||||
import './index.css';
|
||||
|
||||
@@ -73,6 +74,10 @@ const ColumnPopover = ({ target, onChange }) => {
|
||||
} else if (column.type === CellType.DATE) {
|
||||
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 });
|
||||
|
@@ -1,4 +1,4 @@
|
||||
.filter-popover .popover {
|
||||
.sf-metadata-filter-popover .popover {
|
||||
max-width: none;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
@@ -155,7 +155,7 @@ class FilterPopover extends Component {
|
||||
target={target}
|
||||
fade={false}
|
||||
hideArrow={true}
|
||||
className="filter-popover"
|
||||
className="sf-metadata-filter-popover"
|
||||
boundariesElement={document.body}
|
||||
>
|
||||
{({ scheduleUpdate }) => (
|
||||
@@ -180,7 +180,7 @@ class FilterPopover extends Component {
|
||||
addIconClassName="popover-add-icon"
|
||||
/>
|
||||
{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 color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitFilters}>{gettext('Submit')}</Button>
|
||||
</div>
|
||||
|
@@ -40,7 +40,7 @@ class FilterItemUtils {
|
||||
<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-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>
|
||||
)
|
||||
@@ -54,7 +54,7 @@ class FilterItemUtils {
|
||||
<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-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>
|
||||
)
|
||||
|
@@ -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;
|
||||
}
|
@@ -1,8 +1,10 @@
|
||||
import React, { Fragment, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { CustomizeSelect, Icon } from '@seafile/sf-metadata-ui-component';
|
||||
import { FILTER_PREDICATE_TYPE } from '../../../../_basic';
|
||||
import { gettext } from '../../../../utils';
|
||||
import { FILTER_PREDICATE_TYPE } from '../../../../../../_basic';
|
||||
import { gettext } from '../../../../../../utils';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators, placeholder, filter_predicate, onSelectCollaborator }) => {
|
||||
const supportMultipleSelectOptions = useMemo(() => {
|
||||
@@ -73,7 +75,7 @@ const CollaboratorFilter = ({ isLocked, filterIndex, filterTerm, collaborators,
|
||||
|
||||
return (
|
||||
<CustomizeSelect
|
||||
className="selector-collaborator"
|
||||
className="sf-metadata-selector-collaborator"
|
||||
value={selectValue ? { label: selectValue } : {}}
|
||||
onSelectOption={onSelectCollaborator}
|
||||
options={options}
|
@@ -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;
|
||||
}
|
@@ -9,17 +9,20 @@ import {
|
||||
filterTermModifierIsWithin,
|
||||
isDateColumn,
|
||||
FILTER_ERR_MSG,
|
||||
} from '../../../../_basic';
|
||||
getSelectColumnOptions,
|
||||
} from '../../../../../_basic';
|
||||
import CollaboratorFilter from './collaborator-filter';
|
||||
import FilterCalendar from './filter-calendar';
|
||||
import FilterItemUtils from './filter-item-utils';
|
||||
import FilterCalendar from '../filter-calendar';
|
||||
import FilterItemUtils from '../filter-item-utils';
|
||||
import {
|
||||
getFilterByColumn, getUpdatedFilterBySelectSingle, getUpdatedFilterBySelectMultiple,
|
||||
getUpdatedFilterByCreator, getUpdatedFilterByCollaborator, getColumnOptions, getUpdatedFilterByPredicate,
|
||||
} from '../../../../utils/filters-utils';
|
||||
import { isCheckboxColumn } from '../../../../utils/column-utils';
|
||||
import { gettext } from '../../../../utils';
|
||||
import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../../constants';
|
||||
} from '../../../../../utils/filters-utils';
|
||||
import { isCheckboxColumn } from '../../../../../utils/column-utils';
|
||||
import { gettext } from '../../../../../utils';
|
||||
import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../../../constants';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const propTypes = {
|
||||
index: PropTypes.number.isRequired,
|
||||
@@ -333,7 +336,7 @@ class FilterItem extends React.Component {
|
||||
});
|
||||
return (
|
||||
<CustomizeSelect
|
||||
className="selector-multiple-select"
|
||||
className="sf-metadata-selector-multiple-select"
|
||||
value={selectedOptionNames}
|
||||
options={dataOptions}
|
||||
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) => {
|
||||
const { index, filter, collaborators } = this.props;
|
||||
const { type } = filterColumn;
|
||||
@@ -410,6 +419,57 @@ class FilterItem extends React.Component {
|
||||
case CellType.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: {
|
||||
return null;
|
||||
}
|
@@ -226,8 +226,8 @@
|
||||
|
||||
.filters-list .multiple-check-icon .sf-metadata-icon-check-mark,
|
||||
.filters-list .collaborator-check-icon .sf-metadata-icon-check-mark {
|
||||
fill: #798d99;
|
||||
font-size: 12px;
|
||||
color: #798d99;
|
||||
}
|
||||
|
||||
.user-select-item,
|
||||
|
@@ -1,4 +1,4 @@
|
||||
.filter-popover-footer {
|
||||
.sf-metadata-filter-popover-footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
@@ -25,6 +25,6 @@
|
||||
fill: #c2c2c2;
|
||||
}
|
||||
|
||||
.filter-popover .popover-add-tool.disabled {
|
||||
.sf-metadata-filter-popover .popover-add-tool.disabled {
|
||||
color: #c2c2c2;
|
||||
}
|
||||
|
@@ -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 {
|
||||
min-width: 400px;
|
||||
height: auto;
|
||||
@@ -12,6 +18,13 @@
|
||||
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 {
|
||||
margin-bottom: 0;
|
||||
margin-top: 1rem;
|
||||
@@ -19,3 +32,13 @@
|
||||
overflow: auto;
|
||||
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;
|
||||
}
|
||||
|
@@ -157,7 +157,7 @@ const OptionsPopover = ({ target, column, onToggle, onSubmit }) => {
|
||||
<>
|
||||
<CustomizePopover
|
||||
target={target}
|
||||
className="sf-metadata-edit-column-options"
|
||||
className="sf-metadata-edit-column-options-popover"
|
||||
canHide={!deletingOptionId}
|
||||
hide={onToggle}
|
||||
hideWithEsc={onToggle}
|
||||
|
@@ -1,20 +1,20 @@
|
||||
.sort-popover .popover {
|
||||
.sf-metadata-sort-popover .popover {
|
||||
max-width: none;
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.sort-popover .sorts-list {
|
||||
.sf-metadata-sort-popover .sorts-list {
|
||||
min-height: 120px;
|
||||
max-height: 100%;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.sort-popover .sorts-list .option-group {
|
||||
.sf-metadata-sort-popover .sorts-list .option-group {
|
||||
overflow: auto;
|
||||
max-height: 360px;
|
||||
}
|
||||
|
||||
.sort-popover .empty-sorts-container {
|
||||
.sf-metadata-sort-popover .empty-sorts-container {
|
||||
min-height: 80px;
|
||||
padding: 16px;
|
||||
}
|
||||
@@ -51,7 +51,9 @@
|
||||
}
|
||||
|
||||
.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 {
|
||||
|
@@ -245,7 +245,7 @@ class SortPopover extends Component {
|
||||
target={target}
|
||||
fade={false}
|
||||
hideArrow={true}
|
||||
className="sort-popover"
|
||||
className="sf-metadata-sort-popover"
|
||||
boundariesElement={document.body}
|
||||
>
|
||||
<div ref={ref => this.sortPopoverRef = ref} onClick={this.onPopoverInsideClick}>
|
||||
@@ -264,7 +264,7 @@ class SortPopover extends Component {
|
||||
/>
|
||||
}
|
||||
{(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 color="primary" disabled={this.state.isSubmitDisabled} onClick={this.onSubmitSorts}>{gettext('Submit')}</Button>
|
||||
</div>
|
||||
|
@@ -49,122 +49,6 @@
|
||||
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 {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@@ -28,13 +28,12 @@ const Cell = React.memo(({
|
||||
const className = useMemo(() => {
|
||||
const { type } = 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],
|
||||
[highlightClassName]: highlightClassName,
|
||||
'last-cell': isLastCell,
|
||||
'table-last--frozen': isLastFrozenCell,
|
||||
'cell-selected': isCellSelected,
|
||||
// 'draging-file-to-cell': ,
|
||||
// 'dragging-file-to-cell': ,
|
||||
// 'row-comment-cell': ,
|
||||
});
|
||||
}, [column, highlightClassName, isLastCell, isLastFrozenCell, isCellSelected]);
|
||||
|
@@ -1,18 +1,28 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { UncontrolledTooltip, DropdownItem } from 'reactstrap';
|
||||
import classnames from 'classnames';
|
||||
import { Icon } from '@seafile/sf-metadata-ui-component';
|
||||
|
||||
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) => {
|
||||
event.preventDefault();
|
||||
event.nativeEvent.stopImmediatePropagation();
|
||||
event.stopPropagation();
|
||||
}, []);
|
||||
|
||||
if (!disabled) {
|
||||
return (
|
||||
<DropdownItem onClick={onChange} onMouseEnter={onMouseEnter} className={className}>
|
||||
<DropdownItem id={target} onClick={onChange} onMouseEnter={onMouseEnter} className={className}>
|
||||
<Icon iconName={iconName} />
|
||||
<span className="item-text">{title}</span>
|
||||
</DropdownItem>
|
||||
@@ -20,6 +30,7 @@ const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className,
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownItem
|
||||
className={classnames('disabled', className)}
|
||||
toggle={true}
|
||||
@@ -29,12 +40,13 @@ const ColumnDropdownItem = ({ disabled, iconName, target, title, tip, className,
|
||||
>
|
||||
<Icon iconName={iconName} />
|
||||
<span className="item-text">{title}</span>
|
||||
{disabled &&
|
||||
{isShowToolTip && (
|
||||
<UncontrolledTooltip placement="right" target={target} fade={false} delay={{ show: 0, hide: 0 }}>
|
||||
{tip}
|
||||
</UncontrolledTooltip>
|
||||
}
|
||||
)}
|
||||
</DropdownItem>
|
||||
</>
|
||||
);
|
||||
|
||||
};
|
||||
|
@@ -1,3 +1,7 @@
|
||||
.sf-metadata-column-dropdown-menu {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.sf-metadata-column-dropdown-menu .dropdown-item .sf-metadata-icon {
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
@@ -20,3 +24,18 @@
|
||||
.sf-metadata-column-dropdown-menu .dropdown-toggle:hover::after {
|
||||
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;
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import { Dropdown, DropdownToggle, DropdownMenu, DropdownItem as DefaultDropdown
|
||||
import classnames from 'classnames';
|
||||
import { ModalPortal, Icon } from '@seafile/sf-metadata-ui-component';
|
||||
import { isMobile, gettext } from '../../../../../../../utils';
|
||||
import { isFrozen } from '../../../../../../../utils/column-utils';
|
||||
import DropdownItem from './dropdown-item';
|
||||
import { CellType, DEFAULT_DATE_FORMAT, getDateDisplayString } from '../../../../../../../_basic';
|
||||
import { RenamePopover, OptionsPopover } from '../../../../../../popover';
|
||||
@@ -153,15 +152,12 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
|
||||
}, [today, column, isMenuShow, isSubMenuShow, onChangeDateFormat, openSubMenu]);
|
||||
|
||||
const renderDropdownMenu = useCallback(() => {
|
||||
let menuStyle = { transform: 'none' };
|
||||
const { type } = column;
|
||||
if (!isFrozen(column)) {
|
||||
menuStyle['top'] = -5; // - (container padding + menu margin)
|
||||
menuStyle['left'] = - (column.width - 30); // column width - container width - padding
|
||||
}
|
||||
const canModifyColumnData = window.sfMetadataContext.canModifyColumn(column);
|
||||
const canModifyColumnData = window.sfMetadataContext.canModifyColumnData(column);
|
||||
const canDeleteColumn = window.sfMetadataContext.canDeleteColumn(column);
|
||||
const canRenameColumn = window.sfMetadataContext.canRenameColumn(column);
|
||||
return (
|
||||
<DropdownMenu style={menuStyle} ref={menuRef} className="sf-metadata-column-dropdown-menu">
|
||||
<DropdownMenu ref={menuRef} className="sf-metadata-column-dropdown-menu">
|
||||
<div ref={dropdownDomRef}>
|
||||
{type === CellType.SINGLE_SELECT && (
|
||||
<>
|
||||
@@ -200,7 +196,7 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
|
||||
<DefaultDropdownItem key="divider-item" divider />
|
||||
)}
|
||||
<DropdownItem
|
||||
disabled={!canModifyColumnData}
|
||||
disabled={!canRenameColumn}
|
||||
target="sf-metadata-rename-column"
|
||||
iconName="rename"
|
||||
title={gettext('Rename Column')}
|
||||
@@ -209,7 +205,7 @@ const HeaderDropdownMenu = ({ column, renameColumn, modifyColumnData, deleteColu
|
||||
onMouseEnter={hideSubMenu}
|
||||
/>
|
||||
<DropdownItem
|
||||
disabled={!canModifyColumnData}
|
||||
disabled={!canDeleteColumn}
|
||||
target="sf-metadata-delete-column"
|
||||
iconName="delete"
|
||||
title={gettext('Delete Column')}
|
||||
|
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
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 { EVENT_BUS_TYPE } from '../../../../../../constants';
|
||||
import DropdownMenu from './dropdown-menu';
|
||||
@@ -28,7 +28,6 @@ const Cell = ({
|
||||
|
||||
const canEditColumnInfo = useMemo(() => {
|
||||
if (isHideTriangle) return false;
|
||||
if (PRIVATE_COLUMN_KEYS.includes(column.key)) return false;
|
||||
return window.sfMetadataContext.canModifyColumn(column);
|
||||
}, [isHideTriangle, column]);
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
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 { username } from '../../utils/constants';
|
||||
|
||||
@@ -12,6 +13,7 @@ class Context {
|
||||
this.userService = null;
|
||||
this.eventBus = null;
|
||||
this.hasInit = false;
|
||||
this.permission = 'r';
|
||||
}
|
||||
|
||||
async init({ otherSettings }) {
|
||||
@@ -21,7 +23,7 @@ class Context {
|
||||
this.settings = otherSettings || {};
|
||||
|
||||
// init metadataAPI
|
||||
const { mediaUrl } = this.settings;
|
||||
const { mediaUrl, repoInfo } = this.settings;
|
||||
this.metadataAPI = metadataAPI;
|
||||
|
||||
// init localStorage
|
||||
@@ -34,6 +36,8 @@ class Context {
|
||||
const eventBus = new EventBus();
|
||||
this.eventBus = eventBus;
|
||||
|
||||
this.permission = repoInfo.permission !== 'admin' && repoInfo.permission !== 'rw' ? 'r' : 'rw';
|
||||
|
||||
this.hasInit = true;
|
||||
}
|
||||
|
||||
@@ -44,6 +48,7 @@ class Context {
|
||||
this.userService = null;
|
||||
this.eventBus = null;
|
||||
this.hasInit = false;
|
||||
this.permission = 'r';
|
||||
};
|
||||
|
||||
getSetting = (key) => {
|
||||
@@ -81,22 +86,46 @@ class Context {
|
||||
return this.metadataAPI.getView(repoID, viewId);
|
||||
};
|
||||
|
||||
getPermission = () => {
|
||||
return this.permission;
|
||||
};
|
||||
|
||||
canModifyCell = (column) => {
|
||||
if (this.permission === 'r') return false;
|
||||
const { editable } = column;
|
||||
if (!editable) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
canModifyRow = (row) => {
|
||||
if (this.permission === 'r') return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
getPermission = () => {
|
||||
return 'rw';
|
||||
canRenameColumn = (column) => {
|
||||
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 = () => {
|
||||
|
@@ -19,6 +19,12 @@ export const CollaboratorsProvider = ({
|
||||
setCollaborators(store?.collaborators || []);
|
||||
}, [store?.collaborators]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!window.sfMetadata) return;
|
||||
window.sfMetadata.collaborators = collaborators;
|
||||
window.sfMetadata.collaboratorsCache = collaboratorsCache;
|
||||
}, [collaborators, collaboratorsCache]);
|
||||
|
||||
const updateCollaboratorsCache = useCallback((user) => {
|
||||
const newCollaboratorsCache = { ...collaboratorsCacheRef.current, [user.email]: user };
|
||||
collaboratorsCacheRef.current = newCollaboratorsCache;
|
||||
|
@@ -12,7 +12,6 @@ export const MetadataProvider = ({
|
||||
children,
|
||||
repoID,
|
||||
viewID,
|
||||
currentRepoInfo,
|
||||
...params
|
||||
}) => {
|
||||
const [isLoading, setLoading] = useState(true);
|
||||
@@ -37,11 +36,11 @@ export const MetadataProvider = ({
|
||||
setLoading(true);
|
||||
// init context
|
||||
const context = new Context();
|
||||
window.sfMetadata = {};
|
||||
window.sfMetadataContext = context;
|
||||
window.sfMetadataContext.init({ otherSettings: params });
|
||||
window.sfMetadataContext.setSetting('viewID', viewID);
|
||||
window.sfMetadataContext.setSetting('repoID', repoID);
|
||||
window.sfMetadataContext.setSetting('currentRepoInfo', currentRepoInfo);
|
||||
storeRef.current = new Store({ context: window.sfMetadataContext, repoId: repoID, viewId: viewID });
|
||||
window.sfMetadataStore = storeRef.current;
|
||||
storeRef.current.initStartIndex();
|
||||
@@ -59,6 +58,7 @@ export const MetadataProvider = ({
|
||||
const unsubscribeUpdateRows = window.sfMetadataContext.eventBus.subscribe(EVENT_BUS_TYPE.UPDATE_TABLE_ROWS, updateMetadata);
|
||||
|
||||
return () => {
|
||||
window.sfMetadata = {};
|
||||
window.sfMetadataContext.destroy();
|
||||
window.sfMetadataStore.destroy();
|
||||
unsubscribeServerTableChanged();
|
||||
@@ -67,7 +67,7 @@ export const MetadataProvider = ({
|
||||
unsubscribeUpdateRows();
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [repoID, viewID, currentRepoInfo]);
|
||||
}, [repoID, viewID]);
|
||||
|
||||
return (
|
||||
<MetadataContext.Provider value={{ isLoading, metadata, store: storeRef.current }}>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { normalizeColumnData } from '../../utils/column-utils';
|
||||
import { CellType } from '../../_basic';
|
||||
import { CellType, PRIVATE_COLUMN_KEYS, EDITABLE_PRIVATE_COLUMN_KEYS } from '../../_basic';
|
||||
|
||||
class Column {
|
||||
constructor(object) {
|
||||
@@ -8,10 +8,15 @@ class Column {
|
||||
this.type = object.type || '';
|
||||
this.data = object.data || null;
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
@@ -255,26 +255,25 @@ const getFileTypeColumnData = (column) => {
|
||||
'_audio': { name: gettext('Audio'), color: '#FBD44A', textColor: '#FFFFFF', borderColor: '#E5C142', id: '_audio' },
|
||||
'_code': { name: gettext('Code'), color: '#4ad8fb', textColor: '#FFFFFF', borderColor: '#4283e5', id: '_code' },
|
||||
};
|
||||
|
||||
let newData = { ...data };
|
||||
newData.options = Array.isArray(newData.options) ? newData.options.map(o => {
|
||||
return { ..._OPTIONS[o.name] };
|
||||
}) : Object.keys(_OPTIONS);
|
||||
newData.options = Array.isArray(data.options) ? data.options.map(o => {
|
||||
return _OPTIONS[o.name];
|
||||
}) : Object.values(_OPTIONS);
|
||||
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 { 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 };
|
||||
newData.options = Array.isArray(newData.options) ? newData.options.map(o => {
|
||||
return { ..._OPTIONS[o.name] };
|
||||
}) : Object.keys(_OPTIONS);
|
||||
newData.options = Array.isArray(data?.options) ? data.options : getDefaultFileStatusOptions();
|
||||
return newData;
|
||||
};
|
||||
|
||||
@@ -305,7 +304,6 @@ export const normalizeColumns = (columns) => {
|
||||
type: columnType,
|
||||
name: getColumnName(key, name),
|
||||
width: columnsWidth[key] || 200,
|
||||
editable: !key.startsWith('_') && columnType !== CellType.LONG_TEXT
|
||||
};
|
||||
}).filter(column => !NOT_DISPLAY_COLUMN_KEYS.includes(column.key));
|
||||
let displayColumns = [];
|
||||
@@ -332,7 +330,6 @@ export function canEdit(col, record, enableCellSelect) {
|
||||
if (col.editable != null && typeof (col.editable) === 'function') {
|
||||
return enableCellSelect === true && col.editable(record);
|
||||
}
|
||||
console.log(col);
|
||||
return enableCellSelect === true && !!col.editable;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user