Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/npm_and_yarn/nuxt-3.12.4
Browse files Browse the repository at this point in the history
  • Loading branch information
NatVIII authored Aug 27, 2024
2 parents 2710881 + 80ce557 commit c87cc55
Show file tree
Hide file tree
Showing 22 changed files with 1,062 additions and 833 deletions.
1,073 changes: 624 additions & 449 deletions assets/event_sources.json

Large diffs are not rendered by default.

316 changes: 95 additions & 221 deletions components/App.vue

Large diffs are not rendered by default.

19 changes: 0 additions & 19 deletions components/CityFilterItem.vue

This file was deleted.

15 changes: 0 additions & 15 deletions components/CountyFilterItem.vue

This file was deleted.

219 changes: 109 additions & 110 deletions components/FilterModal.vue
Original file line number Diff line number Diff line change
@@ -1,126 +1,125 @@
<script setup lang="ts">
import { VueFinalModal } from 'vue-final-modal'
const props = defineProps<{
title?: string
allCallback: (newIsEnabled: boolean) => void
cityCallback: (newIsEnabled: boolean, city: string) => void
countyCallback: (newIsEnabled: boolean, county: string) => void
}>()
const emit = defineEmits<{
(e: 'confirm'): void
}>()
// There's a lot of redundancy with the cities and counties between this component and the App component.
// Try to reduce it in the future.
import { ref, inject, computed } from 'vue';
import { VueFinalModal } from 'vue-final-modal';
import TopicFilterItem from './TopicFilterItem.vue';
import TagFilterItem from './TagFilterItem.vue';
import eventSourcesJSON from '@/assets/event_sources.json';
// Use composable.
const isAllCitiesInMarinCountyEnabled = useIsAllCitiesInMarinCountyEnabled();
const isSanFranciscoEnabled = useIsSanFranciscoEnabled();
const isOthersInSFSanMateoCountyEnabled = useIsOthersInSFSanMateoCountyEnabled();
const isOaklandEnabled = useIsOaklandEnabled();
const isBerkeleyEnabled = useIsBerkeleyEnabled();
const isOthersInAlamedaCountyEnabled = useIsOthersInAlamedaCountyEnabled();
const isSanJoseEnabled = useIsSanJoseEnabled();
const isOthersInSantaClaraCountyEnabled = useIsOthersInSantaClaraCountyEnabled();
const isSantaCruzEnabled = useIsSantaCruzEnabled();
const isOthersInSantaCruzCountyEnabled = useIsOthersInSantaCruzCountyEnabled();
const tags = inject('tags'); //Grabs the 'tags' array, which features all tags and whether they're hidden, from App.vue
const countyIdToCitiesRefs = {
[MARIN_COUNTY_ID]: [isAllCitiesInMarinCountyEnabled],
[SF_SAN_MATEO_COUNTY_ID]: [isSanFranciscoEnabled, isOthersInSFSanMateoCountyEnabled],
[ALAMEDA_COUNTY_ID]: [isOaklandEnabled, isBerkeleyEnabled, isOthersInAlamedaCountyEnabled],
[SANTA_CLARA_COUNTY_ID]: [isSanJoseEnabled, isOthersInSantaClaraCountyEnabled],
[SANTA_CRUZ_COUNTY_ID]: [isSantaCruzEnabled, isOthersInSantaCruzCountyEnabled],
};
// This function is needed because, since the CityFilterItem component is nested within this component,
// the changes to the state from the App component will not cause a re-render of the CityFilterItem components.
const updateIsCityEnabledLocally = (newIsEnabled, county) => {
countyIdToCitiesRefs[county].forEach((city) => {
city.value = newIsEnabled;
});
function getTagVisibility(tagName) {
const tag = tags.value.find(t => t.name === tagName);
return tag ? tag.isVisible : false;
}
const countyWrapper = (newIsEnabled: boolean, county: string) => {
updateIsCityEnabledLocally(newIsEnabled, county);
props.countyCallback(newIsEnabled, county);
function updateTagVisibility(tagName, visibility) {
const tag = tags.value.find(t => t.name === tagName);
if (tag) {
tag.isVisible = visibility;
}
}
const allWrapper = (newIsEnabled: boolean) => {
updateAllIsCityEnabledLocally(newIsEnabled);
props.allCallback(newIsEnabled);
function setVisibilityForGroup(tagsInGroup, visibility) {
tagsInGroup.forEach(tagName => {
const tag = tags.value.find(t => t.name === tagName.name);
if (tag) {
tag.isVisible = visibility;
}
});
}
const updateAllIsCityEnabledLocally = (newIsEnabled) => {
Object.values(countyIdToCitiesRefs).forEach((cities) => {
cities.forEach((city) => {
city.value = newIsEnabled;
});
});
}
const { enableEventSource, disableEventSource } = defineProps<{
enableEventSource: (name: string) => void;
disableEventSource: (name: string) => void;
}>();
</script>
<template>
<VueFinalModal class="popper-box-wrapper" content-class="popper-box-inner" overlay-transition="vfm-fade"
content-transition="vfm-fade">
<CountyFilterItem :label="ALL_ID" @on-yes="allWrapper(true)" @on-no="allWrapper(false)">
</CountyFilterItem>
const emit = defineEmits<{
(e: 'confirm'): void;
}>();
<CountyFilterItem :label="MARIN_COUNTY_ID"
@on-yes="countyWrapper(true, MARIN_COUNTY_ID); (() => { useIsAllCitiesInMarinCountyEnabled.value = true })()"
@on-no="countyWrapper(false, MARIN_COUNTY_ID); ">
<CityFilterItem v-model="isAllCitiesInMarinCountyEnabled" :label="ALL_CITIES_IN_MARIN_COUNTY_ID"
@on-input="cityCallback($event.target.checked, ALL_CITIES_IN_MARIN_COUNTY_ID)">
</CityFilterItem>
</CountyFilterItem>
// Development environment flag
const isDevelopment = process.env.NODE_ENV === 'development';
<CountyFilterItem :label="SF_SAN_MATEO_COUNTY_ID" @on-yes="countyWrapper(true, SF_SAN_MATEO_COUNTY_ID)"
@on-no="countyWrapper(false, SF_SAN_MATEO_COUNTY_ID)">
<CityFilterItem v-model="isSanFranciscoEnabled" :label="SAN_FRANCISCO_ID"
@on-input="cityCallback($event.target.checked, SAN_FRANCISCO_ID)">
</CityFilterItem>
<CityFilterItem v-model="isOthersInSFSanMateoCountyEnabled" :label="OTHERS_IN_SF_SAN_MATEO_COUNTY_ID"
@on-input="cityCallback($event.target.checked, OTHERS_IN_SF_SAN_MATEO_COUNTY_ID)">
</CityFilterItem>
</CountyFilterItem>
// Accessing tags from the imported JSON
const tagsHeader = ref(eventSourcesJSON.appConfig.tagsHeader);
const tagsHidden = ref(eventSourcesJSON.appConfig.tagsHidden);
const tagsToShow = ref(eventSourcesJSON.appConfig.tagsToShow);
<CountyFilterItem :label="ALAMEDA_COUNTY_ID" @on-yes="countyWrapper(true, ALAMEDA_COUNTY_ID)"
@on-no="countyWrapper(false, ALAMEDA_COUNTY_ID)">
<CityFilterItem v-model="isOaklandEnabled" :label="OAKLAND_ID"
@on-input="cityCallback($event.target.checked, OAKLAND_ID)">
</CityFilterItem>
<CityFilterItem v-model="isBerkeleyEnabled" :label="BERKELEY_ID"
@on-input="cityCallback($event.target.checked, BERKELEY_ID)">
</CityFilterItem>
<CityFilterItem v-model="isOthersInAlamedaCountyEnabled" :label="OTHERS_IN_ALAMEDA_COUNTY_ID"
@on-input="cityCallback($event.target.checked, OTHERS_IN_ALAMEDA_COUNTY_ID)">
</CityFilterItem>
</CountyFilterItem>
// Computed property to flatten tagsToShow into a 1D array of strings, for the purpose of debugging to make sure there's no tags missing
const tagsAllShown = computed(() => {
let flattened = [];
for (let i = 0; i < tagsToShow.value.length; i++) {
if (tagsToShow.value[i].length === 1) {
flattened.push(tagsToShow.value[i][0].map(tag => tag.name));
} else {
flattened.push(...tagsToShow.value[i].slice(1).map(tag => tag.name)); // Skip the first element (label) and add rest
}
}
flattened.push(...tagsHeader.value.map(tag => tag.name)); //Add the tagsHeader values to the array, ensuring that they're not left out from the list of ALL TAGS SHOWN
flattened.push(...tagsHidden.value); //Add the tagsHidden values to the array, ensuring that they're not left out from the list of ALL TAGS SHOWN
return flattened;
});
<CountyFilterItem :label="SANTA_CLARA_COUNTY_ID" @on-yes="countyWrapper(true, SANTA_CLARA_COUNTY_ID)"
@on-no="countyWrapper(false, SANTA_CLARA_COUNTY_ID)">
<CityFilterItem v-model="isSanJoseEnabled" :label="SAN_JOSE_ID"
@on-input="cityCallback($event.target.checked, SAN_JOSE_ID)">
</CityFilterItem>
<CityFilterItem v-model="isOthersInSantaClaraCountyEnabled" :label="OTHERS_IN_SANTA_CLARA_COUNTY_ID"
@on-input="cityCallback($event.target.checked, OTHERS_IN_SANTA_CLARA_COUNTY_ID)">
</CityFilterItem>
</CountyFilterItem>
//
const tagsNotShown = computed(() => { //A 1D array of tags that aren't featured in tagsAllShown but ARE featured in tags; used to show any tags that maybe should be visible in the UI or should be wiped from event_sources.json altogether.
const shownSet = new Set(tagsAllShown.value);
return tags.value.filter(tag => !shownSet.has(tag.name));
});
<CountyFilterItem :label="SANTA_CRUZ_COUNTY_ID" @on-yes="countyWrapper(true, SANTA_CRUZ_COUNTY_ID)"
@on-no="countyWrapper(false, SANTA_CRUZ_COUNTY_ID)">
<CityFilterItem v-model="isSantaCruzEnabled" :label="SANTA_CRUZ_ID"
@on-input="cityCallback($event.target.checked, SANTA_CRUZ_ID)">
</CityFilterItem>
<CityFilterItem v-model="isOthersInSantaCruzCountyEnabled" :label="OTHERS_IN_SANTA_CRUZ_COUNTY_ID"
@on-input="cityCallback($event.target.checked, OTHERS_IN_SANTA_CRUZ_COUNTY_ID)">
</CityFilterItem>
</CountyFilterItem>
<div class="bottom">
function handleEventSourceChange(tag: string, isEnabled: boolean) {
if (isEnabled) {
enableEventSource(tag);
} else {
disableEventSource(tag);
}
}
// Example function to toggle visibility
function toggleTagVisibility(tagName: string) {
const tag = tags.value.find(t => t.name === tagName);
if (tag) {
tag.isVisible = !tag.isVisible;
}
}
<button @click="emit('confirm')">
Done
</button>
</div>
</VueFinalModal>
</template>
</script>

<template>
<VueFinalModal class="popper-box-wrapper" content-class="popper-box-inner" overlay-transition="vfm-fade" content-transition="vfm-fade">
<span class="event-headers">
Event Purpose
</span>
<div class="county-header">
<TagFilterItem v-for="tag in tagsHeader" :key="tag.name" class="tag-group" :label="tag.fullName" :modelValue="getTagVisibility(tag.name)" @update:modelValue="updateTagVisibility(tag.name, $event)">
</TagFilterItem>
</div>
<span class="event-headers">
Event Type
</span>
<div v-for="group in tagsToShow" :key="group[0] || group" class="tag-group">
<template v-if="Array.isArray(group)">
<TopicFilterItem class="tag-header" :label="group[0].fullName" @checkAll="setVisibilityForGroup(group.slice(1), true)" @uncheckAll="setVisibilityForGroup(group.slice(1), false)">
<TagFilterItem v-for="tag in group.slice(1)" :key="tag.name" :label="tag.fullName" :modelValue="getTagVisibility(tag.name)" @update:modelValue="updateTagVisibility(tag.name, $event)">
</TagFilterItem>
</TopicFilterItem>
</template>
<template v-else>
<TagFilterItem class="tag-sub-item" :label="group.fullName" :modelValue="getTagVisibility(group.name)" @update:modelValue="updateTagVisibility(group.name, $event)">
</TagFilterItem>
</template>
</div>
<span v-if="isDevelopment">
<span class="event-headers">
Tags Not Shown
</span>
<div v-for="tag in tagsNotShown" :key="tag">
<input type="checkbox"
:checked="getTagVisibility(tag.name)"
@change="updateTagVisibility(tag.name, $event.target.checked)" /> {{ tag.name }}
</div>
</span>
<div class="bottom filterButton">
<button @click="emit('confirm')">Apply</button>
</div>
</VueFinalModal>
</template>
20 changes: 20 additions & 0 deletions components/TagFilterItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup>
const props = defineProps({
label: String,
modelValue: Boolean,
isVisible: Boolean
});
const emit = defineEmits(['update:modelValue']);
// Emitting visibility changes if needed
function updateVisibility(checked) {
emit('update:modelValue', checked);
}
</script>

<template>
<label class="city-header" :class="{ 'is-hidden': !props.isVisible }">
<input type="checkbox" :checked="props.modelValue" @change="updateVisibility($event.target.checked)">
{{ props.label }}
</label>
</template>
26 changes: 26 additions & 0 deletions components/TopicFilterItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<script setup lang="ts">
const props = defineProps({
label: String
});
const emit = defineEmits(['checkAll', 'uncheckAll']);
function checkAllTags() {
emit('checkAll');
}
function uncheckAllTags() {
emit('uncheckAll');
}
</script>

<template>
<div class="county-header">
<span>
<button class="county-input" @click="checkAllTags">+</button>
<button class="county-input" @click="uncheckAllTags">-</button>
{{ label }}
</span>
<slot></slot>
</div>
</template>
Loading

0 comments on commit c87cc55

Please sign in to comment.