@seafile/seafile-database 0.0.47 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/api.js +11 -0
- package/dist/components/popover/filter-popover/basic-filters/helper.js +60 -0
- package/dist/components/popover/filter-popover/basic-filters/index.js +19 -0
- package/dist/components/popover/filter-popover/basic-filters/parent-dir-filter.js +124 -0
- package/dist/components/popover/filter-popover/basic-filters/state-filter.js +1 -1
- package/dist/components/popover/filter-popover/basic-filters/type-filter.js +31 -10
- package/dist/constants/view/index.js +8 -0
- package/dist/context.js +7 -0
- package/package.json +2 -2
package/dist/api/api.js
CHANGED
|
@@ -300,5 +300,16 @@ class SeafileAPI {
|
|
|
300
300
|
const url = this.server + '/api/v2.1/repos/' + repoID + '/metadata/';
|
|
301
301
|
return this.req.get(url);
|
|
302
302
|
}
|
|
303
|
+
listDirRecursive(repoID) {
|
|
304
|
+
const url = this.server + '/api/v2.1/repos/' + repoID + '/dir/';
|
|
305
|
+
const params = {
|
|
306
|
+
p: '/',
|
|
307
|
+
recursive: 1,
|
|
308
|
+
t: 'd'
|
|
309
|
+
};
|
|
310
|
+
return this.req.get(url, {
|
|
311
|
+
params
|
|
312
|
+
});
|
|
313
|
+
}
|
|
303
314
|
}
|
|
304
315
|
var _default = exports.default = SeafileAPI;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.fetchAllParentDirs = void 0;
|
|
7
|
+
const EXCLUDED_PARENT_DIRS = ['/images', '/_Internal'];
|
|
8
|
+
const normalizeParentDir = path => {
|
|
9
|
+
if (typeof path !== 'string') return '/';
|
|
10
|
+
let normalized = path.trim();
|
|
11
|
+
if (!normalized) return '/';
|
|
12
|
+
if (!normalized.startsWith('/')) normalized = `/${normalized}`;
|
|
13
|
+
normalized = normalized.replace(/\/+$/g, '');
|
|
14
|
+
return normalized || '/';
|
|
15
|
+
};
|
|
16
|
+
const isExcludedParentDir = path => {
|
|
17
|
+
return EXCLUDED_PARENT_DIRS.some(root => path === root || path.startsWith(`${root}/`));
|
|
18
|
+
};
|
|
19
|
+
const getParentDirAncestors = path => {
|
|
20
|
+
const normalized = normalizeParentDir(path);
|
|
21
|
+
if (normalized === '/') return ['/'];
|
|
22
|
+
const segments = normalized.split('/').filter(Boolean);
|
|
23
|
+
const ancestors = ['/'];
|
|
24
|
+
let current = '';
|
|
25
|
+
segments.forEach(segment => {
|
|
26
|
+
current = `${current}/${segment}`;
|
|
27
|
+
ancestors.push(current);
|
|
28
|
+
});
|
|
29
|
+
return ancestors;
|
|
30
|
+
};
|
|
31
|
+
const getParentDirDepth = path => {
|
|
32
|
+
if (path === '/') return 0;
|
|
33
|
+
return path.split('/').filter(Boolean).length;
|
|
34
|
+
};
|
|
35
|
+
const sortParentDirs = (a, b) => {
|
|
36
|
+
if (a === '/') return -1;
|
|
37
|
+
if (b === '/') return 1;
|
|
38
|
+
const depthDiff = getParentDirDepth(a) - getParentDirDepth(b);
|
|
39
|
+
if (depthDiff !== 0) return depthDiff;
|
|
40
|
+
return a.localeCompare(b);
|
|
41
|
+
};
|
|
42
|
+
const fetchAllParentDirs = async context => {
|
|
43
|
+
try {
|
|
44
|
+
var _res$data;
|
|
45
|
+
const res = await context.listDirRecursive();
|
|
46
|
+
const dirents = (res === null || res === void 0 ? void 0 : (_res$data = res.data) === null || _res$data === void 0 ? void 0 : _res$data.dirent_list) || [];
|
|
47
|
+
const dirSet = new Set(['/']);
|
|
48
|
+
dirents.forEach(dirent => {
|
|
49
|
+
const fullPath = `${dirent.parent_dir}/${dirent.name}`.replace(/\/+/g, '/');
|
|
50
|
+
if (isExcludedParentDir(fullPath)) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
getParentDirAncestors(fullPath).forEach(dirPath => dirSet.add(dirPath));
|
|
54
|
+
});
|
|
55
|
+
return Array.from(dirSet).sort(sortParentDirs);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
return ['/'];
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
exports.fetchAllParentDirs = fetchAllParentDirs;
|
|
@@ -11,6 +11,7 @@ var _reactstrap = require("reactstrap");
|
|
|
11
11
|
var _translate = _interopRequireDefault(require("../../../../lang/translate"));
|
|
12
12
|
var _column = require("../../../../utils/column");
|
|
13
13
|
var _constants = require("../../../../constants");
|
|
14
|
+
var _parentDirFilter = _interopRequireDefault(require("./parent-dir-filter"));
|
|
14
15
|
var _stateFilter = _interopRequireDefault(require("./state-filter"));
|
|
15
16
|
var _tagsFilter = _interopRequireDefault(require("./tags-filter"));
|
|
16
17
|
var _typeFilter = _interopRequireDefault(require("./type-filter"));
|
|
@@ -42,6 +43,16 @@ const BasicFilters = _ref => {
|
|
|
42
43
|
};
|
|
43
44
|
onChange && onChange(newFilters);
|
|
44
45
|
}, [filters, onChange]);
|
|
46
|
+
const onParentDirChange = (0, _react.useCallback)(newValue => {
|
|
47
|
+
const filterIndex = filters.findIndex(filter => filter.column_key === '_parent_dir');
|
|
48
|
+
const filter = filters[filterIndex];
|
|
49
|
+
const newFilters = filters.slice(0);
|
|
50
|
+
newFilters[filterIndex] = {
|
|
51
|
+
...filter,
|
|
52
|
+
filter_term: newValue
|
|
53
|
+
};
|
|
54
|
+
onChange && onChange(newFilters);
|
|
55
|
+
}, [filters, onChange]);
|
|
45
56
|
const onTagsChange = (0, _react.useCallback)(newValue => {
|
|
46
57
|
const filterIndex = filters.findIndex(filter => filter.column_key === '_tags');
|
|
47
58
|
const filter = filters[filterIndex];
|
|
@@ -91,6 +102,14 @@ const BasicFilters = _ref => {
|
|
|
91
102
|
onChange: onTagsChange
|
|
92
103
|
});
|
|
93
104
|
}
|
|
105
|
+
if (column_key === '_parent_dir') {
|
|
106
|
+
return /*#__PURE__*/_react.default.createElement(_parentDirFilter.default, {
|
|
107
|
+
readOnly: readOnly,
|
|
108
|
+
value: filter_term,
|
|
109
|
+
key: column_key,
|
|
110
|
+
onChange: onParentDirChange
|
|
111
|
+
});
|
|
112
|
+
}
|
|
94
113
|
return null;
|
|
95
114
|
}))));
|
|
96
115
|
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
|
|
5
|
+
Object.defineProperty(exports, "__esModule", {
|
|
6
|
+
value: true
|
|
7
|
+
});
|
|
8
|
+
exports.default = void 0;
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
|
+
var _components = require("../../../../common/components");
|
|
12
|
+
var _hooks = require("../../../../hooks");
|
|
13
|
+
var _translate = _interopRequireDefault(require("../../../../lang/translate"));
|
|
14
|
+
var _helper = require("./helper");
|
|
15
|
+
const ParentDirFilter = _ref => {
|
|
16
|
+
let {
|
|
17
|
+
readOnly,
|
|
18
|
+
value = [],
|
|
19
|
+
onChange: onChangeAPI
|
|
20
|
+
} = _ref;
|
|
21
|
+
const {
|
|
22
|
+
context
|
|
23
|
+
} = (0, _hooks.useFileViewContext)();
|
|
24
|
+
const [isLoading, setIsLoading] = (0, _react.useState)(false);
|
|
25
|
+
const [directories, setDirectories] = (0, _react.useState)([]);
|
|
26
|
+
const [isInitialized, setIsInitialized] = (0, _react.useState)(false);
|
|
27
|
+
(0, _react.useEffect)(() => {
|
|
28
|
+
let isCanceled = false;
|
|
29
|
+
const loadParentDirs = async () => {
|
|
30
|
+
setIsLoading(true);
|
|
31
|
+
try {
|
|
32
|
+
const allDirs = await (0, _helper.fetchAllParentDirs)(context);
|
|
33
|
+
if (!isCanceled) {
|
|
34
|
+
setDirectories(allDirs);
|
|
35
|
+
}
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (!isCanceled) {
|
|
38
|
+
setDirectories([]);
|
|
39
|
+
}
|
|
40
|
+
} finally {
|
|
41
|
+
if (!isCanceled) {
|
|
42
|
+
setIsLoading(false);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
loadParentDirs();
|
|
47
|
+
return () => {
|
|
48
|
+
isCanceled = true;
|
|
49
|
+
};
|
|
50
|
+
}, [context]);
|
|
51
|
+
|
|
52
|
+
// If selected value is 0, default to select root directory "/"
|
|
53
|
+
(0, _react.useEffect)(() => {
|
|
54
|
+
if (directories.length > 0 && value.length === 0 && !isLoading && !isInitialized) {
|
|
55
|
+
setIsInitialized(true);
|
|
56
|
+
onChangeAPI(['/']);
|
|
57
|
+
}
|
|
58
|
+
}, [directories, value.length, isLoading, isInitialized, onChangeAPI]);
|
|
59
|
+
const options = (0, _react.useMemo)(() => {
|
|
60
|
+
if (isLoading && directories.length === 0) {
|
|
61
|
+
return [{
|
|
62
|
+
value: '__loading__',
|
|
63
|
+
label: /*#__PURE__*/_react.default.createElement("div", {
|
|
64
|
+
className: "select-basic-filter-option"
|
|
65
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
66
|
+
className: "select-basic-filter-option-name"
|
|
67
|
+
}, _translate.default.gettext('Loading...')))
|
|
68
|
+
}];
|
|
69
|
+
}
|
|
70
|
+
if (directories.length === 0) {
|
|
71
|
+
return [{
|
|
72
|
+
value: '__empty__',
|
|
73
|
+
label: /*#__PURE__*/_react.default.createElement("div", {
|
|
74
|
+
className: "select-basic-filter-option"
|
|
75
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
76
|
+
className: "select-basic-filter-option-name"
|
|
77
|
+
}, _translate.default.gettext('No options')))
|
|
78
|
+
}];
|
|
79
|
+
}
|
|
80
|
+
return directories.map(dirPath => {
|
|
81
|
+
return {
|
|
82
|
+
value: dirPath,
|
|
83
|
+
label: /*#__PURE__*/_react.default.createElement("div", {
|
|
84
|
+
className: "select-basic-filter-option"
|
|
85
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
86
|
+
className: "select-basic-filter-option-checkbox mr-2"
|
|
87
|
+
}, /*#__PURE__*/_react.default.createElement("input", {
|
|
88
|
+
type: "checkbox",
|
|
89
|
+
className: "form-check-input",
|
|
90
|
+
checked: value.includes(dirPath),
|
|
91
|
+
readOnly: true
|
|
92
|
+
})), /*#__PURE__*/_react.default.createElement("div", {
|
|
93
|
+
className: "select-basic-filter-option-name",
|
|
94
|
+
title: dirPath,
|
|
95
|
+
"aria-label": dirPath
|
|
96
|
+
}, dirPath))
|
|
97
|
+
};
|
|
98
|
+
});
|
|
99
|
+
}, [directories, isLoading, value]);
|
|
100
|
+
const displayValue = (0, _react.useMemo)(() => {
|
|
101
|
+
return {
|
|
102
|
+
label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, _translate.default.gettext('Parent folder'))
|
|
103
|
+
};
|
|
104
|
+
}, []);
|
|
105
|
+
const onChange = (0, _react.useCallback)(newValue => {
|
|
106
|
+
if (newValue === '__loading__' || newValue === '__empty__') return;
|
|
107
|
+
if (value.includes(newValue)) {
|
|
108
|
+
onChangeAPI(value.filter(v => v !== newValue));
|
|
109
|
+
} else {
|
|
110
|
+
onChangeAPI([...value, newValue]);
|
|
111
|
+
}
|
|
112
|
+
}, [value, onChangeAPI]);
|
|
113
|
+
return /*#__PURE__*/_react.default.createElement(_components.CustomizeSelect, {
|
|
114
|
+
disabled: readOnly,
|
|
115
|
+
supportMultipleSelect: true,
|
|
116
|
+
className: (0, _classnames.default)('sea-metadata-basic-filters-select sea-metadata-table-view-basic-filter-folder-type-select mr-4', {
|
|
117
|
+
highlighted: value.length > 0
|
|
118
|
+
}),
|
|
119
|
+
value: displayValue,
|
|
120
|
+
options: options,
|
|
121
|
+
onChange: onChange
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
var _default = exports.default = ParentDirFilter;
|
|
@@ -9,21 +9,42 @@ exports.default = void 0;
|
|
|
9
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
10
10
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
11
11
|
var _components = require("../../../../common/components");
|
|
12
|
+
var _constants = require("../../../../constants");
|
|
12
13
|
var _translate = _interopRequireDefault(require("../../../../lang/translate"));
|
|
13
14
|
const TypeFilter = _ref => {
|
|
14
15
|
let {
|
|
15
|
-
readOnly
|
|
16
|
+
readOnly,
|
|
16
17
|
value = [],
|
|
17
|
-
column,
|
|
18
18
|
onChange: onChangeAPI
|
|
19
19
|
} = _ref;
|
|
20
|
+
const FILE_TYPE_OPTIONS = (0, _react.useMemo)(() => [{
|
|
21
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.PICTURE,
|
|
22
|
+
name: _translate.default.gettext('Picture')
|
|
23
|
+
}, {
|
|
24
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.DOCUMENT,
|
|
25
|
+
name: _translate.default.gettext('Document')
|
|
26
|
+
}, {
|
|
27
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.VIDEO,
|
|
28
|
+
name: _translate.default.gettext('Video')
|
|
29
|
+
}, {
|
|
30
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.AUDIO,
|
|
31
|
+
name: _translate.default.gettext('Audio')
|
|
32
|
+
}, {
|
|
33
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.CODE,
|
|
34
|
+
name: _translate.default.gettext('Code')
|
|
35
|
+
}, {
|
|
36
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.COMPRESSED,
|
|
37
|
+
name: _translate.default.gettext('Compressed')
|
|
38
|
+
}, {
|
|
39
|
+
value: _constants.PREDEFINED_FILE_TYPE_OPTION_KEY.DIAGRAM,
|
|
40
|
+
name: _translate.default.gettext('Diagram')
|
|
41
|
+
}], []);
|
|
20
42
|
const options = (0, _react.useMemo)(() => {
|
|
21
|
-
return
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
} = o;
|
|
43
|
+
return FILE_TYPE_OPTIONS.map(option => {
|
|
44
|
+
const optionValue = option.value;
|
|
45
|
+
const name = option.name;
|
|
25
46
|
return {
|
|
26
|
-
value:
|
|
47
|
+
value: optionValue,
|
|
27
48
|
label: /*#__PURE__*/_react.default.createElement("div", {
|
|
28
49
|
className: "select-basic-filter-option"
|
|
29
50
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
@@ -31,7 +52,7 @@ const TypeFilter = _ref => {
|
|
|
31
52
|
}, /*#__PURE__*/_react.default.createElement("input", {
|
|
32
53
|
type: "checkbox",
|
|
33
54
|
className: "form-check-input",
|
|
34
|
-
checked: value.includes(
|
|
55
|
+
checked: value.includes(optionValue),
|
|
35
56
|
readOnly: true
|
|
36
57
|
})), /*#__PURE__*/_react.default.createElement("div", {
|
|
37
58
|
className: "select-basic-filter-option-name",
|
|
@@ -40,7 +61,7 @@ const TypeFilter = _ref => {
|
|
|
40
61
|
}, name))
|
|
41
62
|
};
|
|
42
63
|
});
|
|
43
|
-
}, [
|
|
64
|
+
}, [value, FILE_TYPE_OPTIONS]);
|
|
44
65
|
const displayValue = (0, _react.useMemo)(() => {
|
|
45
66
|
return {
|
|
46
67
|
label: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, _translate.default.gettext('File type'))
|
|
@@ -56,7 +77,7 @@ const TypeFilter = _ref => {
|
|
|
56
77
|
return /*#__PURE__*/_react.default.createElement(_components.CustomizeSelect, {
|
|
57
78
|
disabled: readOnly,
|
|
58
79
|
supportMultipleSelect: true,
|
|
59
|
-
className: (0, _classnames.default)('sea-metadata-basic-filters-select sea-metadata-table-view-basic-
|
|
80
|
+
className: (0, _classnames.default)('sea-metadata-basic-filters-select sea-metadata-table-view-basic-filter-file-type-select mr-4', {
|
|
60
81
|
'highlighted': value.length > 0
|
|
61
82
|
}),
|
|
62
83
|
value: displayValue,
|
|
@@ -107,6 +107,10 @@ const VIEW_TYPE_DEFAULT_BASIC_FILTER = exports.VIEW_TYPE_DEFAULT_BASIC_FILTER =
|
|
|
107
107
|
column_key: '_tags',
|
|
108
108
|
filter_predicate: _filter.FILTER_PREDICATE_TYPE.HAS_ANY_OF,
|
|
109
109
|
filter_term: []
|
|
110
|
+
}, {
|
|
111
|
+
column_key: '_parent_dir',
|
|
112
|
+
filter_predicate: _filter.FILTER_PREDICATE_TYPE.IS,
|
|
113
|
+
filter_term: []
|
|
110
114
|
}],
|
|
111
115
|
[VIEW_TYPE.CARD]: [{
|
|
112
116
|
column_key: _column.PRIVATE_COLUMN_KEY.IS_DIR,
|
|
@@ -120,6 +124,10 @@ const VIEW_TYPE_DEFAULT_BASIC_FILTER = exports.VIEW_TYPE_DEFAULT_BASIC_FILTER =
|
|
|
120
124
|
column_key: _column.PRIVATE_COLUMN_KEY.TAGS,
|
|
121
125
|
filter_predicate: _filter.FILTER_PREDICATE_TYPE.HAS_ALL_OF,
|
|
122
126
|
filter_term: []
|
|
127
|
+
}, {
|
|
128
|
+
column_key: '_parent_dir',
|
|
129
|
+
filter_predicate: _filter.FILTER_PREDICATE_TYPE.IS,
|
|
130
|
+
filter_term: []
|
|
123
131
|
}],
|
|
124
132
|
[VIEW_TYPE.GALLERY]: [],
|
|
125
133
|
[VIEW_TYPE.KANBAN]: []
|
package/dist/context.js
CHANGED
|
@@ -364,6 +364,13 @@ class Context {
|
|
|
364
364
|
this.permission = _settings.permission || 'r';
|
|
365
365
|
this.isViewComputedOnServer = isViewComputedOnServer;
|
|
366
366
|
}
|
|
367
|
+
listDirRecursive() {
|
|
368
|
+
if (!this.api) return null;
|
|
369
|
+
const {
|
|
370
|
+
repoID
|
|
371
|
+
} = this.settings;
|
|
372
|
+
return this.api.listDirRecursive(repoID);
|
|
373
|
+
}
|
|
367
374
|
}
|
|
368
375
|
|
|
369
376
|
// const context = new Context();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seafile/seafile-database",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.49",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "This is a seafile database components",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"resolve": "^1.20.0",
|
|
126
126
|
"resolve-url-loader": "5.0.0",
|
|
127
127
|
"sass-loader": "^12.3.0",
|
|
128
|
-
"seafile-js": "0.2.
|
|
128
|
+
"seafile-js": "0.2.239",
|
|
129
129
|
"source-map-loader": "^3.0.0",
|
|
130
130
|
"style-loader": "^3.3.1",
|
|
131
131
|
"tailwindcss": "^3.0.2",
|