diff --git a/frontend/src/metadata/components/cell-editors/tags-editor/index.js b/frontend/src/metadata/components/cell-editors/tags-editor/index.js index 4a6b945aa5e..f7e699e6c70 100644 --- a/frontend/src/metadata/components/cell-editors/tags-editor/index.js +++ b/frontend/src/metadata/components/cell-editors/tags-editor/index.js @@ -23,6 +23,7 @@ const TagsEditor = forwardRef(({ editorPosition = { left: 0, top: 0 }, onPressTab, updateFileTags, + modifyColumnData, }, ref) => { const { tagsData, addTag, context } = useTags(); @@ -104,12 +105,17 @@ const TagsEditor = forwardRef(({ const newValue = [...value, ...tags]; updateFileTags([{ record_id: recordId, tags: newValue, old_tags: value }]); setValue(newValue); + const options = tagsData.rows.map(tag => ({ + row_id: getTagId(tag), + display_value: getTagName(tag), + })) || []; + modifyColumnData(column.key, { options }, { options: column.data.options || [] }); }, fail_callback: () => { }, }); - }, [value, searchValue, record, addTag, updateFileTags]); + }, [value, searchValue, record, addTag, updateFileTags, modifyColumnData, column, tagsData]); const getMaxItemNum = useCallback(() => { let selectContainerStyle = getComputedStyle(editorContainerRef.current, null); diff --git a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/index.js b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/index.js index 3990d684c48..08c5048334d 100644 --- a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/index.js +++ b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/index.js @@ -16,6 +16,8 @@ import { filterTermModifierIsWithin, } from '../../../../../constants'; import FilterItemUtils from '../filter-item-utils'; +import TagsFilter from './tags-filter'; +import { getTagColor, getTagId, getTagName } from '../../../../../../tag/utils'; import './index.css'; @@ -506,6 +508,15 @@ class FilterItem extends React.Component { ); } + case CellType.TAGS: { + const options = (window.sfTagsDataStore.data?.rows || []).map(tag => ({ + id: getTagId(tag), + name: getTagName(tag), + color: getTagColor(tag), + })); + + return ; + } default: { return null; } diff --git a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.css b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.css new file mode 100644 index 00000000000..97a0e9a09b4 --- /dev/null +++ b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.css @@ -0,0 +1,28 @@ + +.sf-metadata-filters-list .sf-metadata-tag-color { + border-radius: 50%; + flex-shrink: 0; +} + +.sf-metadata-filters-list .sf-metadata-tag-name { + flex: 1; + margin-left: 4px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + color: #212529; +} + +.sf-metadata-selector-tags.sf-metadata-select .sf-metadata-option { + line-height: 20px; + padding: 5px 10px 5px 10px !important; +} + +.sf-metadata-selector-tags.sf-metadata-select .sf-metadata-option:hover { + background-color: #f7f7f7; + color: #212529; +} + +.sf-metadata-selector-tags.sf-metadata-select .selected-option-show { + text-overflow: clip; +} diff --git a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.js b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.js new file mode 100644 index 00000000000..16ee0d74b15 --- /dev/null +++ b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/filter-item/tags-filter/index.js @@ -0,0 +1,81 @@ +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { CustomizeSelect, Icon } from '@seafile/sf-metadata-ui-component'; +import { DELETED_OPTION_BACKGROUND_COLOR, DELETED_OPTION_TIPS } from '../../../../../../constants'; +import { gettext } from '../../../../../../../utils/constants'; + +import './index.css'; + +const TagsFilter = ({ options, filterTerm, readOnly, onSelectMultiple }) => { + + const selectValue = useMemo(() => { + return Array.isArray(filterTerm) && filterTerm.length > 0 && filterTerm.map((item) => { + const option = options.find(option => option.id === item); + if (!option) return null; + const optionStyle = { margin: '0 10px 0 0' }; + let optionName = null; + let optionColor = null; + + if (option) { + optionName = option.name; + optionColor = option.color; + optionStyle.background = option.color; + } else { + optionStyle.background = DELETED_OPTION_BACKGROUND_COLOR; + optionName = gettext(DELETED_OPTION_TIPS); + } + + return ( +
+ + {optionName} +
+ ); + }); + }, [filterTerm, options]); + + const dataOptions = useMemo(() => { + return options.map(option => ({ + value: { columnOption: option }, + label: ( +
+
+ + {option.name} +
+
+ {filterTerm.indexOf(option.id) > -1 && ()} +
+
+ ) + })); + }, [options, filterTerm]); + + return ( + + ); +}; + +TagsFilter.propTypes = { + filterTerm: PropTypes.oneOfType([PropTypes.array, PropTypes.string]), + readOnly: PropTypes.bool.isRequired, + onSelectMultiple: PropTypes.func.isRequired, +}; + +export default TagsFilter; diff --git a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/index.css b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/index.css index 1d6d356e83b..861e3468316 100644 --- a/frontend/src/metadata/components/popover/filter-popover/advanced-filters/index.css +++ b/frontend/src/metadata/components/popover/filter-popover/advanced-filters/index.css @@ -107,24 +107,29 @@ .filter-term .selector-single-select .sf-metadata-option:hover .select-option-name, .filter-term .selector-multiple-select .sf-metadata-option:hover .select-option-name, -.filter-term .selector-collaborator .sf-metadata-option:hover .select-option-name { +.filter-term .selector-collaborator .sf-metadata-option:hover .select-option-name, +.filter-term .selector-tags .sf-metadata-option:hover .select-option-name { color: unset; } -.sf-metadata-filters-list .selector-collaborator .selected-option-show { +.sf-metadata-filters-list .selector-collaborator .selected-option-show, +.sf-metadata-filters-list .selector-tags .selected-option-show { text-overflow: unset; } .sf-metadata-filters-list .selector-multiple-select .sf-metadata-option:hover, .sf-metadata-filters-list .selector-multiple-select .sf-metadata-option.sf-metadata-option-active, .sf-metadata-filters-list .selector-collaborator .sf-metadata-option:hover, -.sf-metadata-filters-list .selector-collaborator .sf-metadata-option.sf-metadata-option-active { +.sf-metadata-filters-list .selector-collaborator .sf-metadata-option.sf-metadata-option-active, +.sf-metadata-filters-list .selector-tags .sf-metadata-option:hover, +.sf-metadata-filters-list .selector-tags .sf-metadata-option.sf-metadata-option-active { color: #212529; background-color: #f7f7f7; } .sf-metadata-filters-list .selector-multiple-select .sf-metadata-option.sf-metadata-option-active .select-option-name, -.sf-metadata-filters-list .selector-collaborator .sf-metadata-option.sf-metadata-option-active .select-option-name { +.sf-metadata-filters-list .selector-collaborator .sf-metadata-option.sf-metadata-option-active .select-option-name, +.sf-metadata-filters-list .selector-tags .sf-metadata-option.sf-metadata-option-active .select-option-name { color: #212529; } @@ -213,13 +218,15 @@ fill: #666; } -.sf-metadata-filters-list .multiple-option-name { +.sf-metadata-filters-list .multiple-option-name, +.sf-metadata-filters-list .tags-option-name { display: flex; align-items: center; } .sf-metadata-filters-list .multiple-check-icon, -.sf-metadata-filters-list .collaborator-check-icon { +.sf-metadata-filters-list .collaborator-check-icon, +.sf-metadata-filters-list .tag-check-icon { display: inline-flex; width: 20px; height: 20px; @@ -228,13 +235,15 @@ } .sf-metadata-filters-list .multiple-check-icon .sf-metadata-icon-check-mark, -.sf-metadata-filters-list .collaborator-check-icon .sf-metadata-icon-check-mark { +.sf-metadata-filters-list .collaborator-check-icon .sf-metadata-icon-check-mark, +.sf-metadata-filters-list .tag-check-icon .sf-metadata-icon-check-mark { fill: #666 !important; font-size: 12px; } .user-select-item, -.collaborator { +.collaborator, +.tag-item { display: inline-flex; align-items: center; height: 20px; @@ -245,11 +254,13 @@ background: #eaeaea; } -.sf-metadata-filters-list .collaborator-show { +.sf-metadata-filters-list .collaborator-show, +.sf-metadata-filters-list .tags-show { flex: 1; } -.sf-metadata-filters-list .collaborator-avatar-container { +.sf-metadata-filters-list .collaborator-avatar-container, +.sf-metadata-filters-list .sf-metadata-tag-color { width: 16px; height: 16px; display: flex; @@ -262,16 +273,19 @@ border-radius: 50%; } -.sf-metadata-filters-list .collaborator-name { +.sf-metadata-filters-list .collaborator-name, +.sf-metadata-filters-list .tag-name { margin-left: 5px; max-width: 200px; } -.sf-metadata-filters-list .option-collaborator { +.sf-metadata-filters-list .option-collaborator, +.sf-metadata-filters-list .option-tag { display: flex; } -.sf-metadata-filters-list .collaborator-container { +.sf-metadata-filters-list .collaborator-container, +.sf-metadata-filters-list .sf-metadata-tag-container { flex: 1; display: flex; align-items: center; diff --git a/frontend/src/metadata/components/view-toolbar/table-view-toolbar/index.js b/frontend/src/metadata/components/view-toolbar/table-view-toolbar/index.js index 8d3bc3c6c03..e02277dedd3 100644 --- a/frontend/src/metadata/components/view-toolbar/table-view-toolbar/index.js +++ b/frontend/src/metadata/components/view-toolbar/table-view-toolbar/index.js @@ -4,7 +4,7 @@ import { FilterSetter, GroupbySetter, SortSetter, HideColumnSetter } from '../.. import { PRIVATE_COLUMN_KEY } from '../../../constants'; const TableViewToolbar = ({ - readOnly, view, collaborators, + readOnly, view, collaborators, tags, modifyFilters, modifySorts, modifyGroupbys, modifyHiddenColumns, modifyColumnOrder }) => { const viewType = useMemo(() => view.type, [view]); @@ -33,6 +33,7 @@ const TableViewToolbar = ({ modifyFilters={modifyFilters} collaborators={collaborators} viewType={viewType} + tags={tags} />