dashpresshq/dashpress

View on GitHub
src/frontend/views/entity/Presentation/index.tsx

Summary

Maintainability
B
4 hrs
Test Coverage
A
100%
import { msg } from "@lingui/macro";
import { fakeMessageDescriptor } from "translations/fake";

import { SchemaForm } from "@/components/app/form/schema";
import { SectionBox } from "@/components/app/section-box";
import {
  FormSkeleton,
  FormSkeletonSchema,
} from "@/components/app/skeleton/form";
import { useToast } from "@/components/app/toast/use-toast";
import { ViewStateMachine } from "@/components/app/view-state-machine";
import { useDocumentationActionButton } from "@/frontend/docs/constants";
import { PresentationScriptDocumentation } from "@/frontend/docs/scripts/presentations-scripts";
import { useAppConfigurationDomainMessages } from "@/frontend/hooks/configuration/configuration.constant";
import {
  useEntityConfiguration,
  useUpsertConfigurationMutation,
} from "@/frontend/hooks/configuration/configuration.store";
import { useEntitySlug } from "@/frontend/hooks/entity/entity.config";
import { useEvaluateScriptContext } from "@/frontend/hooks/scripts";
import { useSetPageDetails } from "@/frontend/lib/routing/usePageDetails";
import type { IPresentationScriptParams } from "@/frontend/views/data/evaluatePresentationScript";
import { UserPermissions } from "@/shared/constants/user";
import { evalJavascriptString } from "@/shared/lib/script-runner";

import { BaseEntitySettingsLayout } from "../_Base";
import { ENTITY_CONFIGURATION_VIEW } from "../constants";

const placeholder = `if($.field === "image"){
  return "https://cdn.mycompany.com/" + $.value + "?size=320x640";
}

if($.field === "description" && $.from === "table"){
  return $.value.substr(0, 120)
}

if($.field === "commentsCount"){
  return ($.value / 1000) + "K"
}
          `;

type IEntityPresentationScript = {
  script: string;
};

export function EntityPresentationScriptSettings() {
  const entity = useEntitySlug();
  const entityPresentationScript = useEntityConfiguration(
    "entity_presentation_script",
    entity
  );
  const { toast } = useToast();

  const domainMessages = useAppConfigurationDomainMessages(
    "entity_presentation_script"
  );

  const upsertConfigurationMutation = useUpsertConfigurationMutation(
    "entity_presentation_script",
    entity
  );
  const evaluateScriptContext = useEvaluateScriptContext();

  const documentationActionButton = useDocumentationActionButton(
    domainMessages.TEXT_LANG.TITLE
  );

  useSetPageDetails({
    pageTitle: domainMessages.TEXT_LANG.TITLE,
    viewKey: ENTITY_CONFIGURATION_VIEW,
    permission: UserPermissions.CAN_CONFIGURE_APP,
  });
  return (
    <BaseEntitySettingsLayout>
      <SectionBox
        title={domainMessages.TEXT_LANG.TITLE}
        actionButtons={[documentationActionButton]}
      >
        <ViewStateMachine
          loading={entityPresentationScript.isLoading}
          error={entityPresentationScript.error}
          loader={<FormSkeleton schema={[FormSkeletonSchema.RichTextArea]} />}
        >
          <SchemaForm<IEntityPresentationScript>
            fields={{
              script: {
                type: "json",
                label: msg`Script`,
                validations: [],
                placeholder: fakeMessageDescriptor(placeholder),
              },
            }}
            onSubmit={async (data) => {
              const context: IPresentationScriptParams = {
                field: "test",
                from: "details",
                row: {},
                value: "",
                ...evaluateScriptContext,
              };
              try {
                evalJavascriptString(data.script, context);

                await upsertConfigurationMutation.mutateAsync(data);
              } catch (e) {
                toast({
                  variant: "red",
                  title: msg`Could not parse Javascript`,
                  description: msg`•Expression: \n•JS-Error: ${e}`,
                });
              }
            }}
            initialValues={entityPresentationScript.data}
            systemIcon="Save"
            buttonText={domainMessages.FORM_LANG.UPSERT}
          />
        </ViewStateMachine>
      </SectionBox>
      <PresentationScriptDocumentation />
    </BaseEntitySettingsLayout>
  );
}