Skip to content

Instantly share code, notes, and snippets.

@Alex-Bakic
Last active November 5, 2019 01:15
Show Gist options
  • Save Alex-Bakic/58fad658206bd8db4ee183f983270f3b to your computer and use it in GitHub Desktop.
Save Alex-Bakic/58fad658206bd8db4ee183f983270f3b to your computer and use it in GitHub Desktop.

Mini walkthrough of the reloading issue...

For the moment , with the like button on job cards, when they are clicked they do not trigger reloads of the recommended or dashboard pages, contrary to the blacklist button. What blacklist does is take the job out of the sub-db path [:wh.logged-in.personalised-jobs.db/sub-db ▶{..., :wh.logged-in.personalised-jobs.db/jobs [{} , ... , {}]}] and puts it in the blacklisted ▶{:wh.user.db/sub-db {:wh.user.db/blacklist #{"remote-junior-maker-of-everything-dd48b"}}} section. ::toggle-job-like does the same, but the difference being blacklist will recall either the dashboard or the recommended page to show that it has been removed:

(reg-event-fx
  ::blacklist-job
  db/default-interceptors
  (fn [{db :db} [{:keys [id] :as job} action]]
      {:graphql         {:query      blacklist-job-mutation
                         :variables  {:id id}
                         ;; in the job.cljc file, on-close is passed into blacklist, allowing it to close the job
                         ;; on the relevant page.
                         :on-success (if (= action :reload-recommended)
                                        [:personalised-jobs/fetch-jobs-by-type :recommended 1]
                                        ;; need to refer by full name since it's in another module
                                        [:wh.logged-in.dashboard.events/fetch-recommended-jobs])}
       :analytics/track ["Job Blacklisted" job]}))

So in the case that graphql manages to mutate the persistent storage, which will be reflected in re-frame, we'll recall the approriate page. So by adding the on-close from job.cljc we should be able to add this functionality into the like event:

;; event which moves the job into the liked section, to be shown in the liked page...
;; changing toggle-like-job-success to a general event, this is because of the event chain itself.
;; graphql needs to be triggered first , for assurance that the mutations are in effect. Having them in the same event
;; causes complications if they are not one after another, which isn't always the case. But by separating they will run
;; one after another, it is simply a matter of delay between them.
(reg-event-fx
  ::toggle-job-like-success
  db/default-interceptors
  (fn [{db :db} [id action]]
      {:db (update-in db [:wh.user.db/sub-db :wh.user.db/liked-jobs] util/toggle id)
       :dispatch (case action
                    :reload-recommended [:personalised-jobs/fetch-jobs-by-type :recommended 1]
                    :reload-dashboard [:wh.logged-in.dashboard.events/fetch-recommended-jobs]
                    ;; this is the else clause, as it will cause the personalisations in the liked-jobs page
                    ;; to be re-rendered , showing that it is no longer there , being moved to recommended.
                    [:personalised-jobs/fetch-jobs-by-type :recommended 1])}))

(reg-event-fx
  ::toggle-job-like
  db/default-interceptors
  (fn [{db :db} [{:keys [id] :as job} action]]
     (let [liked (contains? (get-in db [:wh.user.db/sub-db :wh.user.db/liked-jobs]) id)
          event-name (str "Job " (if liked "Removed Like" "Liked"))]
       {:graphql         {:query      like-job-mutation
                          :variables  {:id id, :add (not liked)}
                          :on-success [::toggle-job-like-success id]}
        :analytics/track [event-name job]})))

There are a few problems with this code though... when we go to the liked page, and click to "unlike" a job it will re-render and you will no longer see the job, which is ideal; however, for the other way round , clicking "like" in the dashboard doesn't work as if will evaluate for the case of :reload-recommended. Flipping doesn't solve the problem, as we get the inverse of the issue, but also another facet of the issue is that job cards will be presented in many different parts of the app, under the blog posts, under company profiles etc. But say we don't want jobs to re-render for these cases, we should use case to allow for liking and unliking to work appropriately.

case is important for extensibility , for all the other pages that we want to re-render (if we so choose to). It also helps when bouncing around pages, as we don't have to worry about the order of if. The liked jobs page for example doesn't come under either clause though, so when we "unlike" the job it will mean the page isn't re-rendered and we still see the job. To avoid complications that arise when a user then reclicks this job (when the page should have been re-rendered and the card removed) it needs it's own clause. Once the liked page has it's own clause then it can re-render properly, not using the above , and allow the same functionality as blacklist.

Now then, looking in the page-mappings, it shows that the liked page is just a wrapper of the page function, found in: client/client/src/wh/logged_in/personalised_jobs/views.cljs . It will differ the necessary on-close by taking an argument called type-of-jobs. So for the :liked keyword we can specify the :reload-liked keyword for ::toggle-job-like-success to reload the right thing.

;; for now this can be just an additional when clause beneath the other one, though
;; we may need a cond here, with the :else being an empty map. Or maybe a separate fn
(when (= type-of-jobs :liked) {:on-close :reload-liked})

We've already got a fn which does the work of fetching jobs by type , which includes :liked, so all we have to do is call [:personalised-jobs/fetch-jobs-by-type :liked 1] in our ::toggle-job-like-success, replacing the buggy else clause:

(reg-event-fx
  ::toggle-job-like-success
  db/default-interceptors
  (fn [{db :db} [id action]]
      {:db (update-in db [:wh.user.db/sub-db :wh.user.db/liked-jobs] util/toggle id)
       :dispatch (case action
                    :reload-recommended [:personalised-jobs/fetch-jobs-by-type :recommended 1]
                    :reload-dashboard [:wh.logged-in.dashboard.events/fetch-recommended-jobs]
                    ;; this is the new addition, which handles the like-job page, and fetch-jobs-by-type
                    ;; does the work of re-rendering the page.
                    :reload-liked [:personalised-jobs/fetch-jobs-by-type :liked 1])}))

And with that, we're done (hopefully!) .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment