From e0b56962d260563ce285c96207e573fe8806d251 Mon Sep 17 00:00:00 2001
From: xaralis <filip.varecha@fragaria.cz>
Date: Sun, 2 Aug 2020 13:19:42 +0200
Subject: [PATCH] Persist selected view in URL on elections page

---
 .../_patterns/03-templates/elections.mustache |  2 +-
 source/js/components/ViewProvider.vue         | 54 +++++++++++++++----
 2 files changed, 46 insertions(+), 10 deletions(-)

diff --git a/source/_patterns/03-templates/elections.mustache b/source/_patterns/03-templates/elections.mustache
index d335c82..85451e5 100644
--- a/source/_patterns/03-templates/elections.mustache
+++ b/source/_patterns/03-templates/elections.mustache
@@ -2,7 +2,7 @@
 {{> organisms-elections-hero }}
 
 <div class="__js-root">
-  <ui-view-provider :initial="{candidates: true, program: false}" v-slot="{ isCurrentView, toggleView }">
+  <ui-view-provider :initial="{candidates: true, program: false}" :sync-location="true" v-slot="{ isCurrentView, toggleView }">
     <main>
       <div class="container container--default pt-8 lg:py-24">
         <div class="text-center">
diff --git a/source/js/components/ViewProvider.vue b/source/js/components/ViewProvider.vue
index 2aeb094..9b66dd3 100644
--- a/source/js/components/ViewProvider.vue
+++ b/source/js/components/ViewProvider.vue
@@ -4,6 +4,7 @@
       v-bind:views="views"
       v-bind:isCurrentView="isCurrentView"
       v-bind:toggleView="toggleView"
+      v-bind:showView="showView"
       v-bind:setView="setView"
     ></slot>
   </div>
@@ -14,11 +15,20 @@ export default {
   props: {
     initial: {
       default: () => {}
+    },
+    syncLocation: {
+      type: Boolean,
+      default: false,
+    },
+    locationParam: {
+      type: String,
+      default: "view",
     }
   },
   data() {
     return {
       views: this.$props.initial,
+      queryParams: null,
       keyListener: e => {
         // Esc
         if (e.keyCode === 27) {
@@ -27,21 +37,38 @@ export default {
       }
     };
   },
+  watch: {
+    routeView() {
+      const queryParams = new URLSearchParams(window.location.search);
+    }
+  },
   methods: {
-    setView(viewId, show) {
+    setView(viewId, show, hideOthers = false) {
+      if (hideOthers) {
+        Object.keys(this.$data.views).forEach(key => {
+          if (key !== viewId) {
+            this.setView(key, false);
+          }
+        });
+      }
+
       this.$data.views[viewId] = show;
+
+      if (show && this.$props.syncLocation) {
+        const queryParams = new URLSearchParams(window.location.search);
+
+        queryParams.set(this.$props.locationParam, viewId);
+        history.pushState(null, null, "?" + queryParams.toString());
+      }
     },
     setViews(updates) {
       this.$data.views = Object.assign({}, this.data.views, updates);
     },
     toggleView(viewId) {
-      Object.keys(this.$data.views).forEach(key => {
-        if (key !== viewId) {
-          this.setView(key, false);
-        }
-      });
-
-      this.setView(viewId, !this.isCurrentView(viewId));
+      this.setView(viewId, !this.isCurrentView(viewId), true);
+    },
+    showView(viewId) {
+      this.setView(viewId, true, true);
     },
     isCurrentView(viewId) {
       return this.$data.views[viewId];
@@ -53,7 +80,16 @@ export default {
     }
   },
   mounted() {
-    window.addEventListener('keydown', this.$data.keyListener);;
+    window.addEventListener('keydown', this.$data.keyListener);
+
+    if (this.$props.syncLocation) {
+      const queryParams = new URLSearchParams(window.location.search);
+      const locationView = queryParams.get(this.$props.locationParam);
+
+      if (Object.keys(this.$data.views).indexOf(locationView) !== -1) {
+        this.showView(locationView);
+      }
+    }
   },
   destroyed() {
     window.removeEventListener('keydown', this.$data.keyListener);
-- 
GitLab