mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-10 19:29:56 +00:00
feat: face view support move (#7137)
* feat: face view support move * feat: optimize code * feat: optimize code --------- Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
@@ -17,8 +17,7 @@ const VIEW_OPTIONS = [
|
|||||||
}, {
|
}, {
|
||||||
key: 'kanban',
|
key: 'kanban',
|
||||||
type: VIEW_TYPE.KANBAN,
|
type: VIEW_TYPE.KANBAN,
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
key: 'map',
|
key: 'map',
|
||||||
type: VIEW_TYPE.MAP,
|
type: VIEW_TYPE.MAP,
|
||||||
}
|
}
|
||||||
|
@@ -70,6 +70,7 @@ export const VIEW_TYPE_DEFAULT_BASIC_FILTER = {
|
|||||||
export const VIEW_TYPE_DEFAULT_SORTS = {
|
export const VIEW_TYPE_DEFAULT_SORTS = {
|
||||||
[VIEW_TYPE.TABLE]: [],
|
[VIEW_TYPE.TABLE]: [],
|
||||||
[VIEW_TYPE.GALLERY]: [{ column_key: PRIVATE_COLUMN_KEY.FILE_CTIME, sort_type: SORT_TYPE.DOWN }],
|
[VIEW_TYPE.GALLERY]: [{ column_key: PRIVATE_COLUMN_KEY.FILE_CTIME, sort_type: SORT_TYPE.DOWN }],
|
||||||
|
[VIEW_TYPE.FACE_RECOGNITION]: [],
|
||||||
[VIEW_TYPE.KANBAN]: [],
|
[VIEW_TYPE.KANBAN]: [],
|
||||||
[VIEW_TYPE.MAP]: [],
|
[VIEW_TYPE.MAP]: [],
|
||||||
};
|
};
|
||||||
@@ -77,6 +78,7 @@ export const VIEW_TYPE_DEFAULT_SORTS = {
|
|||||||
export const VIEW_SORT_COLUMN_RULES = {
|
export const VIEW_SORT_COLUMN_RULES = {
|
||||||
[VIEW_TYPE.TABLE]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
[VIEW_TYPE.TABLE]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
||||||
[VIEW_TYPE.GALLERY]: (column) => GALLERY_SORT_COLUMN_OPTIONS.includes(column.type) || GALLERY_SORT_PRIVATE_COLUMN_KEYS.includes(column.key),
|
[VIEW_TYPE.GALLERY]: (column) => GALLERY_SORT_COLUMN_OPTIONS.includes(column.type) || GALLERY_SORT_PRIVATE_COLUMN_KEYS.includes(column.key),
|
||||||
|
[VIEW_TYPE.FACE_RECOGNITION]: () => {},
|
||||||
[VIEW_TYPE.KANBAN]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
[VIEW_TYPE.KANBAN]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
||||||
[VIEW_TYPE.MAP]: () => {},
|
[VIEW_TYPE.MAP]: () => {},
|
||||||
};
|
};
|
||||||
@@ -84,6 +86,7 @@ export const VIEW_SORT_COLUMN_RULES = {
|
|||||||
export const VIEW_FIRST_SORT_COLUMN_RULES = {
|
export const VIEW_FIRST_SORT_COLUMN_RULES = {
|
||||||
[VIEW_TYPE.TABLE]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
[VIEW_TYPE.TABLE]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
||||||
[VIEW_TYPE.GALLERY]: (column) => GALLERY_FIRST_SORT_COLUMN_OPTIONS.includes(column.type) || GALLERY_FIRST_SORT_PRIVATE_COLUMN_KEYS.includes(column.key),
|
[VIEW_TYPE.GALLERY]: (column) => GALLERY_FIRST_SORT_COLUMN_OPTIONS.includes(column.type) || GALLERY_FIRST_SORT_PRIVATE_COLUMN_KEYS.includes(column.key),
|
||||||
|
[VIEW_TYPE.FACE_RECOGNITION]: () => {},
|
||||||
[VIEW_TYPE.KANBAN]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
[VIEW_TYPE.KANBAN]: (column) => SORT_COLUMN_OPTIONS.includes(column.type),
|
||||||
[VIEW_TYPE.MAP]: () => {},
|
[VIEW_TYPE.MAP]: () => {},
|
||||||
};
|
};
|
||||||
|
@@ -15,7 +15,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
const [isLoading, setLoading] = useState(true);
|
const [isLoading, setLoading] = useState(true);
|
||||||
const [enableFaceRecognition, setEnableFaceRecognition] = useState(false);
|
const [enableFaceRecognition, setEnableFaceRecognition] = useState(false);
|
||||||
const [navigation, setNavigation] = useState([]);
|
const [navigation, setNavigation] = useState([]);
|
||||||
const [staticView, setStaticView] = useState([]);
|
|
||||||
const [, setCount] = useState(0);
|
const [, setCount] = useState(0);
|
||||||
|
|
||||||
const viewsMap = useRef({});
|
const viewsMap = useRef({});
|
||||||
@@ -23,14 +22,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
|
|
||||||
const { enableMetadata, isBeingBuilt, setIsBeingBuilt } = useMetadataStatus();
|
const { enableMetadata, isBeingBuilt, setIsBeingBuilt } = useMetadataStatus();
|
||||||
|
|
||||||
const updateEnableFaceRecognition = useCallback((newValue) => {
|
|
||||||
if (newValue === enableFaceRecognition) return;
|
|
||||||
setEnableFaceRecognition(newValue);
|
|
||||||
if (newValue) {
|
|
||||||
toaster.success(gettext('Recognizing portraits. Please refresh the page later.'));
|
|
||||||
}
|
|
||||||
}, [enableFaceRecognition]);
|
|
||||||
|
|
||||||
// views
|
// views
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -42,11 +33,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
viewsMap.current[view._id] = view;
|
viewsMap.current[view._id] = view;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
viewsMap.current[FACE_RECOGNITION_VIEW_ID] = {
|
|
||||||
_id: FACE_RECOGNITION_VIEW_ID,
|
|
||||||
name: gettext('Photos - classified by people'),
|
|
||||||
type: VIEW_TYPE.FACE_RECOGNITION,
|
|
||||||
};
|
|
||||||
setNavigation(navigation);
|
setNavigation(navigation);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
@@ -59,7 +45,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
hideMetadataView && hideMetadataView();
|
hideMetadataView && hideMetadataView();
|
||||||
setEnableFaceRecognition(false);
|
setEnableFaceRecognition(false);
|
||||||
viewsMap.current = {};
|
viewsMap.current = {};
|
||||||
setStaticView([]);
|
|
||||||
setNavigation([]);
|
setNavigation([]);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
@@ -67,7 +52,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!enableMetadata) {
|
if (!enableMetadata) {
|
||||||
setStaticView([]);
|
|
||||||
setEnableFaceRecognition(false);
|
setEnableFaceRecognition(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -79,14 +63,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
});
|
});
|
||||||
}, [repoID, enableMetadata]);
|
}, [repoID, enableMetadata]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!enableFaceRecognition) {
|
|
||||||
setStaticView([]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setStaticView([{ _id: FACE_RECOGNITION_VIEW_ID, type: 'view' }]);
|
|
||||||
}, [enableFaceRecognition]);
|
|
||||||
|
|
||||||
const selectView = useCallback((view, isSelected) => {
|
const selectView = useCallback((view, isSelected) => {
|
||||||
if (isSelected) return;
|
if (isSelected) return;
|
||||||
const node = {
|
const node = {
|
||||||
@@ -176,6 +152,24 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
});
|
});
|
||||||
}, [repoID]);
|
}, [repoID]);
|
||||||
|
|
||||||
|
const updateEnableFaceRecognition = useCallback((newValue) => {
|
||||||
|
if (newValue === enableFaceRecognition) return;
|
||||||
|
if (newValue) {
|
||||||
|
toaster.success(gettext('Recognizing portraits. Please refresh the page later.'));
|
||||||
|
addView(gettext('Photos - classified by people'), VIEW_TYPE.FACE_RECOGNITION, () => {}, () => {});
|
||||||
|
} else {
|
||||||
|
if (viewsMap.current[FACE_RECOGNITION_VIEW_ID]) {
|
||||||
|
let isSelected = false;
|
||||||
|
if (currentPath.includes('/' + PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES + '/')) {
|
||||||
|
const currentViewId = currentPath.split('/').pop();
|
||||||
|
isSelected = currentViewId === FACE_RECOGNITION_VIEW_ID;
|
||||||
|
}
|
||||||
|
deleteView(FACE_RECOGNITION_VIEW_ID, isSelected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setEnableFaceRecognition(newValue);
|
||||||
|
}, [enableFaceRecognition, currentPath, addView, deleteView]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoading) return;
|
if (isLoading) return;
|
||||||
if (isBeingBuilt) {
|
if (isBeingBuilt) {
|
||||||
@@ -228,7 +222,6 @@ export const MetadataProvider = ({ repoID, currentPath, repoInfo, hideMetadataVi
|
|||||||
isBeingBuilt,
|
isBeingBuilt,
|
||||||
setIsBeingBuilt,
|
setIsBeingBuilt,
|
||||||
navigation,
|
navigation,
|
||||||
staticView,
|
|
||||||
viewsMap: viewsMap.current,
|
viewsMap: viewsMap.current,
|
||||||
selectView,
|
selectView,
|
||||||
addView,
|
addView,
|
||||||
|
@@ -22,9 +22,7 @@ const MetadataTreeView = ({ userPerm, currentPath }) => {
|
|||||||
}, [userPerm]);
|
}, [userPerm]);
|
||||||
const [, setState] = useState(0);
|
const [, setState] = useState(0);
|
||||||
const {
|
const {
|
||||||
enableFaceRecognition,
|
|
||||||
navigation,
|
navigation,
|
||||||
staticView,
|
|
||||||
viewsMap,
|
viewsMap,
|
||||||
selectView,
|
selectView,
|
||||||
addView,
|
addView,
|
||||||
@@ -136,20 +134,6 @@ const MetadataTreeView = ({ userPerm, currentPath }) => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{enableFaceRecognition && staticView.map((item) => {
|
|
||||||
const view = viewsMap[item._id];
|
|
||||||
const viewPath = '/' + PRIVATE_FILE_TYPE.FILE_EXTENDED_PROPERTIES + '/' + view._id;
|
|
||||||
const isSelected = currentPath === viewPath;
|
|
||||||
return (
|
|
||||||
<ViewItem
|
|
||||||
key={view._id}
|
|
||||||
userPerm="r"
|
|
||||||
view={view}
|
|
||||||
isSelected={isSelected}
|
|
||||||
onClick={(view) => selectView(view, isSelected)}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
{canAdd && (
|
{canAdd && (
|
||||||
<div id="sf-metadata-view-popover">
|
<div id="sf-metadata-view-popover">
|
||||||
<CustomizeAddTool
|
<CustomizeAddTool
|
||||||
|
@@ -7,7 +7,7 @@ import Icon from '../../../components/icon';
|
|||||||
import ItemDropdownMenu from '../../../components/dropdown-menu/item-dropdown-menu';
|
import ItemDropdownMenu from '../../../components/dropdown-menu/item-dropdown-menu';
|
||||||
import { Utils, isMobile } from '../../../utils/utils';
|
import { Utils, isMobile } from '../../../utils/utils';
|
||||||
import { useMetadata } from '../../hooks';
|
import { useMetadata } from '../../hooks';
|
||||||
import { VIEW_TYPE_ICON } from '../../constants';
|
import { FACE_RECOGNITION_VIEW_ID, VIEW_TYPE_ICON } from '../../constants';
|
||||||
import { isValidViewName } from '../../utils/validate';
|
import { isValidViewName } from '../../utils/validate';
|
||||||
import { isEnter } from '../../utils/hotkey';
|
import { isEnter } from '../../utils/hotkey';
|
||||||
import toaster from '../../../components/toast';
|
import toaster from '../../../components/toast';
|
||||||
@@ -49,6 +49,11 @@ const ViewItem = ({
|
|||||||
|
|
||||||
const operations = useMemo(() => {
|
const operations = useMemo(() => {
|
||||||
if (!canUpdate) return [];
|
if (!canUpdate) return [];
|
||||||
|
if (view._id === FACE_RECOGNITION_VIEW_ID) {
|
||||||
|
return [
|
||||||
|
{ key: 'rename', value: gettext('Rename') },
|
||||||
|
];
|
||||||
|
}
|
||||||
let value = [
|
let value = [
|
||||||
{ key: 'rename', value: gettext('Rename') },
|
{ key: 'rename', value: gettext('Rename') },
|
||||||
{ key: 'duplicate', value: gettext('Duplicate') }
|
{ key: 'duplicate', value: gettext('Duplicate') }
|
||||||
@@ -57,7 +62,7 @@ const ViewItem = ({
|
|||||||
value.push({ key: 'delete', value: gettext('Delete') });
|
value.push({ key: 'delete', value: gettext('Delete') });
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}, [canUpdate, canDelete]);
|
}, [view, canUpdate, canDelete]);
|
||||||
|
|
||||||
const onMouseEnter = useCallback(() => {
|
const onMouseEnter = useCallback(() => {
|
||||||
if (freeze) return;
|
if (freeze) return;
|
||||||
|
@@ -17,7 +17,10 @@ def generate_random_string_lower_digits(length):
|
|||||||
return random_string
|
return random_string
|
||||||
|
|
||||||
|
|
||||||
def generate_view_id(length, view_ids=None):
|
def generate_view_id(length, type, view_ids=None):
|
||||||
|
if type == 'face_recognition':
|
||||||
|
return '_face_recognition'
|
||||||
|
|
||||||
if not view_ids:
|
if not view_ids:
|
||||||
return generate_random_string_lower_digits(length)
|
return generate_random_string_lower_digits(length)
|
||||||
|
|
||||||
@@ -81,7 +84,7 @@ class RepoView(object):
|
|||||||
|
|
||||||
def init_view(self, view_ids=None):
|
def init_view(self, view_ids=None):
|
||||||
self.view_json = {
|
self.view_json = {
|
||||||
"_id": generate_view_id(4, view_ids),
|
"_id": generate_view_id(4, self.type, view_ids),
|
||||||
"table_id": '0001', # by default
|
"table_id": '0001', # by default
|
||||||
"name": self.name,
|
"name": self.name,
|
||||||
"filters": [],
|
"filters": [],
|
||||||
|
Reference in New Issue
Block a user