Skip to content

Commit

Permalink
Merge pull request #2416 from zetkin/undocumented/join-form-smart-search
Browse files Browse the repository at this point in the history
Join form smart search
  • Loading branch information
richardolsson authored Dec 9, 2024
2 parents e5e6a76 + 04c4d35 commit fda9002
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CampaignParticipation from '../filters/CampaignParticipation';
import EmailBlacklist from '../filters/EmailBlacklist';
import EmailClick from '../filters/EmailClick';
import EmailHistory from '../filters/EmailHistory';
import JoinFormFilter from '../filters/JoinForm';
import Journey from '../filters/Journey';
import MostActive from '../filters/MostActive';
import PersonData from '../filters/PersonData';
Expand Down Expand Up @@ -166,6 +167,13 @@ const FilterEditor = ({
onSubmit={onSubmitFilter}
/>
)}
{filter.type === FILTER_TYPE.JOINFORM && (
<JoinFormFilter
filter={filter}
onCancel={onCancelSubmitFilter}
onSubmit={onSubmitFilter}
/>
)}
{filter.type === FILTER_TYPE.JOURNEY && (
<Journey
filter={filter}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,10 +123,10 @@ export default function filterGalleryPattern(
pattern = PATTERN_TEMPLATES.pattern15;
}

pattern.background = pattern.background.replaceAll(
'$strongColor',
colors.strong
);
pattern.background = pattern.background.replaceAll('$paleColor', colors.pale);
return pattern;
return {
...pattern,
background: pattern.background
.replaceAll('$strongColor', colors.strong)
.replaceAll('$paleColor', colors.pale),
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,6 @@ export const GROUPED_FILTERS: {
pale: filterCategoryColors.red.pale,
strong: filterCategoryColors.red.strong,
},
filters: [FILTER_TYPE.RANDOM, FILTER_TYPE.USER],
filters: [FILTER_TYPE.JOINFORM, FILTER_TYPE.RANDOM, FILTER_TYPE.USER],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
Block,
Call,
CheckBoxOutlined,
DoorFrontOutlined,
DraftsOutlined,
Event,
ExploreOutlined,
Expand Down Expand Up @@ -50,6 +51,7 @@ import {
EmailClickFilterConfig,
EmailHistoryFilterConfig,
FILTER_TYPE,
JoinFormFilterConfig,
JourneyFilterConfig,
MostActiveFilterConfig,
OPERATION,
Expand All @@ -66,6 +68,7 @@ import {
TaskFilterConfig,
UserFilterConfig,
} from 'features/smartSearch/components/types';
import DisplayJoinForm from '../../filters/JoinForm/DisplayJoinForm';

export default function getFilterComponents(
filter: SmartSearchFilterWithId<AnyFilterConfig>
Expand Down Expand Up @@ -219,6 +222,13 @@ export default function getFilterComponents(
filterTypeIcon = (
<AccountCircleOutlined color="secondary" fontSize="small" />
);
} else if (filter.type == FILTER_TYPE.JOINFORM) {
displayFilter = (
<DisplayJoinForm
filter={filter as SmartSearchFilterWithId<JoinFormFilterConfig>}
/>
);
filterTypeIcon = <DoorFrontOutlined color="secondary" fontSize="small" />;
}

return {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { FC } from 'react';

import {
JoinFormFilterConfig,
OPERATION,
SmartSearchFilterWithId,
} from '../../types';
import { Msg } from 'core/i18n';
import messageIds from 'features/smartSearch/l10n/messageIds';
import UnderlinedMsg from '../../UnderlinedMsg';
import { useNumericRouteParams } from 'core/hooks';
import DisplayJoinFormTitle from './DisplayJoinFormTitle';
import DisplayTimeFrame from '../DisplayTimeFrame';
import { getTimeFrameWithConfig } from '../../utils';

type Props = {
filter: SmartSearchFilterWithId<JoinFormFilterConfig>;
};

const localMessageIds = messageIds.filters.joinForm;

const DisplayJoinForm: FC<Props> = ({ filter }) => {
const { orgId } = useNumericRouteParams();
const op = filter.op || OPERATION.ADD;
const timeFrame = getTimeFrameWithConfig({
after: filter.config.submitted?.after,
before: filter.config.submitted?.before,
});

return (
<Msg
id={localMessageIds.inputString}
values={{
addRemoveSelect: <UnderlinedMsg id={messageIds.operators[op]} />,
formSelect: filter.config.form ? (
<DisplayJoinFormTitle formId={filter.config.form} orgId={orgId} />
) : (
<UnderlinedMsg id={localMessageIds.anyForm} />
),
timeFrame: <DisplayTimeFrame config={timeFrame} />,
}}
/>
);
};

export default DisplayJoinForm;
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FC } from 'react';

import messageIds from 'features/smartSearch/l10n/messageIds';
import useJoinForm from 'features/joinForms/hooks/useJoinForm';
import UnderlinedMsg from '../../UnderlinedMsg';

type Props = {
formId: number;
orgId: number;
};

const localMessageIds = messageIds.filters.joinForm;

const DisplayJoinFormTitle: FC<Props> = ({ formId, orgId }) => {
const { data } = useJoinForm(orgId, formId);

return (
<UnderlinedMsg
id={localMessageIds.form}
values={{ title: data?.title || '' }}
/>
);
};

export default DisplayJoinFormTitle;
116 changes: 116 additions & 0 deletions src/features/smartSearch/components/filters/JoinForm/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { FC, FormEvent } from 'react';
import { MenuItem } from '@mui/material';

import {
JoinFormFilterConfig,
NewSmartSearchFilter,
OPERATION,
SmartSearchFilterWithId,
TIME_FRAME,
ZetkinSmartSearchFilter,
} from '../../types';
import FilterForm from '../../FilterForm';
import { Msg } from 'core/i18n';
import messageIds from 'features/smartSearch/l10n/messageIds';
import StyledSelect from '../../inputs/StyledSelect';
import useSmartSearchFilter from 'features/smartSearch/hooks/useSmartSearchFilter';
import TimeFrame from '../TimeFrame';
import useJoinForms from 'features/joinForms/hooks/useJoinForms';
import { useNumericRouteParams } from 'core/hooks';

type Props = {
filter: SmartSearchFilterWithId<JoinFormFilterConfig> | NewSmartSearchFilter;
onCancel: () => void;
onSubmit: (
filter:
| SmartSearchFilterWithId<JoinFormFilterConfig>
| ZetkinSmartSearchFilter<JoinFormFilterConfig>
) => void;
};

const localMessageIds = messageIds.filters.joinForm;

const JoinFormFilter: FC<Props> = ({
filter: initialFilter,
onSubmit,
onCancel,
}) => {
const { orgId } = useNumericRouteParams();
const forms = useJoinForms(orgId).data || [];
const { filter, setConfig, setOp } =
useSmartSearchFilter<JoinFormFilterConfig>(initialFilter, {});

const handleSubmit = (e: FormEvent) => {
e.preventDefault();
onSubmit(filter);
};

return (
<FilterForm
onCancel={onCancel}
onSubmit={handleSubmit}
renderSentence={() => (
<Msg
id={localMessageIds.inputString}
values={{
addRemoveSelect: (
<StyledSelect
onChange={(e) => setOp(e.target.value as OPERATION)}
value={filter.op}
>
{Object.values(OPERATION).map((o) => (
<MenuItem key={o} value={o}>
<Msg id={messageIds.operators[o]} />
</MenuItem>
))}
</StyledSelect>
),
formSelect: (
<StyledSelect
onChange={(e) => {
const formId = parseInt(e.target.value);
const config = { ...filter.config };
if (formId) {
config.form = formId;
} else {
delete config.form;
}

setConfig(config);
}}
value={filter.config.form || 'any'}
>
<MenuItem value="any">
<Msg id={localMessageIds.anyForm} />
</MenuItem>
{forms.map((form) => (
<MenuItem key={form.id} value={form.id}>
{form.title}
</MenuItem>
))}
</StyledSelect>
),
timeFrame: (
<TimeFrame
filterConfig={filter.config.submitted || {}}
onChange={(range) =>
setConfig({ ...filter.config, submitted: range })
}
options={[
TIME_FRAME.AFTER_DATE,
TIME_FRAME.BEFORE_DATE,
TIME_FRAME.BEFORE_TODAY,
TIME_FRAME.BETWEEN,
TIME_FRAME.EVER,
TIME_FRAME.LAST_FEW_DAYS,
]}
/>
),
}}
/>
)}
/>
);
};

export default JoinFormFilter;
11 changes: 11 additions & 0 deletions src/features/smartSearch/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum FILTER_TYPE {
EMAIL_BLACKLIST = 'email_blacklist',
EMAIL_CLICK = 'email_click',
EMAIL_HISTORY = 'email_history',
JOINFORM = 'joinform',
JOURNEY = 'journey_subjects',
MOST_ACTIVE = 'most_active',
PERSON_DATA = 'person_data',
Expand Down Expand Up @@ -160,6 +161,15 @@ export interface EmailHistoryFilterConfig {
email?: number;
operator: 'sent' | 'not_sent' | 'opened' | 'not_opened';
}

export interface JoinFormFilterConfig {
form?: number;
submitted?: {
after?: string;
before?: string;
};
}

export interface MostActiveFilterConfig {
after?: string;
before?: string;
Expand Down Expand Up @@ -325,6 +335,7 @@ export type AnyFilterConfig =
| CampaignParticipationConfig
| DefaultFilterConfig
| EmailBlacklistFilterConfig
| JoinFormFilterConfig
| MostActiveFilterConfig
| PersonDataFilterConfig
| PersonFieldFilterConfig
Expand Down
15 changes: 15 additions & 0 deletions src/features/smartSearch/l10n/messageIds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export default makeMessages('feat.smartSearch', {
description: m('Who was sent what, when?'),
title: m('Based on their email history'),
},
joinform: {
description: m('Find people who came in through a join form.'),
title: m('Based on join form source'),
},
journey_subjects: {
description: m(
'Find people who are on a journey or finished it already'
Expand Down Expand Up @@ -301,6 +305,17 @@ export default makeMessages('feat.smartSearch', {
sent: m('been sent'),
},
},
joinForm: {
anyForm: m('any join form'),
form: m<{ title: string }>('"{title}"'),
inputString: m<{
addRemoveSelect: ReactElement;
formSelect: ReactElement;
timeFrame: ReactElement;
}>(
'{addRemoveSelect} people who came in through {formSelect} {timeFrame}'
),
},
journey: {
condition: {
conditionSelect: {
Expand Down

0 comments on commit fda9002

Please sign in to comment.