Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Add ability for gc forms admin to switch to api mode for live form #4709

Merged
merged 12 commits into from
Nov 27, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,12 @@ type APIKeyCustomEventDetails = {
id: string;
};

export const ApiKeyDialog = () => {
/**
* API Key Dialog
* @param isVaultDelivery - boolean - Allows skipping the save request when a form is already saving to the vault -- example a live form swapping to API mode
* @returns JSX.Element
*/
export const ApiKeyDialog = ({ isVaultDelivery = false }: { isVaultDelivery?: boolean }) => {
const dialog = useDialogRef();
const { Event } = useCustomEvent();
const { t } = useTranslation("form-builder");
Expand Down Expand Up @@ -73,15 +78,21 @@ export const ApiKeyDialog = () => {
setHasError(false);
setGenerating(true);
try {
// First ensure all responses are sent to vault
const result = await sendResponsesToVault({
id: id,
});

if (result.error) {
// Throw the generic key creation error
// Handling as generic as we're in the process of creating a key
throw new Error(result.error);
/*
Allows skipping the save request
if it's determined that the form responses
are already being delivered to the vault
*/
if (!isVaultDelivery) {
const result = await sendResponsesToVault({
id: id,
});

if (result.error) {
// Throw the generic key creation error
// Handling as generic as we're in the process of creating a key
throw new Error(result.error);
}
}

const key = await _createKey(id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,22 @@ import { useTranslation } from "@i18n/client";
import { EventKeys, useCustomEvent } from "@lib/hooks/useCustomEvent";
import { DeleteKeyButton } from "./DeleteKeyButton";
import { SubmitButton as GenerateApiKeyButton } from "@clientComponents/globals/Buttons/SubmitButton";
import { Theme } from "@clientComponents/globals/Buttons/themes";
import { useFormBuilderConfig } from "@lib/hooks/useFormBuilderConfig";
import { ResponseDeliveryHelpButtonWithApi } from "./dialogs/ResponseDeliveryHelpDialogApiWithApi";

type ApiKeyButtonProps = {
showDelete?: boolean;
i18nKey?: string;
theme?: Theme;
showHelp?: boolean;
};

export const ApiKeyButton = ({
showDelete = false,
i18nKey = "settings.api.generateKey",
theme = "primary",
showHelp = true,
}: ApiKeyButtonProps) => {
const { t } = useTranslation("form-builder");
const { id } = useParams();
Expand All @@ -36,21 +41,21 @@ export const ApiKeyButton = ({
{showDelete && apiKeyId ? (
<>
<DeleteKeyButton id={id} keyId={apiKeyId} />
<ResponseDeliveryHelpButtonWithApi />
{showHelp && <ResponseDeliveryHelpButtonWithApi />}
</>
) : (
<>
<GenerateApiKeyButton
loading={false}
theme="primary"
theme={theme}
disabled={Boolean(apiKeyId)}
onClick={() => {
openDialog();
}}
>
{t(i18nKey)}
</GenerateApiKeyButton>
<ResponseDeliveryHelpButtonWithApi />
{showHelp && <ResponseDeliveryHelpButtonWithApi />}
</>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const FormOwnership = ({

return (
<>
<div className="mb-20" data-testid="form-ownership">
<div className="mb-10" data-testid="form-ownership">
<h2>{t("Manage ownership")}</h2>
{message && message}
<p className="mb-4">{t("assignUsersToTemplate")}</p>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";
import { useTranslation } from "@i18n/client";
import { ApiKeyButton } from "../components/ApiKeyButton";
import { SettingsApplicationsIcon } from "@serverComponents/icons";
export const ManageApiKey = () => {
const { t } = useTranslation("form-builder");
return (
<div className="mb-10">
<h2>
<SettingsApplicationsIcon className="-mt-10px mr-1 inline-block" />{" "}
{t("switchToApiMode.title")}{" "}
</h2>
<p className="mb-4">{t("switchToApiMode.description")}</p>
<ApiKeyButton
theme="secondary"
i18nKey="switchToApiMode.btnText"
showDelete={true}
showHelp={false}
/>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { SetClosingDate } from "./close/SetClosingDate";
import { FormOwnership } from "./FormOwnership";
import { ErrorPanel } from "@clientComponents/globals/ErrorPanel";
import { updateTemplateUsers } from "@formBuilder/actions";
import { ManageApiKey } from "./ManageApiKey";
import { ThrottlingRate } from "./ThrottlingRate";

interface User {
Expand All @@ -16,7 +17,7 @@ interface User {

interface ManageFormProps {
nonce: string | null;
canManageOwnership: boolean;
canManageAllForms: boolean;
canSetClosingDate: boolean;
formRecord?: FormRecord;
usersAssignedToFormRecord?: User[];
Expand All @@ -31,13 +32,13 @@ export const ManageForm = (props: ManageFormProps) => {
formRecord,
usersAssignedToFormRecord,
allUsers,
canManageOwnership,
canManageAllForms,
canSetClosingDate,
id,
closedDetails,
} = props;

if (!canManageOwnership) {
if (!canManageAllForms) {
return (
<>
{canSetClosingDate && <SetClosingDate formId={id} closedDetails={closedDetails} />}
Expand All @@ -60,7 +61,8 @@ export const ManageForm = (props: ManageFormProps) => {
allUsers={allUsers}
updateTemplateUsers={updateTemplateUsers}
/>
{canManageOwnership && <ThrottlingRate formId={id} />}
{canManageAllForms && <ThrottlingRate formId={id} />}
{canManageAllForms && formRecord.isPublished && <ManageApiKey />}
<DownloadForm />
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ export const ThrottlingRate = ({ formId }: { formId: string }) => {
}, [formId, throttlingErrorString]);

return (
<div className="mb-20">
<div className="mb-10">
<form onSubmit={handleSubmit}>
<h2>{t("throttling.title")}</h2>
<div role="alert">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { UserAbility } from "@lib/types";
import { Session } from "next-auth";
import { getNonce } from "./actions";
import { checkIfClosed } from "@lib/actions/checkIfClosed";
import { ApiKeyDialog } from "../../components/dialogs/ApiKeyDialog/ApiKeyDialog";
import { DeleteApiKeyDialog } from "../../components/dialogs/DeleteApiKeyDialog/DeleteApiKeyDialog";

export async function generateMetadata({
params: { locale },
Expand All @@ -22,7 +24,7 @@ export async function generateMetadata({
};
}

const getCanManageOwnership = (formId: string, ability: UserAbility | null) => {
const canManageAllForms = (formId: string, ability: UserAbility | null) => {
if (!ability || formId === "0000") {
return false;
}
Expand Down Expand Up @@ -68,7 +70,7 @@ export default async function Page({ params: { id } }: { params: { id: string }

let closedDetails;

const canManageOwnership = getCanManageOwnership(id, ability);
const manageAllForms = canManageAllForms(id, ability);
const canSetClosingDate = getCanSetClosingDate(id, ability, session);
const nonce = await getNonce();

Expand All @@ -77,12 +79,12 @@ export default async function Page({ params: { id } }: { params: { id: string }
closedDetails = closedData?.closedDetails;
}

if (!canManageOwnership || id === "0000") {
if (!manageAllForms || id === "0000") {
return (
<ManageForm
nonce={nonce}
id={id}
canManageOwnership={canManageOwnership}
canManageAllForms={false}
canSetClosingDate={canSetClosingDate}
closedDetails={closedDetails}
/>
Expand All @@ -98,16 +100,34 @@ export default async function Page({ params: { id } }: { params: { id: string }

const allUsers = await getAllUsers(ability);

const isPublished = templateWithAssociatedUsers.formRecord.isPublished;
const isVaultDelivery = !templateWithAssociatedUsers.formRecord.deliveryMethod;

return (
<ManageForm
nonce={nonce}
id={id}
canManageOwnership={canManageOwnership}
canSetClosingDate={canSetClosingDate}
formRecord={templateWithAssociatedUsers.formRecord}
usersAssignedToFormRecord={templateWithAssociatedUsers.users}
allUsers={allUsers}
closedDetails={closedDetails}
/>
<>
<ManageForm
nonce={nonce}
id={id}
canManageAllForms={manageAllForms}
canSetClosingDate={canSetClosingDate}
formRecord={templateWithAssociatedUsers.formRecord}
usersAssignedToFormRecord={templateWithAssociatedUsers.users}
allUsers={allUsers}
closedDetails={closedDetails}
/>
{/*
- Only show for users with manage all forms privileges
- we do an additional check here in case the code above to reach this point changes later
- Only show for forms with vault delivery already set
- Only show for live forms
- draft forms should use Response Delivery page
*/}
{isPublished && manageAllForms && isVaultDelivery && (
<>
<ApiKeyDialog isVaultDelivery={true} />
<DeleteApiKeyDialog />
</>
)}
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { serverTranslation } from "@i18n";
import { Metadata } from "next";
import { ResponseDelivery } from "./components/ResponseDelivery";
import { ApiKeyDialog } from "../components/dialogs/ApiKeyDialog/ApiKeyDialog";
import { DeleteApiKeyDialog } from "../components/dialogs/DeleteApiKeyDialog/DeleteApiKeyDialog";
import { authCheckAndRedirect } from "@lib/actions";
import { checkPrivilegesAsBoolean } from "@lib/privileges";
import { ApiKeyDialog } from "../components/dialogs/ApiKeyDialog/ApiKeyDialog";
import { DeleteApiKeyDialog } from "../components/dialogs/DeleteApiKeyDialog/DeleteApiKeyDialog";

export async function generateMetadata({
params: { locale },
Expand All @@ -18,7 +18,6 @@ export async function generateMetadata({
}

export default async function Page() {

const { ability } = await authCheckAndRedirect();

const isFormsAdmin = checkPrivilegesAsBoolean(ability, [
Expand All @@ -27,7 +26,7 @@ export default async function Page() {
subject: "FormRecord",
},
]);

return (
<>
<ResponseDelivery isFormsAdmin={isFormsAdmin} />
Expand Down
5 changes: 5 additions & 0 deletions i18n/translations/en/form-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,11 @@
"downloadBtnText": "Download form file",
"title": "Download form file"
},
"switchToApiMode": {
"title": "Switch to API delivery",
"description": "New responses will be available through the API endpoint",
"btnText": "Switch to API delivery"
},
"formIntroduction": "Form introduction",
"formInvalidProperty": "Invalid: {{property}}",
"formMissingProperty": "Missing: {{property}}",
Expand Down
5 changes: 5 additions & 0 deletions i18n/translations/fr/form-builder.json
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,11 @@
"downloadBtnText": "Télécharger le fichier du formulaire",
"title": "Télécharger le fichier du formulaire"
},
"switchToApiMode": {
"title": "Switch to API delivery [FR]",
"description": "New responses will be available through the API endpoint [FR]",
"btnText": "Switch to API delivery [FR]"
},
"formIntroduction": "Introduction du formulaire ",
"formInvalidProperty": "Invalide : {{property}}",
"formMissingProperty": "Il manque : {{property}}",
Expand Down
Loading