Skip to content

Commit

Permalink
Feat: add OpenGov search (#1886)
Browse files Browse the repository at this point in the history
* feat: add search for OpenGov

* chore: typo

* fix: review
  • Loading branch information
sokolova-an authored Jun 24, 2024
1 parent 764c0e0 commit f600eeb
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { createStore } from 'effector';
import { createEvent, restore } from 'effector';

const $referendums = createStore<any[]>([]);
const queryChanged = createEvent<string>();

const $query = restore<string>(queryChanged, '');

export const referendumFilterModel = {
referendums: $referendums,
$query,
events: {
queryChanged,
},
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
import { useUnit } from 'effector-react';

import { useI18n } from '@app/providers';
import { SearchInput } from '@shared/ui';
import { referendumFilterModel } from '../model/referendum-filter-model';

export const ReferendumFilter = () => {
const { t } = useI18n();
const query = useUnit(referendumFilterModel.$query);

return (
// eslint-disable-next-line i18next/no-literal-string
<div>Referendum filter</div>
<SearchInput
value={query}
placeholder={t('governance.searchPlaceholder')}
wrapperClass="w-[230px]"
onChange={referendumFilterModel.events.queryChanged}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const OngoingReferendums = ({ referendums, onSelected }: Props) => {
<Accordion.Content as="ul" className="flex flex-col gap-y-2">
{Array.from(referendums).map(([index, referendum]) => {
const track = referendumListUtils.getTrackInfo(referendum.track);
const isPassing = supportThresholds[index].passing;
const isPassing = supportThresholds[index]?.passing;

return (
<li key={index}>
Expand All @@ -64,7 +64,7 @@ export const OngoingReferendums = ({ referendums, onSelected }: Props) => {
<div className="basis-[200px] shrink-0">
<VoteChartSm
bgColor="icon-button"
{...referendumListUtils.getVoteFractions(referendum.tally, approvalThresholds[index].value)}
{...referendumListUtils.getVoteFractions(referendum.tally, approvalThresholds[index]?.value)}
/>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ChainId, ReferendumId } from '@shared/core';
import { filterReferendums } from '../utils';

describe('page/governance/lib/governance-page-utils', () => {
const chainId = '0x1';
const referendums = new Map([
['111', {}],
['222', {}],
]);
const details: Record<ChainId, Record<ReferendumId, string>> = {
'0x1': {
111: 'Referendum Title 1',
222: 'Referendum Title 2',
},
};

test('should return all referendums if query is empty', () => {
const query = '';
const result = filterReferendums({ referendums, query, details, chainId });
expect(result).toEqual(referendums);
});

test('should return referendums that match the query in the ID', () => {
const query = '111';
const result = filterReferendums({ referendums, query, details, chainId });
expect(result.size).toEqual(1);
expect(result.has('111')).toEqual(true);
});

test('should return referendums that match the query in the title', () => {
const query = 'Title 2';
const result = filterReferendums({ referendums, query, details, chainId });
expect(result.size).toEqual(1);
expect(result.has('222')).toEqual(true);
});

test('should return an empty map if no referendums match the query', () => {
const query = 'none';
const result = filterReferendums({ referendums, query, details, chainId });
expect(result.size).toEqual(0);
});
});
24 changes: 24 additions & 0 deletions src/renderer/pages/Governance/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ChainId, ReferendumId } from '@shared/core';
import { includes } from '@shared/lib/utils';

type ReferendumMap<T> = Map<ReferendumId, T>;
type Props<T> = {
referendums: ReferendumMap<T>;
query: string;
details: Record<ChainId, Record<ReferendumId, string>>;
chainId: ChainId;
};

export function filterReferendums<T>({ referendums, query, details, chainId }: Props<T>): ReferendumMap<T> {
if (!query || referendums.size === 0) return referendums;

const filteredReferendums = Array.from(referendums.entries()).filter(([key]) => {
const title = details[chainId]?.[key];
const hasIndex = includes(key, query);
const hasTitle = includes(title, query);

return hasIndex || hasTitle;
});

return new Map(filteredReferendums);
}
45 changes: 38 additions & 7 deletions src/renderer/pages/Governance/model/governance-page-model.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { createEvent, sample } from 'effector';
import { createEvent, createStore, sample } from 'effector';

import type { ReferendumId, Chain } from '@shared/core';
import { networkSelectorModel, referendumListModel } from '@features/governance';
import type { ReferendumId, Chain, OngoingReferendum, CompletedReferendum } from '@shared/core';
import { governanceModel } from '@entities/governance';
import { networkSelectorModel, referendumFilterModel, referendumListModel } from '@features/governance';
import { filterReferendums } from '../lib/utils';

const flowStarted = createEvent();
const referendumSelected = createEvent<ReferendumId>();

// const $filteredReferendums = createStore<Record<ReferendumId, ReferendumInfo>>({});
const $ongoingFilteredReferendums = createStore<Map<ReferendumId, OngoingReferendum>>(new Map());
const $completeFilterdReferendums = createStore<Map<ReferendumId, CompletedReferendum>>(new Map());

sample({
clock: flowStarted,
Expand All @@ -32,10 +34,39 @@ sample({
// target: referendumDetailsModel.events.referendumChanged,
// });

sample({
clock: [referendumFilterModel.events.queryChanged, governanceModel.$ongoingReferendums],
source: {
referendums: governanceModel.$ongoingReferendums,
details: referendumListModel.$referendumsDetails,
chain: networkSelectorModel.$governanceChain,
query: referendumFilterModel.$query,
},
filter: ({ chain }) => Boolean(chain),
fn: ({ referendums, details, chain, query }) => {
return filterReferendums({ referendums, details, query, chainId: chain!.chainId });
},
target: $ongoingFilteredReferendums,
});

sample({
clock: [referendumFilterModel.events.queryChanged, governanceModel.$completedReferendums],
source: {
referendums: governanceModel.$completedReferendums,
details: referendumListModel.$referendumsDetails,
chain: networkSelectorModel.$governanceChain,
query: referendumFilterModel.$query,
},
filter: ({ chain }) => Boolean(chain),
fn: ({ referendums, details, chain, query }) => {
return filterReferendums({ referendums, details, query, chainId: chain!.chainId });
},
target: $completeFilterdReferendums,
});

export const governancePageModel = {
// TODO: will be filtered in upcoming tasks
$ongoing: governanceModel.$ongoingReferendums,
$completed: governanceModel.$completedReferendums,
$ongoing: $ongoingFilteredReferendums,
$completed: $completeFilterdReferendums,

events: {
flowStarted,
Expand Down
1 change: 1 addition & 0 deletions src/renderer/shared/api/translation/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
"treasurySmallTips": "Treasury: Small tips",
"wishForChange": "Wish for change"
},
"searchPlaceholder": "Search",
"title": "Governance",
"voted": "Voted"
},
Expand Down

0 comments on commit f600eeb

Please sign in to comment.