Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(): cmdb显示设置 构件支持分组 #702

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libs/cmdb-instances/src/instance-detail/index.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ html[data-ui="v8-2"] .detailCard {
grid-template-columns: auto 1fr auto 1fr;
row-gap: 12px;
column-gap: 16px;
min-width: 120px;
margin-bottom: 0;
}

Expand Down
167 changes: 145 additions & 22 deletions libs/cmdb-instances/src/instance-list-table/DisplaySettings.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import React from "react";
import { debounce, remove, without, get, isEmpty } from "lodash";
import {
debounce,
remove,
without,
get,
isEmpty,
groupBy,
mapValues,
} from "lodash";
import { extraFieldAttrs } from "./constants";
import { Checkbox, Col, Divider, Input, Row } from "antd";
import {
Expand All @@ -24,6 +32,7 @@ interface DisplaySettingsState {
filteredList: any;
extraDisabledFieldSet: Set<string>;
selectAllFields: boolean;
selectCategoryAllFieldsMap: Record<string, boolean>;
allFieldsLength: number;
}

Expand All @@ -32,7 +41,7 @@ export class DisplaySettings extends React.Component<
DisplaySettingsState
> {
debounceHandleSearch: () => void;
attrAndRelationList: { id: string; name: string }[] = [];
attrAndRelationList: { id: string; name: string; category: string }[] = [];

constructor(props: DisplaySettingsProps) {
super(props);
Expand All @@ -54,6 +63,11 @@ export class DisplaySettings extends React.Component<
this.attrAndRelationList = attrAndRelationList.map((attribute: any) => ({
id: attribute.id,
name: attribute.name,
category: get(
attribute,
"tag[0]",
get(attribute, "left_tags[0]", "其他")
),
}));

const filteredList = this.attrAndRelationList;
Expand All @@ -66,16 +80,30 @@ export class DisplaySettings extends React.Component<
const extraAttrs = filteredList.filter((attr: any) =>
extraAttrIds.includes(attr.id)
);

const nextFields = props.currentFields ? props.currentFields.slice() : [];

const allFieldsLength = [...attrs, ...extraAttrs].length;
const selectAllFields =
[...new Set([...nextFields])].length === allFieldsLength;

const categoryOrders = this.getCAategoryOrders();
const categoryMap = groupBy(attrs, "category");
const selectCategoryAllFieldsMap: Record<string, boolean> = {};
categoryOrders.reduce((acc, item) => {
const categoryAttrIds = categoryMap[item]?.map((attr) => attr.id);
acc[item] = selectAllFields
? selectAllFields
: !!categoryAttrIds?.every((id) => nextFields.includes(id));
return acc;
}, selectCategoryAllFieldsMap);
this.state = {
nextFields,
q: "",
filteredList: this.attrAndRelationList,
extraDisabledFieldSet: new Set(props.extraDisabledFields),
selectAllFields: [...new Set([...nextFields])].length === allFieldsLength,
selectAllFields,
allFieldsLength,
selectCategoryAllFieldsMap,
};
this.debounceHandleSearch = debounce(this.filterColTag, 300);
}
Expand All @@ -96,30 +124,75 @@ export class DisplaySettings extends React.Component<
}
}

handleChecked(event: any, attr: any) {
handleChecked(event: any, attr: any, categoryData?: any) {
const fieldsKey = "nextFields";
const { category, attrs } = categoryData ?? {};
const fields = event.target.checked
? this.state[fieldsKey].concat(attr.id)
: without(this.state[fieldsKey], attr.id);
if (category) {
const attrsIds = attrs.map((attr: any) => attr.id);
this.setState({
[fieldsKey]: fields,
selectAllFields: fields.length === this.state.allFieldsLength,
selectCategoryAllFieldsMap: {
...this.state.selectCategoryAllFieldsMap,
[category]: attrsIds.every((id: string) => fields.includes(id)),
},
});
} else {
this.setState({
[fieldsKey]: fields,
selectAllFields: fields.length === this.state.allFieldsLength,
});
}

this.props.onChange?.(fields);
}

handlecCategoryChecked(event: any, categoryData: any) {
const checked = event.target.checked;
const fieldsKey = "nextFields";
const { category, attrs } = categoryData;
const attrsIds = attrs.map((attr: any) => attr.id);
const fields = [
...new Set([
...(checked
? this.state[fieldsKey].concat(attrsIds)
: without(this.state[fieldsKey], ...attrsIds)),
]),
];
this.setState({
[fieldsKey]: fields,
selectAllFields: fields.length === this.state.allFieldsLength,
selectCategoryAllFieldsMap: {
...this.state.selectCategoryAllFieldsMap,
[category]: checked,
},
});
this.props.onChange?.(fields);
}

handleSelectAllFields(event: any, allFields: any[]) {
const fieldsKey = "nextFields";
const fields = event.target.checked ? allFields.map((attr) => attr.id) : [];
const checked = event.target.checked;
const fields = checked ? allFields.map((attr) => attr.id) : [];
this.setState({
[fieldsKey]: fields,
selectAllFields: event.target.checked,
selectCategoryAllFieldsMap: mapValues(
this.state.selectCategoryAllFieldsMap,
() => checked
),
});
this.props.onChange?.(fields);
}

renderCheckbox(attr: any, field: "nextFields" | "otherFields") {
renderCheckbox(
attr: any,
field: "nextFields" | "otherFields",
categoryData?: any
) {
const fieldsKey = "nextFields";
const checked = this.state[fieldsKey].includes(attr.id);
const disabled =
Expand All @@ -140,15 +213,23 @@ export class DisplaySettings extends React.Component<
}}
checked={checked}
disabled={disabled}
onChange={(event) => this.handleChecked(event, attr)}
onChange={(event) => this.handleChecked(event, attr, categoryData)}
data-testid={`${attr.id}-checkbox`}
>
{attr.name}
</Checkbox>
</Col>
);
}

getCAategoryOrders = () => {
const categoryOrders = [
...new Set([
...get(this.props.modelData, "view.attr_category_order", []),
"其他",
]),
]; //分组排序
return categoryOrders;
};
filterColTag = () => {
let filteredList = this.attrAndRelationList;
const q = this.state.q.trim().toLowerCase();
Expand All @@ -157,8 +238,23 @@ export class DisplaySettings extends React.Component<
return attr.name.toLowerCase().includes(q);
});
}
const fieldsKey = "nextFields";
const attrs = this.state[fieldsKey];
const categoryOrders = this.getCAategoryOrders();
const categoryMap = groupBy(filteredList, "category");
const selectAllFields = attrs.length === this.state.allFieldsLength;
const selectCategoryAllFieldsMap: Record<string, boolean> = {};
categoryOrders.reduce((acc, item) => {
const categoryAttrIds = categoryMap[item]?.map((attr) => attr.id);
acc[item] = selectAllFields
? selectAllFields
: !!categoryAttrIds?.every((id) => attrs.includes(id));
return acc;
}, selectCategoryAllFieldsMap);
this.setState({
filteredList,
selectAllFields,
selectCategoryAllFieldsMap,
});
};

Expand All @@ -169,7 +265,6 @@ export class DisplaySettings extends React.Component<
});
this.debounceHandleSearch();
};

render() {
const filteredList = this.state.filteredList;
const extraAttrIds = extraFieldAttrs.map(
Expand All @@ -178,10 +273,11 @@ export class DisplaySettings extends React.Component<
const attrs = filteredList.filter(
(attr: any) => !extraAttrIds.includes(attr.id)
);
const categoryOrders = this.getCAategoryOrders();
const categoryMap = groupBy(attrs, "category");
const extraAttrs = filteredList.filter((attr: any) =>
extraAttrIds.includes(attr.id)
);

return (
<>
<Divider orientation="left" plain style={{ marginTop: 0 }}>
Expand Down Expand Up @@ -218,17 +314,44 @@ export class DisplaySettings extends React.Component<
}}
className="nextFields"
>
<Row>
{attrs.map((attr: any) => this.renderCheckbox(attr, "nextFields"))}
{extraAttrs.length > 0 ? (
<>
<Divider />
{extraAttrs.map((attr: any) =>
this.renderCheckbox(attr, "nextFields")
)}
</>
) : null}
</Row>
{categoryOrders?.map((category, index) => {
const categoryAttrs = categoryMap?.[category] ?? [];
return categoryAttrs.length > 0 ? (
<div
style={{
marginBottom: index === categoryOrders.length - 1 ? 0 : 15,
}}
>
<Checkbox
checked={this.state.selectCategoryAllFieldsMap[category]}
onChange={(e) => {
this.handlecCategoryChecked(e, {
category,
attrs: categoryAttrs,
});
}}
>
{category}
</Checkbox>
<Row style={{ padding: "12px 12px 0px 12px" }}>
{categoryAttrs.map((attr: any) =>
this.renderCheckbox(attr, "nextFields", {
category,
attrs: categoryAttrs,
})
)}
</Row>
</div>
) : null;
})}
{extraAttrs.length > 0 ? (
<Row>
<Divider />
{extraAttrs.map((attr: any) =>
this.renderCheckbox(attr, "nextFields")
)}
</Row>
) : null}
</div>
</>
);
Expand Down
Loading