Skip to content

Commit

Permalink
feat: add v2 feature gating
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuagraber committed Dec 26, 2024
1 parent bac5080 commit f339050
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 24 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
16 changes: 15 additions & 1 deletion 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 @@ -91,6 +104,7 @@ 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
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
2 changes: 1 addition & 1 deletion client/src/pages/profile/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export const useProfileData = defineBasicLoader(
const response = await getUser();
return response.data.data;
},
{ lazy: true },
// { lazy: true },
);
</script>

Expand Down
20 changes: 4 additions & 16 deletions client/src/pages/search/results.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<!-- Follow -->
<div
v-if="!isFollowed"
v-if="!isFollowed && getIsV2FeatureEnabled('ENHANCED_SEARCH')"
class="flex flex-col md:items-end md:row-start-1 md:row-span-2 md:col-start-2 md:col-span-1"
>
<Button
Expand Down Expand Up @@ -134,7 +134,7 @@
// Data loader
import { defineBasicLoader } from 'unplugin-vue-router/data-loaders/basic';
import { useSearchStore } from '@/stores/search';
import { NavigationResult } from 'unplugin-vue-router/runtime';
// import { NavigationResult } from 'unplugin-vue-router/runtime';
import { onMounted, onUnmounted, onUpdated, reactive, ref, watch } from 'vue';
import { ALL_LOCATION_TYPES } from '@/util/constants';
import {
Expand Down Expand Up @@ -242,14 +242,10 @@ import { faUserPlus, faUserCheck } from '@fortawesome/free-solid-svg-icons';
import { toast } from 'vue3-toastify';
import { useAuthStore } from '@/stores/auth';
import { useRoute, useRouter } from 'vue-router';
import { getIsV2FeatureEnabled } from '@/util/featureFlagV2';
const { isAuthenticated } = useAuthStore();
const {
data: searchData,
isLoading,
error,
reload: reloadSearch,
} = useSearchData();
const { data: searchData, isLoading, error } = useSearchData();
const { data: isFollowed, reload: reloadFollowed } = useFollowedData();
const { data: requestData, error: requestsError } = useRequestsData();
const route = useRoute();
Expand All @@ -259,8 +255,6 @@ const isSearchShown = ref(false);
const dims = reactive({ width: window.innerWidth, height: window.innerHeight });
const hasDisplayedErrorByRouteParams = ref(new Map());
// watch(() => route.query, reloadSearch);
watch(
() => route,
(newRoute) => {
Expand All @@ -272,12 +266,6 @@ watch(
{ immediate: true, deep: true },
);
// On initial fetch - get hash
// const hash = normalizeLocaleForHash(searched, response.data);
// if (!route.hash && hash) {
// return new NavigationResult({ ...route, hash: `#${hash}` });
// }
// lifecycle methods
onMounted(() => {
if (window.innerWidth > 1280) isSearchShown.value = true;
Expand Down
2 changes: 1 addition & 1 deletion client/src/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ router.beforeEach(async (to, from, next) => {
if (to.meta?.auth && !auth.isAuthenticated()) {
auth.$patch({ redirectTo: to });

next({ path: '/sign-in', replace: true });
next({ path: '/sign-in' });
} else {
next();
}
Expand Down
14 changes: 14 additions & 0 deletions client/src/util/featureFlagV2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Gets enabled / disabled status for features.
*
* @param {'ENHANCED_SEARCH' | 'AUTHENTICATE' | 'CREATE_RECORDS'} featureName Name of V2 feature to check
* @returns {boolean} Whether the feature is enabled or not
*/
export function getIsV2FeatureEnabled(featureName) {
console.debug({
featureName,
value: import.meta.env[`VITE_V2_FEATURE_${featureName}`],
bool: import.meta.env[`VITE_V2_FEATURE_${featureName}`] === 'enabled',
});
return import.meta.env[`VITE_V2_FEATURE_${featureName}`] === 'enabled';
}
19 changes: 18 additions & 1 deletion client/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import VueRouter from 'unplugin-vue-router/vite';
import path from 'path';

export default defineConfig(({ mode }) => {
loadEnv(mode, process.cwd(), '');
const env = loadEnv(mode, process.cwd(), '');

console.debug({ auth: env.VITE_V2_FEATURE_AUTHENTICATE });

return {
plugins: [
Expand All @@ -18,6 +20,21 @@ export default defineConfig(({ mode }) => {
route.meta = { ...route.meta, ...ROUTES_TO_META.get(route.name) };
}

// Hide authentication routes if flag set to disabled
if (
env.VITE_V2_FEATURE_AUTHENTICATE === 'disabled' &&
[
'change-password',
'reset-password',
'sign-in',
'sign-out',
'sign-up',
'profile',
].some((pathFrag) => route.fullPath.includes(pathFrag))
) {
route.delete();
}

if (route.fullPath.startsWith('/test/') && mode === 'production') {
route.delete();
}
Expand Down

0 comments on commit f339050

Please sign in to comment.