mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-13 13:50:07 +00:00
fix: metadata status toggle (#6530)
* fix: metadata status toggle * feat: optimize code --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
179
frontend/src/metadata/hooks/metadata.js
Normal file
179
frontend/src/metadata/hooks/metadata.js
Normal file
@@ -0,0 +1,179 @@
|
||||
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import metadataAPI from '../api';
|
||||
import { Utils } from '../../utils/utils';
|
||||
import toaster from '../../components/toast';
|
||||
import { gettext } from '../../utils/constants';
|
||||
import { PRIVATE_FILE_TYPE } from '../../constants';
|
||||
|
||||
// This hook provides content related to seahub interaction, such as whether to enable extended attributes, views data, etc.
|
||||
const MetadataContext = React.createContext(null);
|
||||
|
||||
export const MetadataProvider = ({ repoID, hideMetadataView, selectMetadataView, renameMetadataView, 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);
|
||||
const [showFirstView, setShowFirstView] = useState(false);
|
||||
const [navigation, setNavigation] = useState([]);
|
||||
const viewsMap = useRef({});
|
||||
|
||||
useEffect(() => {
|
||||
if (!enableMetadataManagement) {
|
||||
setEnableExtendedProperties(false);
|
||||
return;
|
||||
}
|
||||
metadataAPI.getMetadataStatus(repoID).then(res => {
|
||||
setEnableExtendedProperties(res.data.enabled);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error, true);
|
||||
toaster.danger(errorMsg);
|
||||
setEnableExtendedProperties(false);
|
||||
});
|
||||
}, [repoID, enableMetadataManagement]);
|
||||
|
||||
const updateEnableMetadata = useCallback((newValue) => {
|
||||
if (newValue === enableMetadata) return;
|
||||
if (!newValue) {
|
||||
hideMetadataView && hideMetadataView();
|
||||
} else {
|
||||
setShowFirstView(true);
|
||||
}
|
||||
setEnableExtendedProperties(newValue);
|
||||
}, [enableMetadata, hideMetadataView]);
|
||||
|
||||
// views
|
||||
useEffect(() => {
|
||||
if (enableMetadata) {
|
||||
metadataAPI.listViews(repoID).then(res => {
|
||||
const { navigation, views } = res.data;
|
||||
if (Array.isArray(views)) {
|
||||
views.forEach(view => {
|
||||
viewsMap.current[view._id] = view;
|
||||
});
|
||||
}
|
||||
setNavigation(navigation);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error);
|
||||
toaster.danger(errorMsg);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If attribute extension is turned off, unmark the URL
|
||||
const { origin, pathname, search } = window.location;
|
||||
const urlParams = new URLSearchParams(search);
|
||||
const viewID = urlParams.get('view');
|
||||
if (viewID) {
|
||||
const url = `${origin}${pathname}`;
|
||||
window.history.pushState({ url: url, path: '' }, '', url);
|
||||
}
|
||||
viewsMap.current = {};
|
||||
setNavigation([]);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [repoID, enableMetadata]);
|
||||
|
||||
const selectView = useCallback((view, isSelected) => {
|
||||
if (isSelected) return;
|
||||
const node = {
|
||||
children: [],
|
||||
path: '/' + PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES + '/' + view.name,
|
||||
isExpanded: false,
|
||||
isLoaded: true,
|
||||
isPreload: true,
|
||||
object: {
|
||||
file_tags: [],
|
||||
id: PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES,
|
||||
name: gettext('File extended properties'),
|
||||
type: PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES,
|
||||
isDir: () => false,
|
||||
},
|
||||
parentNode: {},
|
||||
key: repoID,
|
||||
view_id: view._id,
|
||||
};
|
||||
selectMetadataView(node);
|
||||
setShowFirstView(false);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [repoID, selectMetadataView]);
|
||||
|
||||
const addView = useCallback((name, successCallback, failCallback) => {
|
||||
metadataAPI.addView(repoID, name).then(res => {
|
||||
const view = res.data.view;
|
||||
let newNavigation = navigation.slice(0);
|
||||
newNavigation.push({ _id: view._id, type: 'view' });
|
||||
viewsMap.current[view._id] = view;
|
||||
setNavigation(newNavigation);
|
||||
selectView(view);
|
||||
successCallback && successCallback();
|
||||
}).catch(error => {
|
||||
failCallback && failCallback(error);
|
||||
});
|
||||
}, [navigation, repoID, viewsMap, selectView]);
|
||||
|
||||
const deleteView = useCallback((viewId, isSelected) => {
|
||||
metadataAPI.deleteView(repoID, viewId).then(res => {
|
||||
const newNavigation = navigation.filter(item => item._id !== viewId);
|
||||
delete viewsMap.current[viewId];
|
||||
setNavigation(newNavigation);
|
||||
if (isSelected) {
|
||||
const currentViewIndex = navigation.findIndex(item => item._id === viewId);
|
||||
const lastViewId = navigation[currentViewIndex - 1]._id;
|
||||
const lastView = viewsMap.current[lastViewId];
|
||||
selectView(lastView);
|
||||
}
|
||||
}).catch((error => {
|
||||
const errorMsg = Utils.getErrorMsg(error);
|
||||
toaster.danger(errorMsg);
|
||||
}));
|
||||
}, [repoID, navigation, selectView, viewsMap]);
|
||||
|
||||
const updateView = useCallback((viewId, update, successCallback, failCallback) => {
|
||||
metadataAPI.modifyView(repoID, viewId, update).then(res => {
|
||||
const currentView = viewsMap.current[viewId];
|
||||
viewsMap.current[viewId] = { ...currentView, ...update };
|
||||
if (Object.prototype.hasOwnProperty.call(update, 'name')) {
|
||||
renameMetadataView(viewId, '/' + PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES + '/' + update['name']);
|
||||
}
|
||||
successCallback && successCallback();
|
||||
}).catch(error => {
|
||||
failCallback && failCallback(error);
|
||||
});
|
||||
}, [repoID, viewsMap, renameMetadataView]);
|
||||
|
||||
const moveView = useCallback((sourceViewId, targetViewId) => {
|
||||
metadataAPI.moveView(repoID, sourceViewId, targetViewId).then(res => {
|
||||
const { navigation } = res.data;
|
||||
setNavigation(navigation);
|
||||
}).catch(error => {
|
||||
const errorMsg = Utils.getErrorMsg(error);
|
||||
toaster.danger(errorMsg);
|
||||
});
|
||||
}, [repoID]);
|
||||
|
||||
return (
|
||||
<MetadataContext.Provider value={{
|
||||
enableMetadata,
|
||||
updateEnableMetadata,
|
||||
showFirstView,
|
||||
navigation,
|
||||
viewsMap: viewsMap.current,
|
||||
selectView,
|
||||
addView,
|
||||
deleteView,
|
||||
updateView,
|
||||
moveView,
|
||||
}}>
|
||||
{children}
|
||||
</MetadataContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useMetadata = () => {
|
||||
const context = useContext(MetadataContext);
|
||||
if (!context) {
|
||||
throw new Error('\'MetadataContext\' is null');
|
||||
}
|
||||
return context;
|
||||
};
|
Reference in New Issue
Block a user