feat: support group by status in kanban mode, resolved #40

This commit is contained in:
QiShaoXuan 2022-08-02 19:10:51 +08:00
parent 418e260ade
commit f18f51ba7c
10 changed files with 76 additions and 41 deletions

View File

@ -41,6 +41,7 @@ const getKanbanColor = (
return DEFAULT_COLOR;
}
if (
group.type === PropertyType.Status ||
group.type === PropertyType.Select ||
group.type === PropertyType.MultiSelect ||
group.type === DEFAULT_GROUP_ID

View File

@ -4,7 +4,7 @@ import { ModifyPanelContentProps } from './types';
import { StyledDivider, StyledPopoverSubTitle } from '../StyledComponent';
import { BasicSelect } from './Select';
import { InformationProperty, InformationValue } from '../../recast-block';
import { genInitialOptions, getPendantIconsConfigByName } from '../utils';
import { generateInitialOptions, getPendantIconsConfigByName } from '../utils';
export default (props: ModifyPanelContentProps) => {
const { onPropertyChange, onValueChange, initialValue, property } = props;
@ -38,7 +38,7 @@ export default (props: ModifyPanelContentProps) => {
}}
initialOptions={
propProperty?.emailOptions ||
genInitialOptions(
generateInitialOptions(
property?.type,
getPendantIconsConfigByName('Email')
)
@ -66,7 +66,7 @@ export default (props: ModifyPanelContentProps) => {
}}
initialOptions={
propProperty?.phoneOptions ||
genInitialOptions(
generateInitialOptions(
property?.type,
getPendantIconsConfigByName('Phone')
)
@ -94,7 +94,7 @@ export default (props: ModifyPanelContentProps) => {
}}
initialOptions={
propProperty?.locationOptions ||
genInitialOptions(
generateInitialOptions(
property?.type,
getPendantIconsConfigByName('Location')
)

View File

@ -21,7 +21,7 @@ import {
} from '@toeverything/components/ui';
import { HighLightIconInput } from './IconInput';
import { PendantConfig, IconNames, OptionIdType, OptionType } from '../types';
import { genBasicOption } from '../utils';
import { generateBasicOption } from '../utils';
type OptionItemType = {
option: OptionType;
@ -66,7 +66,7 @@ export const BasicSelect = ({
const [selectIds, setSelectIds] = useState<OptionIdType[]>(initialValue);
const insertOption = (insertId: OptionIdType) => {
const newOption = genBasicOption({
const newOption = generateBasicOption({
index: options.length + 1,
iconConfig,
});

View File

@ -1,5 +1,4 @@
import React, { useState, useEffect } from 'react';
import { nanoid } from 'nanoid';
import { Input, Option, Select, Tooltip } from '@toeverything/components/ui';
import { HelpCenterIcon } from '@toeverything/components/icons';
import { AsyncBlock } from '../../editor';
@ -15,13 +14,13 @@ import {
StyledPopoverSubTitle,
StyledPopoverWrapper,
} from '../StyledComponent';
import { genInitialOptions, getPendantConfigByType } from '../utils';
import {
generateRandomFieldName,
generateInitialOptions,
getPendantConfigByType,
} from '../utils';
import { useOnCreateSure } from './hooks';
const upperFirst = (str: string) => {
return `${str[0].toUpperCase()}${str.slice(1)}`;
};
export const CreatePendantPanel = ({
block,
onSure,
@ -35,7 +34,7 @@ export const CreatePendantPanel = ({
useEffect(() => {
selectedOption &&
setFieldName(upperFirst(`${selectedOption.type}#${nanoid(4)}`));
setFieldName(generateRandomFieldName(selectedOption.type));
}, [selectedOption]);
return (
@ -93,7 +92,7 @@ export const CreatePendantPanel = ({
<PendantModifyPanel
type={selectedOption.type}
// Select, MultiSelect, Status use this props as initial property
initialOptions={genInitialOptions(
initialOptions={generateInitialOptions(
selectedOption.type,
getPendantConfigByType(selectedOption.type)
)}

View File

@ -7,6 +7,7 @@ import {
import { OptionIdType, OptionType } from './types';
import { pendantConfig } from './config';
import { PendantConfig, PendantTypes } from './types';
import { nanoid } from 'nanoid';
type Props = {
recastBlockId: string;
blockId: string;
@ -60,7 +61,7 @@ export const getPendantHistory = ({
return data[recastBlockId] ?? {};
};
export const removePropertyValueRecord = ({
export const removePendantHistory = ({
recastBlockId,
propertyId,
}: {
@ -107,7 +108,7 @@ export const getOfficialSelected = ({
.map(id => {
return tempOptions.findIndex((o: OptionType) => o.id === id);
})
.filter(index => index != -1);
.filter(index => index !== -1);
selectedId = selectedIndex.map((index: number) => {
return options[index].id;
});
@ -130,7 +131,7 @@ export const getPendantIconsConfigByName = (
return pendantConfig[pendantName];
};
export const genBasicOption = ({
export const generateBasicOption = ({
index,
iconConfig,
name = '',
@ -159,22 +160,22 @@ export const genBasicOption = ({
/**
* Status Pendant is a Select Pendant built-in some options
* **/
export const genInitialOptions = (
export const generateInitialOptions = (
type: PendantTypes,
iconConfig: PendantConfig
) => {
if (type === PendantTypes.Status) {
return [
genBasicOption({ index: 0, iconConfig, name: 'No Started' }),
genBasicOption({
generateBasicOption({ index: 0, iconConfig, name: 'No Started' }),
generateBasicOption({
index: 1,
iconConfig,
name: 'In Progress',
}),
genBasicOption({ index: 2, iconConfig, name: 'Complete' }),
generateBasicOption({ index: 2, iconConfig, name: 'Complete' }),
];
}
return [genBasicOption({ index: 0, iconConfig })];
return [generateBasicOption({ index: 0, iconConfig })];
};
export const checkPendantForm = (
@ -222,3 +223,10 @@ export const checkPendantForm = (
return { passed: true, message: 'Check passed !' };
};
const upperFirst = (str: string) => {
return `${str[0].toUpperCase()}${str.slice(1)}`;
};
export const generateRandomFieldName = (type: PendantTypes) =>
upperFirst(`${type}#${nanoid(4)}`);

View File

@ -10,6 +10,12 @@ import {
} from '../recast-block/types';
import type { DefaultGroup, KanbanGroup } from './types';
import { DEFAULT_GROUP_ID } from './types';
import {
generateInitialOptions,
generateRandomFieldName,
getPendantIconsConfigByName,
} from '../block-pendant/utils';
import { SelectOption } from '../recast-block';
/**
* - If the `groupBy` is `SelectProperty` or `MultiSelectProperty`, return `(Multi)SelectProperty.options`.
@ -23,6 +29,7 @@ export const getGroupOptions = async (
return [];
}
switch (groupBy.type) {
case PropertyType.Status:
case PropertyType.Select:
case PropertyType.MultiSelect: {
return groupBy.options.map(option => ({
@ -57,6 +64,9 @@ const isValueBelongOption = (
case PropertyType.MultiSelect: {
return propertyValue.value.some(i => i === option.id);
}
case PropertyType.Status: {
return propertyValue.value === option.id;
}
// case PropertyType.Text: {
// TOTODO:DO support this type
// }
@ -107,6 +117,7 @@ export const moveCardToGroup = async (
success = await removeValue(groupById);
return false;
}
switch (group.type) {
case PropertyType.Select: {
success = await setValue({
@ -116,6 +127,14 @@ export const moveCardToGroup = async (
});
break;
}
case PropertyType.Status: {
success = await setValue({
id: groupById,
type: group.type,
value: group.id,
});
break;
}
case PropertyType.MultiSelect: {
success = await setValue({
id: groupById,
@ -194,14 +213,18 @@ export const genDefaultGroup = (groupBy: RecastMetaProperty): DefaultGroup => ({
items: [],
});
export const DEFAULT_GROUP_BY_PROPERTY = {
name: 'Status',
options: [
{ name: 'No Started', color: '#E53535', background: '#FFCECE' },
{ name: 'In Progress', color: '#A77F1A', background: '#FFF5AB' },
{ name: 'Complete', color: '#3C8867', background: '#C5FBE0' },
],
};
export const generateDefaultGroupByProperty = (): {
name: string;
options: Omit<SelectOption, 'id'>[];
type: PropertyType.Status;
} => ({
name: generateRandomFieldName(PropertyType.Status),
type: PropertyType.Status,
options: generateInitialOptions(
PropertyType.Status,
getPendantIconsConfigByName(PropertyType.Status)
),
});
/**
* Unwrap blocks from the grid recursively.

View File

@ -7,6 +7,7 @@ export const useKanbanGroup = (groupBy: RecastMetaProperty) => {
const { updateSelect } = useSelectProperty();
switch (groupBy.type) {
case PropertyType.Status:
case PropertyType.MultiSelect:
case PropertyType.Select: {
const {

View File

@ -18,8 +18,8 @@ import {
import { supportChildren } from '../utils';
import {
calcCardGroup,
DEFAULT_GROUP_BY_PROPERTY,
genDefaultGroup,
generateDefaultGroupByProperty,
getCardGroup,
getGroupOptions,
moveCardToAfter,
@ -48,6 +48,7 @@ export const useRecastKanbanGroupBy = () => {
// Add other type groupBy support
const supportedGroupBy = getProperties().filter(
prop =>
prop.type === PropertyType.Status ||
prop.type === PropertyType.Select ||
prop.type === PropertyType.MultiSelect
);
@ -88,7 +89,8 @@ export const useRecastKanbanGroupBy = () => {
// TODO: support other property type
if (
groupByProperty.type !== PropertyType.Select &&
groupByProperty.type !== PropertyType.MultiSelect
groupByProperty.type !== PropertyType.MultiSelect &&
groupByProperty.type !== PropertyType.Status
) {
console.warn('Not support groupBy type', groupByProperty);
@ -134,7 +136,7 @@ export const useInitKanbanEffect = ():
}
// 3. no group by, no properties
// create a new property and set it as group by
const prop = await createSelect(DEFAULT_GROUP_BY_PROPERTY);
const prop = await createSelect(generateDefaultGroupByProperty());
await setGroupBy(prop.id);
};

View File

@ -46,7 +46,10 @@ export type DefaultGroup = KanbanGroupBase & {
type SelectGroup = KanbanGroupBase &
SelectOption & {
type: PropertyType.Select | PropertyType.MultiSelect;
type:
| PropertyType.Select
| PropertyType.MultiSelect
| PropertyType.Status;
};
type TextGroup = KanbanGroupBase & {

View File

@ -257,14 +257,12 @@ export const getRecastItemValue = (block: RecastItem | AsyncBlock) => {
const isSelectLikeProperty = (
metaProperty?: RecastMetaProperty
): metaProperty is SelectProperty | MultiSelectProperty => {
if (
return !(
!metaProperty ||
(metaProperty.type !== PropertyType.Select &&
(metaProperty.type !== PropertyType.Status &&
metaProperty.type !== PropertyType.Select &&
metaProperty.type !== PropertyType.MultiSelect)
) {
return false;
}
return true;
);
};
/**
@ -312,7 +310,7 @@ export const useSelectProperty = () => {
};
const updateSelect = (
selectProperty: SelectProperty | MultiSelectProperty
selectProperty: StatusProperty | SelectProperty | MultiSelectProperty
) => {
// if (typeof selectProperty === 'string') {
// const maybeSelectProperty = getProperty(selectProperty);