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

Add tag and candidate filter to comparison #448

Merged
merged 12 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ dist
dist-ssr
coverage
*.local
#package-lock.json
krystof-k marked this conversation as resolved.
Show resolved Hide resolved

/cypress/videos/
/cypress/screenshots/
Expand Down
5 changes: 3 additions & 2 deletions frontend/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { StorybookConfig } from '@storybook/types';

const config: StorybookConfig = {
stories: [
'../src/components/**/*.mdx',
Expand All @@ -13,6 +12,8 @@ const config: StorybookConfig = {
framework: {
name: '@storybook/vue3-vite',
},
docs: {
autodocs: false,
},
};

module.exports = config;
4,078 changes: 1,788 additions & 2,290 deletions frontend/package-lock.json

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.1.0",
"@storybook/addon-essentials": "^v7.0.0-beta.12",
"@storybook/addon-interactions": "^v7.0.0-beta.12",
"@storybook/addon-links": "^v7.0.0-beta.12",
"@storybook/testing-library": "^0.0.13",
"@storybook/vue3": "^v7.0.0-beta.12",
"@storybook/vue3-vite": "^v7.0.0-beta.12",
"@storybook/addon-essentials": "^v7.0.0-beta.20",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

storybook updated

"@storybook/addon-interactions": "^v7.0.0-beta.20",
"@storybook/addon-links": "^v7.0.0-beta.20",
"@storybook/testing-library": "^0.0.14-next.1",
"@storybook/vue3": "^v7.0.0-beta.20",
"@storybook/vue3-vite": "^v7.0.0-beta.20",
"@types/jsdom": "^20.0.1",
"@types/markdown-it": "^12.2.3",
"@types/node": "^18.11.17",
Expand All @@ -66,10 +66,12 @@
"prettier": "^2.5.1",
"prettier-plugin-sh": "^0.12.8",
"prisma": "^4.6.1",
"react": "^18.2.0",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed by storybook

"react-dom": "^18.2.0",
"sass": "^1.54.3",
"sass-loader": "^13.0.2",
"start-server-and-test": "^1.14.0",
"storybook": "^v7.0.0-beta.12",
"storybook": "^v7.0.0-beta.20",
"typescript": "~4.9.4",
"vercel": "^28.10.0",
"vite": "^4.0.1",
Expand Down
77 changes: 77 additions & 0 deletions frontend/src/components/QuestionCandidateFilter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<script setup lang="ts">
import { useElectionStore } from '@/stores/electionStore';
import { ref, watch } from 'vue';

import PillGroupComponent from '@/components/design-system/input/PillGroupComponent.vue';
import PillGroupItemComponent from '@/components/design-system/input/PillGroupItemComponent.vue';
import TitleText from './design-system/typography/TitleText.vue';

export interface Props {
modelValue?: Set<string>;
}

defineProps<Props>();
const emit = defineEmits(['update:modelValue']);

const electionStore = useElectionStore();

const uniqueCandidateIds = new Set<string>(
electionStore.calculator?.candidates.map((x) => x.id)
);
const selectedCandidateIds = ref(new Set<string>(uniqueCandidateIds));
const onSelectAllClicked = (event: MouseEvent) => {
if ((event.target as HTMLInputElement).checked) {
uniqueCandidateIds.forEach((x) => {
selectedCandidateIds.value.add(x);
});
} else {
selectedCandidateIds.value.clear();
}
};

watch(
selectedCandidateIds,
(newValue, oldValue) => {
emit('update:modelValue', newValue);
},
{ deep: true, immediate: true }
);
</script>

<template>
<form>
<TitleText class="tag-filter-title" tag="h3" size="small">
Filtrovat podle kandidujících
</TitleText>
<pill-group-component>
<pill-group-item-component
key="select-all"
type="checkbox"
group-name="select-all"
:checked="true"
@click="onSelectAllClicked"
>
Vybrat vše
</pill-group-item-component>
<pill-group-item-component
v-for="(candidateId, idx) in uniqueCandidateIds"
:key="idx"
v-model="selectedCandidateIds"
type="checkbox"
:group-name="candidateId"
:value="candidateId"
:checked="selectedCandidateIds.has(candidateId)"
>
{{
electionStore.calculator?.candidates.find((x) => x.id === candidateId)
?.name
}}
</pill-group-item-component>
</pill-group-component>
</form>
</template>
<style lang="scss" scoped>
.tag-filter-title {
padding-bottom: var(--spacing-small);
}
</style>
3 changes: 1 addition & 2 deletions frontend/src/components/QuestionCard.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup lang="ts">
import type { Question } from '@/types/question';

import AccordionComponent from '@/components/design-system/containers/AccordionComponent.vue';
import BodyText from '@/components/design-system/typography/BodyText.vue';
import CardComponent from '@/components/design-system/containers/CardComponent.vue';
import HeadingComponent from '@/components/design-system/typography/HeadingComponent.vue';
Expand All @@ -23,7 +22,7 @@ defineProps<Props>();
corner="top-left"
border
shadow
padding="medium"
:padding="Object('medium')"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without Object it throws bunch of errors in the console. I don't understand the reasons really

padding-responsive
padding-asymmetric
>
Expand Down
72 changes: 72 additions & 0 deletions frontend/src/components/QuestionTagFilter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<script setup lang="ts">
import { useElectionStore } from '@/stores/electionStore';
import { ref, watch } from 'vue';

import PillGroupComponent from '@/components/design-system/input/PillGroupComponent.vue';
import PillGroupItemComponent from '@/components/design-system/input/PillGroupItemComponent.vue';
import TitleText from './design-system/typography/TitleText.vue';

export interface Props {
modelValue?: Set<string>;
}

defineProps<Props>();
const emit = defineEmits(['update:modelValue']);

const electionStore = useElectionStore();

const uniqueTags = electionStore.uniqueQuestionTags;
const selectedTags = ref(new Set<string>(electionStore.uniqueQuestionTags));
const onSelectAllClicked = (event: MouseEvent) => {
if ((event.target as HTMLInputElement).checked) {
electionStore.uniqueQuestionTags.forEach((x) => {
selectedTags.value.add(x);
});
} else {
selectedTags.value.clear();
}
};

watch(
selectedTags,
(newValue, oldValue) => {
emit('update:modelValue', newValue);
},
{ deep: true, immediate: true }
);
</script>

<template>
<form>
<TitleText class="tag-filter-title" tag="h3" size="small">
Filtrovat podle témat
</TitleText>
<pill-group-component>
<pill-group-item-component
key="select-all"
type="checkbox"
group-name="select-all"
:checked="true"
@click="onSelectAllClicked"
>
Vybrat vše
</pill-group-item-component>
<pill-group-item-component
v-for="(tag, idx) in uniqueTags"
:key="idx"
v-model="selectedTags"
type="checkbox"
:group-name="tag"
:value="tag"
:checked="selectedTags.has(tag)"
>
{{ tag }}
</pill-group-item-component>
</pill-group-component>
</form>
</template>
<style lang="scss" scoped>
.tag-filter-title {
padding-bottom: var(--spacing-small);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@ const props = withDefaults(defineProps<Props>(), {
backgroundColor: 'rgb(var(--color-neutral-bg-container))',
border: false,
borderKind: 'normal',
// eslint-disable-next-line vue/require-valid-default-prop
borderRadius: 'small',
// eslint-disable-next-line vue/require-valid-default-prop
padding: 'medium',
padding: Object('medium') as Props['padding'],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

without Object it throws bunch of errors in the console. I don't understand the reasons really

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WTF? It may be related to the bug in Vue, which should be resolved soon by the vuejs/core#7394 PR (already approved).

responsive: true,
shadow: false,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const PillGroup: StoryFn<typeof PillGroupComponent> = (args) => ({
<pill-group-item-component
v-for="(item, idx) in args.items"
:value="item.value"
type="checkbox"
:groupName="args.groupName"
:checked="idx === 0"
:key="idx"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
padding: 0;
margin: 0;
list-style-type: none;
flex-wrap: wrap;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
<script setup lang="ts">
import { ref } from 'vue';
import { computed } from 'vue';
import LabelText from '@/components/design-system/typography/LabelText.vue';

export interface Props {
groupName: string;
type: 'radio' | 'checkbox';
value?: string;
checked?: boolean;
modelValue?: Set<string>;
}

const props = withDefaults(defineProps<Props>(), {
value: 'on',
checked: false,
modelValue: undefined,
});

const isChecked = ref(props.checked);
const isChecked = computed(() => props.checked);

const emit = defineEmits(['update:modelValue']);
const onInput = (payload: Event) => {
if (props.modelValue?.has((payload.target as HTMLInputElement).value)) {
props.modelValue.delete((payload.target as HTMLInputElement).value);
} else {
props.modelValue?.add((payload.target as HTMLInputElement).value);
}
emit('update:modelValue', props.modelValue);
};
</script>

<template>
Expand All @@ -22,10 +35,11 @@ const isChecked = ref(props.checked);
<input
ref="input"
class="pill-input"
type="radio"
:type="props.type"
:value="value || 'on'"
:name="props.groupName"
:checked="isChecked"
@input="onInput"
/>
<LabelText class="pill-label">
<slot />
Expand Down
Loading