Skip to content

Commit

Permalink
feat: new data source route (#184)
Browse files Browse the repository at this point in the history
* refactor(pages): update request create route

* refactor: move data source func to data-source store

* feat: data source create route
also updates search typeahead just slightly

* fix: final removal of typeahead caching

* fix: update data source id route

* fix: update location typeahead

* refactor: little improvements to request and search

* refactor: data source create

* chore(deps): add vue3-toastify

* feat: add toast messages with vue3-toastify

* feat: add toast to create routes
  • Loading branch information
joshuagraber authored Nov 18, 2024
1 parent 14eda58 commit b7a4f28
Show file tree
Hide file tree
Showing 15 changed files with 647 additions and 142 deletions.
2 changes: 1 addition & 1 deletion client/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
},
"rules": {
"vue/multi-word-component-names": ["warn", {
"ignores": ["login", "index", "search", "search.results", "request", "profile", "[id]", "results"]
"ignores": ["login", "index", "search", "search.results", "request", "profile", "[id]", "results", "create"]
}]
}
}
28 changes: 23 additions & 5 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
"axios": "^1.6.0",
"jwt-decode": "^4.0.0",
"lodash": "^4.17.21",
"pdap-design-system": "^3.1.0-beta.19",
"pdap-design-system": "^3.1.0-beta.20",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.1",
"vue": "^3.4.19",
"vue-router": "^4.4.3"
"vue-router": "^4.4.3",
"vue3-toastify": "^0.2.4"
},
"devDependencies": {
"@pdap-design-system/eslint-config": "^1.0.1",
Expand Down
42 changes: 42 additions & 0 deletions client/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import acronym from 'pdap-design-system/images/acronym.svg';
import lockup from 'pdap-design-system/images/lockup.svg';
import { NAV_LINKS as links } from '@/util/constants';
import useThemePreference from '@/composables/useThemePreference';
export default {
name: 'App',
Expand All @@ -40,6 +41,9 @@ export default {
navLinks: [...links],
footerLinks: [...links],
},
setup() {
useThemePreference();
},
data() {
return {
acronym,
Expand Down Expand Up @@ -76,4 +80,42 @@ main {
.route-fade-leave-to {
opacity: 0;
}
.pdap-toast-container {
top: 120px;
}
:root {
--toastify-color-light: rgb(255 253 253);
--toastify-color-dark: rgb(26 26 26);
--toastify-color-info: #44799d;
--toastify-color-success: #49934b;
--toastify-color-warning: rgb(184 138 42);
--toastify-color-error: #f15d4c;
--toastify-color-transparent: rgba(255, 255, 255, 0.7);
--toastify-icon-color-info: var(--toastify-color-info);
--toastify-icon-color-success: var(--toastify-color-success);
--toastify-icon-color-warning: var(--toastify-color-warning);
--toastify-icon-color-error: var(--toastify-color-error);
--toastify-toast-width: auto;
--toastify-toast-background: #fff;
--toastify-toast-min-height: 64px;
--toastify-toast-max-height: 800px;
--toastify-font-family: inherit;
--toastify-z-index: 9999;
--toastify-text-color-light: rgb(26 26 26);
--toastify-text-color-dark: rgb(255 253 253);
}
@media (prefers-color-scheme: dark) {
:root {
--toastify-color-info: #67baf2;
--toastify-color-success: #51eb56;
--toastify-color-warning: rgb(184 138 42);
--toastify-color-error: #b53b2d;
}
}
</style>
37 changes: 13 additions & 24 deletions client/src/components/SearchForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<p class="text-lg mt-8 mb-4">
If you have a question to answer, we can help
</p>
<RouterLink class="pdap-button-primary" to="/request">
<RouterLink class="pdap-button-primary" to="/request/create">
Make a Request
</RouterLink>
</div>
Expand All @@ -76,11 +76,8 @@ import { STATES_TO_ABBREVIATIONS } from '@/util/constants';
import _debounce from 'lodash/debounce';
import _isEqual from 'lodash/isEqual';
import { useRouter, RouterLink, useRoute } from 'vue-router';
import { useSearchStore } from '@/stores/search';
const router = useRouter();
const { sessionLocationTypeaheadCache, upsertSessionLocationTypeaheadCache } =
useSearchStore();
const { buttonCopy } = defineProps({
buttonCopy: String,
Expand Down Expand Up @@ -286,27 +283,19 @@ const fetchTypeaheadResults = _debounce(
async (e) => {
try {
if (e.target.value.length > 1) {
const suggestions =
// Cache has search results return that
sessionLocationTypeaheadCache?.[e.target.value.toLowerCase()] ??
// Otherwise fetch
(
await axios.get(
`${import.meta.env.VITE_VUE_API_BASE_URL}/typeahead/locations`,
{
headers: {
Authorization: import.meta.env.VITE_ADMIN_API_KEY,
},
params: {
query: e.target.value,
},
},
)
).data.suggestions;
const response = await axios.get(
`${import.meta.env.VITE_VUE_API_BASE_URL}/typeahead/locations`,
{
headers: {
Authorization: import.meta.env.VITE_ADMIN_API_KEY,
},
params: {
query: e.target.value,
},
},
);
upsertSessionLocationTypeaheadCache({
[e.target.value.toLowerCase()]: suggestions,
});
const suggestions = response.data.suggestions;
items.value = suggestions.length ? suggestions : undefined;
} else {
Expand Down
41 changes: 41 additions & 0 deletions client/src/composables/useThemePreference.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { onMounted } from 'vue';

/** Sets theme as class to document.documentElement
* This is only necessary because `vue3-toastify` expects global themes to be set this way.
* 🙄 https://github.com/jerrywu001/vue3-toastify/blob/96706e8399c336bd1d8c458cf872b6df395352a0/src/utils/tools.ts#L60-L62*/
export default function useThemePreference() {
const applyTheme = (newTheme) => {
// Remove any existing theme classes
document.documentElement.classList.remove('light', 'dark');
// Add the new theme class
document.documentElement.classList.add(newTheme);
};

const initializeTheme = () => {
// Check system preference
const prefersDark = window.matchMedia(
'(prefers-color-scheme: dark)',
).matches;
applyTheme(prefersDark ? 'dark' : 'light');
};

// Watch for system theme changes
const setupThemeListener = () => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

mediaQuery.addEventListener('change', (e) => {
const newTheme = e.matches ? 'dark' : 'light';
// Only apply system preference if no stored preference exists
if (!localStorage.getItem('theme')) {
applyTheme(newTheme);
}
});
};

onMounted(() => {
initializeTheme();
setupThemeListener();
});

return true;
}
11 changes: 11 additions & 0 deletions client/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { createApp } from 'vue';
import { createPinia } from 'pinia';
import piniaPersistState from 'pinia-plugin-persistedstate';
import { DataLoaderPlugin } from 'unplugin-vue-router/data-loaders';
import Vue3Toastify from 'vue3-toastify';
import 'vue3-toastify/dist/index.css';
import App from './App.vue';
import router from './router';
import 'pdap-design-system/styles';
Expand All @@ -14,5 +16,14 @@ const app = createApp(App);
app.use(pinia);
app.use(DataLoaderPlugin, { router });
app.use(router);
app.use(Vue3Toastify, {
autoClose: 5000,
containerClassName: 'pdap-toast-container',
toastClassName: 'pdap-toast',
style: {
opacity: 0.95,
},
theme: 'auto',
});

app.mount('#app');
30 changes: 16 additions & 14 deletions client/src/pages/data-source/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@

<!-- Agency data -->
<div class="flex-[0_0_100%] flex flex-col gap-2 w-full">
<!-- For each agency, TODO: does UI need to be updated? -->
<div class="agency-row-container">
<div class="agency-row">
<div>
Expand Down Expand Up @@ -147,11 +146,15 @@
<h4>{{ record.title }}</h4>

<!-- If an array, render and nest inside of div -->
<div v-if="Array.isArray(dataSource[record.key])">
<div
v-if="Array.isArray(dataSource[record.key])"
class="flex gap-2"
>
<component
:is="record.component ?? 'p'"
v-for="item in dataSource[record.key]"
:key="item"
:class="record.classNames"
>
{{ formatResult(record, item) }}
</component>
Expand Down Expand Up @@ -189,28 +192,30 @@ import { useRoute, useRouter } from 'vue-router';
import _cloneDeep from 'lodash/cloneDeep';
import { useSwipe } from '@vueuse/core';
import { ref } from 'vue';
import { useDataSourceStore } from '@/stores/data-source';
const search = useSearchStore();
const dataSourceStore = useDataSourceStore();
const previous = ref(search.getPreviousDataSourceRoute);
const previous = ref(dataSourceStore.previousDataSourceRoute);
export const useDataSourceData = defineBasicLoader(
'/data-source/:id',
async (route) => {
const dataSourceId = route.params.id;
// create deep clone of previous route.
previous.value = _cloneDeep(search.getPreviousDataSourceRoute);
previous.value = _cloneDeep(dataSourceStore.previousDataSourceRoute);
// Use previous route to determine if nav is increment or decrement (this is for dynamic transition)
const navIs =
search.mostRecentSearchIds.indexOf(Number(previous.value?.params?.id)) >
search.mostRecentSearchIds.indexOf(Number(dataSourceId))
? 'decrement'
: 'increment';
const results = await search.getDataSource(dataSourceId);
const results = await dataSourceStore.getDataSource(dataSourceId);
// Then set current route to prev before returning data
search.setPreviousDataSourceRoute(route);
dataSourceStore.setPreviousDataSourceRoute(route);
return {
...results.data.data,
Expand Down Expand Up @@ -306,7 +311,7 @@ function formatResult(record, item) {
}
hgroup {
@apply mt-4;
@apply mt-4 self-start;
flex: 0 0 100%;
}
Expand Down Expand Up @@ -351,16 +356,13 @@ hgroup {
opacity: 0;
}
.increment-enter-from {
.increment-enter-from,
.decrement-leave-to {
transform: translateX(15%);
}
.decrement-enter-from {
.decrement-enter-from,
.increment-leave-to {
transform: translateX(-15%);
}
.increment-leave-to,
.decrement-leave-to {
transform: translateX(0);
}
</style>
16 changes: 10 additions & 6 deletions client/src/pages/data-source/_util.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ export const DATA_SOURCE_UI_SHAPE = [
{ title: 'Access Type', key: 'access_type' },
{
title: 'Record Formats',
key: 'record_format',
key: 'record_formats',
component: 'span',
classNames:
'mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit small',
'mt-1 py-[.125rem] px-3 rounded-full bg-slate-200 dark:bg-slate-600 w-fit small text-neutral-800 border-solid border-[1px] border-neutral-500 rounded-xl px-2 bg-neutral-200 text-xs sm:text-sm [&>*]:md:text-med [&>*]:lg:text-lg p-1 overflow-hidden',
},
{ title: 'Detail Level', key: 'detail_level' },
{ title: 'Size', key: 'size' },
Expand Down Expand Up @@ -103,7 +103,7 @@ export const DATA_SOURCE_UI_SHAPE = [
{ title: 'Coverage End Date', key: 'coverage_end', isDate: true },
{
title: 'Source Last Updated',
key: 'source_last_updated',
key: 'updated_at',
isDate: true,
},
{ title: 'Update Frequency', key: 'update_frequency' },
Expand All @@ -125,9 +125,9 @@ export const DATA_SOURCE_UI_SHAPE = [
attributes: { target: '_blank', rel: 'noreferrer' },
classNames: 'w-full inline-block truncate-text',
},
{ title: 'Created', key: 'data_source_created', isDate: true },
{ title: 'Agency ID', key: 'agency_id' },
{ title: 'Data Source ID', key: 'data_source_id' },
{ title: 'Created', key: 'created_at', isDate: true },
{ title: 'Agency ID', key: 'agency_ids' },
{ title: 'Data Source ID', key: 'id' },
],
},
];
Expand Down Expand Up @@ -159,3 +159,7 @@ export function formatDateForSearchResults(date) {
return date.toLocaleDateString('es-pa');
}
}

export function formatText(item) {
return item.display_name;
}
Loading

0 comments on commit b7a4f28

Please sign in to comment.