mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-18 00:00:00 +00:00
feat: metadata add geoloaction (#6425)
Co-authored-by: 杨国璇 <ygx@Hello-word.local>
This commit is contained in:
14
frontend/package-lock.json
generated
14
frontend/package-lock.json
generated
@@ -19,7 +19,7 @@
|
||||
"@seafile/sdoc-editor": "1.0.35",
|
||||
"@seafile/seafile-calendar": "0.0.12",
|
||||
"@seafile/seafile-editor": "1.0.107",
|
||||
"@seafile/sf-metadata-ui-component": "0.0.13",
|
||||
"@seafile/sf-metadata-ui-component": "0.0.14",
|
||||
"@uiw/codemirror-extensions-langs": "^4.19.4",
|
||||
"@uiw/react-codemirror": "^4.19.4",
|
||||
"chart.js": "2.9.4",
|
||||
@@ -4971,9 +4971,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@seafile/sf-metadata-ui-component": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.13.tgz",
|
||||
"integrity": "sha512-AVKM/4wKcXkc0UWhWHLfvWtfC0Ox18VfX0QBoypY/RxPLXS1mQecw1DMdXVgnZNN22KdmiyZiNRkagmP1ARNhg==",
|
||||
"version": "0.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.14.tgz",
|
||||
"integrity": "sha512-4IUQ5LahSMfEEMoBIr76OAYjpS2KdLuZs5+17asRJVImmqJPLB/HwbiqfsGsmCsAcOefiB9MFAu19i5ai3mngQ==",
|
||||
"dependencies": {
|
||||
"@seafile/seafile-calendar": "0.0.24",
|
||||
"classnames": "2.3.2",
|
||||
@@ -32200,9 +32200,9 @@
|
||||
}
|
||||
},
|
||||
"@seafile/sf-metadata-ui-component": {
|
||||
"version": "0.0.13",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.13.tgz",
|
||||
"integrity": "sha512-AVKM/4wKcXkc0UWhWHLfvWtfC0Ox18VfX0QBoypY/RxPLXS1mQecw1DMdXVgnZNN22KdmiyZiNRkagmP1ARNhg==",
|
||||
"version": "0.0.14",
|
||||
"resolved": "https://registry.npmjs.org/@seafile/sf-metadata-ui-component/-/sf-metadata-ui-component-0.0.14.tgz",
|
||||
"integrity": "sha512-4IUQ5LahSMfEEMoBIr76OAYjpS2KdLuZs5+17asRJVImmqJPLB/HwbiqfsGsmCsAcOefiB9MFAu19i5ai3mngQ==",
|
||||
"requires": {
|
||||
"@seafile/seafile-calendar": "0.0.24",
|
||||
"classnames": "2.3.2",
|
||||
|
@@ -14,7 +14,7 @@
|
||||
"@seafile/sdoc-editor": "1.0.35",
|
||||
"@seafile/seafile-calendar": "0.0.12",
|
||||
"@seafile/seafile-editor": "1.0.107",
|
||||
"@seafile/sf-metadata-ui-component": "0.0.13",
|
||||
"@seafile/sf-metadata-ui-component": "0.0.14",
|
||||
"@uiw/codemirror-extensions-langs": "^4.19.4",
|
||||
"@uiw/react-codemirror": "^4.19.4",
|
||||
"chart.js": "2.9.4",
|
||||
|
1
frontend/src/assets/icons/location.svg
Normal file
1
frontend/src/assets/icons/location.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1721898242394" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="18903" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M518.4 32C316.8 32 153.6 192 153.6 390.4c0 156.8 224 454.4 320 582.4 9.6 12.8 25.6 22.4 41.6 22.4 19.2 0 32-9.6 41.6-22.4 96-124.8 320-425.6 320-582.4C880 192 720 32 518.4 32z m0 486.4c-86.4 0-156.8-70.4-156.8-153.6s70.4-153.6 156.8-153.6 156.8 70.4 156.8 153.6c0 86.4-70.4 153.6-156.8 153.6z" fill="#949494" p-id="18904"></path></svg>
|
After Width: | Height: | Size: 669 B |
@@ -75,6 +75,15 @@ const DATE_DEFAULT_TYPES = {
|
||||
DAYS_AFTER: 'days_after',
|
||||
};
|
||||
|
||||
const GEOLOCATION_FORMAT = {
|
||||
LNG_LAT: 'lng_lat',
|
||||
COUNTRY_REGION: 'country_region',
|
||||
PROVINCE: 'province',
|
||||
PROVINCE_CITY: 'province_city',
|
||||
PROVINCE_CITY_DISTRICT: 'province_city_district',
|
||||
MAP_SELECTION: 'map_selection',
|
||||
};
|
||||
|
||||
export {
|
||||
COLLABORATOR_COLUMN_TYPES,
|
||||
DATE_COLUMN_OPTIONS,
|
||||
@@ -89,4 +98,5 @@ export {
|
||||
NOT_SUPPORT_EDIT_COLUMN_TYPE_MAP,
|
||||
MULTIPLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
||||
SINGLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
||||
GEOLOCATION_FORMAT,
|
||||
};
|
||||
|
@@ -14,6 +14,7 @@ const COLUMNS_ICON_CONFIG = {
|
||||
[CellType.LONG_TEXT]: 'long-text',
|
||||
[CellType.SINGLE_SELECT]: 'single-select',
|
||||
[CellType.NUMBER]: 'number',
|
||||
[CellType.GEOLOCATION]: 'location',
|
||||
};
|
||||
|
||||
const COLUMNS_ICON_NAME = {
|
||||
@@ -30,6 +31,7 @@ const COLUMNS_ICON_NAME = {
|
||||
[CellType.LONG_TEXT]: 'Long text',
|
||||
[CellType.SINGLE_SELECT]: 'Single select',
|
||||
[CellType.NUMBER]: 'Number',
|
||||
[CellType.GEOLOCATION]: 'Geolocation',
|
||||
};
|
||||
|
||||
export {
|
||||
|
@@ -18,6 +18,7 @@ export {
|
||||
NOT_SUPPORT_EDIT_COLUMN_TYPE_MAP,
|
||||
MULTIPLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
||||
SINGLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
||||
GEOLOCATION_FORMAT,
|
||||
} from './format';
|
||||
|
||||
export {
|
||||
|
@@ -21,6 +21,7 @@ export const PRIVATE_COLUMN_KEY = {
|
||||
FILE_SUMMARY: '_summary',
|
||||
FILE_EXPIRED: '_expired',
|
||||
FILE_STATUS: '_status',
|
||||
LOCATION: '_location',
|
||||
};
|
||||
|
||||
export const PRIVATE_COLUMN_KEYS = [
|
||||
@@ -43,4 +44,5 @@ export const PRIVATE_COLUMN_KEYS = [
|
||||
PRIVATE_COLUMN_KEY.FILE_SUMMARY,
|
||||
PRIVATE_COLUMN_KEY.FILE_EXPIRED,
|
||||
PRIVATE_COLUMN_KEY.FILE_STATUS,
|
||||
PRIVATE_COLUMN_KEY.LOCATION,
|
||||
];
|
||||
|
@@ -12,6 +12,7 @@ const CellType = {
|
||||
LONG_TEXT: 'long-text',
|
||||
SINGLE_SELECT: 'single-select',
|
||||
NUMBER: 'number',
|
||||
GEOLOCATION: 'geolocation',
|
||||
};
|
||||
|
||||
export default CellType;
|
||||
|
@@ -23,6 +23,7 @@ export {
|
||||
NOT_DISPLAY_COLUMN_KEYS,
|
||||
VIEW_NOT_DISPLAY_COLUMN_KEYS,
|
||||
PREDEFINED_COLUMN_KEYS,
|
||||
GEOLOCATION_FORMAT,
|
||||
} from './column';
|
||||
export {
|
||||
FILTER_CONJUNCTION_TYPE,
|
||||
|
@@ -147,4 +147,6 @@ export {
|
||||
debounce,
|
||||
throttle,
|
||||
isRegExpression,
|
||||
getGeolocationDisplayString,
|
||||
getGeolocationByGranularity,
|
||||
} from './utils';
|
||||
|
@@ -0,0 +1,82 @@
|
||||
import { GROUP_GEOLOCATION_GRANULARITY, GEOLOCATION_FORMAT } from '../../../constants';
|
||||
import { isValidPosition } from '../../validate';
|
||||
|
||||
/**
|
||||
* Get formatted geolocation
|
||||
* @param {object} loc
|
||||
* @param {object} formats , e.g. { geo_format, ... }
|
||||
* @param {bool} isBaiduMap Determine the way to connect latitude and longitude. Default as true
|
||||
* @param {string} hyphen Used as a connector between province, city, district and detail. Default as empty string
|
||||
* @returns formatted geolocation, string
|
||||
*/
|
||||
const getGeolocationDisplayString = (loc, formats, { isBaiduMap = true, hyphen = '' } = {}) => {
|
||||
if (!loc) return '';
|
||||
const { geo_format } = formats || {};
|
||||
switch (geo_format) {
|
||||
case GEOLOCATION_FORMAT.LNG_LAT: {
|
||||
const { lng, lat } = loc;
|
||||
if (!isValidPosition(lng, lat)) return '';
|
||||
return isBaiduMap ? `${lng}, ${lat}` : `${lat}, ${lng}`;
|
||||
}
|
||||
case GEOLOCATION_FORMAT.COUNTRY_REGION: {
|
||||
const { country_region } = loc;
|
||||
return country_region || '';
|
||||
}
|
||||
case GEOLOCATION_FORMAT.PROVINCE: {
|
||||
const { province } = loc;
|
||||
return province || '';
|
||||
}
|
||||
case GEOLOCATION_FORMAT.PROVINCE_CITY: {
|
||||
const { province, city } = loc;
|
||||
return (`${province || ''}${hyphen}${city || ''}`).trim();
|
||||
}
|
||||
case GEOLOCATION_FORMAT.PROVINCE_CITY_DISTRICT: {
|
||||
const { province, city, district } = loc;
|
||||
return (`${province || ''}${hyphen}${city || ''}${hyphen}${district || ''}`).trim();
|
||||
}
|
||||
case GEOLOCATION_FORMAT.MAP_SELECTION: {
|
||||
const { address, title } = loc;
|
||||
return (`${address || ''}${hyphen}${title || ''}`).trim();
|
||||
}
|
||||
default: {
|
||||
// default as 'geolocation'
|
||||
const {
|
||||
province, city, district, detail,
|
||||
} = loc;
|
||||
if (!province && !city && !district && !detail) return '';
|
||||
return (`${province || ''}${hyphen}${city || ''}${hyphen}${district || ''}${hyphen}${detail || ''}`).trim();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get geolocation by granularity
|
||||
* @param {object} geolocation e.g. { province, ... }
|
||||
* @param {string} granularity
|
||||
* @returns geolocation string
|
||||
*/
|
||||
const getGeolocationByGranularity = (geolocation, granularity) => {
|
||||
if (!geolocation) return '';
|
||||
const {
|
||||
province, city, district, country_region,
|
||||
} = geolocation;
|
||||
switch (granularity) {
|
||||
case GROUP_GEOLOCATION_GRANULARITY.CITY: {
|
||||
return city || '';
|
||||
}
|
||||
case GROUP_GEOLOCATION_GRANULARITY.DISTRICT: {
|
||||
return district || '';
|
||||
}
|
||||
case GROUP_GEOLOCATION_GRANULARITY.COUNTRY: {
|
||||
return country_region || '';
|
||||
}
|
||||
default: {
|
||||
return province || '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export {
|
||||
getGeolocationDisplayString,
|
||||
getGeolocationByGranularity,
|
||||
};
|
@@ -19,3 +19,7 @@ export {
|
||||
getCollaboratorEmailsByNames,
|
||||
} from './collaborator';
|
||||
export { getLongtextDisplayString } from './long-text';
|
||||
export {
|
||||
getGeolocationDisplayString,
|
||||
getGeolocationByGranularity,
|
||||
} from './geolocation';
|
||||
|
@@ -19,4 +19,6 @@ export {
|
||||
getCollaboratorsName,
|
||||
getCollaboratorEmailsByNames,
|
||||
getLongtextDisplayString,
|
||||
getGeolocationDisplayString,
|
||||
getGeolocationByGranularity,
|
||||
} from './column';
|
||||
|
@@ -19,6 +19,8 @@ export {
|
||||
getCollaboratorsName,
|
||||
getCollaboratorEmailsByNames,
|
||||
getLongtextDisplayString,
|
||||
getGeolocationDisplayString,
|
||||
getGeolocationByGranularity,
|
||||
} from './cell';
|
||||
export {
|
||||
getColumnType,
|
||||
|
@@ -0,0 +1,5 @@
|
||||
const isValidPosition = (lng, lat) => (lng || lng === 0) && (lat || lat === 0);
|
||||
|
||||
export {
|
||||
isValidPosition,
|
||||
};
|
@@ -3,3 +3,6 @@ export {
|
||||
ValidateFilter,
|
||||
DATE_MODIFIERS_REQUIRE_TERM,
|
||||
} from './filter';
|
||||
export {
|
||||
isValidPosition,
|
||||
} from './geolocation';
|
||||
|
@@ -10,6 +10,10 @@
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.sf-metadata-result-table-cell:not(.table-cell-uneditable):hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.sf-metadata-result-table-cell.index {
|
||||
width: 90px;
|
||||
height: 100%;
|
||||
|
@@ -29,7 +29,7 @@ const Cell = React.memo(({
|
||||
const { type } = column;
|
||||
const canEditable = window.sfMetadataContext.canModifyCell(column);
|
||||
return classnames('sf-metadata-result-table-cell', `sf-metadata-result-table-${type}-cell`, {
|
||||
'table-cell-uneditable': !canEditable && TABLE_SUPPORT_EDIT_TYPE_MAP[type],
|
||||
'table-cell-uneditable': !canEditable || !TABLE_SUPPORT_EDIT_TYPE_MAP[type],
|
||||
[highlightClassName]: highlightClassName,
|
||||
'last-cell': isLastCell,
|
||||
'table-last--frozen': isLastFrozenCell,
|
||||
|
@@ -38,6 +38,11 @@ export const TABLE_NOT_SUPPORT_EDIT_TYPE_MAP = {
|
||||
|
||||
export const TABLE_SUPPORT_EDIT_TYPE_MAP = {
|
||||
[CellType.TEXT]: true,
|
||||
[CellType.DATE]: true,
|
||||
[CellType.NUMBER]: true,
|
||||
[CellType.SINGLE_SELECT]: true,
|
||||
[CellType.COLLABORATOR]: true,
|
||||
[CellType.CHECKBOX]: true,
|
||||
};
|
||||
|
||||
export const TABLE_MOBILE_SUPPORT_EDIT_CELL_TYPE_MAP = {
|
||||
|
@@ -202,6 +202,8 @@ export const getColumnName = (key, name) => {
|
||||
return gettext('Is expired');
|
||||
case PRIVATE_COLUMN_KEY.FILE_STATUS:
|
||||
return gettext('File status');
|
||||
case PRIVATE_COLUMN_KEY.LOCATION:
|
||||
return gettext('Image location');
|
||||
default:
|
||||
return name;
|
||||
}
|
||||
@@ -237,6 +239,8 @@ const getColumnType = (key, type) => {
|
||||
return CellType.CHECKBOX;
|
||||
case PRIVATE_COLUMN_KEY.FILE_STATUS:
|
||||
return CellType.SINGLE_SELECT;
|
||||
case PRIVATE_COLUMN_KEY.LOCATION:
|
||||
return CellType.GEOLOCATION;
|
||||
default:
|
||||
return type;
|
||||
}
|
||||
|
Reference in New Issue
Block a user