|
| 1 | +import { |
| 2 | + AutocompleteInput, |
| 3 | + Datagrid, |
| 4 | + DateField, |
| 5 | + FilterForm, |
| 6 | + FunctionField, |
| 7 | + ListContextProvider, |
| 8 | + ReferenceInput, |
| 9 | + ResourceContextProvider, |
| 10 | + TextField, |
| 11 | + TextInput, |
| 12 | + useListController, |
| 13 | +} from "react-admin"; |
| 14 | + |
| 15 | +import { CustomPagination } from "../../commons/custom_fields/CustomPagination"; |
| 16 | +import { feature_vex_enabled } from "../../commons/functions"; |
| 17 | +import { AutocompleteInputMedium, AutocompleteInputWide } from "../../commons/layout/themes"; |
| 18 | +import { getSettingListSize } from "../../commons/user_settings/functions"; |
| 19 | +import { ASSESSMENT_STATUS_NEEDS_APPROVAL } from "../types"; |
| 20 | +import { OBSERVATION_SEVERITY_CHOICES, OBSERVATION_STATUS_CHOICES } from "../types"; |
| 21 | +import { commentShortened } from "./functions"; |
| 22 | + |
| 23 | +function listFilters(product: any) { |
| 24 | + const filters = []; |
| 25 | + if (product && product.has_branches) { |
| 26 | + filters.push( |
| 27 | + <ReferenceInput |
| 28 | + source="branch" |
| 29 | + reference="branches" |
| 30 | + queryOptions={{ meta: { api_resource: "branch_names" } }} |
| 31 | + sort={{ field: "name", order: "ASC" }} |
| 32 | + filter={{ product: product.id }} |
| 33 | + alwaysOn |
| 34 | + > |
| 35 | + <AutocompleteInputMedium optionText="name" label="Branch / Version" /> |
| 36 | + </ReferenceInput> |
| 37 | + ); |
| 38 | + } |
| 39 | + filters.push(<TextInput source="observation_title" label="Observation title" alwaysOn />); |
| 40 | + |
| 41 | + if (product && product.has_component) { |
| 42 | + filters.push(<TextInput source="origin_component_name_version" label="Component" alwaysOn />); |
| 43 | + } |
| 44 | + if (product && product.has_docker_image) { |
| 45 | + filters.push(<TextInput source="origin_docker_image_name_tag_short" label="Container" alwaysOn />); |
| 46 | + } |
| 47 | + if (product && product.has_endpoint) { |
| 48 | + filters.push(<TextInput source="origin_endpoint_hostname" label="Host" alwaysOn />); |
| 49 | + } |
| 50 | + if (product && product.has_source) { |
| 51 | + filters.push(<TextInput source="origin_source_file" label="Source" alwaysOn />); |
| 52 | + } |
| 53 | + if (product && product.has_cloud_resource) { |
| 54 | + filters.push(<TextInput source="origin_cloud_qualified_resource" label="Cloud resource" alwaysOn />); |
| 55 | + } |
| 56 | + if (product && product.has_kubernetes_resource) { |
| 57 | + filters.push(<TextInput source="origin_kubernetes_qualified_resource" label="Kubernetes resource" alwaysOn />); |
| 58 | + } |
| 59 | + |
| 60 | + filters.push( |
| 61 | + <ReferenceInput source="user" reference="users" sort={{ field: "full_name", order: "ASC" }} alwaysOn> |
| 62 | + <AutocompleteInputMedium optionText="full_name" /> |
| 63 | + </ReferenceInput>, |
| 64 | + <AutocompleteInput source="severity" label="Severity" choices={OBSERVATION_SEVERITY_CHOICES} alwaysOn />, |
| 65 | + <AutocompleteInput source="status" label="Status" choices={OBSERVATION_STATUS_CHOICES} alwaysOn /> |
| 66 | + ); |
| 67 | + return filters; |
| 68 | +} |
| 69 | + |
| 70 | +type ObservationLogApprovalEmbeddedListProps = { |
| 71 | + product: any; |
| 72 | +}; |
| 73 | + |
| 74 | +const ObservationLogApprovalEmbeddedList = ({ product }: ObservationLogApprovalEmbeddedListProps) => { |
| 75 | + const listContext = useListController({ |
| 76 | + filter: { product: Number(product.id), assessment_status: ASSESSMENT_STATUS_NEEDS_APPROVAL }, |
| 77 | + perPage: 25, |
| 78 | + resource: "observation_logs", |
| 79 | + sort: { field: "created", order: "ASC" }, |
| 80 | + disableSyncWithLocation: true, |
| 81 | + storeKey: "observation_logs.approvalembedded", |
| 82 | + }); |
| 83 | + |
| 84 | + if (listContext.isLoading) { |
| 85 | + return <div>Loading...</div>; |
| 86 | + } |
| 87 | + |
| 88 | + const ShowObservationLogs = (id: any) => { |
| 89 | + return "../../../../observation_logs/" + id + "/show"; |
| 90 | + }; |
| 91 | + |
| 92 | + localStorage.setItem("observationlogapprovalembeddedlist", "true"); |
| 93 | + localStorage.removeItem("observationlogapprovallist"); |
| 94 | + localStorage.removeItem("observationlogembeddedlist"); |
| 95 | + |
| 96 | + return ( |
| 97 | + <ResourceContextProvider value="observation_logs"> |
| 98 | + <ListContextProvider value={listContext}> |
| 99 | + <div style={{ width: "100%" }}> |
| 100 | + <FilterForm filters={listFilters(product)} /> |
| 101 | + <Datagrid |
| 102 | + size={getSettingListSize()} |
| 103 | + sx={{ width: "100%" }} |
| 104 | + bulkActionButtons={false} |
| 105 | + rowClick={ShowObservationLogs} |
| 106 | + resource="observation_logs" |
| 107 | + > |
| 108 | + {product && product.has_branches && <TextField source="branch_name" label="Branch / Version" />} |
| 109 | + <TextField source="observation_data.title" label="Observation" /> |
| 110 | + {product && product.has_component && ( |
| 111 | + <TextField |
| 112 | + source="observation_data.origin_component_name_version" |
| 113 | + label="Component" |
| 114 | + sx={{ wordBreak: "break-word" }} |
| 115 | + /> |
| 116 | + )} |
| 117 | + {product && product.has_docker_image && ( |
| 118 | + <TextField |
| 119 | + source="observation_data.origin_docker_image_name_tag_short" |
| 120 | + label="Container" |
| 121 | + sx={{ wordBreak: "break-word" }} |
| 122 | + /> |
| 123 | + )} |
| 124 | + {product && product.has_endpoint && ( |
| 125 | + <TextField |
| 126 | + source="observation_data.origin_endpoint_hostname" |
| 127 | + label="Host" |
| 128 | + sx={{ wordBreak: "break-word" }} |
| 129 | + /> |
| 130 | + )} |
| 131 | + {product && product.has_source && ( |
| 132 | + <TextField |
| 133 | + source="observation_data.origin_source_file" |
| 134 | + label="Source" |
| 135 | + sx={{ wordBreak: "break-word" }} |
| 136 | + /> |
| 137 | + )} |
| 138 | + {product && product.has_cloud_resource && ( |
| 139 | + <TextField |
| 140 | + source="observation_data.origin_cloud_qualified_resource" |
| 141 | + label="Cloud resource" |
| 142 | + sx={{ wordBreak: "break-word" }} |
| 143 | + /> |
| 144 | + )} |
| 145 | + {product && product.has_kubernetes_resource && ( |
| 146 | + <TextField |
| 147 | + source="observation_data.origin_kubernetes_qualified_resource" |
| 148 | + label="Kubernetes resource" |
| 149 | + sx={{ wordBreak: "break-word" }} |
| 150 | + /> |
| 151 | + )} |
| 152 | + <TextField source="user_full_name" label="User" /> |
| 153 | + <TextField source="severity" emptyText="---" /> |
| 154 | + <TextField source="status" emptyText="---" /> |
| 155 | + {feature_vex_enabled() && ( |
| 156 | + <TextField |
| 157 | + label="VEX justification" |
| 158 | + source="vex_justification" |
| 159 | + emptyText="---" |
| 160 | + sx={{ wordBreak: "break-word" }} |
| 161 | + /> |
| 162 | + )} |
| 163 | + <FunctionField |
| 164 | + label="Comment" |
| 165 | + render={(record) => commentShortened(record.comment)} |
| 166 | + sortable={false} |
| 167 | + sx={{ wordBreak: "break-word" }} |
| 168 | + /> |
| 169 | + <DateField source="created" showTime /> |
| 170 | + </Datagrid> |
| 171 | + <CustomPagination /> |
| 172 | + </div> |
| 173 | + </ListContextProvider> |
| 174 | + </ResourceContextProvider> |
| 175 | + ); |
| 176 | +}; |
| 177 | + |
| 178 | +export default ObservationLogApprovalEmbeddedList; |
0 commit comments