mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-06 17:33:18 +00:00
feat: sdoc metadata (#6687)
* feat: sdoc metadata * feat: update code --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
8
frontend/package-lock.json
generated
8
frontend/package-lock.json
generated
@@ -16,7 +16,7 @@
|
||||
"@gatsbyjs/reach-router": "1.3.9",
|
||||
"@seafile/react-image-lightbox": "2.0.8",
|
||||
"@seafile/resumablejs": "1.1.16",
|
||||
"@seafile/sdoc-editor": "^1.0.66",
|
||||
"@seafile/sdoc-editor": "^1.0.70",
|
||||
"@seafile/seafile-calendar": "0.0.12",
|
||||
"@seafile/seafile-editor": "^1.0.115",
|
||||
"@seafile/sf-metadata-ui-component": "^0.0.29",
|
||||
@@ -4783,9 +4783,9 @@
|
||||
"integrity": "sha512-8rBbmAEuuwOAGHYGCtEzpx+bxAcGS+V30otMmhRe7bPAdh4E57RWgCa8x7pkzHGFlY1t5d+ILz1gojvPVMYQig=="
|
||||
},
|
||||
"node_modules/@seafile/sdoc-editor": {
|
||||
"version": "1.0.66",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-1.0.66.tgz",
|
||||
"integrity": "sha512-7v3mynzapsUKNwb5AHadXsR0/RzTmFAJNeJSe5ncjNgB0Ys+q1guM3iLARi96Tw7pEoTutzezUN/vI7qIZNWUw==",
|
||||
"version": "1.0.70",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sdoc-editor/-/sdoc-editor-1.0.70.tgz",
|
||||
"integrity": "sha512-lPOj07d3uVXIwUdKgdMsAFMPS3eejkGDMSR6V12tjYwahIXy64ApPALiWimF7rG49p9nsjqKRBbygrhrgCeNuA==",
|
||||
"dependencies": {
|
||||
"@seafile/print-js": "1.6.6",
|
||||
"@seafile/react-image-lightbox": "2.0.4",
|
||||
|
@@ -11,7 +11,7 @@
|
||||
"@gatsbyjs/reach-router": "1.3.9",
|
||||
"@seafile/react-image-lightbox": "2.0.8",
|
||||
"@seafile/resumablejs": "1.1.16",
|
||||
"@seafile/sdoc-editor": "^1.0.66",
|
||||
"@seafile/sdoc-editor": "^1.0.70",
|
||||
"@seafile/seafile-calendar": "0.0.12",
|
||||
"@seafile/seafile-editor": "^1.0.115",
|
||||
"@seafile/sf-metadata-ui-component": "^0.0.29",
|
||||
|
@@ -0,0 +1,51 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Formatter } from '@seafile/sf-metadata-ui-component';
|
||||
import DetailItem from '../detail-item';
|
||||
import { CellType } from '../../../metadata/metadata-view/_basic';
|
||||
import { gettext } from '../../../utils/constants';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import { MetadataDetails, useEnableMetadata } from '../../../metadata';
|
||||
|
||||
const FileDetails = ({ repoID, repoInfo, path, direntDetail }) => {
|
||||
const { enableMetadata } = useEnableMetadata();
|
||||
|
||||
const sizeField = useMemo(() => ({ type: 'size', name: gettext('Size') }), []);
|
||||
const lastModifierField = useMemo(() => ({ type: CellType.LAST_MODIFIER, name: gettext('Last modifier') }), []);
|
||||
const lastModifiedTimeField = useMemo(() => ({ type: CellType.MTIME, name: gettext('Last modified time') }), []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<DetailItem field={sizeField} className="sf-metadata-property-detail-formatter">
|
||||
<Formatter field={sizeField} value={Utils.bytesToSize(direntDetail.size)} />
|
||||
</DetailItem>
|
||||
<DetailItem field={lastModifierField} className="sf-metadata-property-detail-formatter">
|
||||
<Formatter
|
||||
field={lastModifierField}
|
||||
value={direntDetail.last_modifier_email}
|
||||
collaborators={[{
|
||||
name: direntDetail.last_modifier_name,
|
||||
contact_email: direntDetail.last_modifier_contact_email,
|
||||
email: direntDetail.last_modifier_email,
|
||||
avatar_url: direntDetail.last_modifier_avatar,
|
||||
}]}
|
||||
/>
|
||||
</DetailItem >
|
||||
<DetailItem field={lastModifiedTimeField} className="sf-metadata-property-detail-formatter">
|
||||
<Formatter field={lastModifiedTimeField} value={direntDetail.last_modified}/>
|
||||
</DetailItem>
|
||||
{window.app.pageOptions.enableMetadataManagement && enableMetadata && (
|
||||
<MetadataDetails repoID={repoID} filePath={path} repoInfo={repoInfo} direntType="file" />
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
FileDetails.propTypes = {
|
||||
repoID: PropTypes.string,
|
||||
repoInfo: PropTypes.object,
|
||||
path: PropTypes.string,
|
||||
direntDetail: PropTypes.object,
|
||||
};
|
||||
|
||||
export default FileDetails;
|
@@ -0,0 +1,3 @@
|
||||
.detail-body .empty-tip-text {
|
||||
color: #666;
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classnames from 'classnames';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import toaster from '../../toast';
|
||||
import { Header, Body } from '../detail';
|
||||
import FileDetails from './file-details';
|
||||
import { MetadataContext } from '../../../metadata';
|
||||
|
||||
import './index.css';
|
||||
|
||||
const EmbeddedFileDetails = ({ repoID, repoInfo, dirent, path, onClose, width = 300, className }) => {
|
||||
|
||||
const [direntDetail, setDirentDetail] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
// init context
|
||||
const context = new MetadataContext();
|
||||
window.sfMetadataContext = context;
|
||||
window.sfMetadataContext.init({ repoID, repoInfo });
|
||||
seafileAPI.getFileInfo(repoID, path).then(res => {
|
||||
setDirentDetail(res.data);
|
||||
}).catch(error => {
|
||||
const errMessage = Utils.getErrorMsg(error);
|
||||
toaster.danger(errMessage);
|
||||
});
|
||||
|
||||
return () => {
|
||||
window.sfMetadataContext.destroy();
|
||||
delete window['sfMetadataContext'];
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const direntName = dirent?.name || '';
|
||||
const smallIconUrl = Utils.getDirentIcon(dirent);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classnames('cur-view-detail', className, {
|
||||
'cur-view-detail-small': width < 400,
|
||||
'cur-view-detail-large': width > 400
|
||||
})}
|
||||
style={{ width }}
|
||||
>
|
||||
<Header title={direntName} icon={smallIconUrl} onClose={onClose} />
|
||||
<Body>
|
||||
{dirent && direntDetail && (
|
||||
<div className="detail-content">
|
||||
<FileDetails
|
||||
repoID={repoID}
|
||||
repoInfo={repoInfo}
|
||||
path={path}
|
||||
direntDetail={direntDetail}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</Body>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
EmbeddedFileDetails.propTypes = {
|
||||
repoID: PropTypes.string.isRequired,
|
||||
dirent: PropTypes.object,
|
||||
path: PropTypes.string.isRequired,
|
||||
repoInfo: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default EmbeddedFileDetails;
|
@@ -7,7 +7,7 @@ import { Utils } from '../../utils/utils';
|
||||
import toaster from '../toast';
|
||||
import FileInfo from './file-info';
|
||||
import FileToolbar from './file-toolbar';
|
||||
import FileDetails from '../dirent-detail/file-details';
|
||||
import FileDetails from '../dirent-detail/old-file-details';
|
||||
|
||||
import '../../css/file-view.css';
|
||||
|
||||
|
45
frontend/src/metadata/hooks/enable-metadata.js
Normal file
45
frontend/src/metadata/hooks/enable-metadata.js
Normal file
@@ -0,0 +1,45 @@
|
||||
import React, { useContext, useEffect, useMemo, useState } from 'react';
|
||||
import metadataAPI from '../api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
|
||||
// This hook provides content related to seahub interaction, such as whether to enable extended attributes
|
||||
const EnableMetadataContext = React.createContext(null);
|
||||
|
||||
export const EnableMetadataProvider = ({ repoID, children }) => {
|
||||
const enableMetadataManagement = useMemo(() => {
|
||||
return window.app.pageOptions.enableMetadataManagement;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [window.app.pageOptions.enableMetadataManagement]);
|
||||
|
||||
const [enableMetadata, setEnableExtendedProperties] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableMetadataManagement) {
|
||||
return;
|
||||
}
|
||||
metadataAPI.getMetadataStatus(repoID).then(res => {
|
||||
const enableMetadata = res.data.enabled;
|
||||
setEnableExtendedProperties(enableMetadata);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(errorMsg);
|
||||
setEnableExtendedProperties(false);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [repoID, enableMetadataManagement]);
|
||||
|
||||
return (
|
||||
<EnableMetadataContext.Provider value={{ enableMetadata }}>
|
||||
{children}
|
||||
</EnableMetadataContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useEnableMetadata = () => {
|
||||
const context = useContext(EnableMetadataContext);
|
||||
if (!context) {
|
||||
throw new Error('\'EnableMetadataContext\' is null');
|
||||
}
|
||||
return context;
|
||||
};
|
@@ -1,2 +1,3 @@
|
||||
export { MetadataProvider, useMetadata } from './metadata';
|
||||
export { EnableMetadataProvider, useEnableMetadata } from './enable-metadata';
|
||||
export { CollaboratorsProvider, useCollaborators } from './collaborators';
|
||||
|
@@ -2,7 +2,8 @@ class User {
|
||||
constructor(object) {
|
||||
this.avatar_url = object.avatar_url || '';
|
||||
this.contact_email = object.contact_email || '';
|
||||
this.email = object.email || '';
|
||||
this.username = object.email || object.username || '';
|
||||
this.email = this.username;
|
||||
this.name = object.name || '';
|
||||
this.name_pinyin = object.name_pinyin || '';
|
||||
this.id = object.id_in_org || '';
|
||||
|
@@ -1,81 +1,90 @@
|
||||
import React, { Fragment } from 'react';
|
||||
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { SimpleEditor } from '@seafile/sdoc-editor';
|
||||
import ExternalOperations from './external-operations';
|
||||
import { seafileAPI } from '../../../utils/seafile-api';
|
||||
import Dirent from '../../../models/dirent';
|
||||
import { Utils } from '../../../utils/utils';
|
||||
import { useCollaborators } from '../../../metadata';
|
||||
import EmbeddedFileDetails from '../../../components/dirent-detail/embedded-file-details';
|
||||
|
||||
export default class SdocEditor extends React.Component {
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
const { isStarred, isSdocDraft } = window.app.pageOptions;
|
||||
this.state = {
|
||||
isStarred: isStarred,
|
||||
isDraft: isSdocDraft,
|
||||
direntList: []
|
||||
};
|
||||
const SdocEditor = () => {
|
||||
const [isStarred, setStarted] = useState(window.app.pageOptions.isStarred);
|
||||
const [isDraft] = useState(window.app.pageOptions.isSdocDraft);
|
||||
const [direntList, setDirentList] = useState([]);
|
||||
const [currentDirent, setCurrentDirent] = useState(null);
|
||||
const { collaborators } = useCollaborators();
|
||||
const plugins = useMemo(() => {
|
||||
const { repoID, docPath, docPerm } = window.seafile;
|
||||
return [
|
||||
{
|
||||
name: 'sdoc-info',
|
||||
icon: 'sdoc-info',
|
||||
resizable_width: true,
|
||||
display_type: 'right-panel',
|
||||
component: ({ onClose, width }) => {
|
||||
return (<EmbeddedFileDetails repoID={repoID} onClose={onClose} path={docPath} dirent={currentDirent} repoInfo={{ permission: docPerm }} width={width} />);
|
||||
},
|
||||
}
|
||||
];
|
||||
}, [currentDirent]);
|
||||
|
||||
componentDidMount() {
|
||||
this.onSetFavicon();
|
||||
this.getDirentList();
|
||||
}
|
||||
|
||||
toggleStar = (isStarred) => {
|
||||
this.setState({ isStarred: isStarred });
|
||||
};
|
||||
|
||||
onSetFavicon = (suffix) => {
|
||||
let { docName } = window.seafile;
|
||||
if (suffix) {
|
||||
docName = docName + suffix;
|
||||
}
|
||||
const fileIcon = Utils.getFileIconUrl(docName);
|
||||
document.getElementById('favicon').href = fileIcon;
|
||||
};
|
||||
|
||||
onNewNotification = () => {
|
||||
this.onSetFavicon('_notification');
|
||||
};
|
||||
|
||||
onClearNotification = () => {
|
||||
this.onSetFavicon();
|
||||
};
|
||||
|
||||
getDirPath = () => {
|
||||
const dirPath = useMemo(() => {
|
||||
const { docPath } = window.seafile;
|
||||
const index = docPath.lastIndexOf('/');
|
||||
if (index) {
|
||||
return docPath.slice(0, index);
|
||||
}
|
||||
return '/';
|
||||
}, []);
|
||||
|
||||
const onSetFavicon = useCallback((suffix) => {
|
||||
let { docName } = window.seafile;
|
||||
if (suffix) {
|
||||
docName = docName + suffix;
|
||||
}
|
||||
const fileIcon = Utils.getFileIconUrl(docName);
|
||||
document.getElementById('favicon').href = fileIcon;
|
||||
}, []);
|
||||
|
||||
const toggleStar = (isStarred) => {
|
||||
setStarted(isStarred);
|
||||
};
|
||||
|
||||
getDirentList = () => {
|
||||
const { repoID } = window.seafile;
|
||||
const path = this.getDirPath();
|
||||
seafileAPI.listDir(repoID, path, { 'with_thumbnail': true }).then(res => {
|
||||
const onNewNotification = useCallback(() => {
|
||||
onSetFavicon('_notification');
|
||||
}, [onSetFavicon]);
|
||||
|
||||
const onClearNotification = useCallback(() => {
|
||||
onSetFavicon();
|
||||
}, [onSetFavicon]);
|
||||
|
||||
const getDirentList = () => {
|
||||
const { repoID, docPath } = window.seafile;
|
||||
seafileAPI.listDir(repoID, dirPath, { 'with_thumbnail': true }).then(res => {
|
||||
let direntList = [];
|
||||
res.data.dirent_list.forEach(item => {
|
||||
let dirent = new Dirent(item);
|
||||
const dirent = new Dirent(item);
|
||||
if (Utils.joinPath(item.parent_dir, item.name) === docPath) {
|
||||
setCurrentDirent(dirent);
|
||||
}
|
||||
direntList.push(dirent);
|
||||
});
|
||||
this.setState({
|
||||
direntList: direntList
|
||||
});
|
||||
setDirentList(direntList);
|
||||
}).catch((err) => {
|
||||
Utils.getErrorMsg(err, true);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
useEffect(() => {
|
||||
onSetFavicon();
|
||||
getDirentList();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const { repoID, docPath, docName, docPerm } = window.seafile;
|
||||
const { isStarred, isDraft, direntList } = this.state;
|
||||
const dirPath = this.getDirPath();
|
||||
return (
|
||||
<Fragment>
|
||||
<SimpleEditor isStarred={isStarred} isDraft={isDraft} />
|
||||
<>
|
||||
<SimpleEditor isStarred={isStarred} isDraft={isDraft} plugins={plugins} collaborators={collaborators} showComment={true} />
|
||||
<ExternalOperations
|
||||
repoID={repoID}
|
||||
docPath={docPath}
|
||||
@@ -84,11 +93,12 @@ export default class SdocEditor extends React.Component {
|
||||
isStarred={isStarred}
|
||||
direntList={direntList}
|
||||
dirPath={dirPath}
|
||||
toggleStar={this.toggleStar}
|
||||
onNewNotification={this.onNewNotification}
|
||||
onClearNotification={this.onClearNotification}
|
||||
toggleStar={toggleStar}
|
||||
onNewNotification={onNewNotification}
|
||||
onClearNotification={onClearNotification}
|
||||
/>
|
||||
</Fragment>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default SdocEditor;
|
||||
|
@@ -5,6 +5,7 @@ import i18n from './_i18n/i18n-sdoc-editor';
|
||||
import { Utils } from './utils/utils';
|
||||
import Loading from './components/loading';
|
||||
import SdocEditor from './pages/sdoc/sdoc-editor';
|
||||
import { CollaboratorsProvider, EnableMetadataProvider } from './metadata';
|
||||
|
||||
const { serviceURL, avatarURL, siteRoot, lang, mediaUrl, isPro } = window.app.config;
|
||||
const { username, name } = window.app.userInfo;
|
||||
@@ -51,7 +52,11 @@ window.seafile = {
|
||||
ReactDom.render(
|
||||
<I18nextProvider i18n={ i18n } >
|
||||
<Suspense fallback={<Loading />}>
|
||||
<EnableMetadataProvider repoID={repoID} >
|
||||
<CollaboratorsProvider repoID={repoID}>
|
||||
<SdocEditor />
|
||||
</CollaboratorsProvider>
|
||||
</EnableMetadataProvider>
|
||||
</Suspense>
|
||||
</I18nextProvider>,
|
||||
document.getElementById('wrapper')
|
||||
|
@@ -1,11 +1,11 @@
|
||||
@font-face {
|
||||
font-family: "sdocfont"; /* Project id 4097705 */
|
||||
src: url('./sdoc-editor-font/iconfont.eot?t=1722915152576'); /* IE9 */
|
||||
src: url('./sdoc-editor-font/iconfont.eot?t=1722915152576#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('./sdoc-editor-font/iconfont.woff2?t=1722915152576') format('woff2'),
|
||||
url('./sdoc-editor-font/iconfont.woff?t=1722915152576') format('woff'),
|
||||
url('./sdoc-editor-font/iconfont.ttf?t=1722915152576') format('truetype'),
|
||||
url('./sdoc-editor-font/iconfont.svg?t=1722915152576#sdocfont') format('svg');
|
||||
src: url('./sdoc-editor-font/iconfont.eot?t=1725002301707'); /* IE9 */
|
||||
src: url('./sdoc-editor-font/iconfont.eot?t=1725002301707#iefix') format('embedded-opentype'), /* IE6-IE8 */
|
||||
url('./sdoc-editor-font/iconfont.woff2?t=1725002301707') format('woff2'),
|
||||
url('./sdoc-editor-font/iconfont.woff?t=1725002301707') format('woff'),
|
||||
url('./sdoc-editor-font/iconfont.ttf?t=1725002301707') format('truetype'),
|
||||
url('./sdoc-editor-font/iconfont.svg?t=1725002301707#sdocfont') format('svg');
|
||||
}
|
||||
|
||||
.sdocfont {
|
||||
@@ -16,6 +16,14 @@
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.sdoc-info:before {
|
||||
content: "\e677";
|
||||
}
|
||||
|
||||
.sdoc-inline-code:before {
|
||||
content: "\e676";
|
||||
}
|
||||
|
||||
.sdoc-sort:before {
|
||||
content: "\e674";
|
||||
}
|
||||
|
Binary file not shown.
@@ -14,6 +14,10 @@
|
||||
/>
|
||||
<missing-glyph />
|
||||
|
||||
<glyph glyph-name="sdoc-info" unicode="" d="M512 896c281.6 0 512-230.4 512-512s-230.4-512-512-512S0 102.4 0 384 230.4 896 512 896z m0-96C281.6 800 96 614.4 96 384s185.6-416 416-416 416 185.6 416 416c0 108.8-44.8 217.6-121.6 294.4S620.8 800 512 800z m32-352c19.2 0 32-12.8 32-32v-256c0-19.2-12.8-32-32-32h-64c-19.2 0-32 12.8-32 32V416c0 19.2 12.8 32 32 32h64z m-19.2 192c9.6 0 16-3.2 22.4-9.6 3.2-3.2 6.4-6.4 9.6-6.4 25.6-25.6 25.6-64 0-89.6-3.2-3.2-6.4-6.4-9.6-6.4-6.4-3.2-16-6.4-22.4-9.6h-25.6c-9.6 0-16 3.2-22.4 9.6-3.2 3.2-6.4 6.4-9.6 6.4-25.6 25.6-25.6 64 0 89.6 3.2 3.2 6.4 6.4 9.6 6.4 6.4 3.2 16 6.4 22.4 9.6h25.6z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="sdoc-inline-code" unicode="" d="M1024 384l-272-288-67.2 70.4 204.8 217.6-204.8 217.6L752 672l272-288zM0 384l272-288 67.2 70.4L134.4 384l204.8 217.6L272 672 0 384z m451.2-512l-99.2 3.2L579.2 896h99.2l-227.2-1024z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="sdoc-sort" unicode="" d="M294.4 790.4l201.6-204.8c19.2-19.2 19.2-51.2 0-73.6-19.2-19.2-51.2-19.2-70.4 0L320 620.8v-604.8c0-25.6-22.4-48-48-48S224-9.6 224 16V620.8L118.4 512c-19.2-19.2-48-19.2-67.2-3.2l-3.2 3.2c-19.2 19.2-19.2 51.2 0 73.6l201.6 204.8c12.8 12.8 32 12.8 44.8 0zM752 800c25.6 0 48-22.4 48-48v-604.8l105.6 108.8c19.2 19.2 51.2 19.2 70.4 0 19.2-19.2 19.2-51.2 0-73.6l-201.6-204.8c-12.8-12.8-32-12.8-44.8 0l-201.6 204.8c-19.2 19.2-19.2 51.2 0 73.6l3.2 3.2c19.2 16 48 16 67.2-3.2l105.6-108.8V752c0 25.6 22.4 48 48 48z" horiz-adv-x="1024" />
|
||||
|
||||
<glyph glyph-name="sdoc-set-up" unicode="" d="M598.52384 809.6l12.8-92.8 6.4-38.4 35.2-16c12.8-6.4 28.8-16 41.6-25.6l32-19.2 35.2 12.8 92.8 35.2 86.4-140.8-76.8-54.4-32-25.6 3.2-38.4v-44.8l-3.2-38.4 32-25.6 76.8-57.6-83.2-140.8-92.8 35.2-35.2 12.8-32-19.2c-12.8-9.6-28.8-19.2-41.6-25.6l-35.2-16-6.4-38.4-12.8-92.8h-172.8l-12.8 92.8-6.4 38.4-35.2 16c-12.8 6.4-28.8 16-41.6 25.6l-32 19.2-35.2-12.8-92.8-35.2-86.4 140.8L160.12384 297.6l32 25.6-3.2 38.4V384v22.4l3.2 38.4-32 25.6-76.8 57.6 83.2 140.8 92.8-35.2 35.2-12.8 32 19.2c12.8 9.6 28.8 19.2 41.6 25.6l35.2 16 6.4 38.4 12.8 92.8h176m12.8 83.2H416.12384c-32 0-57.6-22.4-60.8-51.2l-16-105.6c-19.2-9.6-35.2-19.2-54.4-32L182.52384 748.8c-9.6 3.2-16 3.2-22.4 3.2-22.4 0-41.6-9.6-54.4-28.8L6.52384 560c-12.8-28.8-6.4-60.8 16-80l86.4-67.2c0-9.6-3.2-22.4-3.2-28.8 0-9.6 0-19.2 3.2-28.8L22.52384 288c-22.4-19.2-28.8-51.2-16-76.8l96-163.2c9.6-19.2 32-32 54.4-32 6.4 0 12.8 0 22.4 3.2l102.4 41.6c16-12.8 35.2-22.4 54.4-28.8l16-105.6c3.2-28.8 28.8-51.2 60.8-51.2H608.12384c32 0 57.6 22.4 60.8 51.2l16 105.6c19.2 9.6 35.2 19.2 54.4 28.8l102.4-41.6c6.4-3.2 16-3.2 22.4-3.2 22.4 0 41.6 9.6 54.4 28.8l99.2 166.4c16 25.6 9.6 57.6-16 76.8l-86.4 67.2c0 9.6 3.2 19.2 3.2 28.8s0 22.4-3.2 28.8l86.4 67.2c22.4 19.2 28.8 51.2 16 76.8l-96 163.2c-9.6 19.2-32 32-54.4 32-6.4 0-12.8 0-22.4-3.2l-102.4-41.6c-16 12.8-35.2 22.4-54.4 28.8L672.12384 844.8C665.72384 873.6 640.12384 896 611.32384 896zM512.12384 512c70.4 0 128-57.6 128-128s-57.6-128-128-128-128 57.6-128 128 57.6 128 128 128m0 86.4a214.4 214.4 0 1 1 0-428.8 214.4 214.4 0 0 1 0 428.8z" horiz-adv-x="1026" />
|
||||
|
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 66 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -42,6 +42,7 @@ window.app.pageOptions = {
|
||||
canEditFile: {% if can_edit_file %}true{% else %}false{% endif %}, // only for some file types
|
||||
canDownloadFile: {% if can_download_file %}true{% else %}false{% endif %},
|
||||
enableWatermark: {% if enable_watermark %}true{% else %}false{% endif %},
|
||||
enableMetadataManagement: {% if enable_metadata_management %} true {% else %} false {% endif %},
|
||||
|
||||
// for {{filetype}} file
|
||||
{% block extra_data %}
|
||||
|
@@ -571,6 +571,7 @@ def view_lib_file(request, repo_id, path):
|
||||
'share_link_expire_days_max': SHARE_LINK_EXPIRE_DAYS_MAX,
|
||||
'can_download_file': parse_repo_perm(permission).can_download,
|
||||
'seafile_collab_server': SEAFILE_COLLAB_SERVER,
|
||||
'enable_metadata_management': settings.ENABLE_METADATA_MANAGEMENT,
|
||||
}
|
||||
|
||||
# check whether file is starred
|
||||
|
Reference in New Issue
Block a user