Skip to content

Commit

Permalink
Merge branch 'dev' into mc_568_containerize_flask_app
Browse files Browse the repository at this point in the history
  • Loading branch information
maxachis committed Jan 1, 2025
2 parents 0c621c0 + f339050 commit 08a0074
Show file tree
Hide file tree
Showing 21 changed files with 898 additions and 243 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ The environment variables are as follows:
* GH_API_ACCESS_TOKEN: Used to authenticate with GitHub when adding or getting information about Github Issues. Must correspond to the `access_token` provided by GitHub.
* GH_ISSUE_REPO_NAME: Identifies the repository, in `<github-username>/<github-repo-name>` format, where the issue will be created, and where information about issues will be retrieved. Can be customized for local development.
* VALIDATE_EMAIL_SECRET_KEY: Used to sign and verify JWT tokens for the validate email feature. Used to identify that any JWT tokens for the validate email feature produced are recognizable by this version of the app and no other.
V2 Feature gating
* VITE_V2_FEATURE_ENHANCED_SEARCH: 'enabled' shows enhanced search features (like follow) in the client app, 'disabled' hides them
* VITE_V2_FEATURE_AUTHENTICATE: 'enabled' allows sign in and sign out of the web app, 'disabled' disallows.
* VITE_V2_FEATURE_CREATE_RECORDS: 'enabled' allows user to create data sources and requests from within the app, 'disabled' changes the links to lead to the current Airtable forms



#### .env Example
Expand Down
11 changes: 11 additions & 0 deletions client/src/api/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ export async function resetPassword(password, token) {
);
}

export async function generateAPIKey() {
const auth = useAuthStore();

return await axios.post(`${AUTH_BASE}/${ENDPOINTS.AUTH.API_KEY}`, null, {
headers: {
...HEADERS,
Authorization: `Bearer ${auth.$state.tokens.accessToken.value}`,
},
});
}

/**
* @deprecated validation now done by parsing JWT directly
*/
Expand Down
16 changes: 13 additions & 3 deletions client/src/api/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const HEADERS_BASIC = {
};

export async function search(params) {
const authStore = useAuthStore();
const searchStore = useSearchStore();
const cached = searchStore.getSearchFromCache(JSON.stringify(params));

Expand All @@ -32,7 +33,14 @@ export async function search(params) {
`${SEARCH_BASE}/${ENDPOINTS.SEARCH.RESULTS}`,
{
params,
headers: HEADERS_BASIC,
headers: {
...HEADERS_BASIC,
...(authStore.isAuthenticated()
? {
Authorization: `Bearer ${authStore.$state.tokens.accessToken.value}`,
}
: {}),
},
},
);

Expand Down Expand Up @@ -86,9 +94,11 @@ export async function getFollowedSearch(location_id) {
try {
const response = await getFollowedSearches();

return response.data.data.find(
({ id: followed_id }) => Number(followed_id) === Number(location_id),
const found = response.data.data.find(
({ location_id: followed_id }) =>
Number(followed_id) === Number(location_id),
);
return found;
} catch (error) {
return null;
}
Expand Down
12 changes: 12 additions & 0 deletions client/src/api/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,15 @@ export async function changePassword(oldPassword, newPassword) {

return await auth.signInWithEmail(user.email, newPassword);
}

export async function getUser() {
const auth = useAuthStore();
const user = useUserStore();

return await axios.get(`${USER_BASE}/${user.id}`, {
headers: {
...HEADERS,
Authorization: `Bearer ${auth.$state.tokens.accessToken.value}`,
},
});
}
29 changes: 29 additions & 0 deletions client/src/components/AuthWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,35 @@ import { useAuthStore } from '@/stores/auth';
import { useRoute, useRouter } from 'vue-router';
import { useUserStore } from '@/stores/user';
import { refreshTokens, signOut } from '@/api/auth';
import { updateGlobalOptions, globalOptions } from 'vue3-toastify';
import { watch, ref, onMounted } from 'vue';
const isHeaderVisible = ref(true);
watch(isHeaderVisible, (visible) => {
updateGlobalOptions({
...globalOptions.value,
style: {
...globalOptions.style,
top: visible ? '120px' : '20px',
},
theme: 'auto',
});
});
onMounted(() => {
const observer = new IntersectionObserver(
([entry]) => {
isHeaderVisible.value = entry.isIntersecting;
},
{ threshold: 0 },
);
const navbar = document.querySelector('.pdap-header');
if (navbar) {
observer.observe(navbar);
}
});
const route = useRoute();
const router = useRouter();
Expand Down
49 changes: 24 additions & 25 deletions client/src/components/SearchForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,22 @@
<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="/data-request/create">
<RouterLink
v-if="getIsV2FeatureEnabled('CREATE_RECORDS')"
class="pdap-button-primary"
:to="'/data-request/create'"
>
Make a Request
</RouterLink>
<a
v-else
class="pdap-button-primary"
href="https://airtable.com/app473MWXVJVaD7Es/shrbFfWk6fjzGnNsk"
target="_blank"
rel="noreferrer"
>
Make a request
</a>
</div>
</template>

Expand All @@ -82,11 +95,16 @@ import {
} from 'pdap-design-system';
import TypeaheadInput from '@/components/TypeaheadInput.vue';
import { computed, onMounted, ref } from 'vue';
import { getFullLocationText } from '@/util/locationFormatters';
import {
getFullLocationText,
mapLocationToSearchParams,
mapSearchParamsToLocation,
} from '@/util/locationFormatters';
import _debounce from 'lodash/debounce';
import _isEqual from 'lodash/isEqual';
import { useRouter, RouterLink, useRoute } from 'vue-router';
import { getTypeaheadLocations } from '@/api/typeahead';
import { getIsV2FeatureEnabled } from '@/util/featureFlagV2';
const router = useRouter();
Expand Down Expand Up @@ -186,17 +204,7 @@ const isButtonDisabled = computed(() => {
onMounted(() => {
// Set up selected state based on params
if (params.state) {
const record = (({
state_name,
county_name,
locality_name,
location_id,
}) => ({
state: state_name,
county: county_name,
locality: locality_name,
location_id,
}))(params);
const record = mapSearchParamsToLocation(params);
selectedRecord.value = record;
initiallySearchedRecord.value = record;
Expand All @@ -223,18 +231,9 @@ function buildParams(values) {
const obj = {};
/* Handle record from typeahead input */
const recordFilteredByParamsKeys = (({
state_name,
county_name,
locality_name,
location_id,
}) => ({
state: state_name,
county: county_name,
locality: locality_name,
location_id,
// If no selected record, fall back to the initial search
}))(selectedRecord.value ?? initiallySearchedRecord.value);
const recordFilteredByParamsKeys = mapLocationToSearchParams(
selectedRecord.value ?? initiallySearchedRecord.value,
);
Object.keys(recordFilteredByParamsKeys).forEach((key) => {
if (recordFilteredByParamsKeys[key])
Expand Down
7 changes: 3 additions & 4 deletions client/src/pages/data-request/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,6 @@
<script>
// Data loader
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic';
import { useRoute, useRouter } from 'vue-router';
import { useSwipe } from '@vueuse/core';
import { ref } from 'vue';
import { useDataRequestsStore } from '@/stores/data-requests';
import { DataLoaderErrorPassThrough } from '@/util/errors';
import { getDataRequest } from '@/api/data-requests';
Expand Down Expand Up @@ -124,7 +121,9 @@ import { faLink } from '@fortawesome/free-solid-svg-icons';
import { useSearchStore } from '@/stores/search';
import { getMinimalLocationText } from '@/util/locationFormatters';
import { REQUEST_URGENCY } from './_constants';
import { computed, onMounted, onUnmounted } from 'vue';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { useSwipe } from '@vueuse/core';
const route = useRoute();
const router = useRouter();
Expand Down
21 changes: 10 additions & 11 deletions client/src/pages/data-source/[id].vue
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,9 @@ const descriptionRef = ref();
const mainRef = ref();
const navIs = ref('');
console.debug({ nextIdIndex, previousIdIndex });
// Handle swipe
const { direction } = useSwipe(mainRef, {
onSwipe: (e) => {
console.debug({ e });
const { direction, isSwiping } = useSwipe(mainRef, {
onSwipeEnd: (e) => {
if (isDescendantOf(e.target, agenciesRef.value)) {
e.preventDefault();
e.stopImmediatePropagation();
Expand All @@ -265,25 +262,27 @@ const { direction } = useSwipe(mainRef, {
case 'left':
navIs.value = 'increment';
if (typeof nextIdIndex.value === 'number' && nextIdIndex.value > -1)
router.replace(
`/data-source/${searchStore.mostRecentSearchIds[nextIdIndex.value]}`,
);
router.replace(`/data-source/${getNext()}`);
break;
case 'right':
navIs.value = 'decrement';
if (
typeof previousIdIndex.value === 'number' &&
previousIdIndex.value > -1
)
router.replace(
`/data-source/${searchStore.mostRecentSearchIds[previousIdIndex.value]}`,
);
router.replace(`/data-source/${getPrev()}`);
break;
default:
return;
}
},
});
function getNext() {
return searchStore.mostRecentSearchIds[nextIdIndex.value];
}
function getPrev() {
return searchStore.mostRecentSearchIds[previousIdIndex.value];
}
onMounted(() => {
handleShowMoreButton();
Expand Down
Loading

0 comments on commit 08a0074

Please sign in to comment.