Skip to content

Commit

Permalink
Initial groundwork for DM Screen / Campaign UI (#103)
Browse files Browse the repository at this point in the history
* Add routing for DM screens ("campaigns")

Refs #69

* Scaffold out Campaign pages

Refs #69

* Add initial campaign creation UI/UX

* Include campaigns in "query-sheets" results; implement :known-campaigns

* Add preliminary chars carousel widget

Refs #69

Mostly just ensures sheets are loaded; styling to come... eventually

* Persist sheet type properly from `:put-sheet!`

* Introduce reg-id-sub that supports passing the sheet-id of interest

Refs #69

This is not 100% bullet-proof, but it's relatively painless to use in
place of an existing subscription, and it allows those subscriptions to
*optionally* be used with an arbitrary sheet-id, for use on character
cards for a campaign page.

* Fix merge error

* Implement some core styling for chars carousel, hp bar, etc.

Refs #69

The character card is starting to look useful!

* Compute smooth color transitions for the HP bar

* Add a nice CSS transition on the HP bar

* Scaffold out campaign invitation

Refs #69

Basically the DM has to add them to the DM sheet, then the player has to
open a special "invite" link to "accept" (IE: save the "campaign" field
in their own sheet).

Sort of an extra step, but reasonable, I think.

* Fix ::limited-use being an id-sub

* Support including campaign name in invite URLs

Also makes it possible to hot-swap routes, which is just fantastic

* Sketch out UI for joining a campaign

* Implement event flow for joining a campaign

We'd probably like to expand the "update-notifier" functionality to be
more general so we can show "Campaign joined!" or something as we enter
the sheet page

* Refactor to have a more general notifiers system

* Fix typo

* Show notification when joining/leaving a campaign

* Move Campaign events/subs to own file; support add/remove members

Refs #69

* Add campaign invite instructions + some minor style improvements

* Sort others' characters before your own in "add" screen

* Show notifiers above overlays

* Move "add character" button to the end of the carousel

* Add some placeholders and a link to the Campaign UI ticket

It's about time for this branch to get merged; there's a ton of
refactoring in it already; all the remaining features can be done
in one or more seperate branches.

The only thing we really need to do before merging is allow players
to detach the campaign from their character.

* Add a widget in the Builder for leaving the current campaign
  • Loading branch information
dhleong committed Feb 10, 2019
1 parent 116af6a commit c5c9ae4
Show file tree
Hide file tree
Showing 37 changed files with 1,143 additions and 180 deletions.
1 change: 1 addition & 0 deletions dev/cljs/wish/config.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
^boolean goog.DEBUG)

(def server-root "")
(def full-url-root (str "http://localhost:3450" server-root))

(def gdrive-client-id "661182319990-1uerkr0pue6k60a83atj2f58md95fb1b.apps.googleusercontent.com")

Expand Down
119 changes: 112 additions & 7 deletions less/site.less
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ a {
cursor: pointer;
}

.metadata() {
font-size: 80%;
}

.scrollable() {
overflow-y: scroll;
.box-shadow(inset 0 -8px 12px -4px fade(#333, 50%));
Expand Down Expand Up @@ -189,10 +193,14 @@ a {
}

.metadata {
font-size: 80%;
.metadata();
}
}

.group {
margin: 8px 0;
}

.sections {
.flex(wrap);
.justify-content(center);
Expand Down Expand Up @@ -259,13 +267,20 @@ a {
margin-top: 12px;
}

.update-notifier {
.notifiers {
@media @smartphones {
left: 0;
right: 0;
bottom: 0;
}

position: fixed;
right: 24px;
bottom: 24px;
z-index: 2;
}

.notifier {
@keyframes slide-in {
from {
transform: translateY(100%);
Expand All @@ -282,13 +297,11 @@ a {
background-color: #666666;
color: #fff;

position: fixed;
right: 24px;
bottom: 24px;

padding: 4px;
vertical-align: center;

margin-top: 8px;

.ignore {
.justify-content(center);

Expand All @@ -307,12 +320,104 @@ a {
.flex-grow();
}

.update {
.action {
margin-right: 8px;
padding: 8px;
}
}

//
// Campaign screen widgets

.add-chars-overlay {
padding: 32px;

.desc {
.metadata();
padding: 8px;
}

.character {
.flex();
.align-items(center);

width: 100%;
margin: 8px 0;

.name {
width: 45%;
}
}
}

.carousel-container {
width: 100%;
overflow-x: auto;

.carousel {
.flex();

a.add-button {
.flex();
.flex-direction(row);
.align-items(center);

padding: 8px;
}

a.card {
color: inherit;
margin: 8px 4px;
padding: 0px;
}
div.card {
background-color: #eee;
border-radius: 4px;
padding: 8px;
text-align: center;
width: 220px;

&:hover {
background-color: #ddd;
}

&:active {
background-color: #ccc;
}
}
}
}

.hp-bar {
@height: 32pt;

position: relative;
background-color: #fcfcfc;
border-radius: 4px;
height: @height;
margin: 8px 0;

.bar {
position: absolute;
left: 0;
top: 0;
bottom: 0;
border-radius: 4px;

transition: all 450ms cubic-bezier(0, 0, 0.2, 1);
}

.label {
font-size: 16pt;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
line-height: @height;
}
}

//
// shared widgets

Expand Down
3 changes: 3 additions & 0 deletions prod/cljs/wish/config.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
; IE: https://dhleong.github.io/wish
(def server-root "/wish")

; TODO good-define?
(def full-url-root (str "https://dhleong.github.io" server-root))

(def gdrive-client-id "661182319990-3aa8akj9fh8eva9lf7bt02621q2i18s6.apps.googleusercontent.com")

(def push-server "https://wish-server.now.sh")
4 changes: 3 additions & 1 deletion src/cljs/wish/db.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,6 @@

::save-errors #{}
::pending-saves #{}
::processing-saves #{}})
::processing-saves #{}

:notifications {}})
43 changes: 41 additions & 2 deletions src/cljs/wish/events.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
:dispatch-n [[::update-keymap page-spec]
[:push/check]]}))

(reg-event-fx
:nav/replace!
[trim-v]
(fn-traced [_ [new-location]]
{:nav/replace! new-location}))

(reg-event-db
:set-device
[trim-v]
Expand Down Expand Up @@ -135,6 +141,36 @@
:ready)}))


; ======= notifications ===================================

(reg-event-fx
:notify!
[trim-v]
(fn [{:keys [db]} [{:keys [duration duration-ms content
dismissable?]
:or {dismissable? true}}]]
(let [created (js/Date.now)
id (keyword (str created))]
{:db (assoc-in db [:notifications id]
{:id id
:created created
:content content
:dismiss-event (when (or (nil? duration)
dismissable?)
[::remove-notify! id])})
:dispatch-later [(when (or duration duration-ms)
{:ms (case duration
:short 3000
:long 7500
duration-ms)
:dispatch [::remove-notify! id]})]})))

(reg-event-db
::remove-notify!
[trim-v (path :notifications)]
(fn-traced [notifications [id]]
(dissoc notifications id)))


; ======= Provider management ==============================

Expand Down Expand Up @@ -259,7 +295,11 @@
[trim-v]
(fn-traced [{:keys [db]} [sheet-id sheet]]
{:db (-> db
(assoc-in [:sheets sheet-id] sheet)
(update-in [:sheets sheet-id]
(fn [old-value]
(merge
(select-keys old-value [:type])
sheet)))
(reset-sheet-err sheet-id))

; NOTE: we're probably on a :sheet page, and we might not have
Expand Down Expand Up @@ -757,4 +797,3 @@
(when (contains? changed-ids active-sheet-id)
; trigger sheet data reload
{:load-sheet! active-sheet-id})))

4 changes: 4 additions & 0 deletions src/cljs/wish/fx.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
(log "document.title <-" title)
(set! js/document.title title)))

(reg-fx
:nav/replace!
nav/replace!)


; ======= keymaps =========================================

Expand Down
19 changes: 12 additions & 7 deletions src/cljs/wish/providers.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,20 @@
(let [[provider-id _] (unpack-id sheet-id)]
(provider-key provider-id :share!)))

(defn create-sheet-with-data
"Returns a channel that emits [err sheet-id] on success"
[sheet-name provider-id data]
(defn create-file-with-data
"Returns a channel that emits [err sheet-id] on success.
`kind` may be one of:
- :campaign
- :sheet"
[kind sheet-name provider-id data]
{:pre [(not (nil? provider-id))
(not (nil? data))]}
(not (nil? data))
(contains? #{:campaign :sheet} kind)]}
(if-let [inst (provider-key provider-id :inst)]
(provider/create-sheet inst
sheet-name
data)
(provider/create-file inst
kind
sheet-name
data)

(throw (js/Error. (str "No provider instance for " provider-id)))))

Expand Down
4 changes: 2 additions & 2 deletions src/cljs/wish/providers/caching.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@
(deftype CachingProvider [base my-id storage dirty?-storage]
IProvider
(id [this] my-id)
(create-sheet [this file-name data]
(provider/create-sheet base file-name data))
(create-file [this kind file-name data]
(provider/create-file base kind file-name data))

(init! [this]
(go (let [base-state (or (<! (<!timeout (provider/init! base)))
Expand Down
9 changes: 6 additions & 3 deletions src/cljs/wish/providers/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@
See the comments on `:provider-states` in `db.cljs` for all acceptable
states.")

(create-sheet
[this sheet-name data]
"Create a new sheet with the given name and data")
(create-file
[this kind sheet-name data]
"Create a new file with the given name, kind, and data.
`kind` will be one of:
- :sheet
- :campaign")

(load-raw
[this id]
Expand Down
26 changes: 19 additions & 7 deletions src/cljs/wish/providers/gdrive.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
["https://www.googleapis.com/auth/drive.file"
"https://www.googleapis.com/auth/drive.install"]))

(def ^:private campaign-desc "WISH Campaign")
(def ^:private campaign-mime "application/edn")
(def ^:private campaign-props {:wish-type "wish-campaign"})
(def ^:private sheet-desc "WISH Character Sheet")
(def ^:private sheet-mime "application/edn")
(def ^:private sheet-props {:wish-type "wish-sheet"})
Expand Down Expand Up @@ -431,18 +434,25 @@

; ======= Provider def =====================================

(defn- meta-for [kind file-name]
(let [base (case kind
:campaign {:description campaign-desc
:mimeType campaign-mime
:appProperties campaign-props}
:sheet {:description sheet-desc
:mimeType sheet-mime
:appProperties sheet-props})]
(assoc base :name file-name)))

(deftype GDriveProvider []
IProvider
(id [this] :gdrive)

(create-sheet [this file-name data]
(log/info "Create sheet " file-name)
(create-file [this kind file-name data]
(log/info "Create " kind ": " file-name)
(go (let [[err resp] (<! (upload-data
:create
{:name file-name
:description sheet-desc
:mimeType sheet-mime
:appProperties sheet-props}
(meta-for kind file-name)
(str data)))]
(if err
[err nil]
Expand Down Expand Up @@ -500,7 +510,9 @@
(query-sheets [this]
(when-gapi-available
query-files
"appProperties has { key='wish-type' and value='wish-sheet' }"))
#_"appProperties has { key='wish-type' and value='wish-sheet' }"
(str "(appProperties has { key='wish-type' and value='wish-sheet' }) "
"or (appProperties has { key='wish-type' and value='wish-campaign' })")))

(register-data-source [this]
; TODO sanity checks galore
Expand Down
Loading

0 comments on commit c5c9ae4

Please sign in to comment.