diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ebd3f2f40f..2b74c47a91 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -18,8 +18,8 @@ "@seafile/resumablejs": "1.1.16", "@seafile/sdoc-editor": "^1.0.64", "@seafile/seafile-calendar": "0.0.12", - "@seafile/seafile-editor": "1.0.109", - "@seafile/sf-metadata-ui-component": "^0.0.28", + "@seafile/seafile-editor": "1.0.114", + "@seafile/sf-metadata-ui-component": "^0.0.29", "@uiw/codemirror-extensions-langs": "^4.19.4", "@uiw/react-codemirror": "^4.19.4", "axios": "^1.7.4", @@ -4982,9 +4982,9 @@ } }, "node_modules/@seafile/seafile-editor": { - "version": "1.0.109", - "resolved": "https://registry.npmjs.org/@seafile/seafile-editor/-/seafile-editor-1.0.109.tgz", - "integrity": "sha512-zj5WiflAgiOpW6fXYigFSDB1XHYPHFxET7Gr3Dc0s3UA5S4Vexl9Yjf/oqX0HHu2jHX+fbtYkFoh/F29AGz39A==", + "version": "1.0.114", + "resolved": "https://registry.npmjs.org/@seafile/seafile-editor/-/seafile-editor-1.0.114.tgz", + "integrity": "sha512-4P7wJhNqK8WrJ1+8OPPo9mP/GNnfTv07bq6+B3DJ46syqIAJzy3KF7GC0enVfOaJm7jOEmwdvu3b00/a3ruBSw==", "dependencies": { "@seafile/react-image-lightbox": "2.0.5", "classnames": "2.3.2", @@ -5092,9 +5092,9 @@ } }, "node_modules/@seafile/sf-metadata-ui-component": { - "version": "0.0.28", - "resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.28.tgz", - "integrity": "sha512-jKrA6Q8q+8jS2sMVPEoddhRZ1rWpTL3zWyRryKvYlAPu7A2pW/uqlB9tyw1qumCwkhH8cYtjgKZzmD9pfeBmtQ==", + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.29.tgz", + "integrity": "sha512-sQwlqbdv2qJs/Qh+jyxtSJ57I+FeV51T7JwYXaL29VbB9EC9/Af6EfZ05wiPu+FH0aciNDa1thxQtj8l67JRLA==", "dependencies": { "@seafile/seafile-calendar": "0.0.24", "@seafile/seafile-editor": "~1.0.102", diff --git a/frontend/package.json b/frontend/package.json index 632c94c809..c8209deb42 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,8 +13,8 @@ "@seafile/resumablejs": "1.1.16", "@seafile/sdoc-editor": "^1.0.64", "@seafile/seafile-calendar": "0.0.12", - "@seafile/seafile-editor": "1.0.109", - "@seafile/sf-metadata-ui-component": "^0.0.28", + "@seafile/seafile-editor": "1.0.114", + "@seafile/sf-metadata-ui-component": "^0.0.29", "@uiw/codemirror-extensions-langs": "^4.19.4", "@uiw/react-codemirror": "^4.19.4", "axios": "^1.7.4", diff --git a/frontend/src/components/dialog/insert-file-dialog.js b/frontend/src/components/dialog/insert-file-dialog.js index 0a81f3faed..bd0a961df5 100644 --- a/frontend/src/components/dialog/insert-file-dialog.js +++ b/frontend/src/components/dialog/insert-file-dialog.js @@ -51,7 +51,7 @@ class InsertFileDialog extends React.Component { render() { const toggle = this.props.toggleCancel; return ( - + {gettext('Select File')} { @@ -12,7 +11,7 @@ const Index = React.memo(({ repoID, path, dirent, currentRepoInfo, repoTags, fil // init context const context = new MetadataContext(); window.sfMetadataContext = context; - window.sfMetadataContext.init({ repoID, mediaUrl, repoInfo: currentRepoInfo }); + window.sfMetadataContext.init({ repoID, repoInfo: currentRepoInfo }); return () => { window.sfMetadataContext.destroy(); delete window['sfMetadataContext']; diff --git a/frontend/src/metadata/metadata-view/_basic/constants/column/index.js b/frontend/src/metadata/metadata-view/_basic/constants/column/index.js index bd5a0a419a..77a673ced0 100644 --- a/frontend/src/metadata/metadata-view/_basic/constants/column/index.js +++ b/frontend/src/metadata/metadata-view/_basic/constants/column/index.js @@ -43,3 +43,9 @@ export { NOT_DISPLAY_COLUMN_KEYS, VIEW_NOT_DISPLAY_COLUMN_KEYS, } from './common'; + +export { + INPUT_LENGTH_LIMIT, + LONG_TEXT_EXCEED_LIMIT_MESSAGE, + LONG_TEXT_EXCEED_LIMIT_SUGGEST, +} from './limit'; diff --git a/frontend/src/metadata/metadata-view/_basic/constants/column/limit.js b/frontend/src/metadata/metadata-view/_basic/constants/column/limit.js new file mode 100644 index 0000000000..8a28b4b83b --- /dev/null +++ b/frontend/src/metadata/metadata-view/_basic/constants/column/limit.js @@ -0,0 +1,16 @@ +import CellType from './type'; +import { gettext } from '../../../../../utils/constants'; + +// text value limit +const _TEXT_MAX_LENGTH = 10000; + +// long-text value limit +export const _LONG_TEXT_MAX_LENGTH = 10 * 10000; + +export const INPUT_LENGTH_LIMIT = { + [CellType.TEXT]: _TEXT_MAX_LENGTH, + [CellType.LONG_TEXT]: _LONG_TEXT_MAX_LENGTH +}; + +export const LONG_TEXT_EXCEED_LIMIT_MESSAGE = gettext('The content of the document has exceeded the limit of 100000 characters, and the content cannot be saved'); +export const LONG_TEXT_EXCEED_LIMIT_SUGGEST = gettext('The content of the document has exceeded the limit of 100000 characters, and only the first 100000 characters are saved'); diff --git a/frontend/src/metadata/metadata-view/_basic/constants/index.js b/frontend/src/metadata/metadata-view/_basic/constants/index.js index baf5d82c04..ff0137fd3a 100644 --- a/frontend/src/metadata/metadata-view/_basic/constants/index.js +++ b/frontend/src/metadata/metadata-view/_basic/constants/index.js @@ -1,73 +1,14 @@ import KeyCodes from './key-codes'; import * as Z_INDEX from './z-index'; -export { - CellType, - COLUMNS_ICON_CONFIG, - COLUMNS_ICON_NAME, - COLLABORATOR_COLUMN_TYPES, - DATE_COLUMN_OPTIONS, - NUMERIC_COLUMNS_TYPES, - DEFAULT_DATE_FORMAT, - UTC_FORMAT_DEFAULT, - DATE_UNIT, - DATE_FORMAT_MAP, - DEFAULT_NUMBER_FORMAT, - DATE_DEFAULT_TYPES, - NOT_SUPPORT_EDIT_COLUMN_TYPE, - NOT_SUPPORT_EDIT_COLUMN_TYPE_MAP, - MULTIPLE_CELL_VALUE_COLUMN_TYPE_MAP, - SINGLE_CELL_VALUE_COLUMN_TYPE_MAP, - PRIVATE_COLUMN_KEY, - PRIVATE_COLUMN_KEYS, - NOT_DISPLAY_COLUMN_KEYS, - 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, - FILTER_ERR_MSG, - FILTER_COLUMN_OPTIONS, - FILTER_TERM_MODIFIER_TYPE, - FILTER_TERM_MODIFIER_SHOW, - FILTER_PREDICATE_TYPE, - FILTER_PREDICATE_SHOW, - filterTermModifierIsWithin, - filterTermModifierNotWithin, -} from './filter'; -export { - MAX_GROUP_LEVEL, - GROUP_DATE_GRANULARITY, - DISPLAY_GROUP_DATE_GRANULARITY, - GROUP_GEOLOCATION_GRANULARITY, - DISPLAY_GROUP_GEOLOCATION_GRANULARITY, - SUPPORT_GROUP_COLUMN_TYPES, - GROUPBY_DATE_GRANULARITY_LIST, -} from './group'; -export { - HEADER_HEIGHT_TYPE -} from './grid-header'; -export { - REG_STRING_NUMBER_PARTS, - REG_NUMBER_DIGIT, -} from './reg'; -export { - SELECT_OPTION_COLORS, - HIGHLIGHT_COLORS, -} from './select-option'; -export { - SORT_TYPE, - SORT_COLUMN_OPTIONS, - TEXT_SORTER_COLUMN_TYPES, - NUMBER_SORTER_COLUMN_TYPES, -} from './sort'; -export { - DISPLAY_INTERNAL_ERRORS, -} from './error'; +export * from './column'; +export * from './filter'; +export * from './group'; +export * from './grid-header'; +export * from './reg'; +export * from './select-option'; +export * from './sort'; +export * from './error'; export { KeyCodes, diff --git a/frontend/src/metadata/metadata-view/_basic/index.js b/frontend/src/metadata/metadata-view/_basic/index.js index 79e4c2298c..457dcadf37 100644 --- a/frontend/src/metadata/metadata-view/_basic/index.js +++ b/frontend/src/metadata/metadata-view/_basic/index.js @@ -53,6 +53,9 @@ export { EDITABLE_PRIVATE_COLUMN_KEYS, EDITABLE_DATA_PRIVATE_COLUMN_KEYS, DELETABLE_PRIVATE_COLUMN_KEY, + INPUT_LENGTH_LIMIT, + LONG_TEXT_EXCEED_LIMIT_MESSAGE, + LONG_TEXT_EXCEED_LIMIT_SUGGEST, } from './constants'; export { @@ -156,4 +159,6 @@ export { getCellValueStringResult, getColumnOptionNamesByIds, getColumnOptionIdsByNames, + isLongTextValueExceedLimit, + getValidLongTextValue, } from './utils'; diff --git a/frontend/src/metadata/metadata-view/_basic/utils/column/index.js b/frontend/src/metadata/metadata-view/_basic/utils/column/index.js index b9abe07838..380fcaf2e9 100644 --- a/frontend/src/metadata/metadata-view/_basic/utils/column/index.js +++ b/frontend/src/metadata/metadata-view/_basic/utils/column/index.js @@ -23,4 +23,8 @@ export { generatorCellOption, generatorCellOptions, } from './option'; +export { + isLongTextValueExceedLimit, + getValidLongTextValue, +} from './long-text'; diff --git a/frontend/src/metadata/metadata-view/_basic/utils/column/long-text.js b/frontend/src/metadata/metadata-view/_basic/utils/column/long-text.js new file mode 100644 index 0000000000..3334957b58 --- /dev/null +++ b/frontend/src/metadata/metadata-view/_basic/utils/column/long-text.js @@ -0,0 +1,16 @@ +import { CellType, INPUT_LENGTH_LIMIT } from '../../constants/column'; + +export const isLongTextValueExceedLimit = (value) => { + const limit = INPUT_LENGTH_LIMIT[CellType.LONG_TEXT]; + const { text } = value; + return text ? text.length >= limit : false; +}; + +export const getValidLongTextValue = (value) => { + const limit = INPUT_LENGTH_LIMIT[CellType.LONG_TEXT]; + const newValue = { ...value }; + const { text, preview } = newValue; + newValue.text = text ? text.slice(0, limit) : ''; + newValue.preview = preview ? preview.slice(0, limit) : ''; + return newValue; +}; diff --git a/frontend/src/metadata/metadata-view/_basic/utils/index.js b/frontend/src/metadata/metadata-view/_basic/utils/index.js index 5fad636016..97980624c3 100644 --- a/frontend/src/metadata/metadata-view/_basic/utils/index.js +++ b/frontend/src/metadata/metadata-view/_basic/utils/index.js @@ -44,6 +44,8 @@ export { createOption, generatorCellOption, generatorCellOptions, + isLongTextValueExceedLimit, + getValidLongTextValue, } from './column'; export { getValidFilters, diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/editor-container/popup-editor-container.js b/frontend/src/metadata/metadata-view/components/cell-editor/editor-container/popup-editor-container.js index 45c2d12792..9357cba1a9 100644 --- a/frontend/src/metadata/metadata-view/components/cell-editor/editor-container/popup-editor-container.js +++ b/frontend/src/metadata/metadata-view/components/cell-editor/editor-container/popup-editor-container.js @@ -59,7 +59,7 @@ class PopupEditorContainer extends React.Component { createEditor = () => { const { column, record, height, onPressTab, editorPosition, columns, modifyColumnData } = this.props; - const readOnly = canEditCell(column, record, true) || NOT_SUPPORT_EDITOR_COLUMN_TYPES.includes(column.type); + const readOnly = !canEditCell(column, record, true) || NOT_SUPPORT_EDITOR_COLUMN_TYPES.includes(column.type); const value = this.getInitialValue(readOnly); let editorProps = { diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/editor.js b/frontend/src/metadata/metadata-view/components/cell-editor/editor.js index 506413d00e..1dd025508d 100644 --- a/frontend/src/metadata/metadata-view/components/cell-editor/editor.js +++ b/frontend/src/metadata/metadata-view/components/cell-editor/editor.js @@ -8,32 +8,36 @@ import NumberEditor from './number-editor'; import SingleSelectEditor from './single-select-editor'; import MultipleSelectEditor from './multiple-select-editor'; import CollaboratorEditor from './collaborator-editor'; +import LongTextEditor from './long-text-editor'; +import { lang } from '../../../../utils/constants'; // eslint-disable-next-line react/display-name const Editor = React.forwardRef((props, ref) => { switch (props.column.type) { case CellType.FILE_NAME: { - return (); + return (); } case CellType.TEXT: { - return (); + return (); } case CellType.DATE: { - const lang = window.sfMetadataContext.getSetting('lang'); - return (); + return (); } case CellType.NUMBER: { return (); } case CellType.SINGLE_SELECT: { - return (); + return (); } case CellType.MULTIPLE_SELECT: { - return (); + return (); } case CellType.COLLABORATOR: { - return (); + return (); + } + case CellType.LONG_TEXT: { + return (); } default: { return null; diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/api.js b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/api.js new file mode 100644 index 0000000000..6675457507 --- /dev/null +++ b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/api.js @@ -0,0 +1,73 @@ +import moment from 'moment'; +import { seafileAPI } from '../../../../../utils/seafile-api'; +import { Utils } from '../../../../../utils/utils'; + +const getImageFileNameWithTimestamp = () => { + var d = Date.now(); + return 'image-' + d.toString() + '.png'; +}; + +class LongtextAPI { + + constructor({ repoID, repoName, server }) { + const { name, username, contactEmail } = window.app.pageOptions; + this.repoID = repoID; + this.repoName = repoName; + this.server = server; + this.name = name; + this.contact_email = contactEmail; + this.userName = username; + this.relativePath = 'metadata'; + } + + _getImageURL(parentPath, fileName) { + return `${this.server}/lib/${this.repoID}/file/${parentPath}/${fileName}?raw=1`; + } + + uploadLocalImage = (imageFile) => { + const month = moment().format('YYYY-MM'); + const parentPath = `images/${this.relativePath}/${month}`; + return ( + seafileAPI.getFileServerUploadLink(this.repoID, '/').then((res) => { + const uploadLink = res.data + '?ret-json=1'; + const name = getImageFileNameWithTimestamp(); + const newFile = new File([imageFile], name, { type: imageFile.type }); + const formData = new FormData(); + formData.append('parent_dir', '/'); + formData.append('relative_path', parentPath); + formData.append('file', newFile); + return seafileAPI.uploadImage(uploadLink, formData); + }).then ((res) => { + return this._getImageURL(parentPath, res.data[0].name); + }) + ); + }; + + getFileURL(fileNode) { + if (fileNode.type !== 'file') { + return this.server + '/library/' + this.repoID + '/' + encodeURIComponent(this.repoName) + Utils.encodePath(fileNode.path()); + } + if (fileNode.isImage()) { + return this.server + '/lib/' + this.repoID + '/file' + Utils.encodePath(fileNode.path()) + '?raw=1'; + } + return this.server + '/lib/' + this.repoID + '/file' + Utils.encodePath(fileNode.path()); + } + + isInternalFileLink(url) { + var re = new RegExp(this.serviceUrl + '/lib/[0-9a-f-]{36}/file.*'); + return re.test(url); + } + + isInternalDirLink(url) { + // eslint-disable-next-line + var re = new RegExp(this.serviceUrl + '/library/' + '[0-9a-f\-]{36}.*'); + return re.test(url); + } + + markdownLint(slateValue) { + return seafileAPI.markdownLint(slateValue); + } + +} + +export default LongtextAPI; diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.css b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.css new file mode 100644 index 0000000000..739dd34b72 --- /dev/null +++ b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.css @@ -0,0 +1,3 @@ +.sf-metadata-long-text-editor-dialog { + z-index: 1049 !important; +} diff --git a/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.js b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.js new file mode 100644 index 0000000000..7a520684fa --- /dev/null +++ b/frontend/src/metadata/metadata-view/components/cell-editor/long-text-editor/index.js @@ -0,0 +1,115 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { LongTextEditorDialog, getPreviewContent } from '@seafile/seafile-editor'; +import LongtextAPI from './api'; +import { getValidLongTextValue, isLongTextValueExceedLimit, LONG_TEXT_EXCEED_LIMIT_MESSAGE, + LONG_TEXT_EXCEED_LIMIT_SUGGEST, +} from '../../../_basic'; +import toaster from '../../../../../components/toast'; +import { lang, serviceURL } from '../../../../../utils/constants'; + +import './index.css'; + +class LongTextEditor extends React.PureComponent { + + constructor(props) { + super(props); + this.isLongTextValueChanged = false; + this.repoID = window.sfMetadataContext.getSetting('repoID'); + this.filePath = '/'; + const repoInfo = window.sfMetadataContext.getSetting('repoInfo'); + const { repo_name } = repoInfo; + this.api = new LongtextAPI({ repoID: this.repoID, repoName: repo_name, server: serviceURL }); + this.value = this.initEditorValue(); + } + + initEditorValue = () => { + const value = this.props.value; + if (value) { + if (typeof value === 'object') return value; + if (typeof value === 'string') { + if (value.length === 1) { + this.isLongTextValueChanged = true; + } + const { previewText, images, links, checklist } = getPreviewContent(value); + return Object.assign({}, { text: value, preview: previewText, images, links, checklist }); + } + // When typing fast in a long text, first keystroke should be saved + if (typeof value === 'string' && value.length === 1) { + this.isLongTextValueChanged = true; + return { text: value, preview: value, links: [], images: [] }; + } + } + + return { text: '', preview: '', links: [], images: [], checklist: { completed: 0, count: 0 } }; + }; + + getValue = () => { + const updated = {}; + updated[this.props.column.key] = this.value.text; + return updated; + }; + + onEditorValueChanged = (value) => { + this.value = value; + this.isLongTextValueChanged = true; + }; + + onSaveEditorValue = (value) => { + if (isLongTextValueExceedLimit(value)) { + toaster.closeAll(); + toaster.danger(LONG_TEXT_EXCEED_LIMIT_MESSAGE, { duration: null }); + return; + } + this.props.onCommit(value?.text); + this.isLongTextValueChanged = false; + }; + + onCloseEditorDialog = () => { + const { readOnly } = this.props; + if (!readOnly && this.isLongTextValueChanged) { + if (isLongTextValueExceedLimit(this.value)) { + toaster.closeAll(); + toaster.warning(LONG_TEXT_EXCEED_LIMIT_SUGGEST, { duration: null }); + this.value = getValidLongTextValue(this.value); + } + + this.props.onCommit(this.value?.text); + this.isLongTextValueChanged = false; + } + + this.props.onCommitCancel(); + }; + + render() { + const { column, readOnly } = this.props; + const headerName = column.name; + + return ( + + ); + } +} + +LongTextEditor.propTypes = { + readOnly: PropTypes.bool, + column: PropTypes.object, + onCommit: PropTypes.func, + onCommitCancel: PropTypes.func, +}; + +export default LongTextEditor; diff --git a/frontend/src/metadata/metadata-view/components/detail-editor/index.js b/frontend/src/metadata/metadata-view/components/detail-editor/index.js index 0adbf09e1f..637b57ddf5 100644 --- a/frontend/src/metadata/metadata-view/components/detail-editor/index.js +++ b/frontend/src/metadata/metadata-view/components/detail-editor/index.js @@ -8,6 +8,7 @@ import SingleSelectEditor from './single-select-editor'; import MultipleSelectEditor from './multiple-select-editor'; import CollaboratorEditor from './collaborator-editor'; import DateEditor from './date-editor'; +import LongTextEditor from './long-text-editor'; import { lang } from '../../../../utils/constants'; import './index.css'; @@ -39,6 +40,9 @@ const DetailEditor = ({ field, onChange: onChangeAPI, ...props }) => { case CellType.COLLABORATOR: { return (); } + case CellType.LONG_TEXT: { + return (); + } default: { return null; } diff --git a/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.css b/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.css new file mode 100644 index 0000000000..2ef56e158c --- /dev/null +++ b/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.css @@ -0,0 +1,9 @@ +.sf-metadata-long-text-property-detail-editor { + min-height: 34px; + width: 100%; + padding: 7px 6px 0 6px; +} + +.sf-metadata-long-text-property-detail-editor .sf-metadata-property-detail-formatter { + line-height: 1.5; +} diff --git a/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.js b/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.js new file mode 100644 index 0000000000..e4d0760ec7 --- /dev/null +++ b/frontend/src/metadata/metadata-view/components/detail-editor/long-text-editor/index.js @@ -0,0 +1,55 @@ +import React, { useCallback, useState } from 'react'; +import PropTypes from 'prop-types'; +import { LongTextFormatter } from '@seafile/sf-metadata-ui-component'; +import Editor from '../../cell-editor/long-text-editor'; +import { gettext } from '../../../../../utils/constants'; + +import './index.css'; + +const LongTextEditor = ({ field, value: oldValue, onChange }) => { + const [value, setValue] = useState(oldValue); + const [showEditor, setShowEditor] = useState(false); + + const openEditor = useCallback(() => { + setShowEditor(true); + }, []); + + const onCommit = useCallback((newValue) => { + onChange && onChange(newValue); + setValue(newValue); + }, [onChange]); + + const onCommitCancel = useCallback(() => { + setShowEditor(false); + }, []); + + const isEmpty = !value || !value.trim(); + + return ( + <> +
+ {!isEmpty && ()} +
+ {showEditor && ( + + )} + + ); +}; + +LongTextEditor.propTypes = { + field: PropTypes.object.isRequired, + value: PropTypes.string, + onChange: PropTypes.func.isRequired, +}; + +export default LongTextEditor; diff --git a/frontend/src/metadata/metadata-view/components/detail-editor/multiple-select-editor/index.js b/frontend/src/metadata/metadata-view/components/detail-editor/multiple-select-editor/index.js index dbdf235a1a..d06fc2db4e 100644 --- a/frontend/src/metadata/metadata-view/components/detail-editor/multiple-select-editor/index.js +++ b/frontend/src/metadata/metadata-view/components/detail-editor/multiple-select-editor/index.js @@ -8,7 +8,7 @@ import DeleteOptions from '../../cell-editor/multiple-select-editor/delete-optio import './index.css'; -const MultipleSelectEditor = ({ field, value, record, fields, onChange, modifyColumnData }) => { +const MultipleSelectEditor = ({ field, value, onChange, modifyColumnData }) => { const ref = useRef(null); const [showEditor, setShowEditor] = useState(false); const options = useMemo(() => getColumnOptions(field), [field]); @@ -75,14 +75,12 @@ const MultipleSelectEditor = ({ field, value, record, fields, onChange, modifyCo saveImmediately={true} value={value} column={{ ...field, width: Math.max(width - 2, 200) }} - columns={fields} modifyColumnData={modifyColumnData} - record={record} onCommit={onCommit} /> ); - }, [showEditor, onCommit, record, value, modifyColumnData, fields, field]); + }, [showEditor, onCommit, value, modifyColumnData, field]); const isEmpty = useMemo(() => { if (!Array.isArray(value) || value.length === 0) return true; @@ -108,6 +106,7 @@ MultipleSelectEditor.propTypes = { field: PropTypes.object.isRequired, value: PropTypes.array, onChange: PropTypes.func.isRequired, + modifyColumnData: PropTypes.func, }; export default MultipleSelectEditor; diff --git a/frontend/src/metadata/metadata-view/components/popover/filter-popover/widgets/filter-calendar.js b/frontend/src/metadata/metadata-view/components/popover/filter-popover/widgets/filter-calendar.js index 4ad5fc8e14..c772349966 100644 --- a/frontend/src/metadata/metadata-view/components/popover/filter-popover/widgets/filter-calendar.js +++ b/frontend/src/metadata/metadata-view/components/popover/filter-popover/widgets/filter-calendar.js @@ -2,10 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import { SfFilterCalendar } from '@seafile/sf-metadata-ui-component'; import { getDateColumnFormat } from '../../../../utils/column-utils'; +import { lang } from '../../../../../../utils/constants'; const FilterCalendar = ({ value, filterColumn, readOnly, onChange }) => { const format = getDateColumnFormat(filterColumn).trim(); - const lang = window.sfMetadataContext.getSetting('lang'); return ( { if (PRIVATE_COLUMN_KEYS.includes(key)) return EDITABLE_PRIVATE_COLUMN_KEYS.includes(key); - return type !== CellType.LONG_TEXT; + return true; }; } diff --git a/frontend/src/metadata/metadata-view/utils/convert-utils.js b/frontend/src/metadata/metadata-view/utils/convert-utils.js index c69f4bdc47..923c5fb5dd 100644 --- a/frontend/src/metadata/metadata-view/utils/convert-utils.js +++ b/frontend/src/metadata/metadata-view/utils/convert-utils.js @@ -1,7 +1,6 @@ import { CellType, DEFAULT_DATE_FORMAT, generatorCellOption, getCollaboratorsName, getOptionName, getDateDisplayString, PREDEFINED_COLUMN_KEYS, getFloatNumber, getNumberDisplayString, formatStringToNumber, isNumber, getColumnOptions, - generatorCellOptions, - getColumnOptionNamesByIds, + generatorCellOptions, getColumnOptionNamesByIds, isLongTextValueExceedLimit, getValidLongTextValue, } from '../_basic'; import { formatTextToDate } from './date'; @@ -133,21 +132,6 @@ function convert2SingleSelect(cellValue, oldCellValue, fromColumn, targetColumn) return PREDEFINED_COLUMN_KEYS.includes(targetColumn.key) ? newOption.id : newOption.name; } -const LONG_TEXT_LENGTH_LIMIT = 10 * 10000; - -export const isLongTextValueExceedLimit = (value) => { - const { text } = value; - return text ? text.length >= LONG_TEXT_LENGTH_LIMIT : false; -}; - -export const getValidLongTextValue = (value) => { - const newValue = { ...value }; - const { text, preview } = newValue; - newValue.text = text ? text.slice(0, LONG_TEXT_LENGTH_LIMIT) : ''; - newValue.preview = preview ? preview.slice(0, LONG_TEXT_LENGTH_LIMIT) : ''; - return newValue; -}; - function convert2LongText(cellValue, oldCellValue, fromColumn) { const { type: fromColumnType, data: fromColumnData } = fromColumn; switch (fromColumnType) { diff --git a/frontend/src/pages/markdown-editor/index.js b/frontend/src/pages/markdown-editor/index.js index 99d974cc02..60f7230367 100644 --- a/frontend/src/pages/markdown-editor/index.js +++ b/frontend/src/pages/markdown-editor/index.js @@ -460,7 +460,7 @@ class MarkdownEditor extends React.Component { onSave={this.onSaveEditorContent} onContentChanged={this.onContentChanged} mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'} - isSupportInsertSeafileImage={true} + // isSupportInsertSeafileImage={true} > @@ -470,7 +470,7 @@ class MarkdownEditor extends React.Component { isFetching={loading} value={markdownContent} mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'} - isSupportInsertSeafileImage={true} + // isSupportInsertSeafileImage={true} isShowOutline={true} > diff --git a/media/css/seafile-editor-font/iconfont.eot b/media/css/seafile-editor-font/iconfont.eot index a948870c6c..6b358c0c86 100644 Binary files a/media/css/seafile-editor-font/iconfont.eot and b/media/css/seafile-editor-font/iconfont.eot differ diff --git a/media/css/seafile-editor-font/iconfont.svg b/media/css/seafile-editor-font/iconfont.svg index 47f3df843c..9920f9e4f3 100644 --- a/media/css/seafile-editor-font/iconfont.svg +++ b/media/css/seafile-editor-font/iconfont.svg @@ -14,6 +14,24 @@ /> + + + + + + + + + + + + + + + + + + @@ -24,16 +42,12 @@ - - - - diff --git a/media/css/seafile-editor-font/iconfont.ttf b/media/css/seafile-editor-font/iconfont.ttf index a5cbc33e03..fc687b61d1 100644 Binary files a/media/css/seafile-editor-font/iconfont.ttf and b/media/css/seafile-editor-font/iconfont.ttf differ diff --git a/media/css/seafile-editor-font/iconfont.woff b/media/css/seafile-editor-font/iconfont.woff index 32560000d8..fd05ad597b 100644 Binary files a/media/css/seafile-editor-font/iconfont.woff and b/media/css/seafile-editor-font/iconfont.woff differ diff --git a/media/css/seafile-editor-font/iconfont.woff2 b/media/css/seafile-editor-font/iconfont.woff2 index 11d8f109e6..536312e969 100644 Binary files a/media/css/seafile-editor-font/iconfont.woff2 and b/media/css/seafile-editor-font/iconfont.woff2 differ diff --git a/media/css/seafile-editor-font/seafile-editor-font.css b/media/css/seafile-editor-font/seafile-editor-font.css index 7fb57cf0c9..814f07148d 100644 --- a/media/css/seafile-editor-font/seafile-editor-font.css +++ b/media/css/seafile-editor-font/seafile-editor-font.css @@ -1,11 +1,11 @@ @font-face { font-family: "iconfont"; /* Project id 1206766 */ - src: url('./iconfont.eot?t=1645422890587'); /* IE9 */ - src: url('./iconfont.eot?t=1645422890587#iefix') format('embedded-opentype'), /* IE6-IE8 */ - url('./iconfont.woff2?t=1645422890587') format('woff2'), - url('./iconfont.woff?t=1645422890587') format('woff'), - url('./iconfont.ttf?t=1645422890587') format('truetype'), - url('./iconfont.svg?t=1645422890587#iconfont') format('svg'); + src: url('./iconfont.eot?t=1724814278764'); /* IE9 */ + src: url('./iconfont.eot?t=1724814278764#iefix') format('embedded-opentype'), /* IE6-IE8 */ + url('./iconfont.woff2?t=1724814278764') format('woff2'), + url('./iconfont.woff?t=1724814278764') format('woff'), + url('./iconfont.ttf?t=1724814278764') format('truetype'), + url('./iconfont.svg?t=1724814278764#iconfont') format('svg'); } .iconfont { @@ -16,6 +16,42 @@ -moz-osx-font-smoothing: grayscale; } +.icon-description:before { + content: "\e627"; +} + +.icon-more:before { + content: "\e626"; +} + +.icon-drop-down:before { + content: "\e685"; +} + +.icon-caret-up:before { + content: "\e686"; +} + +.icon-x:before { + content: "\e683"; +} + +.icon-full-screen:before { + content: "\e684"; +} + +.icon-text-style:before { + content: "\e682"; +} + +.icon-check-mark:before { + content: "\e680"; +} + +.icon-choose-column:before { + content: "\e681"; +} + .icon-edit:before { content: "\e64b"; } @@ -36,10 +72,6 @@ content: "\e64f"; } -.icon-caret-up:before { - content: "\e650"; -} - .icon-delete-table:before { content: "\e651"; } @@ -52,10 +84,6 @@ content: "\e653"; } -.icon-drop-down:before { - content: "\e654"; -} - .icon-link:before { content: "\e655"; }