diff options
author | Raphael Kabo <raphaelkabo@hey.com> | 2023-10-09 19:22:39 +0100 |
---|---|---|
committer | Raphael Kabo <raphaelkabo@hey.com> | 2023-10-09 19:22:39 +0100 |
commit | 7fe1f42d56edb98875399b1da5e9b7e972209a0d (patch) | |
tree | 6f96696b583e4fab1a2d1f54a2f99bcee3267c04 | |
parent | dbbb94117c2d6266cfc45a091b4b87012024f788 (diff) |
Add known group linker to event form
-rwxr-xr-x | public/css/style.css | 41 | ||||
-rw-r--r-- | public/images/seigaiha-single.png | bin | 0 -> 3463 bytes | |||
-rw-r--r-- | public/js/modules/event-edit.js | 7 | ||||
-rw-r--r-- | public/js/modules/group-linker.js | 85 | ||||
-rw-r--r-- | src/routes/group.ts | 60 | ||||
-rwxr-xr-x | views/newevent.handlebars | 13 | ||||
-rw-r--r-- | views/partials/editeventmodal.handlebars | 12 | ||||
-rwxr-xr-x | views/partials/eventForm.handlebars | 36 |
8 files changed, 243 insertions, 11 deletions
diff --git a/public/css/style.css b/public/css/style.css index 8e6322e..04d6e97 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -405,3 +405,44 @@ article.static-page header { margin-bottom: 1rem; border-bottom: 1px solid #e0e0e0; } + +.card--group-preview { + display: grid; + grid-template-columns: 60px 1fr; + overflow: hidden; + gap: 1rem; + + transition: background-color 0.15s; +} + +.card--group-preview:hover { + background-color: #f5f5f5; +} + +.card--group-preview img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.card--group-preview__text { + text-decoration: none; + color: #1b1b1b; + overflow: hidden; + padding-right: 1rem; + display: flex; + flex-direction: column; + justify-content: center; +} + +.card--group-preview__text strong, +.card--group-preview__text p { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; + margin: 0; +} + +.card--group-preview:hover { + text-decoration: none; +} diff --git a/public/images/seigaiha-single.png b/public/images/seigaiha-single.png Binary files differnew file mode 100644 index 0000000..e963ad6 --- /dev/null +++ b/public/images/seigaiha-single.png diff --git a/public/js/modules/event-edit.js b/public/js/modules/event-edit.js index 65d9889..0a295cb 100644 --- a/public/js/modules/event-edit.js +++ b/public/js/modules/event-edit.js @@ -47,6 +47,13 @@ function editEventForm() { this.data.timezone = event.target.value; }); this.data.timezone = this.select2.val(); + + // Set checkboxes + this.data.eventGroupCheckbox = window.eventData.eventGroupID !== ""; + this.data.interactionCheckbox = window.eventData.usersCanComment; + this.data.joinCheckbox = window.eventData.usersCanAttend; + this.data.maxAttendeesCheckbox = + window.eventData.maxAttendees !== null; }, async submitForm() { this.submitting = true; diff --git a/public/js/modules/group-linker.js b/public/js/modules/group-linker.js new file mode 100644 index 0000000..ca5e159 --- /dev/null +++ b/public/js/modules/group-linker.js @@ -0,0 +1,85 @@ +function eventGroupLinker() { + return { + data: { + eventGroupID: "", + eventGroupEditToken: "", + groups: [], + }, + async init() { + this.$watch("data.eventGroupID", () => { + this.$dispatch( + "event-group-id-changed", + this.data.eventGroupID, + ); + }); + this.$watch("data.eventGroupEditToken", () => { + this.$dispatch( + "event-group-edit-token-changed", + this.data.eventGroupEditToken, + ); + }); + if (window.eventData && window.eventData.eventGroupID !== "") { + this.data.eventGroupID = window.eventData.eventGroupID; + } + if (window.eventData && window.eventGroupEditToken !== "") { + this.data.eventGroupEditToken = + window.eventData.eventGroupEditToken; + } + try { + const editTokens = JSON.parse( + localStorage.getItem("editTokens"), + ); + if (!editTokens) { + return; + } + const response = await fetch("/known/groups", { + method: "POST", + body: JSON.stringify(editTokens), + headers: { + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + return; + } + const json = await (await response).json(); + this.data.groups = json; + } catch (e) { + return false; + } + }, + selectGroup(e) { + const group = this.data.groups.find( + (group) => group.id === e.target.value, + ); + if (!group) { + this.data.eventGroupID = ""; + this.data.eventGroupEditToken = ""; + return; + } + this.data.eventGroupID = group.id; + this.data.eventGroupEditToken = group.editToken; + }, + showGroupPreview() { + return ( + this.data.eventGroupID !== "" && + this.data.groups.some( + (group) => + group.id === this.data.eventGroupID && + group.editToken === this.data.eventGroupEditToken, + ) + ); + }, + groupPreview() { + if (!this.showGroupPreview()) { + return {}; + } + return this.data.groups.find( + (group) => group.id === this.data.eventGroupID, + ); + }, + resetGroupSelector() { + this.$refs.eventGroupSelect.value = ""; + }, + }; +} diff --git a/src/routes/group.ts b/src/routes/group.ts index 2801248..40dcccb 100644 --- a/src/routes/group.ts +++ b/src/routes/group.ts @@ -7,6 +7,8 @@ import Jimp from "jimp"; import { addToLog } from "../helpers.js"; import EventGroup from "../models/EventGroup.js"; import { sendEmailFromTemplate } from "../lib/email.js"; +import { marked } from "marked"; +import { renderPlain } from "../util/markdown.js"; const config = getConfig(); @@ -237,4 +239,62 @@ router.put( }, ); +// Accepts a JSON object of event/group IDs mapped to edit tokens. +// Returns an object of basic group data for each of the IDs +// which are valid groups and have an edit token which matches. +router.post("/known/groups", async (req: Request, res: Response) => { + const known = req.body; + if (!known) { + return res.status(400).json({ + errors: [ + { + message: "No known IDs were provided.", + }, + ], + }); + } + + try { + const knownIDs = Object.keys(known); + const groups = await EventGroup.find({ + id: { $in: knownIDs }, + }); + const knownGroups = groups.filter((group) => { + return group.editToken === known[group.id]; + }); + const groupData = knownGroups.map((group) => { + return { + id: group.id, + name: group.name, + description: marked + .parse(group.description, { + renderer: renderPlain(), + }) + .split(" ") + .splice(0, 40) + .join(" ") + .trim(), + image: group.image, + editToken: group.editToken, + url: `/group/${group.id}`, + }; + }); + return res.status(200).json(groupData); + } catch (err) { + console.error(err); + addToLog( + "getKnownGroups", + "error", + "Attempt to get known groups failed with error: " + err, + ); + return res.status(500).json({ + errors: [ + { + message: err, + }, + ], + }); + } +}); + export default router; diff --git a/views/newevent.handlebars b/views/newevent.handlebars index a3b35b3..d8d2f28 100755 --- a/views/newevent.handlebars +++ b/views/newevent.handlebars @@ -19,7 +19,15 @@ <div id="newEventFormContainer"> <h4 class="mb-2">Create an event</h4> - <form id="newEventForm" enctype="multipart/form-data" x-data="newEventForm()" x-init="init()" @submit.prevent="submitForm"> + <form + id="newEventForm" + enctype="multipart/form-data" + x-data="newEventForm()" + x-init="init()" + @submit.prevent="submitForm" + @event-group-id-changed="data.eventGroupID = $event.detail" + @event-group-edit-token-changed="data.eventGroupEditToken = $event.detail" + > {{>eventForm}} <div class="form-group row"> <div class="col-sm-12 pt-3 pb-3 text-center"> @@ -55,4 +63,5 @@ </article> <script src="/js/generate-timezones.js"></script> -<script src="/js/modules/new.js"></script>
\ No newline at end of file +<script src="/js/modules/new.js"></script> +<script src="/js/modules/group-linker.js"></script>
\ No newline at end of file diff --git a/views/partials/editeventmodal.handlebars b/views/partials/editeventmodal.handlebars index a36cd98..a9fe626 100644 --- a/views/partials/editeventmodal.handlebars +++ b/views/partials/editeventmodal.handlebars @@ -8,8 +8,15 @@ </button> </div> <div class="modal-body"> - <form id="editEventForm" enctype="multipart/form-data" x-data="editEventForm()" x-init="init()" - @submit.prevent="submitForm"> + <form + id="editEventForm" + enctype="multipart/form-data" + x-data="editEventForm()" + x-init="init()" + @submit.prevent="submitForm" + @event-group-id-changed="data.eventGroupID = $event.detail" + @event-group-edit-token-changed="data.eventGroupEditToken = $event.detail" + > {{> eventForm }} @@ -47,3 +54,4 @@ <script type="text/javascript" src="/js/generate-timezones.js"></script> <script type="text/javascript" src="/js/modules/event-edit.js"></script> +<script src="/js/modules/group-linker.js"></script> diff --git a/views/partials/eventForm.handlebars b/views/partials/eventForm.handlebars index 93d679d..49c0f86 100755 --- a/views/partials/eventForm.handlebars +++ b/views/partials/eventForm.handlebars @@ -80,18 +80,40 @@ <div class="card-header"> <strong>Link this event to an event group</strong> </div> - <div class="card-body"> + <div class="card-body" x-data="eventGroupLinker()"> + <div class="form-group-label" x-show="data.groups.length > 0"> + <label>Choose a group you've edited before</label> + </div> + <div class="form-group" x-show="data.groups.length > 0"> + <select x-ref="eventGroupSelect" id="eventGroupSelect" name="eventGroupSelect" class="form-control" x-on:change="selectGroup"> + <option value="">Choose a group</option> + <template x-for="group in data.groups"> + <option :value="group.id" x-text="group.name"></option> + </template> + </select> + </div> + <a class="card shadow-sm card--group-preview mb-3" x-show="showGroupPreview()" x-bind:href="groupPreview().url" target="_blank"> + <img :src="'/events/' + groupPreview().image" x-show="groupPreview().image"/> + <img src="/images/seigaiha-single.png" x-show="!groupPreview().image"/> + <div class="card--group-preview__text"> + <strong x-text="groupPreview().name"></strong> + <p x-text="groupPreview().description"></p> + </div> + </a> + <div class="alert alert-info text-center" role="alert" x-show="data.groups.length > 0"> + <i class="fas fa-info-circle"></i> You can also enter the group ID and secret editing code manually. + </div> <div class="form-group"> - <label for="eventGroupID" class="col-12">Event group ID</label> - <div class="form-group col-12"> - <input type="text" class="form-control" id="eventGroupID" name="eventGroupID" placeholder="" x-model="data.eventGroupID" > + <label for="eventGroupID">Event group ID</label> + <div class="form-group"> + <input type="text" class="form-control" id="eventGroupID" name="eventGroupID" x-model="data.eventGroupID" x-on:input="resetGroupSelector"> <small class="form-text">You can find this short string of characters in the event group's link, in your confirmation email, or on the event group's page.</small> </div> </div> <div class="form-group"> - <label for="eventGroupEditToken" class="col-12">Event group secret editing code</label> - <div class="form-group col-12"> - <input type="text" class="form-control" id="eventGroupEditToken" name="eventGroupEditToken" placeholder="" x-model="data.eventGroupEditToken" > + <label for="eventGroupEditToken">Event group secret editing code</label> + <div class="form-group"> + <input type="text" class="form-control" id="eventGroupEditToken" name="eventGroupEditToken" x-model="data.eventGroupEditToken" x-on:input="resetGroupSelector"> <small class="form-text">You can find this long string of characters in the confirmation email you received when you created the event group.</small> </div> </div> |