admin icon indicating copy to clipboard operation
admin copied to clipboard

Admin interface not rendering dropdown for Enum on HydraAdmin

Open mihai-amihailesei opened this issue 2 years ago • 2 comments

API Platform version(s) affected: 3.1.1

Description
HydraAdmin component does not render an Enum type field as a dropdown selection. OpenApiAdmin component renders correctly.

How to reproduce
Create an entity and a backed Enum, set the backed enum as a property on the entity. Configure the property openapi context with enum and values from the backed enum.

API documentation properly shows the property as an enum on both schemas, however, when rendered with the HydraAdmin component it gets rendered as a plain text field.

https://github.com/mihai-amihailesei/api-platform-admin-bug

mihai-amihailesei avatar Jan 29 '23 23:01 mihai-amihailesei

It's because API Platform doesn't return information about the enum with Hydra.

alanpoulain avatar Jan 30 '23 09:01 alanpoulain

A workaround for now to have OpenAPi3 enums with Hydra is a proxy of Hydra doc parser, ex.

import {
  parseOpenApi3Documentation,
  parseHydraDocumentation,
} from "@api-platform/api-doc-parser";

// parseHydraDocumentation proxy to add enum fields values what for now is
// supported only in openapi parser.
export const parseHydraDocumentationWithEnums = new Proxy(
  parseHydraDocumentation,
  {
    async apply(target, thisArg, args) {
      const result = await target.apply(thisArg, args);
      const enums = (
        await parseOpenApi3Documentation(args[0] + "docs.json")
      ).api.resources.reduce(
        (enums, resource) =>
          Object.assign(enums, {
            [resource.name]: Object.fromEntries(
              resource.fields
                .filter((field) => field.enum)
                .map((field) =>
                  Object.assign(enums[resource.name] ?? {}, [
                    field.name,
                    { enum: field.enum },
                  ])
                )
            ),
          }),
        {}
      );
      result.api.resources = result.api.resources.map((resource) =>
        Object.assign(resource, {
          fields: resource.fields.map((field) =>
            Object.assign(field, enums[resource.name][field.name] ?? {})
          ),
        })
      );

      return result;
    },
  }
);

PawelSuwinski avatar Feb 13 '23 11:02 PawelSuwinski