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>  | 
