Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import { CollapsibleDescription } from "./CollapsibleDescription";
import type { TicketFieldObject } from "../../../ticket-fields/data-types/TicketFieldObject";
import type { CustomObjectRecord } from "../../../ticket-fields/data-types/CustomObjectRecord";
import { useAssetDataFetchers } from "../../../service-catalog/hooks/useAssetDataFetchers";
import type { ITAMAssetOptionObject } from "../../data-types/ITAMAssetOptionObject";
import { Span } from "@zendeskgarden/react-typography";
import { Option } from "@zendeskgarden/react-dropdowns.next";

const Form = styled.form`
display: flex;
Expand Down Expand Up @@ -238,11 +241,17 @@ export function ItemRequestForm({
const buildLookupFieldOptions = async (
records: CustomObjectRecord[],
field: TicketFieldObject
) => {
): Promise<ITAMAssetOptionObject[]> => {
if (!Array.isArray(records) || records.length === 0) return [];

const options = records.map((rec) => {
const base = { name: rec.name, value: rec.id };
const options: ITAMAssetOptionObject[] = records.map((rec) => {
const base = {
name: rec.name,
value: rec.id,
serialNumber: rec.custom_object_fields["standard::serial_number"] as
| string
| undefined,
};

if (rec.custom_object_key === "standard::itam_asset") {
const fields = (rec.custom_object_fields ?? {}) as {
Expand Down Expand Up @@ -271,7 +280,31 @@ export function ItemRequestForm({
}
return list;
}
return options.map(({ name, value }) => ({ name, value }));
return options.map(({ name, value, serialNumber }) => ({
name,
value,
serialNumber,
}));
};

const renderLookupFieldOption = (option: ITAMAssetOptionObject) => {
if (option.serialNumber) {
return (
<>
{option.name}
<Option.Meta>
<Span hue="grey">
{t(
"service-catalog.item.serial-number-label",
"SN: {{serialNumber}}",
{ serialNumber: option.serialNumber }
)}
</Span>
</Option.Meta>
</>
);
}
return option.name;
};

return (
Expand Down Expand Up @@ -319,6 +352,7 @@ export function ItemRequestForm({
handleChange={handleChange}
visibleFields={requestFields}
buildLookupFieldOptions={buildLookupFieldOptions}
renderLookupFieldOption={renderLookupFieldOption}
/>
);
})}
Expand Down
10 changes: 10 additions & 0 deletions src/modules/service-catalog/data-types/ITAMAssetOptionObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { TicketFieldOptionObject } from "../../ticket-fields/data-types/TicketFieldObject";

/**
* Extended option type for ITAM (IT Asset Management) assets from Service Catalog.
* These options include additional metadata like serial numbers and asset type IDs.
*/
export interface ITAMAssetOptionObject extends TicketFieldOptionObject {
serialNumber?: string;
item_asset_type_id?: string;
}
3 changes: 3 additions & 0 deletions src/modules/ticket-fields/RequestFormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ interface RequestFormFieldProps {
value: TicketFieldObject["value"]
) => void;
buildLookupFieldOptions?: LookupFieldProps["buildLookupFieldOptions"];
renderLookupFieldOption?: LookupFieldProps["renderOption"];
}

export const RequestFormField = ({
Expand All @@ -43,6 +44,7 @@ export const RequestFormField = ({
handleDueDateChange,
handleChange,
buildLookupFieldOptions,
renderLookupFieldOption,
}: RequestFormFieldProps) => {
switch (field.type) {
case "text":
Expand Down Expand Up @@ -144,6 +146,7 @@ export const RequestFormField = ({
visibleFields={visibleFields}
onChange={(value) => handleChange(field, value)}
buildLookupFieldOptions={buildLookupFieldOptions}
renderOption={renderLookupFieldOption}
/>
);
default:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ export interface CustomObjectRecord {
id: string;
name: string;
custom_object_key: string;
custom_object_fields: object;
custom_object_fields: Record<string, string | number | boolean | unknown>;
}
8 changes: 6 additions & 2 deletions src/modules/ticket-fields/fields/LookupField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@
buildLookupFieldOptions?: (
records: CustomObjectRecord[],
field: TicketFieldObject
) => Promise<{ name: string; value: string }[]>;
) => Promise<TicketFieldOptionObject[]>;
renderOption?: (option: TicketFieldOptionObject) => React.ReactNode;
}

export function LookupField({
Expand All @@ -74,6 +75,7 @@
onChange,
visibleFields,
buildLookupFieldOptions,
renderOption,
}: LookupFieldProps) {
const {
id: fieldId,
Expand Down Expand Up @@ -252,7 +254,7 @@
if (value) {
fetchSelectedOption(value as string);
}
}, []); //we don't set dependency array as we want this hook to be called only once

Check warning on line 257 in src/modules/ticket-fields/fields/LookupField.tsx

View workflow job for this annotation

GitHub Actions / Lint JS files

React Hook useEffect has missing dependencies: 'fetchSelectedOption' and 'value'. Either include them or remove the dependency array

const onFocus = () => {
setInputValue("");
Expand All @@ -263,7 +265,7 @@
<GardenField>
<Label>
{label}
{required && <Span aria-hidden="true">*</Span>}

Check warning on line 268 in src/modules/ticket-fields/fields/LookupField.tsx

View workflow job for this annotation

GitHub Actions / Lint JS files

Do not use hardcoded content as the children of the Span component
</Label>
{description && (
<Hint dangerouslySetInnerHTML={{ __html: description }} />
Expand Down Expand Up @@ -315,7 +317,9 @@
value={option.value}
label={option.name}
data-test-id={`option-${option.name}`}
/>
>
{renderOption ? renderOption(option) : option.name}
</Option>
))}
</Combobox>
{error && <Message validation="error">{error}</Message>}
Expand Down
Loading