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

feat: metadata longtext editor (#6666)

* feat: metadata longtext editor

* feat: optimize code

* feat: optimize code

* feat: optimize code

* feat: delete code

* feat: update code

* feat: update font

* feat: update font

* feat: optimize code

---------

Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
杨国璇
2024-08-30 07:00:26 +08:00
committed by GitHub
parent d8816fa2e1
commit fa6427f9dc
31 changed files with 414 additions and 152 deletions

View File

@@ -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",

View File

@@ -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",

View File

@@ -4,7 +4,6 @@ import LibDetail from './lib-details';
import DirentDetail from './dirent-details';
import ObjectUtils from '../../metadata/metadata-view/utils/object-utils';
import { MetadataContext } from '../../metadata';
import { mediaUrl } from '../../utils/constants';
const Index = React.memo(({ repoID, path, dirent, currentRepoInfo, repoTags, fileTags, onClose, onFileTagChanged }) => {
@@ -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'];

View File

@@ -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';

View File

@@ -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');

View File

@@ -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,

View File

@@ -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';

View File

@@ -23,4 +23,8 @@ export {
generatorCellOption,
generatorCellOptions,
} from './option';
export {
isLongTextValueExceedLimit,
getValidLongTextValue,
} from './long-text';

View File

@@ -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;
};

View File

@@ -44,6 +44,8 @@ export {
createOption,
generatorCellOption,
generatorCellOptions,
isLongTextValueExceedLimit,
getValidLongTextValue,
} from './column';
export {
getValidFilters,

View File

@@ -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 = {

View File

@@ -8,6 +8,8 @@ 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) => {
@@ -20,7 +22,6 @@ const Editor = React.forwardRef((props, ref) => {
return (<TextEditor ref={ref} { ...props } />);
}
case CellType.DATE: {
const lang = window.sfMetadataContext.getSetting('lang');
return (<SfCalendar ref={ref} { ...props } lang={lang} />);
}
case CellType.NUMBER: {
@@ -35,6 +36,9 @@ const Editor = React.forwardRef((props, ref) => {
case CellType.COLLABORATOR: {
return (<CollaboratorEditor ref={ref} { ...props } />);
}
case CellType.LONG_TEXT: {
return (<LongTextEditor ref={ref} { ...props } lang={lang} />);
}
default: {
return null;
}

View File

@@ -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;

View File

@@ -0,0 +1,3 @@
.sf-metadata-long-text-editor-dialog {
z-index: 1049 !important;
}

View File

@@ -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 (
<LongTextEditorDialog
className="sf-metadata-long-text-editor-dialog"
lang={lang}
readOnly={readOnly}
headerName={headerName}
value={this.value.text}
autoSave={true}
saveDelay={20 * 1000}
isCheckBrowser={true}
editorApi={this.api}
// mathJaxSource={mediaUrl + 'js/mathjax/tex-svg.js'}
onSaveEditorValue={this.onSaveEditorValue}
onEditorValueChanged={this.onEditorValueChanged}
onCloseEditorDialog={this.onCloseEditorDialog}
/>
);
}
}
LongTextEditor.propTypes = {
readOnly: PropTypes.bool,
column: PropTypes.object,
onCommit: PropTypes.func,
onCommitCancel: PropTypes.func,
};
export default LongTextEditor;

View File

@@ -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 (<CollaboratorEditor { ...props } field={field} onChange={onChange} />);
}
case CellType.LONG_TEXT: {
return (<LongTextEditor { ...props } field={field} onChange={onChange} />);
}
default: {
return null;
}

View File

@@ -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;
}

View File

@@ -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 (
<>
<div
className="sf-metadata-property-detail-editor sf-metadata-long-text-property-detail-editor"
placeholder={gettext('Empty')}
onClick={openEditor}
>
{!isEmpty && (<LongTextFormatter value={value} className="sf-metadata-property-detail-formatter" />)}
</div>
{showEditor && (
<Editor
value={value}
column={field}
onCommit={onCommit}
onCommitCancel={onCommitCancel}
/>
)}
</>
);
};
LongTextEditor.propTypes = {
field: PropTypes.object.isRequired,
value: PropTypes.string,
onChange: PropTypes.func.isRequired,
};
export default LongTextEditor;

View File

@@ -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}
/>
</Popover>
);
}, [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;

View File

@@ -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 (
<SfFilterCalendar
isReadOnly={readOnly}

View File

@@ -428,26 +428,6 @@
width: 20px;
}
.table-more-operations-dropdown-toggle {
display: inline-flex;
align-items: center;
height: 22px;
padding: 0 .5rem;
transition: all .1s ease-in;
border-radius: 3px;
}
.table-more-operations-dropdown-toggle:hover {
background-color: #f1f1f1;
cursor: pointer;
}
.table-more-operations-dropdown-toggle .sf-metadata-font {
font-size: 14px;
line-height: 22px;
color: #666;
}
.sf-metadata-wrapper .table-main-container {
display: flex;
flex: 1 1;
@@ -460,3 +440,8 @@
font-size: 13px;
color: #666;
}
.sf-metadata-select.custom-select,
.sf-metadata-select.custom-select .select-option-name {
color: #212529;
}

View File

@@ -1,5 +1,5 @@
import { normalizeColumnData, getColumnDisplayName } from '../../utils/column-utils';
import { CellType, PRIVATE_COLUMN_KEYS, EDITABLE_PRIVATE_COLUMN_KEYS, PRIVATE_COLUMN_KEY } from '../../_basic';
import { PRIVATE_COLUMN_KEYS, EDITABLE_PRIVATE_COLUMN_KEYS, PRIVATE_COLUMN_KEY } from '../../_basic';
class Column {
constructor(object) {
@@ -19,7 +19,7 @@ class Column {
enable_edit = (key, type) => {
if (PRIVATE_COLUMN_KEYS.includes(key)) return EDITABLE_PRIVATE_COLUMN_KEYS.includes(key);
return type !== CellType.LONG_TEXT;
return true;
};
}

View File

@@ -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) {

View File

@@ -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}
>
<DetailListView fileInfo={fileInfo} fileTagList={fileTagList} onFileTagChanged={this.onFileTagChanged}/>
</SeafileMarkdownEditor>
@@ -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}
>
</SeafileMarkdownViewer>

View File

@@ -14,6 +14,24 @@
/>
<missing-glyph />
<glyph glyph-name="description" unicode="&#58919;" d="M512 864C249.6 864 32 649.6 32 384s217.6-480 480-480 480 214.4 480 480S777.6 864 512 864z m-32-755.2c-19.2 0-35.2 16-35.2 35.2V419.2c0 19.2 16 35.2 35.2 35.2h67.2c19.2 0 35.2-16 35.2-35.2V144c0-19.2-16-35.2-35.2-35.2H480z m0 412.8c-19.2 0-35.2 16-35.2 35.2V624c0 19.2 16 35.2 35.2 35.2h67.2c19.2 0 35.2-16 35.2-35.2v-67.2c0-19.2-16-35.2-35.2-35.2H480z" horiz-adv-x="1024" />
<glyph glyph-name="more" unicode="&#58918;" d="M835.2 387.2c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z m-416 0c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z m-416 0c0-54.4 41.6-96 96-96s96 41.6 96 96-41.6 96-96 96c-51.2 0-96-41.6-96-96z" horiz-adv-x="1027" />
<glyph glyph-name="drop-down" unicode="&#59013;" d="M550.4 169.6l265.6 336c32 38.4 6.4 102.4-38.4 102.4H246.4c-44.8 0-70.4-60.8-38.4-102.4l265.6-336c19.2-25.6 57.6-25.6 76.8 0z" horiz-adv-x="1024" />
<glyph glyph-name="caret-up" unicode="&#59014;" d="M550.4 588.8l265.6-336c32-38.4 6.4-102.4-38.4-102.4H246.4c-44.8 0-70.4 60.8-38.4 102.4l265.6 336c19.2 25.6 57.6 25.6 76.8 0z" horiz-adv-x="1024" />
<glyph glyph-name="x" unicode="&#59011;" d="M489.6 451.2L784 745.6l67.2-67.2L556.8 384l294.4-294.4-67.2-67.2-294.4 294.4-272-272-67.2 67.2 272 272-272 272 67.2 67.2z" horiz-adv-x="1024" />
<glyph glyph-name="full-screen" unicode="&#59012;" d="M147.2 489.6c28.8 0 54.4 22.4 54.4 51.2V646.4c0 12.8 6.4 25.6 16 35.2s22.4 16 35.2 16h105.6c28.8 0 51.2 22.4 51.2 51.2C406.4 777.6 384 800 358.4 800H147.2C118.4 800 96 777.6 96 748.8v-211.2c0-25.6 22.4-48 51.2-48z m105.6-419.2c-12.8 0-25.6 6.4-35.2 16s-16 22.4-16 35.2V227.2c0 12.8-6.4 25.6-16 35.2s-22.4 16-35.2 16c-32 0-54.4-22.4-54.4-51.2v-208c0-28.8 22.4-51.2 51.2-51.2h208c28.8 0 51.2 22.4 51.2 51.2 0 28.8-22.4 51.2-51.2 51.2H252.8z m620.8 211.2c-28.8 0-51.2-22.4-51.2-51.2v-105.6c0-12.8-6.4-25.6-16-35.2-9.6-9.6-22.4-16-35.2-16H665.6c-28.8 0-51.2-22.4-51.2-51.2v-3.2c0-12.8 6.4-25.6 16-35.2 9.6-9.6 22.4-16 35.2-16h211.2c12.8 0 25.6 6.4 35.2 16 9.6 9.6 16 22.4 16 35.2V230.4c0 25.6-22.4 51.2-54.4 51.2zM665.6 800c-28.8 0-51.2-22.4-51.2-51.2v-3.2c0-28.8 22.4-51.2 51.2-51.2h105.6c12.8 0 25.6-6.4 35.2-16 9.6-9.6 16-22.4 16-35.2v-105.6c0-28.8 22.4-51.2 51.2-51.2h3.2c28.8 3.2 51.2 25.6 51.2 51.2V748.8c0 28.8-22.4 51.2-51.2 51.2H665.6z m6.4-320v-192c0-35.2-28.8-64-64-64H416c-35.2 0-64 28.8-64 64V480c0 35.2 28.8 64 64 64h192c35.2 0 64-28.8 64-64z" horiz-adv-x="1024" />
<glyph glyph-name="text-style" unicode="&#59010;" d="M147.2 156.8h160l67.2 153.6h278.4l67.2-153.6h160L598.4 896h-169.6L147.2 156.8z m348.8 512h35.2l83.2-227.2h-204.8l86.4 227.2zM774.4-128v160h160v-160h-160z m-355.2 160h160v-160h-160v160zM96 32h160v-160H96v160z" horiz-adv-x="1024" />
<glyph glyph-name="check-mark" unicode="&#59008;" d="M390.4 25.6c-41.6 0-86.4 16-112 48l-256 268.8c-35.2 32-25.6 89.6 16 121.6 35.2 25.6 86.4 25.6 118.4-9.6L387.2 208l480 499.2c35.2 32 92.8 32 128-9.6 35.2-32 35.2-83.2 9.6-115.2L499.2 76.8c-25.6-35.2-67.2-51.2-108.8-51.2z" horiz-adv-x="1024" />
<glyph glyph-name="choose-column" unicode="&#59009;" d="M620.8 438.4l384-214.4-144-41.6L931.2 32c16-25.6 6.4-60.8-16-80-25.6-16-57.6-16-80 6.4L704 96 592-6.4l28.8 444.8zM464 160c9.6 0 16-6.4 16-16v-128c0-9.6-6.4-16-16-16H48c-9.6 0-16 6.4-16 16V144c0 9.6 6.4 16 16 16h416z m64 320c9.6 0 16-6.4 16-16v-128c0-9.6-6.4-16-16-16H48c-9.6 0-16 6.4-16 16V464c0 9.6 6.4 16 16 16h480zM944 800c9.6 0 16-6.4 16-16v-128c0-9.6-6.4-16-16-16H48c-9.6 0-16 6.4-16 16V784c0 9.6 6.4 16 16 16h896z" horiz-adv-x="1024" />
<glyph glyph-name="edit" unicode="&#58955;" d="M691.2 640l140.8-140.8c6.4-6.4 6.4-16 0-22.4L489.6 137.6l-144-16c-19.2-3.2-35.2 12.8-32 32l16 144L668.8 640c6.4 3.2 16 3.2 22.4 0z m249.6 35.2L864 752c-22.4 22.4-60.8 22.4-86.4 0l-54.4-54.4c-6.4-6.4-6.4-16 0-22.4l140.8-140.8c6.4-6.4 16-6.4 22.4 0l54.4 54.4c25.6 22.4 25.6 60.8 0 86.4z m-278.4-444.8v-156.8H163.2V569.6h358.4c6.4 0 9.6 3.2 12.8 6.4l60.8 60.8c12.8 12.8 3.2 32-12.8 32H137.6C96 668.8 64 633.6 64 595.2v-547.2c0-41.6 32-73.6 73.6-73.6h547.2c41.6 0 73.6 32 73.6 73.6v246.4c0 16-19.2 25.6-32 12.8l-60.8-60.8c-3.2-6.4-3.2-12.8-3.2-16z" horiz-adv-x="1024" />
<glyph glyph-name="exclamation-triangle" unicode="&#58956;" d="M583.63328 76.8v108.8c0 6.4-3.2 9.6-6.4 12.8-3.2 3.2-6.4 6.4-12.8 6.4h-108.8c-6.4 0-9.6-3.2-12.8-6.4-3.2-3.2-6.4-9.6-6.4-12.8v-108.8c0-6.4 3.2-9.6 6.4-12.8s6.4-6.4 12.8-6.4h108.8c6.4 0 9.6 3.2 12.8 6.4 3.2 3.2 6.4 9.6 6.4 12.8z m-3.2 214.4l9.6 262.4c0 3.2-3.2 9.6-6.4 9.6-6.4 3.2-9.6 6.4-12.8 6.4h-124.8c-3.2 0-9.6-3.2-12.8-6.4-3.2-3.2-6.4-6.4-6.4-12.8l9.6-262.4c0-3.2 3.2-6.4 6.4-9.6 3.2-3.2 9.6-3.2 12.8-3.2h105.6c6.4 0 9.6 0 12.8 3.2 3.2 3.2 6.4 9.6 6.4 12.8z m-6.4 534.4l438.4-803.2c12.8-25.6 12.8-48 0-70.4-6.4-9.6-16-19.2-25.6-25.6-12.8-6.4-22.4-9.6-35.2-9.6H71.63328c-12.8 0-25.6 3.2-35.2 9.6-9.6 6.4-19.2 16-25.6 25.6-12.8 25.6-16 48 0 70.4L446.03328 825.6c6.4 12.8 16 22.4 25.6 28.8 12.8 6.4 25.6 9.6 38.4 9.6 12.8 0 25.6-3.2 38.4-9.6 12.8-6.4 19.2-16 25.6-28.8z" horiz-adv-x="1025" />
@@ -24,16 +42,12 @@
<glyph glyph-name="comment" unicode="&#58959;" d="M512 800C249.6 800 32 627.2 32 409.6c0-92.8 38.4-176 108.8-246.4-25.6-92.8-102.4-179.2-102.4-179.2-6.4-3.2-6.4-9.6-6.4-16s9.6-9.6 16-9.6c121.6 0 217.6 60.8 262.4 96 60.8-25.6 128-35.2 201.6-35.2 262.4 0 480 172.8 480 390.4S774.4 800 512 800z" horiz-adv-x="1024" />
<glyph glyph-name="caret-up" unicode="&#58960;" d="M870.4 137.6H153.6c-51.2 0-73.6 60.8-38.4 96L473.6 592c22.4 22.4 57.6 22.4 80 0l358.4-358.4c35.2-38.4 9.6-96-41.6-96z" horiz-adv-x="1024" />
<glyph glyph-name="delete-table" unicode="&#58961;" d="M752 355.2c115.2 0 208-96 208-208S864-64 752-64 544 32 544 144s92.8 211.2 208 211.2zM835.2 832c35.2 0 64-28.8 64-64v-400c-41.6 28.8-92.8 44.8-150.4 44.8-147.2 0-268.8-121.6-268.8-268.8 0-9.6 0-19.2 3.2-28.8H128c-35.2 0-64 28.8-64 64V768c0 35.2 28.8 64 64 64h707.2z m-32-656h-115.2c-16 0-25.6-12.8-25.6-28.8 0-12.8 12.8-28.8 25.6-28.8h115.2c16 0 25.6 12.8 25.6 28.8 0 12.8-9.6 28.8-25.6 28.8z m-374.4 198.4H192c-16 0-28.8-12.8-32-28.8v-118.4c0-16 12.8-28.8 28.8-32H425.6c16 0 28.8 12.8 32 28.8v118.4c3.2 19.2-12.8 32-28.8 32z m0 256H192c-16 0-28.8-12.8-32-28.8v-118.4c0-16 12.8-28.8 28.8-32H425.6c16 0 28.8 12.8 32 28.8V598.4c3.2 16-12.8 32-28.8 32z m352 0h-233.6c-16 0-28.8-12.8-32-28.8v-118.4c0-16 12.8-28.8 28.8-32H780.8c16 0 28.8 12.8 32 28.8V598.4c0 16-16 32-32 32z" horiz-adv-x="1024" />
<glyph glyph-name="check-circle" unicode="&#58962;" d="M992 384c0-265.6-214.4-480-480-480S32 118.4 32 384 246.4 864 512 864s480-214.4 480-480z m-534.4-252.8l355.2 355.2c12.8 12.8 12.8 32 0 44.8L768 572.8c-12.8 12.8-32 12.8-44.8 0l-291.2-291.2-137.6 137.6c-12.8 12.8-32 12.8-44.8 0l-44.8-44.8c-12.8-12.8-12.8-32 0-44.8l201.6-201.6c19.2-9.6 38.4-9.6 51.2 3.2z" horiz-adv-x="1024" />
<glyph glyph-name="ellipsis-v" unicode="&#58963;" d="M512 512c70.4 0 128-57.6 128-128s-57.6-128-128-128-128 57.6-128 128 57.6 128 128 128z m-128 224c0-70.4 57.6-128 128-128s128 57.6 128 128-57.6 128-128 128-128-57.6-128-128z m0-704c0-70.4 57.6-128 128-128s128 57.6 128 128-57.6 128-128 128-128-57.6-128-128z" horiz-adv-x="1024" />
<glyph glyph-name="drop-down" unicode="&#58964;" d="M563.2 160l345.6 342.4c41.6 38.4 9.6 105.6-51.2 105.6H166.4c-60.8 0-92.8-64-51.2-105.6L460.8 160c28.8-25.6 73.6-25.6 102.4 0z" horiz-adv-x="1024" />
<glyph glyph-name="link" unicode="&#58965;" d="M627.2 499.2c96-96 96-252.8 0-348.8l-108.8-108.8c-96-96-252.8-96-348.8 0s-96 252.8 0 348.8L227.2 448c16 16 44.8 6.4 44.8-16 0-28.8 6.4-57.6 16-86.4 3.2-9.6 0-19.2-6.4-25.6l-22.4-22.4c-44.8-44.8-48-118.4-3.2-166.4 44.8-44.8 121.6-48 166.4 0l108.8 108.8c44.8 44.8 44.8 118.4 0 166.4-6.4 6.4-12.8 9.6-16 12.8-6.4 3.2-9.6 12.8-12.8 19.2 0 16 6.4 35.2 19.2 48l35.2 35.2c9.6 9.6 22.4 9.6 32 3.2 16-6.4 25.6-16 38.4-25.6z m227.2 227.2c-96 96-252.8 96-348.8 0l-108.8-108.8c-96-96-96-249.6 0-348.8 9.6-9.6 22.4-19.2 32-28.8 9.6-6.4 25.6-6.4 32 3.2l35.2 35.2c12.8 12.8 19.2 32 19.2 48 0 9.6-3.2 16-12.8 19.2-3.2 3.2-9.6 6.4-16 12.8-44.8 44.8-44.8 118.4 0 166.4l108.8 108.8c44.8 44.8 121.6 44.8 166.4 0 44.8-44.8 44.8-118.4-3.2-166.4l-19.2-19.2c-6.4-6.4-9.6-16-6.4-25.6 9.6-28.8 16-57.6 16-86.4 0-22.4 28.8-32 44.8-16l60.8 60.8c96 92.8 96 249.6 0 345.6z" horiz-adv-x="1024" />
<glyph glyph-name="center-horizontally" unicode="&#58966;" d="M748.8 771.2v-73.6c0-16-12.8-28.8-28.8-28.8h-416c-16 0-28.8 12.8-28.8 28.8V771.2c0 16 12.8 28.8 28.8 28.8h416c16 0 28.8-12.8 28.8-28.8zM124.8 435.2H896c16 0 28.8 12.8 28.8 28.8v73.6c0 16-12.8 28.8-28.8 28.8H124.8c-16 0-28.8-12.8-28.8-28.8v-73.6c0-16 12.8-28.8 28.8-28.8z m0-467.2H896c16 0 28.8 12.8 28.8 28.8v73.6c0 16-12.8 28.8-28.8 28.8H124.8c-16 0-28.8-12.8-28.8-28.8v-73.6c0-16 12.8-28.8 28.8-28.8z m595.2 364.8h-416c-16 0-28.8-12.8-28.8-28.8v-73.6c0-16 12.8-28.8 28.8-28.8h416c16 0 28.8 12.8 28.8 28.8v73.6c0 16-12.8 28.8-28.8 28.8z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@@ -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";
}