Skip to content

Commit

Permalink
COM-962: Improve UI/UX of target group page (#64)
Browse files Browse the repository at this point in the history
* add dialog for creating a new target group

* add filter

* set filters to optional and assign contacts only if a filter is given

* fix prettier errors

* simplify onSubmit

* rename FormProps to TargetGroupDialogProps

* use EditDialog from comet

* remove create from TargetGroupForm as it is not possible to create a new TargetGroup here

* fix EditDialog to not redirect back to grid

* set id to required and remove conditions where id is not given

* remove Stackpage for adding a targetGroup as this page doesn't exist anymore

---------

Co-authored-by: Julia Wegmayr <[email protected]>
  • Loading branch information
juliawegmayr and Julia Wegmayr authored Aug 6, 2024
1 parent 34beaac commit 1fc8d9d
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 96 deletions.
9 changes: 9 additions & 0 deletions packages/admin/src/targetGroups/TargetGroupDialog.gql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { gql } from "@apollo/client";

export const createTargetGroupMutation = gql`
mutation CreateTargetGroup($scope: EmailCampaignContentScopeInput!, $input: TargetGroupInput!) {
createTargetGroup(scope: $scope, input: $input) {
id
}
}
`;
58 changes: 58 additions & 0 deletions packages/admin/src/targetGroups/TargetGroupDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { useApolloClient } from "@apollo/client";
import { Field, FinalForm, FinalFormInput, FinalFormSubmitEvent, useStackSwitchApi } from "@comet/admin";
import { ContentScopeInterface } from "@comet/cms-admin";
import { FormApi } from "final-form";
import React from "react";
import { FormattedMessage } from "react-intl";

import { createTargetGroupMutation } from "./TargetGroupDialog.gql";
import { GQLCreateTargetGroupMutation, GQLCreateTargetGroupMutationVariables } from "./TargetGroupDialog.gql.generated";
import { EditTargetGroupFinalFormValues } from "./TargetGroupForm";

interface TargetGroupDialogProps {
scope: ContentScopeInterface;
}

export function TargetGroupDialog({ scope }: TargetGroupDialogProps): React.ReactElement {
const client = useApolloClient();
const mode = "add";
const stackSwitchApi = useStackSwitchApi();

const handleSubmit = async (
state: EditTargetGroupFinalFormValues,
form: FormApi<EditTargetGroupFinalFormValues>,
event: FinalFormSubmitEvent,
) => {
const output = {
...state,
};

const { data: mutationResponse } = await client.mutate<GQLCreateTargetGroupMutation, GQLCreateTargetGroupMutationVariables>({
mutation: createTargetGroupMutation,
variables: { scope, input: output },
});
if (!event.navigatingBack) {
const id = mutationResponse?.createTargetGroup.id;
if (id) {
setTimeout(() => {
stackSwitchApi.activatePage("edit", id);
});
}
}
};
return (
<FinalForm<EditTargetGroupFinalFormValues> onSubmit={handleSubmit} mode={mode}>
{() => {
return (
<Field
required
fullWidth
name="title"
component={FinalFormInput}
label={<FormattedMessage id="cometBrevoModule.targetGroup.title" defaultMessage="Title" />}
/>
);
}}
</FinalForm>
);
}
95 changes: 33 additions & 62 deletions packages/admin/src/targetGroups/TargetGroupForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
ToolbarTitleItem,
useFormApiRef,
useStackApi,
useStackSwitchApi,
} from "@comet/admin";
import { ArrowLeft } from "@comet/admin-icons";
import { ContentScopeInterface, EditPageLayout, queryUpdatedAt, resolveHasSaveConflict, useFormSaveConflict } from "@comet/cms-admin";
Expand All @@ -28,10 +27,8 @@ export { namedOperations as targetGroupFormNamedOperations } from "./TargetGroup

import { AddContactsGridSelect } from "./addContacts/AddContactsGridSelect";
import { AllAssignedContactsGrid } from "./allAssignedContacts/AllAssignedContactsGrid";
import { createTargetGroupMutation, targetGroupFormQuery, updateTargetGroupMutation } from "./TargetGroupForm.gql";
import { targetGroupFormQuery, updateTargetGroupMutation } from "./TargetGroupForm.gql";
import {
GQLCreateTargetGroupMutation,
GQLCreateTargetGroupMutationVariables,
GQLTargetGroupFormQuery,
GQLTargetGroupFormQueryVariables,
GQLUpdateTargetGroupMutation,
Expand All @@ -44,7 +41,7 @@ export interface EditTargetGroupFinalFormValues {
}

interface FormProps {
id?: string;
id: string;
scope: ContentScopeInterface;
additionalFormFields?: React.ReactNode;
nodeFragment?: { name: string; fragment: DocumentNode };
Expand All @@ -54,9 +51,8 @@ interface FormProps {
export function TargetGroupForm({ id, scope, additionalFormFields, input2State, nodeFragment }: FormProps): React.ReactElement {
const stackApi = useStackApi();
const client = useApolloClient();
const mode = id ? "edit" : "add";
const mode = "edit";
const formApiRef = useFormApiRef<EditTargetGroupFinalFormValues>();
const stackSwitchApi = useStackSwitchApi();

const targetGroupFormFragment = gql`
fragment TargetGroupForm on TargetGroup {
Expand All @@ -67,7 +63,7 @@ export function TargetGroupForm({ id, scope, additionalFormFields, input2State,

const { data, error, loading, refetch } = useQuery<GQLTargetGroupFormQuery, GQLTargetGroupFormQueryVariables>(
targetGroupFormQuery(targetGroupFormFragment),
id ? { variables: { id } } : { skip: true },
{ variables: { id } },
);

const initialValues = React.useMemo<Partial<EditTargetGroupFinalFormValues>>(() => {
Expand Down Expand Up @@ -104,28 +100,10 @@ export function TargetGroupForm({ id, scope, additionalFormFields, input2State,
...state,
};

if (mode === "edit") {
if (!id) {
throw new Error("Missing id in edit mode");
}
await client.mutate<GQLUpdateTargetGroupMutation, GQLUpdateTargetGroupMutationVariables>({
mutation: updateTargetGroupMutation(targetGroupFormFragment),
variables: { id, input: output, lastUpdatedAt: data?.targetGroup?.updatedAt },
});
} else {
const { data: mutationResponse } = await client.mutate<GQLCreateTargetGroupMutation, GQLCreateTargetGroupMutationVariables>({
mutation: createTargetGroupMutation(targetGroupFormFragment),
variables: { scope, input: output },
});
if (!event.navigatingBack) {
const id = mutationResponse?.createTargetGroup.id;
if (id) {
setTimeout(() => {
stackSwitchApi.activatePage("edit", id);
});
}
}
}
await client.mutate<GQLUpdateTargetGroupMutation, GQLUpdateTargetGroupMutationVariables>({
mutation: updateTargetGroupMutation(targetGroupFormFragment),
variables: { id, input: output, lastUpdatedAt: data?.targetGroup?.updatedAt },
});
};

if (error) throw error;
Expand Down Expand Up @@ -175,38 +153,31 @@ export function TargetGroupForm({ id, scope, additionalFormFields, input2State,
{additionalFormFields}
</FieldSet>
)}
{id && (
<>
<FieldSet
title={
<FormattedMessage
id="cometBrevoModule.targetGroup.manuallyAddContacts"
defaultMessage="Manually add contacts"
/>
}
initiallyExpanded
disablePadding
>
<AddContactsGridSelect
assignedContactsTargetGroupBrevoId={data?.targetGroup.assignedContactsTargetGroupBrevoId ?? undefined}
id={id}
scope={scope}
/>
</FieldSet>
<FieldSet
title={
<FormattedMessage
id="cometBrevoModule.targetGroup.allAssignedContacts"
defaultMessage="All assigned contacts"
/>
}
disablePadding
initiallyExpanded={false}
>
<AllAssignedContactsGrid brevoId={data?.targetGroup.brevoId ?? undefined} id={id} scope={scope} />
</FieldSet>
</>
)}

<>
<FieldSet
title={
<FormattedMessage id="cometBrevoModule.targetGroup.manuallyAddContacts" defaultMessage="Manually add contacts" />
}
initiallyExpanded
disablePadding
>
<AddContactsGridSelect
assignedContactsTargetGroupBrevoId={data?.targetGroup.assignedContactsTargetGroupBrevoId ?? undefined}
id={id}
scope={scope}
/>
</FieldSet>
<FieldSet
title={
<FormattedMessage id="cometBrevoModule.targetGroup.allAssignedContacts" defaultMessage="All assigned contacts" />
}
disablePadding
initiallyExpanded={false}
>
<AllAssignedContactsGrid brevoId={data?.targetGroup.brevoId ?? undefined} id={id} scope={scope} />
</FieldSet>
</>
</MainContent>
</EditPageLayout>
)}
Expand Down
53 changes: 33 additions & 20 deletions packages/admin/src/targetGroups/TargetGroupsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
ToolbarItem,
useBufferedRowCount,
useDataGridRemote,
useEditDialog,
usePersistentColumnState,
} from "@comet/admin";
import { Add as AddIcon, Download, Edit } from "@comet/admin-icons";
Expand All @@ -24,6 +25,7 @@ import { DocumentNode } from "graphql";
import * as React from "react";
import { FormattedMessage, useIntl } from "react-intl";

import { TargetGroupDialog } from "./TargetGroupDialog";
import {
GQLCreateTargetGroupMutation,
GQLCreateTargetGroupMutationVariables,
Expand Down Expand Up @@ -93,26 +95,6 @@ const createTargetGroupMutation = gql`
}
`;

function TargetGroupsGridToolbar() {
return (
<Toolbar>
<ToolbarAutomaticTitleItem />
<ToolbarItem>
<GridToolbarQuickFilter />
</ToolbarItem>
<ToolbarItem>
<GridFilterButton />
</ToolbarItem>
<ToolbarFillSpace />
<ToolbarActions>
<Button startIcon={<AddIcon />} component={StackLink} pageName="add" payload="add" variant="contained" color="primary">
<FormattedMessage id="cometBrevoModule.targetGroup.newTargetGroup" defaultMessage="New target group" />
</Button>
</ToolbarActions>
</Toolbar>
);
}

export function TargetGroupsGrid({
scope,
exportTargetGroupOptions,
Expand All @@ -126,6 +108,34 @@ export function TargetGroupsGrid({
const client = useApolloClient();
const intl = useIntl();
const dataGridProps = { ...useDataGridRemote(), ...usePersistentColumnState("TargetGroupsGrid") };
const [EditDialog, , editDialogApi] = useEditDialog();

function TargetGroupsGridToolbar() {
return (
<Toolbar>
<ToolbarAutomaticTitleItem />
<ToolbarItem>
<GridToolbarQuickFilter />
</ToolbarItem>
<ToolbarItem>
<GridFilterButton />
</ToolbarItem>
<ToolbarFillSpace />
<ToolbarActions>
<Button
startIcon={<AddIcon />}
variant="contained"
color="primary"
onClick={() => {
editDialogApi.openAddDialog();
}}
>
<FormattedMessage id="cometBrevoModule.targetGroup.newTargetGroup" defaultMessage="New target group" />
</Button>
</ToolbarActions>
</Toolbar>
);
}

const targetGroupContactsQuery = gql`
query TargetGroupContacts($targetGroupId: ID!, $offset: Int, $limit: Int, $scope: EmailCampaignContentScopeInput!) {
Expand Down Expand Up @@ -282,6 +292,9 @@ export function TargetGroupsGrid({
Toolbar: TargetGroupsGridToolbar,
}}
/>
<EditDialog disableCloseAfterSave componentsProps={{ dialog: { maxWidth: "sm" } }}>
<TargetGroupDialog scope={scope} />
</EditDialog>
</MainContent>
);
}
11 changes: 0 additions & 11 deletions packages/admin/src/targetGroups/TargetGroupsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,6 @@ export function createTargetGroupsPage({
/>
)}
</StackPage>
<StackPage
name="add"
title={intl.formatMessage({ id: "cometBrevoModule.targetGroups.addTargetGroup", defaultMessage: "Add target group" })}
>
<TargetGroupForm
scope={scope}
additionalFormFields={additionalFormFields}
nodeFragment={nodeFragment}
input2State={input2State}
/>
</StackPage>
</StackSwitch>
</Stack>
);
Expand Down
6 changes: 4 additions & 2 deletions packages/api/src/target-group/target-group.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,9 @@ export function createTargetGroupsResolver({

await this.entityManager.flush();

await this.targetGroupsService.assignContactsToContactList(input.filters, targetGroup, targetGroup.scope);
if (input.filters) {
await this.targetGroupsService.assignContactsToContactList(targetGroup, targetGroup.scope, input.filters);
}

return targetGroup;
}
Expand Down Expand Up @@ -194,7 +196,7 @@ export function createTargetGroupsResolver({
validateNotModified(targetGroup, lastUpdatedAt);
}

await this.targetGroupsService.assignContactsToContactList(input.filters, targetGroup, targetGroup.scope);
await this.targetGroupsService.assignContactsToContactList(targetGroup, targetGroup.scope, input.filters);

if (input.title && input.title !== targetGroup.title) {
const successfullyUpdatedContactList = await this.brevoApiContactsService.updateBrevoContactList(
Expand Down
2 changes: 1 addition & 1 deletion packages/api/src/target-group/target-groups.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ export class TargetGroupsService {
}

public async assignContactsToContactList(
filters: BrevoContactFilterAttributesInterface = {},
targetGroup: TargetGroupInterface,
scope: EmailCampaignScopeInterface,
filters?: BrevoContactFilterAttributesInterface,
): Promise<true> {
const mainScopeTargetGroupList = await this.repository.findOneOrFail({ scope, isMainList: true });

Expand Down

0 comments on commit 1fc8d9d

Please sign in to comment.