Skip to content

Commit

Permalink
Merge pull request #260 from phyloref/store-info-in-cookies
Browse files Browse the repository at this point in the history
While writing the tutorial, I realized that users currently need to re-enter their name, e-mail address and ORCID every time they create a new Phyx file. This PR changes that so that those four pieces of information -- as well as the default nomenclatural code -- are stored in the users' browser in cookies for 30 days.
  • Loading branch information
gaurav authored Nov 30, 2022
2 parents b263f2e + 5500fc1 commit d3049cd
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 8 deletions.
11 changes: 11 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"newick-js": "^1.1.1",
"popper.js": "^1.16.1",
"vue": "^2.6.11",
"vue-cookies": "^1.8.1",
"vue-resize": "^0.4.5",
"vuex": "^3.5.1",
"x-hub-signature": "^1.2.0"
Expand Down
39 changes: 37 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ import PhyxView from './components/phyx/PhyxView.vue';
import AboutCurationToolModal from './components/modals/AboutCurationToolModal.vue';
import AdvancedOptionsModal from './components/modals/AdvancedOptionsModal.vue';
// Load some configuration options.
import {
COOKIE_ALLOWED,
COOKIE_CURATOR_NAME,
COOKIE_CURATOR_EMAIL,
COOKIE_CURATOR_ORCID,
} from './config';
export default {
name: 'App',
components: {
Expand Down Expand Up @@ -74,6 +82,28 @@ export default {
},
},
created() {
// We store some information as browser cookies so that users don't need to re-enter them
// every time. One of these (the default nomenclatural code) is entirely handled in
// modules/phyx.js.
//
// Three of them need to be set on the default empty Phyx file here:
if (this.$cookies.get(COOKIE_ALLOWED) === 'true') {
if (this.$cookies.get(COOKIE_CURATOR_NAME)) {
this.$store.commit('setCurator', {name: this.$cookies.get(COOKIE_CURATOR_NAME)});
}
if (this.$cookies.get(COOKIE_CURATOR_EMAIL)) {
this.$store.commit('setCurator', {email: this.$cookies.get(COOKIE_CURATOR_EMAIL)});
}
if (this.$cookies.get(COOKIE_CURATOR_ORCID)) {
this.$store.commit('setCurator', {orcid: this.$cookies.get(COOKIE_CURATOR_ORCID)});
}
}
// Reset the "changed" flags (in case the above code changed the Phyx file)
this.$store.commit('setLoadedPhyx');
// If someone tries to navigate away from the window while the
// PHYX has been modified, ask users to confirm before leaving.
// Confirmation message to display to the user. Note that modern
Expand All @@ -82,8 +112,13 @@ export default {
$(window).on('beforeunload', () => {
const confirmationMessage = 'Your modifications have not been saved and will be lost if you close Klados. Confirm to discard your changes, or cancel to return to Klados.';
if (!isEqual(this.loadedPhyx, this.currentPhyx)) return confirmationMessage;
return false;
console.info('beforeUnload() called!');
if (!isEqual(this.loadedPhyx, this.currentPhyx)) {
console.warn('Difference in loadedPhyx and currentPhyx detected, warning user before closing window:', this.loadedPhyx, this.currentPhyx);
return confirmationMessage;
}
return undefined;
});
},
};
Expand Down
21 changes: 19 additions & 2 deletions src/components/phyx/PhyxView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,28 @@
@change="$store.commit('setDefaultNomenCodeURI', { defaultNomenclaturalCodeURI: $event.target.value })"
>
<option
v-for="(nomenCode, nomenCodeIndex) of nomenCodes"
:value="nomenCode.uri"
v-for="nomenCode of nomenCodes"
:value="nomenCode.iri"
>
{{ nomenCode.label }}
</option>
</select>
</div>
</div>

<!-- Checkbox for permission to save this information to browser -->
<div class="form-group row">
<div class="col-md-2">&nbsp;</div>
<div class="col-md-10">
<input type="checkbox"
:checked="cookieCheckbox"
@click="$store.commit('toggleCookieAllowed')"
/>
Save curator information and
default nomenclatural code as a browser cookie (currently for thirty days). If changed to unchecked,
delete Klados cookies from your browser.
</div>
</div>
</form>
</div>
</div>
Expand Down Expand Up @@ -284,6 +298,9 @@ export default {
get() { return this.phyx.curatorORCID; },
set(orcid) { this.$store.commit('setCurator', { orcid }); },
},
cookieCheckbox() {
return this.$store.getters.isCookieAllowed;
},
...mapState({
phyx: state => state.phyx.currentPhyx,
phylorefs: state => state.phyx.currentPhyx.phylorefs,
Expand Down
16 changes: 16 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,20 @@ module.exports = {
// Open Tree Taxonomy IDs
// (https://github.com/OpenTreeOfLife/germinator/wiki/Synthetic-tree-API-v3#induced_subtree)
OPEN_TREE_INDUCED_SUBTREE_URL: 'https://api.opentreeoflife.org/v3/tree_of_life/induced_subtree',

// The default cookie expiry setting (see https://www.npmjs.com/package/vue-cookies for formats)
COOKIE_EXPIRY: '30d', // Expire cookies in 30 days

// Cookie names to use for:
// - the 'allowed' cookie -- if set to 'true', this means that the user has granted us permission
// to store their information in cookies.
COOKIE_ALLOWED: 'kladosCookieAllowed',
// - the default nomenclatural code
COOKIE_DEFAULT_NOMEN_CODE_URI: 'kladosDefaultNomenclaturalCodeURI',
// - curator name
COOKIE_CURATOR_NAME: 'kladosCuratorName',
// - curator e-mail address
COOKIE_CURATOR_EMAIL: 'kladosCuratorEmail',
// - curator ORCID
COOKIE_CURATOR_ORCID: 'kladosCuratorORCID',
};
1 change: 1 addition & 0 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ Vue.prototype.$config = require('./config.js');
// Add additional features to Vue.
Vue.use(BootstrapVue);
Vue.use(VueResize);
Vue.use(require('vue-cookies')); // Use https://www.npmjs.com/package/vue-cookies

// Turn off the Vue production tip on the console on Vue startup.
Vue.config.productionTip = false;
Expand Down
65 changes: 61 additions & 4 deletions src/store/modules/phyx.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,31 @@ import {
OPEN_TREE_ABOUT_URL,
OPEN_TREE_TNRS_MATCH_NAMES_URL,
OPEN_TREE_INDUCED_SUBTREE_URL,

COOKIE_EXPIRY,
COOKIE_ALLOWED, COOKIE_DEFAULT_NOMEN_CODE_URI, COOKIE_CURATOR_NAME, COOKIE_CURATOR_EMAIL, COOKIE_CURATOR_ORCID,
} from '../../config';

// Shared code for reading and writing cookies.

/** Check whether we are allowed to store cookies on this users' browser.
* We determine this based on whether the COOKIE_ALLOWED cookie is set. */
function checkCookieAllowed() {
return (Vue.$cookies.get(COOKIE_ALLOWED) === 'true');
}

/** Get a cookie from the browser (if we're allowed to). */
function getKladosCookie(keyName, valueIfNotSet = undefined) {
if (checkCookieAllowed()) return Vue.$cookies.get(keyName) || valueIfNotSet;
return valueIfNotSet;
}

/** Set a cookie on the browser (if we're allowed to). */
function setKladosCookie(keyName, value, expiry = COOKIE_EXPIRY) {
// Only set the cookie if we are allowed (the COOKIE_ALLOWED is set).
if (checkCookieAllowed()) Vue.$cookies.set(keyName, value, expiry);
}

export default {
state: {
// The currently loaded Phyx file. All methods modify and change this variable.
Expand All @@ -39,8 +62,10 @@ export default {
return !isEqual(state.currentPhyx, state.loadedPhyx);
},
getDefaultNomenCodeURI(state) {
// If no default nomenclatural code is set in the Phyx file, we will attempt to look up that information
// using a cookie.
return state.currentPhyx.defaultNomenclaturalCodeURI
|| TaxonNameWrapper.UNKNOWN_CODE;
|| getKladosCookie(COOKIE_DEFAULT_NOMEN_CODE_URI, TaxonNameWrapper.UNKNOWN_CODE);
},
getDownloadFilenameForPhyx(state) {
// Return a filename to be used to name downloads of this Phyx document.
Expand Down Expand Up @@ -69,8 +94,28 @@ export default {
if (phylorefLabels.length === 3) return `${phylorefLabels[0]}_${phylorefLabels[1]}_and_${phylorefLabels[2]}`;
return `${phylorefLabels[0]}_${phylorefLabels[1]}_and_${phylorefLabels.length - 2}_others`;
},
isCookieAllowed() {
// Checks to see if cookies are allowed. We can check this by seeing if a cookie named
// COOKIE_ALLOWED is set.
return checkCookieAllowed();
},
},
mutations: {
toggleCookieAllowed(state) {
if (checkCookieAllowed()) {
// Cookie allowed! Toggle it by deleting all Klados cookies.
Vue.$cookies.keys().forEach(key => Vue.$cookies.remove(key));
} else {
// Cookie not allowed! Toggle it to cookie allowed. We don't use setKladosCookie() because
// it includes a check for COOKIE_ALLOWED; instead, we set it directly.
Vue.$cookies.set(COOKIE_ALLOWED, 'true', COOKIE_EXPIRY);

// Then, save all current curator information.
setKladosCookie(COOKIE_CURATOR_NAME, state.currentPhyx.curator || '');
setKladosCookie(COOKIE_CURATOR_EMAIL, state.currentPhyx.curatorEmail || '');
setKladosCookie(COOKIE_CURATOR_ORCID, state.currentPhyx.curatorORCID || '');
}
},
setCurrentPhyx(state, phyx) {
// Replace the current Phyx file using an object. This method does NOT
// update the loaded Phyx file, so these changes are treated as changes
Expand Down Expand Up @@ -131,6 +176,9 @@ export default {
throw new Error('No default nomenclatural code URI provided to setDefaultNomenCodeURI');
}

// Overwrite the current default nomenclatural code cookie.
setKladosCookie(COOKIE_DEFAULT_NOMEN_CODE_URI, payload.defaultNomenclaturalCodeURI);

Vue.set(state.currentPhyx, 'defaultNomenclaturalCodeURI', payload.defaultNomenclaturalCodeURI);
},
duplicatePhyloref(state, payload) {
Expand All @@ -144,9 +192,18 @@ export default {
},
setCurator(state, payload) {
// Set the curator name, e-mail address or (eventually) ORCID.
if (has(payload, 'name')) Vue.set(state.currentPhyx, 'curator', payload.name);
if (has(payload, 'email')) Vue.set(state.currentPhyx, 'curatorEmail', payload.email);
if (has(payload, 'orcid')) Vue.set(state.currentPhyx, 'curatorORCID', payload.orcid);
if (has(payload, 'name')) {
setKladosCookie(COOKIE_CURATOR_NAME, payload.name);
Vue.set(state.currentPhyx, 'curator', payload.name);
}
if (has(payload, 'email')) {
setKladosCookie(COOKIE_CURATOR_EMAIL, payload.email);
Vue.set(state.currentPhyx, 'curatorEmail', payload.email);
}
if (has(payload, 'orcid')) {
setKladosCookie(COOKIE_CURATOR_ORCID, payload.orcid);
Vue.set(state.currentPhyx, 'curatorORCID', payload.orcid);
}
},
},
actions: {
Expand Down

0 comments on commit d3049cd

Please sign in to comment.