Get more fields figured out

This commit is contained in:
2024-04-30 10:24:23 -05:00
parent 999713bb0e
commit 436b4a4a0d
11 changed files with 218 additions and 80 deletions

View File

@@ -0,0 +1,33 @@
<script lang="ts">
import type {
FormElementLabelPart,
FormElementPart,
RichTextFragment,
} from "../gql/graphql";
import ExplanationPart from "./ExplanationPart.svelte";
export let formElementLabel: FormElementLabelPart | undefined | null;
export let formElement: FormElementPart | undefined | null;
export let explanation:
| ({
__typename?: "HtmlBodyPart" | undefined;
} & {
" $fragmentRefs"?:
| {
RichTextFragment: RichTextFragment;
}
| undefined;
})
| null
| undefined;
</script>
{#if formElementLabel?.label}
<label for={formElement?.id} class="block mt-2 font-bold text-gray-900">
{formElementLabel.label}
</label>
{/if}
{#if explanation}
<ExplanationPart fragment={explanation} />
{/if}

View File

@@ -16,6 +16,8 @@
...LabelPart ...LabelPart
...ButtonPart ...ButtonPart
...InputPart ...InputPart
...SelectPart
...TextAreaPart
} }
} }
} }
@@ -28,6 +30,7 @@
import InputPart from "./InputPart.svelte"; import InputPart from "./InputPart.svelte";
import LabelPart from "./LabelPart.svelte"; import LabelPart from "./LabelPart.svelte";
import SelectPart from "./SelectPart.svelte"; import SelectPart from "./SelectPart.svelte";
import TextAreaPart from "./TextAreaPart.svelte";
export let antiForgeryToken: string; export let antiForgeryToken: string;
export let fragment: FragmentType<typeof FormFragment>; export let fragment: FragmentType<typeof FormFragment>;
@@ -61,6 +64,10 @@
<div> <div>
<SelectPart fragment={widget} /> <SelectPart fragment={widget} />
</div> </div>
{:else if widget?.__typename === "TextArea"}
<div>
<TextAreaPart fragment={widget} />
</div>
{/if} {/if}
{/each} {/each}
{/if} {/if}

View File

@@ -26,7 +26,7 @@
<script lang="ts"> <script lang="ts">
import { useFragment, type FragmentType } from "../gql"; import { useFragment, type FragmentType } from "../gql";
import ExplanationPart from "./ExplanationPart.svelte"; import CommonFieldParts from "./CommonFieldParts.svelte";
export let fragment: FragmentType<typeof InputPartFragment>; export let fragment: FragmentType<typeof InputPartFragment>;
const content = useFragment(InputPartFragment, fragment); const content = useFragment(InputPartFragment, fragment);
@@ -41,18 +41,9 @@
let value = content.input?.defaultValue ?? ""; let value = content.input?.defaultValue ?? "";
</script> </script>
{#if content.formElementLabel?.label} <CommonFieldParts formElementLabel={content.formElementLabel}
<label formElement={content.formElement}
for={content.formElement?.id} explanation={content.explanation} />
class="block mt-2 font-bold text-gray-900"
>
{content.formElementLabel.label}
</label>
{/if}
{#if content.explanation?.html}
<ExplanationPart fragment={content.explanation}/>
{/if}
<input <input
id={content.formElement?.id} id={content.formElement?.id}

View File

@@ -13,7 +13,15 @@
id id
} }
explanation { explanation {
html ...RichText
}
select {
defaultValue
editor
options {
text
value
}
} }
} }
`); `);
@@ -21,56 +29,48 @@
<script lang="ts"> <script lang="ts">
import { useFragment, type FragmentType } from "../gql"; import { useFragment, type FragmentType } from "../gql";
import CommonFieldParts from "./CommonFieldParts.svelte";
export let fragment: FragmentType<typeof SelectPartFragment>; export let fragment: FragmentType<typeof SelectPartFragment>;
const content = useFragment(SelectPartFragment, fragment); const content = useFragment(SelectPartFragment, fragment);
let cssClasses = const showDropdown = content.select?.editor === "select";
"block w-full rounded-md border-0 py-1.5 px-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600";
</script> </script>
{#if content.formElementLabel?.label} <CommonFieldParts formElementLabel={content.formElementLabel}
<label formElement={content.formElement}
for={content.formElement?.id} explanation={content.explanation} />
class="block mt-2 font-bold text-gray-900"
>
{content.formElementLabel.label}
</label>
{/if}
{#if content.explanation?.html} {#if !showDropdown}
<ExplanationPart fragment={content.explanation}/>
{/if}
@if (Model.Value.Editor == SelectEditorOption.Checkbox || Model.Value.Editor == SelectEditorOption.Radio)
{
int i = 0;
var htmlType = Model.Value.Editor == SelectEditorOption.Checkbox ? "checkbox" : "radio";
<div class="mt-2 space-y-2"> <div class="mt-2 space-y-2">
@foreach (var option in Model.Value.Options) {#each content.select?.options ?? [] as option, index}
{
<div class="flex items-center gap-x-3"> <div class="flex items-center gap-x-3">
<input type="@htmlType" id="@(fieldId + "_" + i)" name="@fieldName" <input
class="@validationClass h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600" type={content.select?.editor}
value="@option.Value" @(option.Value == fieldValue ? "checked='checked'" : "") /> id={content.formElement?.id + "_" + index}
<label class="block text-sm font-medium text-gray-900" for="@(fieldId + "_" + i)">@option.Text</label> name={content.formInputElement?.name}
class="h-4 w-4 border-gray-300 text-indigo-600 focus:ring-indigo-600"
value={option?.value}
/>
<label
class="block text-sm font-medium text-gray-900"
for={content.formElement?.id + "_" + index}
>{option?.text}</label
>
</div> </div>
i++; {/each}
}
</div> </div>
} {:else}
else
{
<div class="mt-2"> <div class="mt-2">
<select id="@fieldId" name="@fieldName" <select
class="@validationClass block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6"> id={content.formElement?.id}
@foreach (var option in Model.Value.Options) name={content.formInputElement?.name}
{ class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:max-w-xs sm:text-sm sm:leading-6"
var optionValue = !string.IsNullOrWhiteSpace(option.Value) ? option.Value : option.Text; >
var isOptionSelected = optionValue == fieldValue; {#each content.select?.options ?? [] as option}
<option value="@optionValue" selected="@isOptionSelected">@option.Text</option> <option value={option?.value ?? option?.text} selected={false}
} >{option?.text}</option
>
{/each}
</select> </select>
</div> </div>
} {/if}

View File

@@ -0,0 +1,41 @@
<script context="module" lang="ts">
import { graphql } from "../gql";
export const TextAreaPartFragment = graphql(/* GraphQL */ `
fragment TextAreaPart on TextArea {
explanation {
...RichText
}
formElement {
id
}
formElementLabel {
label
}
formInputElement {
name
}
textArea {
defaultValue
placeholder
}
}
`);
</script>
<script lang="ts">
import { useFragment, type FragmentType } from "../gql";
import CommonFieldParts from "./CommonFieldParts.svelte";
export let fragment: FragmentType<typeof TextAreaPartFragment>;
const content = useFragment(TextAreaPartFragment, fragment);
</script>
<CommonFieldParts formElementLabel={content.formElementLabel}
formElement={content.formElement}
explanation={content.explanation} />
<textarea id={content.formElement?.id}
name={content.formInputElement?.name}
class="block w-full rounded-md border-0 py-1.5 px-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600"
placeholder={content.textArea?.placeholder}>
</textarea>

View File

@@ -15,12 +15,13 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
const documents = { const documents = {
"\n\t\tquery OapApplicationForm($contentItemId: ID!) {\n\t\t\toapApplicationForm(where: { contentItemId: $contentItemId }) {\n\t\t\t\tdisplayText\n\t\t\t\tcontentItemId\n\t\t\t\tlist {\n\t\t\t\t\tcontentItems {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\t...OapApplicationFormStep\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormDocument, "\n\t\tquery OapApplicationForm($contentItemId: ID!) {\n\t\t\toapApplicationForm(where: { contentItemId: $contentItemId }) {\n\t\t\t\tdisplayText\n\t\t\t\tcontentItemId\n\t\t\t\tlist {\n\t\t\t\t\tcontentItems {\n\t\t\t\t\t\t__typename\n\t\t\t\t\t\t...OapApplicationFormStep\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormDocument,
"\n fragment ButtonPart on Button {\n button {\n type\n text\n }\n formInputElement {\n name\n }\n formElement {\n id\n }\n }\n ": types.ButtonPartFragmentDoc, "\n fragment ButtonPart on Button {\n button {\n type\n text\n }\n formInputElement {\n name\n }\n formElement {\n id\n }\n }\n ": types.ButtonPartFragmentDoc,
"\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.FormFragmentDoc, "\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t\t...SelectPart\n\t\t\t\t\t...TextAreaPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.FormFragmentDoc,
"\n\t\tfragment InputPart on Input {\n\t\t\tinput {\n\t\t\t\tdefaultValue\n\t\t\t\tplaceholder\n\t\t\t\ttype\n\t\t\t}\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\thtml\n\t\t\t}\n\t\t}\n\t": types.InputPartFragmentDoc, "\n\t\tfragment InputPart on Input {\n\t\t\tinput {\n\t\t\t\tdefaultValue\n\t\t\t\tplaceholder\n\t\t\t\ttype\n\t\t\t}\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\thtml\n\t\t\t}\n\t\t}\n\t": types.InputPartFragmentDoc,
"\n\t\tfragment LabelPart on Label {\n\t\t\tdisplayText\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfor\n\t\t\t\tvalue\n\t\t\t}\n\t\t\tcontentType\n\t\t}\n\t": types.LabelPartFragmentDoc, "\n\t\tfragment LabelPart on Label {\n\t\t\tdisplayText\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tlabel {\n\t\t\t\tfor\n\t\t\t\tvalue\n\t\t\t}\n\t\t\tcontentType\n\t\t}\n\t": types.LabelPartFragmentDoc,
"\n\t\tfragment OapApplicationFormStep on OapApplicationFormStep {\n\t\t\tdisplayText\n\t\t\tcontentItemId\n\t\t\thtmlBody {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...Form\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormStepFragmentDoc, "\n\t\tfragment OapApplicationFormStep on OapApplicationFormStep {\n\t\t\tdisplayText\n\t\t\tcontentItemId\n\t\t\thtmlBody {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...Form\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.OapApplicationFormStepFragmentDoc,
"\n\t\tfragment RichText on HtmlBodyPart {\n\t\t\thtml\n\t\t}\n\t": types.RichTextFragmentDoc, "\n\t\tfragment RichText on HtmlBodyPart {\n\t\t\thtml\n\t\t}\n\t": types.RichTextFragmentDoc,
"\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\thtml\n\t\t\t}\n\t\t}\n\t": types.SelectPartFragmentDoc, "\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tselect {\n\t\t\t\tdefaultValue\n\t\t\t\teditor\n\t\t\t\toptions {\n\t\t\t\t\ttext\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t": types.SelectPartFragmentDoc,
"\n\t\tfragment TextAreaPart on TextArea {\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\ttextArea {\n\t\t\t\tdefaultValue\n\t\t\t\tplaceholder\n\t\t\t}\n\t\t}\n\t": types.TextAreaPartFragmentDoc,
}; };
/** /**
@@ -48,7 +49,7 @@ export function graphql(source: "\n fragment ButtonPart on Button {\n
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
export function graphql(source: "\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"]; export function graphql(source: "\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t\t...SelectPart\n\t\t\t\t\t...TextAreaPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment Form on Form {\n\t\t\tdisplayText\n\t\t\tform {\n\t\t\t\taction\n\t\t\t\tmethod\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tflow {\n\t\t\t\twidgets {\n\t\t\t\t\t...LabelPart\n\t\t\t\t\t...ButtonPart\n\t\t\t\t\t...InputPart\n\t\t\t\t\t...SelectPart\n\t\t\t\t\t...TextAreaPart\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"];
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
@@ -68,7 +69,11 @@ export function graphql(source: "\n\t\tfragment RichText on HtmlBodyPart {\n\t\t
/** /**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/ */
export function graphql(source: "\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\thtml\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\thtml\n\t\t\t}\n\t\t}\n\t"]; export function graphql(source: "\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tselect {\n\t\t\t\tdefaultValue\n\t\t\t\teditor\n\t\t\t\toptions {\n\t\t\t\t\ttext\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment SelectPart on Select {\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tselect {\n\t\t\t\tdefaultValue\n\t\t\t\teditor\n\t\t\t\toptions {\n\t\t\t\t\ttext\n\t\t\t\t\tvalue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n\t\tfragment TextAreaPart on TextArea {\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\ttextArea {\n\t\t\t\tdefaultValue\n\t\t\t\tplaceholder\n\t\t\t}\n\t\t}\n\t"): (typeof documents)["\n\t\tfragment TextAreaPart on TextArea {\n\t\t\texplanation {\n\t\t\t\t...RichText\n\t\t\t}\n\t\t\tformElement {\n\t\t\t\tid\n\t\t\t}\n\t\t\tformElementLabel {\n\t\t\t\tlabel\n\t\t\t}\n\t\t\tformInputElement {\n\t\t\t\tname\n\t\t\t}\n\t\t\ttextArea {\n\t\t\t\tdefaultValue\n\t\t\t\tplaceholder\n\t\t\t}\n\t\t}\n\t"];
export function graphql(source: string) { export function graphql(source: string) {
return (documents as any)[source] ?? {}; return (documents as any)[source] ?? {};

File diff suppressed because one or more lines are too long

View File

@@ -1,8 +1,8 @@
using GraphQL.Types; using GraphQL.Types;
using OrchardCore.Forms.Models; using OrchardCore.Forms.Models;
namespace OrchardCore.Forms.GraphQL namespace OrchardCore.Forms.GraphQL;
{
public class FormElementLabelPartQueryObjectType : ObjectGraphType<FormElementLabelPart> public class FormElementLabelPartQueryObjectType : ObjectGraphType<FormElementLabelPart>
{ {
public FormElementLabelPartQueryObjectType() public FormElementLabelPartQueryObjectType()
@@ -12,4 +12,3 @@ namespace OrchardCore.Forms.GraphQL
Field(x => x.Label, nullable: true); Field(x => x.Label, nullable: true);
} }
} }
}

View File

@@ -0,0 +1,15 @@
using GraphQL.Types;
using OrchardCore.Forms.Models;
namespace OrchardCore.Forms.GraphQL;
public class SelectOptionQueryObjectType : ObjectGraphType<SelectOption>
{
public SelectOptionQueryObjectType()
{
Name = "SelectOption";
Field(x => x.Text, nullable: true);
Field(x => x.Value, nullable: true);
}
}

View File

@@ -0,0 +1,16 @@
using GraphQL.Types;
using OrchardCore.Forms.Models;
namespace OrchardCore.Forms.GraphQL;
public class SelectPartQueryObjectType : ObjectGraphType<SelectPart>
{
public SelectPartQueryObjectType()
{
Name = "SelectPart";
Field(x => x.DefaultValue, nullable: true);
Field<ListGraphType<SelectOptionQueryObjectType>>("options");
Field("editor", x => x.Editor.ToString().ToLowerInvariant(), nullable: true);
}
}

View File

@@ -14,5 +14,7 @@ public class Startup : StartupBase
{ {
services.AddTransient<IConfigureOptions<ResourceManagementOptions>, ResourceManagementOptionsConfiguration>(); services.AddTransient<IConfigureOptions<ResourceManagementOptions>, ResourceManagementOptionsConfiguration>();
services.AddObjectGraphType<FormElementLabelPart, FormElementLabelPartQueryObjectType>(); services.AddObjectGraphType<FormElementLabelPart, FormElementLabelPartQueryObjectType>();
services.AddObjectGraphType<SelectPart, SelectPartQueryObjectType>();
services.AddObjectGraphType<SelectOption, SelectOptionQueryObjectType>();
} }
} }