Skip to content

Commit

Permalink
feat: added lookup fields
Browse files Browse the repository at this point in the history
  • Loading branch information
Fredx87 committed May 13, 2024
1 parent 2fa52ab commit b3b8910
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 7 deletions.
2 changes: 1 addition & 1 deletion assets/addFlashNotification-bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 51 additions & 1 deletion assets/new-request-form-bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion assets/notifications-bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion assets/vendor-bundle.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"dompurify": "3.0.5",
"eslint-plugin-check-file": "^2.6.2",
"i18next": "^23.10.1",
"lodash.debounce": "^4.0.8",
"node-fetch": "2.6.9",
"react": "^17.0.2",
"react-dom": "^17.0.2",
Expand All @@ -61,6 +62,7 @@
"@testing-library/dom": "^9.3.1",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/user-event": "^14.4.3",
"@types/lodash.debounce": "^4.0.9",
"@types/react": "^17.0.62",
"@types/react-dom": "^17.0.20",
"@types/styled-components": "^5.1.26",
Expand Down
9 changes: 9 additions & 0 deletions src/modules/new-request-form/NewRequestForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { SuggestedArticles } from "./suggested-articles/SuggestedArticles";
import { AnswerBotModal } from "./answer-bot-modal/AnswerBotModal";
import { useTranslation } from "react-i18next";
import { Paragraph } from "@zendeskgarden/react-typography";
import { LookupField } from "./fields/LookupField";

export interface NewRequestFormProps {
requestForm: RequestForm;
Expand Down Expand Up @@ -282,6 +283,14 @@ export function NewRequestForm({
onChange={(value) => handleChange(field, value)}
/>
);
case "lookup":
return (
<LookupField
key={field.name}
field={field}
onChange={(value) => handleChange(field, value)}
/>
);
default:
return <></>;
}
Expand Down
1 change: 1 addition & 0 deletions src/modules/new-request-form/data-types/Field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface Field {
description: string;
type: string;
options: FieldOption[];
relationship_target_type?: string;
}

export interface FieldOption {
Expand Down
133 changes: 133 additions & 0 deletions src/modules/new-request-form/fields/LookupField.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import type {
IComboboxProps,
ISelectedOption,
} from "@zendeskgarden/react-dropdowns.next";
import {
Field as GardenField,
Label,
Hint,
Combobox,
Option,
Message,
} from "@zendeskgarden/react-dropdowns.next";
import { useCallback, useEffect, useMemo, useState } from "react";
import type { Field, FieldOption } from "../data-types";
import { Span } from "@zendeskgarden/react-typography";
import { EmptyValueOption } from "./EmptyValueOption";
import debounce from "lodash.debounce";

function getCustomObjectKey(targetType: string) {
return targetType.replace("zen:custom_object:", "");
}

interface LookupFieldProps {
field: Field;
onChange: (value: string) => void;
}

export function LookupField({ field, onChange }: LookupFieldProps) {
const {
id: fieldId,
label,
error,
value,
name,
required,
description,
relationship_target_type,
} = field;
const [options, setOptions] = useState<FieldOption[]>([]);

const customObjectKey = getCustomObjectKey(
relationship_target_type as string
);

const handleChange = useCallback<NonNullable<IComboboxProps["onChange"]>>(
async ({ inputValue, selectionValue }) => {
if (selectionValue !== undefined) {
onChange(selectionValue as string);
return;
}

if (inputValue !== undefined) {
if (inputValue === "") {
setOptions([]);
} else {
const searchParams = new URLSearchParams();
searchParams.set("name", inputValue.toLocaleLowerCase());
searchParams.set("source", "zen:ticket");
searchParams.set("field_id", fieldId.toString());

const response = await fetch(
`/api/v2/custom_objects/${customObjectKey}/records/autocomplete?${searchParams.toString()}`
);
const data = await response.json();
setOptions(
data.custom_object_records.map(
({ name, id }: { name: string; id: string }) => ({
name,
value: id,
})
)
);
}
}
},
[customObjectKey]

Check warning on line 76 in src/modules/new-request-form/fields/LookupField.tsx

View workflow job for this annotation

GitHub Actions / Lint JS files

React Hook useCallback has missing dependencies: 'fieldId' and 'onChange'. Either include them or remove the dependency array. If 'onChange' changes too often, find the parent component that defines it and wrap that definition in useCallback
);

const debounceHandleChange = useMemo(
() => debounce(handleChange, 300),
[handleChange]
);

useEffect(() => {
return () => debounceHandleChange.cancel();
}, [debounceHandleChange]);

useEffect(() => {
if (value && !options.find((option) => option.value === value)) {
fetch(`/api/v2/custom_objects/${customObjectKey}/records/${value}`)
.then((res) => res.json())
.then(({ custom_object_record }) => {
setOptions([
{ name: custom_object_record.name, value: value as string },
]);
});
}
}, [value, customObjectKey, options]);

return (
<GardenField>
<Label>
{label}
{required && <Span aria-hidden="true">*</Span>}

Check warning on line 104 in src/modules/new-request-form/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 }} />
)}
<Combobox
isAutocomplete
inputProps={{ name, required }}
validation={error ? "error" : undefined}
inputValue={value as string}
selectionValue={value as string}
renderValue={({ selection }) =>
(selection as ISelectedOption | null)?.label || <EmptyValueOption />
}
onChange={debounceHandleChange}
>
{!required && (
<Option value="" label="-">
<EmptyValueOption />
</Option>
)}
{options.map((option) => (
<Option key={option.value} value={option.value} label={option.name} />
))}
</Combobox>
{error && <Message validation="error">{error}</Message>}
{JSON.stringify(options)}
</GardenField>
);
}
43 changes: 40 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3223,6 +3223,18 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==

"@types/lodash.debounce@^4.0.9":
version "4.0.9"
resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz#0f5f21c507bce7521b5e30e7a24440975ac860a5"
integrity sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==
dependencies:
"@types/lodash" "*"

"@types/lodash@*":
version "4.17.1"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.1.tgz#0fabfcf2f2127ef73b119d98452bd317c4a17eb8"
integrity sha512-X+2qazGS3jxLAIz5JDXDzglAF3KpijdhFxlf/V1+hEsOUc+HnWi81L/uv/EvGuV90WY+7mPGFCUDGfQC3Gj95Q==

"@types/minimatch@^3.0.3":
version "3.0.5"
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40"
Expand Down Expand Up @@ -12163,7 +12175,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"

"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -12282,7 +12303,14 @@ string_decoder@~1.1.1:
dependencies:
safe-buffer "~5.1.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -13310,7 +13338,7 @@ wordwrap@^1.0.0:
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb"
integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -13328,6 +13356,15 @@ wrap-ansi@^6.0.1:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down

0 comments on commit b3b8910

Please sign in to comment.