mirror of
https://github.com/haiwen/seahub.git
synced 2025-09-12 21:30:39 +00:00
305 lines
10 KiB
JavaScript
305 lines
10 KiB
JavaScript
import { DateUtils } from '../date';
|
|
import {
|
|
sortDate,
|
|
sortText,
|
|
sortNumber,
|
|
sortCheckbox,
|
|
sortCollaborator,
|
|
sortSingleSelect,
|
|
sortMultipleSelect,
|
|
} from '../sort/sort-column';
|
|
import { MAX_GROUP_LEVEL } from '../../constants/group';
|
|
import {
|
|
CellType,
|
|
DATE_COLUMN_OPTIONS,
|
|
MULTIPLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
|
SINGLE_CELL_VALUE_COLUMN_TYPE_MAP,
|
|
} from '../../constants/column';
|
|
import {
|
|
SORT_COLUMN_OPTIONS,
|
|
SORT_TYPE,
|
|
TEXT_SORTER_COLUMN_TYPES,
|
|
NUMBER_SORTER_COLUMN_TYPES,
|
|
} from '../../constants/sort';
|
|
import { deleteInvalidGroupby } from './core';
|
|
import { getGeolocationByGranularity, getCollaboratorsNames, getCellValueByColumn, isValidCellValue } from '../cell';
|
|
|
|
const _getFormattedCellValue = (cellValue, groupby) => {
|
|
const { column, count_type: countType } = groupby;
|
|
const { type: columnType } = column;
|
|
switch (columnType) {
|
|
case CellType.TEXT:
|
|
case CellType.LAST_MODIFIER:
|
|
case CellType.CREATOR: {
|
|
return cellValue || null;
|
|
}
|
|
case CellType.DATE:
|
|
case CellType.CTIME:
|
|
case CellType.MTIME: {
|
|
return DateUtils.getDateByGranularity(cellValue, countType) || null;
|
|
}
|
|
case CellType.NUMBER: {
|
|
return (cellValue || cellValue === 0) ? cellValue : null;
|
|
}
|
|
case CellType.CHECKBOX: {
|
|
return !!cellValue;
|
|
}
|
|
case CellType.SINGLE_SELECT: {
|
|
return cellValue || null;
|
|
}
|
|
case CellType.MULTIPLE_SELECT: {
|
|
return Array.isArray(cellValue) ? cellValue : [];
|
|
}
|
|
case CellType.COLLABORATOR: {
|
|
return Array.isArray(cellValue) ? cellValue : [];
|
|
}
|
|
case CellType.GEOLOCATION: {
|
|
return getGeolocationByGranularity(cellValue, countType);
|
|
}
|
|
default: {
|
|
return null;
|
|
}
|
|
}
|
|
};
|
|
|
|
const _getStrCellValue = (cellValue, columnType) => {
|
|
let sCellValue = null;
|
|
if (SINGLE_CELL_VALUE_COLUMN_TYPE_MAP[columnType]) {
|
|
sCellValue = typeof cellValue === 'string' ? cellValue : String(cellValue);
|
|
} else if (MULTIPLE_CELL_VALUE_COLUMN_TYPE_MAP[columnType]) {
|
|
sCellValue = [...cellValue].sort().toString();
|
|
}
|
|
return sCellValue;
|
|
};
|
|
|
|
const _findGroupIndexWithMultipleGroupbys = (sCellValue, cellValue2GroupIndexMap, groupsLength) => {
|
|
const target = cellValue2GroupIndexMap[sCellValue];
|
|
if (target && target.index > -1) {
|
|
return target.index;
|
|
}
|
|
|
|
// eslint-disable-next-line
|
|
cellValue2GroupIndexMap[sCellValue] = {};
|
|
|
|
// eslint-disable-next-line
|
|
cellValue2GroupIndexMap[sCellValue].subgroups = {};
|
|
|
|
// eslint-disable-next-line
|
|
cellValue2GroupIndexMap[sCellValue].index = groupsLength;
|
|
return -1;
|
|
};
|
|
|
|
const _findGroupIndex = (sCellValue, cellValue2GroupIndexMap, groupsLength) => {
|
|
const index = cellValue2GroupIndexMap[sCellValue];
|
|
if (index > -1) {
|
|
return index;
|
|
}
|
|
|
|
// eslint-disable-next-line
|
|
cellValue2GroupIndexMap[sCellValue] = groupsLength;
|
|
return -1;
|
|
};
|
|
|
|
const getSortedGroups = (groups, groupbys, level, collaborators = []) => {
|
|
const sortFlag = 0;
|
|
const { column, sort_type } = groupbys[level];
|
|
const { type: columnType, data: columnData } = column;
|
|
const normalizedSortType = sort_type || SORT_TYPE.UP;
|
|
let option_id_index_map = {};
|
|
if (columnType === CellType.SINGLE_SELECT || columnType === CellType.MULTIPLE_SELECT) {
|
|
const { options } = columnData || {};
|
|
if (Array.isArray(options)) {
|
|
options.forEach((option, index) => {
|
|
option_id_index_map[option.id] = index;
|
|
});
|
|
}
|
|
}
|
|
|
|
groups.sort((currGroupRow, nextGroupRow) => {
|
|
let { cell_value: currCellVal } = currGroupRow;
|
|
let { cell_value: nextCellVal } = nextGroupRow;
|
|
if (SORT_COLUMN_OPTIONS.includes(columnType)) {
|
|
let sortResult;
|
|
if (TEXT_SORTER_COLUMN_TYPES.includes(columnType)) {
|
|
sortResult = sortText(currCellVal, nextCellVal, normalizedSortType);
|
|
} else if (DATE_COLUMN_OPTIONS.includes(columnType)) {
|
|
sortResult = sortDate(currCellVal, nextCellVal, normalizedSortType);
|
|
} else if (NUMBER_SORTER_COLUMN_TYPES.includes(columnType)) {
|
|
sortResult = sortNumber(currCellVal, nextCellVal, normalizedSortType);
|
|
} else if (columnType === CellType.CHECKBOX) {
|
|
sortResult = sortCheckbox(currCellVal, nextCellVal, normalizedSortType);
|
|
} else if (columnType === CellType.COLLABORATOR) {
|
|
let currCollaborators = currCellVal;
|
|
let nextCollaborators = nextCellVal;
|
|
if (collaborators) {
|
|
currCollaborators = getCollaboratorsNames(currCollaborators, collaborators);
|
|
nextCollaborators = getCollaboratorsNames(nextCollaborators, collaborators);
|
|
}
|
|
sortResult = sortCollaborator(currCollaborators, nextCollaborators, normalizedSortType);
|
|
} else if (columnType === CellType.SINGLE_SELECT) {
|
|
sortResult = sortSingleSelect(currCellVal, nextCellVal, { sort_type: normalizedSortType, option_id_index_map });
|
|
} else if (columnType === CellType.MULTIPLE_SELECT) {
|
|
sortResult = sortMultipleSelect(currCellVal, nextCellVal, { sort_type: normalizedSortType, option_id_index_map });
|
|
}
|
|
return sortFlag || sortResult;
|
|
}
|
|
|
|
const isValidCurrCellVal = isValidCellValue(currCellVal);
|
|
const isValidNextCellVal = isValidCellValue(nextCellVal);
|
|
if (!isValidCurrCellVal && !isValidNextCellVal) return 0;
|
|
if (!isValidCurrCellVal) return 1;
|
|
if (!isValidNextCellVal) return -1;
|
|
return 0;
|
|
});
|
|
|
|
// for nested group.
|
|
const isNestedGroup = Array.isArray(groups[0].subgroups) && groups[0].subgroups.length > 0;
|
|
if (isNestedGroup) {
|
|
const nextLevel = level + 1;
|
|
|
|
// eslint-disable-next-line
|
|
groups = groups.map((group) => {
|
|
const sortedSubgroups = getSortedGroups(group.subgroups, groupbys, nextLevel, collaborators);
|
|
return {
|
|
...group,
|
|
subgroups: sortedSubgroups,
|
|
};
|
|
});
|
|
}
|
|
return groups;
|
|
};
|
|
|
|
const groupRowsWithMultipleGroupbys = (groupbys, rows, collaborators) => {
|
|
const validGroupbys = groupbys.length > MAX_GROUP_LEVEL
|
|
? groupbys.slice(0, MAX_GROUP_LEVEL)
|
|
: [...groupbys];
|
|
let groups = [];
|
|
let cellValue2GroupIndexMap = {};
|
|
rows.forEach((row) => {
|
|
const rowId = row._id;
|
|
let updatedGroup;
|
|
let updateCellValue2GroupIndexMap;
|
|
for (let level = 0; level < validGroupbys.length; level++) {
|
|
const currentGroupby = validGroupbys[level];
|
|
const { column, column_key } = currentGroupby;
|
|
const { type: columnType } = column;
|
|
const cellValue = getCellValueByColumn(row, column);
|
|
const formattedValue = _getFormattedCellValue(cellValue, currentGroupby);
|
|
const sCellValue = _getStrCellValue(formattedValue, columnType);
|
|
const group = {
|
|
cell_value: formattedValue,
|
|
original_cell_value: cellValue,
|
|
row_ids: null,
|
|
column_key,
|
|
subgroups: [],
|
|
summaries: {},
|
|
};
|
|
if (level === 0) {
|
|
let groupedRowIndex = _findGroupIndexWithMultipleGroupbys(sCellValue, cellValue2GroupIndexMap, groups.length);
|
|
updateCellValue2GroupIndexMap = cellValue2GroupIndexMap[sCellValue].subgroups;
|
|
if (groupedRowIndex < 0) {
|
|
groups.push(group);
|
|
updatedGroup = groups[groups.length - 1];
|
|
} else {
|
|
updatedGroup = groups[groupedRowIndex];
|
|
}
|
|
} else {
|
|
let groupedRowIndex = _findGroupIndexWithMultipleGroupbys(sCellValue, updateCellValue2GroupIndexMap, updatedGroup.subgroups.length);
|
|
updateCellValue2GroupIndexMap = updateCellValue2GroupIndexMap[sCellValue].subgroups;
|
|
if (groupedRowIndex < 0) {
|
|
updatedGroup.subgroups.push(group);
|
|
updatedGroup = updatedGroup.subgroups[updatedGroup.subgroups.length - 1];
|
|
} else {
|
|
updatedGroup = updatedGroup.subgroups[groupedRowIndex];
|
|
}
|
|
|
|
// update row_ids in the deepest group.
|
|
if (level === validGroupbys.length - 1) {
|
|
if (!updatedGroup.row_ids) {
|
|
updatedGroup.row_ids = [rowId];
|
|
} else {
|
|
updatedGroup.row_ids.push(rowId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
groups = getSortedGroups(groups, validGroupbys, 0, collaborators);
|
|
|
|
return groups;
|
|
};
|
|
|
|
/**
|
|
* Group table rows
|
|
* @param {array} groupbys e.g. [{ column_key, count_type, column, ... }, ...]
|
|
* @param {array} rows e.g. [{ _id, ... }, ...]
|
|
* @param {array} collaborators e.g. [ collaborator, ... ]
|
|
* @returns groups: [{
|
|
* cell_value, original_cell_value, column_key,
|
|
row_ids, subgroups, summaries, ...}, ...], array
|
|
*/
|
|
const groupTableRows = (groupbys, rows, collaborators = []) => {
|
|
if (groupbys.length === 0) {
|
|
return [];
|
|
}
|
|
if (groupbys.length > 1) {
|
|
return groupRowsWithMultipleGroupbys(groupbys, rows, collaborators);
|
|
}
|
|
const groupby = groupbys[0];
|
|
const { column_key, column } = groupby;
|
|
const { type: columnType } = column;
|
|
let groups = [];
|
|
let cellValue2GroupIndexMap = {};
|
|
rows.forEach((r) => {
|
|
const cellValue = getCellValueByColumn(r, column);
|
|
const formattedValue = _getFormattedCellValue(cellValue, groupby);
|
|
const cellValueStr = _getStrCellValue(formattedValue, columnType);
|
|
let groupedRowIndex = _findGroupIndex(cellValueStr, cellValue2GroupIndexMap, groups.length);
|
|
if (groupedRowIndex > -1) {
|
|
groups[groupedRowIndex].row_ids.push(r._id);
|
|
} else {
|
|
groups.push({
|
|
cell_value: formattedValue,
|
|
original_cell_value: cellValue,
|
|
column_key,
|
|
row_ids: [r._id],
|
|
subgroups: null,
|
|
summaries: {},
|
|
});
|
|
}
|
|
});
|
|
|
|
// sort groups
|
|
groups = getSortedGroups(groups, groupbys, 0, collaborators);
|
|
|
|
return groups;
|
|
};
|
|
|
|
/**
|
|
* Group view rows
|
|
* @param {array} groupbys e.g. [{ column_key, count_type, column, ... }, ...]
|
|
* @param {object} table e.g. { id_row_map, ... }
|
|
* @param {array} rowsIds e.g. [ row._id, ...]
|
|
* @param {array} value e.g. { collaborators }
|
|
* @returns groups: [{
|
|
* cell_value, original_cell_value, column_key,
|
|
row_ids, subgroups, summaries, ...}, ...], array
|
|
*/
|
|
const getGroupRows = (table, rows, groupbys, { collaborators }) => {
|
|
if (rows.length === 0) return [];
|
|
if (groupbys.length === 0) return rows;
|
|
let validGroupbys = [];
|
|
try {
|
|
validGroupbys = deleteInvalidGroupby(groupbys, table.columns);
|
|
} catch (err) {
|
|
validGroupbys = [];
|
|
}
|
|
return groupTableRows(validGroupbys, rows, collaborators);
|
|
};
|
|
|
|
export {
|
|
groupTableRows,
|
|
getGroupRows,
|
|
};
|