summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.example.toml2
-rw-r--r--package.json2
-rwxr-xr-xpublic/css/style.css230
-rw-r--r--public/js/modules/event-edit.js11
-rw-r--r--public/js/modules/group-edit.js9
-rw-r--r--public/js/modules/new.js42
-rw-r--r--src/lib/config.ts26
-rw-r--r--src/routes/frontend.ts11
-rw-r--r--src/routes/static.ts3
-rw-r--r--static/instance-description.md1
-rw-r--r--views/createEventMagicLink.handlebars2
-rwxr-xr-xviews/event.handlebars68
-rwxr-xr-xviews/eventgroup.handlebars28
-rwxr-xr-xviews/home.handlebars24
-rwxr-xr-xviews/newevent.handlebars33
-rw-r--r--views/partials/editeventgroupmodal.handlebars8
-rw-r--r--views/partials/editeventmodal.handlebars8
-rwxr-xr-xviews/partials/eventForm.handlebars4
-rw-r--r--views/partials/importeventform.handlebars4
-rw-r--r--views/partials/instanceRules.handlebars11
-rwxr-xr-xviews/partials/sidebar.handlebars2
-rw-r--r--views/publicEventList.handlebars23
22 files changed, 387 insertions, 165 deletions
diff --git a/config/config.example.toml b/config/config.example.toml
index 4e00171..5502038 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -4,7 +4,7 @@
domain = "localhost:3000"
port = "3000"
email = "contact@example.com"
-site_name = "gathio"
+site_name = "Gathio"
is_federated = true
# Events will be deleted this many days after they have ended. Set to 0 to
# disable automatic deletion (old events will never be deleted).
diff --git a/package.json b/package.json
index faa6a59..8f830db 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "gathio",
- "version": "1.4.1",
+ "version": "1.5.0",
"description": "A simple, federated, privacy-first event hosting platform",
"main": "index.js",
"type": "module",
diff --git a/public/css/style.css b/public/css/style.css
index 938e6a5..9a81967 100755
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -1,6 +1,10 @@
/* TYPOGRAPHY */
@import url("https://fonts.googleapis.com/css2?family=Fredoka:wght@300..700&display=swap");
+body {
+ color: var(--color--black);
+}
+
h1,
h2,
h3 {
@@ -18,6 +22,187 @@ h3 {
font-style: normal;
}
+:root {
+ --color-purple: hsl(273, 44%, 58%);
+ --color-purple-dark: hsl(273, 44%, 38%);
+ --color-purple-lighter: hsl(273, 44%, 86%);
+ --color-purple-light: hsl(273, 44%, 96%);
+ --color-red: hsl(359, 100%, 65%);
+ --color-red-dark: hsl(359, 100%, 45%);
+ --color-grey-99: hsl(0, 0%, 99%);
+ --color-grey-97: hsl(0, 0%, 97%);
+ --color-grey-95: hsl(0, 0%, 95%);
+ --color-grey-90: hsl(0, 0%, 90%);
+ --color-grey-85: hsl(0, 0%, 85%);
+ --color-grey-80: hsl(0, 0%, 80%);
+ --color-grey-75: hsl(0, 0%, 75%);
+ --color-grey-70: hsl(0, 0%, 70%);
+ --color-grey-60: hsl(0, 0%, 60%);
+ --color-grey-50: hsl(0, 0%, 50%);
+ --color-grey-40: hsl(0, 0%, 40%);
+ --color-grey-30: hsl(0, 0%, 30%);
+ --color-grey-20: hsl(0, 0%, 20%);
+ --color--black: hsl(0, 0%, 10%);
+ --transition: 0.15s ease-in;
+}
+
+.flex-gap {
+ display: flex;
+ gap: 1rem;
+}
+
+.flex-gap--small {
+ display: flex;
+ gap: 0.5rem;
+}
+
+.button {
+ display: inline-block;
+ height: 2.25rem;
+ line-height: 2.25rem;
+ border-radius: 2.25rem;
+ font-weight: 500;
+ letter-spacing: 0.35px;
+ transition: background var(--transition);
+ text-decoration: none;
+ border: none;
+ font-size: 0.95rem;
+ padding: 0 1rem;
+ white-space: nowrap;
+ text-align: center;
+}
+
+.button:hover {
+ text-decoration: none;
+ color: inherit;
+}
+
+.button--primary {
+ background: var(--color-purple);
+ color: #fff;
+}
+
+.button--primary:hover {
+ background: var(--color-purple-dark);
+ color: #fff;
+}
+
+.button--secondary {
+ background: var(--color-grey-85);
+ color: var(--color-black);
+}
+
+.button--secondary:hover {
+ background: var(--color-grey-70);
+}
+
+.button--outline-primary {
+ background: transparent;
+ border: 1px solid var(--color-purple);
+ color: var(--color-purple);
+}
+
+.button--outline-primary:hover {
+ border: 1px solid var(--color-purple-dark);
+ background: var(--color-purple-light);
+ color: var(--color-purple-dark);
+}
+
+.button--outline-secondary {
+ background: transparent;
+ border: 1px solid var(--color-grey-75);
+ color: var(--color-grey-30);
+}
+
+.button--outline-secondary:hover {
+ border: 1px solid var(--color-grey-70);
+ background: var(--color-purple-light);
+}
+
+.button--sm {
+ height: 1.75rem;
+ line-height: 1.65rem;
+ border-radius: 1.75rem;
+ font-size: 0.85rem;
+ padding: 0 0.75rem;
+}
+
+.button--lg {
+ height: 2.75rem;
+ line-height: 2.75rem;
+ border-radius: 2.75rem;
+ font-size: 1.05rem;
+ padding: 0 1.25rem;
+}
+
+.button--danger {
+ background: var(--color-red);
+ color: #fff;
+}
+
+.button--danger:hover {
+ background: var(--color-red-dark);
+ color: #fff;
+}
+
+.button--primary:disabled {
+ background: var(--color-purple-lighter);
+ color: var(--color-grey-50);
+}
+
+.button--secondary:disabled {
+ background: var(--color-grey-97);
+ color: var(--color-grey-75);
+}
+
+.button--danger:disabled {
+ background: #f9d4d4;
+ color: #ff4d4f;
+}
+
+.button--outline-primary:disabled {
+ background: transparent;
+ border: 1px solid var(--color-purple-lighter);
+ color: var(--color-purple-lighter);
+}
+
+.button--outline-secondary:disabled {
+ background: transparent;
+ border: 1px solid var(--color-grey-85);
+ color: var(--color-grey-85);
+}
+
+.button-stack {
+ display: flex;
+ flex-direction: column;
+}
+
+.button-stack > .button:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+
+.button-stack > .button:not(:last-child) {
+ border-bottom: none;
+}
+
+.button-stack > .button:first-child {
+ border-radius: 1rem 1rem 0 0;
+}
+
+.button-stack > .button:last-child {
+ border-radius: 0 0 1rem 1rem;
+}
+
+.button-stack > .button.button--sm {
+ height: 2rem;
+ line-height: 2rem;
+}
+
+.button-stack > .button.button--sm {
+ height: 2rem;
+ line-height: 2rem;
+}
+
/* LAYOUT */
html {
@@ -25,11 +210,7 @@ html {
}
body {
- background: #f8f8f8;
- display: flex;
- flex-direction: column;
- min-height: 100vh;
- align-items: center;
+ background: var(--color-grey-97);
}
body > #container {
@@ -37,14 +218,16 @@ body > #container {
width: 100%;
max-width: 75rem;
display: grid;
+ margin: 0 auto;
grid-template-columns: 1fr;
+ grid-template-rows: min-content auto;
padding: 0;
}
#container > #content {
overflow: hidden;
- border: 1px solid #eaeaea;
- background: #ffffff;
+ border: 1px solid var(--color-grey-90);
+ background: #fff;
display: flex;
flex-direction: column;
}
@@ -66,7 +249,7 @@ body > #container {
border-top: 1px solid #e0e0e0;
text-align: center;
padding: 0.25rem 0;
- background: #fdfdfd;
+ background: var(--color-grey-99);
}
#container > #content > footer p {
@@ -77,6 +260,7 @@ body > #container {
body > #container {
padding: 1rem;
grid-template-columns: 1fr 4fr;
+ grid-template-rows: auto;
gap: 1rem;
}
#container > #content {
@@ -117,7 +301,12 @@ body > #container {
#sidebar h1 a:hover {
text-decoration: none;
- background: linear-gradient(to right, #27aa45, #7fe0c8, #5d26c1);
+ background: linear-gradient(
+ to right,
+ rgb(1, 76, 173),
+ rgb(128, 224, 200),
+ var(--color-purple)
+ );
background-size: 100% 100%;
background-clip: text;
-webkit-background-clip: text;
@@ -157,7 +346,7 @@ ul#sidebar__nav a {
width: 100%;
padding: 0 0 0.5rem 0;
}
- ul#sidebar__nav li:has(a:not(.btn)):not(:last-child) {
+ ul#sidebar__nav li:has(a:not(.button)):not(:last-child) {
border-bottom: 1px solid #e0e0e0;
}
@@ -252,6 +441,11 @@ ul#sidebar__nav a {
flex-wrap: wrap;
}
+#event__actions #editEvent {
+ width: 100%;
+ margin-top: 16px;
+}
+
.attendeesList > li {
border: 4px solid #0ea130;
border-radius: 2em;
@@ -355,7 +549,7 @@ li.hidden-attendee .attendee-name {
flex-direction: column;
align-items: flex-start;
}
-#eventAttendees h5 .btn-group {
+#eventAttendees h5 .button--group {
margin-top: 0.5rem;
}
@@ -365,7 +559,7 @@ li.hidden-attendee .attendee-name {
justify-content: space-between;
align-items: center;
}
- #eventAttendees h5 .btn-group {
+ #eventAttendees h5 .button--group {
margin-top: 0;
}
}
@@ -428,12 +622,6 @@ li.hidden-attendee .attendee-name {
/* FORMS */
-#newEventFormContainer,
-#importEventFormContainer,
-#newEventGroupFormContainer {
- display: none;
-}
-
#icsImportLabel {
overflow: hidden;
text-overflow: ellipsis;
@@ -524,10 +712,10 @@ img.group-preview__image {
}
}
-.btn--loading {
+.button--loading {
position: relative;
}
-.btn--loading::after {
+.button--loading::after {
content: "";
position: absolute;
left: -45%;
@@ -573,7 +761,7 @@ img.group-preview__image {
/* EVENT AND GROUP LISTS */
.list-group-item-action:hover {
- background-color: #f2f8ff;
+ background-color: var(--color-purple-light);
}
/* STATIC PAGES */
diff --git a/public/js/modules/event-edit.js b/public/js/modules/event-edit.js
index 736547f..6d2c216 100644
--- a/public/js/modules/event-edit.js
+++ b/public/js/modules/event-edit.js
@@ -7,7 +7,6 @@ $(document).ready(function () {
label_selected: "Change file",
no_label: false,
});
- autosize($("textarea"));
if (window.eventData.image) {
$("#event-image-preview").css(
"background-image",
@@ -18,6 +17,16 @@ $(document).ready(function () {
}
});
+$('#editModal').on('shown.bs.modal', function (e) {
+ console.log('hii');
+ const ta = document.querySelector("#editModal textarea");
+ ta.style.display = 'none';
+ autosize(ta);
+ ta.style.display = '';
+ // Call the update method to recalculate the size:
+ autosize.update(ta);
+});
+
function editEventForm() {
return {
data: {
diff --git a/public/js/modules/group-edit.js b/public/js/modules/group-edit.js
index 2d55346..db2d411 100644
--- a/public/js/modules/group-edit.js
+++ b/public/js/modules/group-edit.js
@@ -7,7 +7,6 @@ $(document).ready(function () {
label_selected: "Change file",
no_label: false,
});
- autosize($("textarea"));
if (window.groupData.image) {
$("#group-image-preview").css(
"background-image",
@@ -19,6 +18,14 @@ $(document).ready(function () {
$("#timezone").val(window.groupData.timezone).trigger("change");
});
+$('#editModal').on('shown.bs.modal', function (e) {
+ const ta = document.querySelector("#editModal textarea");
+ ta.style.display = 'none';
+ autosize(ta);
+ ta.style.display = '';
+ autosize.update(ta);
+});
+
function editEventGroupForm() {
return {
data: {
diff --git a/public/js/modules/new.js b/public/js/modules/new.js
index f7c3e34..7915b59 100644
--- a/public/js/modules/new.js
+++ b/public/js/modules/new.js
@@ -5,48 +5,6 @@ $(document).ready(function () {
.next("label")
.html('<i class="far fa-file-alt"></i> ' + file);
}
- $("#showNewEventFormButton").click(function () {
- $("button").removeClass("active");
- $(
- "#showImportEventFormButton #showNewEventGroupFormButton",
- ).removeClass("active");
- if ($("#newEventFormContainer").is(":visible")) {
- $("#newEventFormContainer").slideUp("fast");
- } else {
- $("#newEventFormContainer").slideDown("fast");
- $("#importEventFormContainer").slideUp("fast");
- $("#newEventGroupFormContainer").slideUp("fast");
- $(this).addClass("active");
- }
- });
- $("#showImportEventFormButton").click(function () {
- $("button").removeClass("active");
- $("#showNewEventFormButton #showNewEventGroupFormButton").removeClass(
- "active",
- );
- if ($("#importEventFormContainer").is(":visible")) {
- $("#importEventFormContainer").slideUp("fast");
- } else {
- $("#importEventFormContainer").slideDown("fast");
- $("#newEventFormContainer").slideUp("fast");
- $("#newEventGroupFormContainer").slideUp("fast");
- $(this).addClass("active");
- }
- });
- $("#showNewEventGroupFormButton").click(function () {
- $("button").removeClass("active");
- $("#showNewEventFormButton #showImportEventFormButton").removeClass(
- "active",
- );
- if ($("#newEventGroupFormContainer").is(":visible")) {
- $("#newEventGroupFormContainer").slideUp("fast");
- } else {
- $("#newEventGroupFormContainer").slideDown("fast");
- $("#newEventFormContainer").slideUp("fast");
- $("#importEventFormContainer").slideUp("fast");
- $(this).addClass("active");
- }
- });
$("#icsImportControl").change(function () {
var file = $("#icsImportControl")[0].files[0].name;
$(this)
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 4bc43bd..b4086d8 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -2,6 +2,7 @@ import fs from "fs";
import toml from "toml";
import { exitWithError } from "./process.js";
import { Response } from "express";
+import { markdownToSanitizedHTML } from "../util/markdown.js";
interface StaticPage {
title: string;
@@ -152,6 +153,31 @@ export const instanceRules = (): InstanceRule[] => {
return rules;
};
+export const instanceDescription = (): string => {
+ const config = getConfig();
+ const defaultInstanceDescription =
+ "**{{ siteName }}** is running on Gathio — a simple, federated, privacy-first event hosting platform.";
+ let instanceDescription = defaultInstanceDescription;
+ try {
+ if (fs.existsSync("./static/instance-description.md")) {
+ const fileBody = fs.readFileSync(
+ "./static/instance-description.md",
+ "utf-8",
+ );
+ instanceDescription = markdownToSanitizedHTML(fileBody);
+ }
+ // Replace {{siteName}} with the instance name
+ instanceDescription = instanceDescription.replace(
+ /\{\{ ?siteName ?\}\}/g,
+ config?.general.site_name,
+ );
+ return instanceDescription;
+ } catch (err) {
+ console.log(err);
+ return defaultInstanceDescription;
+ }
+};
+
// Attempt to load our global config. Will stop the app if the config file
// cannot be read (there's no point trying to continue!)
export const getConfig = (): GathioConfig => {
diff --git a/src/routes/frontend.ts b/src/routes/frontend.ts
index 4d977d7..86ad69c 100644
--- a/src/routes/frontend.ts
+++ b/src/routes/frontend.ts
@@ -1,8 +1,13 @@
import { Router, Request, Response } from "express";
+import fs from "fs";
import moment from "moment-timezone";
import { marked } from "marked";
import { markdownToSanitizedHTML, renderPlain } from "../util/markdown.js";
-import { frontendConfig, instanceRules } from "../lib/config.js";
+import {
+ frontendConfig,
+ instanceDescription,
+ instanceRules,
+} from "../lib/config.js";
import { addToLog, exportICal } from "../helpers.js";
import Event from "../models/Event.js";
import EventGroup, { IEventGroup } from "../models/EventGroup.js";
@@ -26,6 +31,7 @@ router.get("/", (_: Request, res: Response) => {
return res.render("home", {
...frontendConfig(res),
instanceRules: instanceRules(),
+ instanceDescription: instanceDescription(),
});
});
@@ -33,6 +39,7 @@ router.get("/about", (_: Request, res: Response) => {
return res.render("home", {
...frontendConfig(res),
instanceRules: instanceRules(),
+ instanceDescription: instanceDescription(),
});
});
@@ -126,6 +133,8 @@ router.get("/events", async (_: Request, res: Response) => {
upcomingEvents: upcomingEvents,
pastEvents: pastEvents,
eventGroups: updatedEventGroups,
+ instanceDescription: instanceDescription(),
+ instanceRules: instanceRules(),
...frontendConfig(res),
});
});
diff --git a/src/routes/static.ts b/src/routes/static.ts
index 6fab98d..6670214 100644
--- a/src/routes/static.ts
+++ b/src/routes/static.ts
@@ -2,10 +2,13 @@ import { Router, Request, Response } from "express";
import fs from "fs";
import getConfig, { frontendConfig } from "../lib/config.js";
import { markdownToSanitizedHTML } from "../util/markdown.js";
+import { getConfigMiddleware } from "../lib/middleware.js";
const config = getConfig();
const router = Router();
+router.use(getConfigMiddleware);
+
if (config.static_pages?.length) {
config.static_pages
.filter((page) => page.path?.startsWith("/") && page.filename)
diff --git a/static/instance-description.md b/static/instance-description.md
new file mode 100644
index 0000000..747850d
--- /dev/null
+++ b/static/instance-description.md
@@ -0,0 +1 @@
+**{{ siteName }}** is running on Gathio — a simple, federated, privacy-first event hosting platform.
diff --git a/views/createEventMagicLink.handlebars b/views/createEventMagicLink.handlebars
index 7329801..d0a0a49 100644
--- a/views/createEventMagicLink.handlebars
+++ b/views/createEventMagicLink.handlebars
@@ -23,7 +23,7 @@
<input type="email" class="form-control" id="email" placeholder="Email address" required name="email">
</div>
<div class="form-group text-center">
- <button type="submit" class="btn btn-primary w-50">Request magic link</button>
+ <button type="submit" class="button button--primary w-50">Request magic link</button>
</div>
</form>
</main>
diff --git a/views/event.handlebars b/views/event.handlebars
index 3ccbc08..cd1645a 100755
--- a/views/event.handlebars
+++ b/views/event.handlebars
@@ -11,9 +11,7 @@
</div>
<div class="col-lg-3 ml-2 edit-buttons">
{{#if editingEnabled}}
- <button type="button" id="editEvent" class="btn btn-success" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit event</button>
- {{else}}
- <button type="button" id="editEvent" class="btn btn-success" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Edit event</button>
+ <button type="button" id="editEvent" class="button button--primary" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit event</button>
{{/if}}
</div>
</div>
@@ -75,7 +73,7 @@
<i class="fas fa-fw fa-share-square"></i>
</span>
<a class="u-url" href="https://{{domain}}/{{eventData.id}}">https://{{domain}}/{{eventData.id}}</a>
- <button type="button" id="copyEventLink" class="eventInformationAction btn btn-outline-secondary btn-sm" data-clipboard-text="https://{{domain}}/{{eventData.id}}">
+ <button type="button" id="copyEventLink" class="eventInformationAction button button--outline-secondary button--sm" data-clipboard-text="https://{{domain}}/{{eventData.id}}">
<i class="fas fa-copy"></i> Copy
</button>
</li>
@@ -85,7 +83,7 @@
<i class="fas fa-fw fa-share-square"></i>
</span>
@{{eventData.id}}@{{domain}}
- <button type="button" id="copyAPLink" class="eventInformationAction btn btn-outline-secondary btn-sm" data-clipboard-text="@{{eventData.id}}@{{domain}}">
+ <button type="button" id="copyAPLink" class="eventInformationAction button button--outline-secondary button--sm" data-clipboard-text="@{{eventData.id}}@{{domain}}">
<i class="fas fa-copy"></i> Copy
</button>
</li>
@@ -94,20 +92,24 @@
</div> <!-- .card-body -->
</div> <!-- .card#event__data -->
<aside id="event__actions">
- <div class="btn-group-vertical d-flex" role="group" aria-label="Event actions">
- <a href="http://www.google.com/calendar/event?action=TEMPLATE&dates={{parsedStart}}%2F{{parsedEnd}}&text={{escapedName}}&location={{parsedLocation}}&ctz={{timezone}}" class="btn btn-outline-secondary btn-sm">
+ <div class="button-stack" role="group" aria-label="Event actions">
+ <a href="http://www.google.com/calendar/event?action=TEMPLATE&dates={{parsedStart}}%2F{{parsedEnd}}&text={{escapedName}}&location={{parsedLocation}}&ctz={{timezone}}" class="button button--outline-secondary button--sm">
<i class="far fa-calendar-plus"></i> Add to Google Calendar
</a>
- <button type="button" id="exportICS" class="btn btn-outline-secondary btn-sm" data-event-id="{{eventData.id}}">
+ <button type="button" id="exportICS" class="button button--outline-secondary button--sm" data-event-id="{{eventData.id}}">
<i class="fas fa-download"></i> Export as ICS
</button>
- <a target="_blank" href="http://maps.google.com/?q={{parsedLocation}}" class="btn btn-outline-secondary btn-sm">
+ <a target="_blank" href="http://maps.google.com/?q={{parsedLocation}}" class="button button--outline-secondary button--sm">
<i class="fas fa-map-marked"></i> Show on Google Maps
</a>
- <a target="_blank" href="https://www.openstreetmap.org/search?query={{parsedLocation}}" class="btn btn-outline-secondary btn-sm">
+ <a target="_blank" href="https://www.openstreetmap.org/search?query={{parsedLocation}}" class="button button--outline-secondary button--sm">
<i class="fas fa-map-marked"></i> Show on OpenStreetMap
</a>
</div>
+
+ {{#unless editingEnabled}}
+ <button type="button" id="editEvent" class="button button--outline-secondary button--sm" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Switch to editing mode</button>
+ {{/unless}}
</aside> <!-- #event__actions -->
</div>
@@ -136,11 +138,11 @@
{{#if eventData.usersCanAttend}}
<div class="card mb-4" id="eventAttendees">
<h5 class="card-header">Attendees {{#if numberOfAttendees}}({{numberOfAttendees}}){{/if}}
- <div class="btn-group" role="group" aria-label="Attendance controls">
+ <div class="button--group" role="group" aria-label="Attendance controls">
{{#unless noMoreSpots}}
- <button type="button" id="attendEvent" class="btn btn-success" data-event-id="{{eventData.id}}"><i class="fas fa-user-plus"></i> Add me</button>
+ <button type="button" id="attendEvent" class="button button--primary" data-event-id="{{eventData.id}}"><i class="fas fa-user-plus"></i> Add me</button>
{{/unless}}
- <button type="button" id="unattendEvent" class="btn btn-secondary" data-toggle="modal" data-target="#unattendModal"><i class="fas fa-user-times"></i> Remove me</button>
+ <button type="button" id="unattendEvent" class="button button--secondary" data-toggle="modal" data-target="#unattendModal"><i class="fas fa-user-times"></i> Remove me</button>
</div>
</h5>
<div class="card-body text-center">
@@ -218,8 +220,8 @@
</div>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-primary">Add myself</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--primary">Add myself</button>
</div>
</form>
</div>
@@ -245,8 +247,8 @@
</div>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-primary">Remove myself</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--primary">Remove myself</button>
</div>
</form>
</div>
@@ -268,8 +270,8 @@
<p>Are you sure you want to remove this attendee from the event? This action cannot be undone.</p>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-danger">Remove attendee</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--danger">Remove attendee</button>
</div>
</form>
</div>
@@ -286,14 +288,14 @@
<form id="commentForm" action="/post/comment/{{eventData.id}}/" method="post">
<label for="commentAuthor">Name</label>
<div class="form-group">
- <input type="text" class="form-control" id="commentAuthor" name="commentAuthor" placeholder="Your name" data-validation="required length" data-validation-length="1-60">
+ <input type="text" class="form-control" id="commentAuthor" name="commentAuthor" placeholder="Your name" required>
</div>
<label for="commentContent">Comment</label>
<div class="form-group">
- <div class="input-group">
- <textarea class="form-control" id="commentContent" name="commentContent" style="resize: none;" placeholder="What would you like to say?" data-validation="required length" data-validation-length="1-280"></textarea>
+ <div class="d-flex flex-gap">
+ <textarea class="form-control" id="commentContent" name="commentContent" style="resize: none;" placeholder="What would you like to say?" required></textarea>
<div class="input-group-append">
- <button type="submit" class="btn btn-primary btn-block h-100" id="postComment">Send <i class="fas fa-chevron-right"></i></button>
+ <button type="submit" class="button button--primary" id="postComment">Send <i class="fas fa-chevron-right"></i></button>
</div>
</div>
</div>
@@ -322,12 +324,12 @@
{{/if}}
</div>
<div class="col-lg-3 commentMetadata text-right">
- <button type="button" class="btn btn-outline-primary btn-sm openReplyBox">
+ <button type="button" class="button button--outline button--sm openReplyBox">
<i class="fas fa-comment"></i> Reply
</button>
{{#if ../editingEnabled}}
<form class="d-inline" action="/deletecomment/{{../eventData.id}}/{{this._id}}/{{../eventData.editToken}}" method="post">
- <button type="submit" class="btn btn-outline-danger btn-sm deleteComment">
+ <button type="submit" class="button button--outline button--sm deleteComment">
<i class="fas fa-trash"></i> Delete
</button>
</form>
@@ -338,13 +340,13 @@
<div class="col-md">
<form id="replyForm" action="/post/reply/{{../eventData.id}}/{{this._id}}" method="post">
<div class="form-group">
- <input type="text" class="form-control form-control-sm" id="replyAuthor" name="replyAuthor" placeholder="Your name" data-validation="required length" data-validation-length="1-60">
+ <input type="text" class="form-control form-control-sm" id="replyAuthor" name="replyAuthor" placeholder="Your name" required>
</div>
<div class="form-group">
- <div class="input-group">
- <textarea class="form-control form-control-sm" id="replyContent" name="replyContent" style="resize: none;" placeholder="What would you like to reply?" data-validation="required length" data-validation-length="1-280"></textarea>
+ <div class="d-flex flex-gap">
+ <textarea class="form-control form-control-sm" id="replyContent" name="replyContent" style="resize: none;" placeholder="What would you like to reply?" required></textarea>
<div class="input-group-append">
- <button type="submit" class="btn btn-primary btn-block h-100 btn-sm" id="postReply">Reply <i class="fas fa-chevron-right"></i></button>
+ <button type="submit" class="button button--primary button--sm" id="postReply">Reply <i class="fas fa-chevron-right"></i></button>
</div>
</div>
</div>
@@ -381,8 +383,8 @@
</div>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-primary">Edit event</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--primary">Edit event</button>
</div>
</form>
</div>
@@ -408,8 +410,8 @@
<p>Are you sure you want to delete this event? This action cannot be undone.</p>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-danger">Delete event</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--danger">Delete event</button>
</div>
</form>
</div>
diff --git a/views/eventgroup.handlebars b/views/eventgroup.handlebars
index 9fb2276..8fbedbc 100755
--- a/views/eventgroup.handlebars
+++ b/views/eventgroup.handlebars
@@ -10,9 +10,9 @@
</div>
<div class="col-lg-2 ml-2 edit-buttons">
{{#if editingEnabled}}
- <button type="button" id="editGroup" class="btn btn-success text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit group</button>
+ <button type="button" id="editGroup" class="button button--primary text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit group</button>
{{else}}
- <button type="button" id="editGroup" class="btn btn-success text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Edit group</button>
+ <button type="button" id="editGroup" class="button button--primary text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Edit group</button>
{{/if}}
</div>
</div>
@@ -52,7 +52,7 @@
<i class="fas fa-share-square"></i>
</span>
<a href="https://{{domain}}/group/{{eventGroupData.id}}">https://{{domain}}/group/{{eventGroupData.id}}</a>
- <button type="button" id="copyEventLink" class="eventInformationAction btn btn-outline-secondary btn-sm" data-clipboard-text="https://{{domain}}/group/{{eventGroupData.id}}">
+ <button type="button" id="copyEventLink" class="eventInformationAction button button--outline-secondary button--sm" data-clipboard-text="https://{{domain}}/group/{{eventGroupData.id}}">
<i class="fas fa-copy"></i> Copy
</button>
</li>
@@ -63,7 +63,7 @@
<a
href="https://{{domain}}/group/{{eventGroupData.id}}/feed.ics">https://{{domain}}/group/{{eventGroupData.id}}/feed.ics</a>&nbsp;
<button type="button" id="copyFeedLink"
- class="eventInformationAction btn btn-outline-secondary btn-sm"
+ class="eventInformationAction button button--outline-secondary button--sm"
data-clipboard-text="https://{{domain}}/group/{{eventGroupData.id}}/feed.ics">
<i class="fas fa-copy"></i> Copy
</button>
@@ -74,14 +74,14 @@
</div> <!-- /card -->
</div>
<aside id="event__actions">
- <div class="btn-group-vertical d-flex" role="group" aria-label="Event group actions">
- <button type="button" class="btn btn-outline-secondary btn-sm"
+ <div class="button-stack" role="group" aria-label="Event group actions">
+ <button type="button" class="button button--outline-secondary button--sm"
data-event-id="{{eventGroupData.id}}" data-toggle="modal"
data-target="#subscribeModal">
<i class="fas fa-envelope"></i> Subscribe to updates
</button>
- <button type="button" id="exportICS" class="btn btn-outline-secondary
- btn-sm" data-event-id="{{eventGroupData.id}}">
+ <button type="button" id="exportICS" class="button button--outline-secondary
+ button--sm" data-event-id="{{eventGroupData.id}}">
<i class="fas fa-download"></i> Export as ICS
</button>
</div>
@@ -152,8 +152,8 @@
<p>This will <strong>not</strong> delete the individual events contained in this group. They can be linked to another group later.</p>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-danger">Delete event group</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--danger">Delete event group</button>
</div>
</form>
</div>
@@ -184,8 +184,8 @@
</div>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-success">Subscribe</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--primary">Subscribe</button>
</div>
</form>
</div>
@@ -214,8 +214,8 @@
</div>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
- <button type="submit" class="btn btn-primary">Edit group</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="button button--primary">Edit group</button>
</div>
</form>
</div>
diff --git a/views/home.handlebars b/views/home.handlebars
index 7b4608a..0d294d3 100755
--- a/views/home.handlebars
+++ b/views/home.handlebars
@@ -1,19 +1,17 @@
<main class="page">
-<p class="lead">Gathio is a simple, federated, privacy-first event hosting platform.</p>
+<h2 class="mb-3 pb-2 text-center border-bottom">About {{siteName}}</h2>
-<div class="card mb-3 border-primary">
-<div class="card-header">
- This instance, <strong>{{siteName}}</strong>, has the following features:
-</div>
+{{#if instanceDescription}}
+ <div class="instance-description mb-4">
+ {{{instanceDescription}}}
+ </div>
+{{/if}}
-<div class="card-body m-0 p-0">
- <ul class="list-group list-group-flush">
- {{#each instanceRules}}
- <li class="list-group-item"><i class="{{this.icon}} fa-fw mr-2"></i> {{this.text}}</li>
- {{/each}}
- </ul>
-</div>
-</div>
+{{> instanceRules }}
+
+<h2 class="mb-3 mt-5 pb-2 text-center border-bottom">About Gathio</h2>
+
+<p class="lead text-center">Gathio is a simple, federated, privacy-first event hosting platform.</p>
<div id="example-event" class="text-center w-100 mt-4 mb-5">
<img alt ="An example event page for a picnic. The page shows the event's location, host, date and time, and description, as well as buttons to save the event to Google Calendar, export it, and open the location in OpenStreetMap and Google Maps." src="images/example-event-2023.png" class="img-fluid w-75 mx-auto shadow-lg rounded">
diff --git a/views/newevent.handlebars b/views/newevent.handlebars
index 9df69db..d6d7024 100755
--- a/views/newevent.handlebars
+++ b/views/newevent.handlebars
@@ -1,14 +1,15 @@
-<main class="page">
-<div class="container mb-4">
+<main class="page" x-data="{currentTab: null}">
+<h2 class="mb-3 pb-2 text-center border-bottom">What would you like to do?</h2>
+<div class="container-fluid mb-4">
<div class="row">
- <div class="col-sm-4 p-2">
- <button type="button" id="showNewEventFormButton" class="btn btn-secondary w-100"><i class="fas fa-calendar-day"></i> Create a new event</button>
+ <div class="col-lg-4 p-2">
+ <button type="button" id="showNewEventFormButton" class="button w-100" x-bind:class="currentTab === 'event' ? 'button--primary' : 'button--secondary'" x-on:click="currentTab = 'event'"><i class="fas fa-calendar-day"></i> Create a new event</button>
</div>
- <div class="col-sm-4 p-2">
- <button type="button" id="showImportEventFormButton" class="btn btn-secondary w-100"><i class="fas fa-file-import"></i> Import an existing event</button>
+ <div class="col-lg-4 p-2">
+ <button type="button" id="showImportEventFormButton" class="button w-100" x-bind:class="currentTab === 'importEvent' ? 'button--primary' : 'button--secondary'" x-on:click="currentTab = 'importEvent'"><i class="fas fa-file-import"></i> Import an existing event</button>
</div>
- <div class="col-sm-4 p-2">
- <button type="button" id="showNewEventGroupFormButton" class="btn btn-secondary w-100"><i class="fas fa-calendar-alt"></i> Create a new event group </button>
+ <div class="col-lg-4 p-2">
+ <button type="button" id="showNewEventGroupFormButton" class="button w-100" x-bind:class="currentTab === 'group' ? 'button--primary' : 'button--secondary'" x-on:click="currentTab = 'group'"><i class="fas fa-calendar-alt"></i> Create a new event group </button>
</div>
</div>
</div>
@@ -17,7 +18,7 @@
<i class="fas fa-exclamation-circle"></i> Events are visible to anyone who knows the link.
</div>
-<div id="newEventFormContainer">
+<div id="newEventFormContainer" x-show="currentTab === 'event'" style="display: none">
<h4 class="mb-2">Create an event</h4>
<form
id="newEventForm"
@@ -34,9 +35,9 @@
<button
id="newEventFormSubmit"
type="submit"
- class="btn btn-primary w-50"
+ class="button button--primary w-50"
x-bind:disabled="submitting"
- x-bind:class="submitting ? 'btn--loading' : ''"
+ x-bind:class="submitting ? 'button--loading' : ''"
x-text="submitting ? 'Creating...' : 'Create'"
></button>
</div>
@@ -44,11 +45,11 @@
</form>
</div>
-<div id="importEventFormContainer">
+<div id="importEventFormContainer" x-show="currentTab === 'importEvent'" style="display: none">
{{>importeventform}}
</div>
-<div id="newEventGroupFormContainer">
+<div id="newEventGroupFormContainer" x-show="currentTab === 'group'" style="display: none">
<h4 class="mb-2">Create an event group</h4>
<p class="text-muted">An event group is a holding area for a set of linked events, like a recurring game night, a festival, or a band tour. You can share a public link to your event group just like an individual event link, and people who know the secret editing code will be able to add future events to the group.</p>
<p class="text-muted">Event groups do not get automatically removed like events do, but events which have been removed from {{siteName}} will of course not show up in an event group.</p>
@@ -58,9 +59,9 @@
<div class="col-sm-12 pt-3 pb-3 text-center">
<button
type="submit"
- class="btn btn-primary w-50"
+ class="button button--primary w-50"
x-bind:disabled="submitting"
- x-bind:class="submitting ? 'btn--loading' : ''"
+ x-bind:class="submitting ? 'button--loading' : ''"
x-text="submitting ? 'Creating...' : 'Create'"
></button>
</div>
@@ -72,4 +73,4 @@
<script src="/js/generate-timezones.js"></script>
<script src="/js/modules/new.js"></script>
-<script src="/js/modules/group-linker.js"></script> \ No newline at end of file
+<script src="/js/modules/group-linker.js"></script>
diff --git a/views/partials/editeventgroupmodal.handlebars b/views/partials/editeventgroupmodal.handlebars
index 41e7f00..046d15e 100644
--- a/views/partials/editeventgroupmodal.handlebars
+++ b/views/partials/editeventgroupmodal.handlebars
@@ -16,20 +16,20 @@
<div class="card border-danger mb-3">
<div class="card-header text-danger">Delete this event group</div>
<div class="card-body text-danger">
- <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal" data-target="#deleteModal"><i class="fas fa-trash"></i> Delete event group</button>
+ <button type="button" id="deleteEvent" class="button button--danger" data-toggle="modal" data-target="#deleteModal"><i class="fas fa-trash"></i> Delete event group</button>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
<button
type="submit"
- class="btn btn-primary"
+ class="button button--primary"
@click="submitForm"
x-bind:disabled="submitting"
- x-bind:class="submitting ? 'btn--loading' : ''"
+ x-bind:class="submitting ? 'button--loading' : ''"
x-text="submitting ? 'Saving...' : 'Save'"
></button>
</div>
diff --git a/views/partials/editeventmodal.handlebars b/views/partials/editeventmodal.handlebars
index 528dc1e..986da9c 100644
--- a/views/partials/editeventmodal.handlebars
+++ b/views/partials/editeventmodal.handlebars
@@ -21,7 +21,7 @@
<div class="card border-danger mb-3">
<div class="card-header text-danger">Delete this event</div>
<div class="card-body text-danger">
- <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal"
+ <button type="button" id="deleteEvent" class="button button--danger" data-toggle="modal"
data-target="#deleteModal" data-event-id="{{eventData.id}}"><i class="fas fa-trash"></i>
Delete</button>
</div>
@@ -30,13 +30,13 @@
</form>
</div>
<div class="modal-footer">
- <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="button" class="button button--secondary" data-dismiss="modal">Close</button>
<button
type="submit"
- class="btn btn-primary"
+ class="button button--primary"
@click="submitForm"
x-bind:disabled="submitting"
- x-bind:class="submitting ? 'btn--loading' : ''"
+ x-bind:class="submitting ? 'button--loading' : ''"
x-text="submitting ? 'Saving...' : 'Save'"
></button>
</div>
diff --git a/views/partials/eventForm.handlebars b/views/partials/eventForm.handlebars
index 9227300..161f44b 100755
--- a/views/partials/eventForm.handlebars
+++ b/views/partials/eventForm.handlebars
@@ -52,7 +52,7 @@
<small class="form-text">Recommended dimensions (w x h): 920px by 300px.</small>
{{#if eventData.image}}
<div class="form-group my-2">
- <button type="button" class="btn btn-danger" id="deleteImage">Delete image</button>
+ <button type="button" class="button button--danger" id="deleteImage">Delete image</button>
</div>
{{/if}}
</div>
@@ -109,7 +109,7 @@
</template>
</select>
</div>
- <button type="button" class="btn btn-outline-secondary w-100 text-center" x-on:click="manualGroupInputVisible = !manualGroupInputVisible">
+ <button type="button" class="button button--outline-primary w-100 text-center" x-on:click="manualGroupInputVisible = !manualGroupInputVisible">
Enter group details manually <i class="fas" :class="{'fa-caret-down': !manualGroupInputVisible, 'fa-caret-up': manualGroupInputVisible}"></i>
</button>
<div
diff --git a/views/partials/importeventform.handlebars b/views/partials/importeventform.handlebars
index ac3c673..a8c0f0e 100644
--- a/views/partials/importeventform.handlebars
+++ b/views/partials/importeventform.handlebars
@@ -40,9 +40,9 @@
</div>
<button
type="submit"
- class="d-block mt-3 mx-auto btn btn-primary w-50 mb-4"
+ class="d-block mx-auto button button--primary w-50"
x-bind:disabled="submitting"
- x-bind:class="submitting ? 'btn--loading' : ''"
+ x-bind:class="submitting ? 'button--loading' : ''"
x-text="submitting ? 'Importing...' : 'Import'"
></button>
</form>
diff --git a/views/partials/instanceRules.handlebars b/views/partials/instanceRules.handlebars
new file mode 100644
index 0000000..c7fa9be
--- /dev/null
+++ b/views/partials/instanceRules.handlebars
@@ -0,0 +1,11 @@
+<div class="card mb-4">
+ <div class="card-header">
+ <h6 class="mb-1">Instance settings</h6>
+ </div>
+
+ <ul class="list-group list-group-flush">
+ {{#each instanceRules}}
+ <li class="list-group-item"><i class="{{this.icon}} fa-fw mr-2"></i> {{this.text}}</li>
+ {{/each}}
+ </ul>
+</div> \ No newline at end of file
diff --git a/views/partials/sidebar.handlebars b/views/partials/sidebar.handlebars
index 6aa13b3..c1184be 100755
--- a/views/partials/sidebar.handlebars
+++ b/views/partials/sidebar.handlebars
@@ -2,7 +2,7 @@
<h1><a href="/">gathio</a></h1>
<ul id="sidebar__nav">
- <li><a class="btn btn-success" href="/new"><i class="far fa-calendar-plus"></i> New</a></li>
+ <li><a class="button button--primary" href="/new"><i class="far fa-calendar-plus"></i> Create an event</a></li>
{{#if showPublicEventList}}
<li><a href="/events">View events</a></li>
<li><a href="/about">About</a></li>
diff --git a/views/publicEventList.handlebars b/views/publicEventList.handlebars
index 1dbeffc..8dccaaa 100644
--- a/views/publicEventList.handlebars
+++ b/views/publicEventList.handlebars
@@ -1,12 +1,21 @@
<main class="page" x-data="{currentTab: 'events'}">
-<h2 class="mb-4">{{siteName}}</h2>
-<p><strong>{{siteName}}</strong> runs on <a href="/about">Gathio</a> — a simple, federated, privacy-first event hosting platform.</p>
-<ul class="nav nav-pills">
- <li class="nav-item">
- <a id="eventsTab" class="nav-link" x-bind:class="currentTab === 'events' && 'active'" aria-current="page" href="#" x-on:click.prevent="currentTab = 'events'">Events</a>
+
+<h2 class="mb-3 pb-2 text-center border-bottom">{{siteName}}</h2>
+
+{{#if instanceDescription}}
+ <div class="instance-description mb-4">
+ {{{instanceDescription}}}
+ </div>
+{{/if}}
+
+{{> instanceRules }}
+
+<ul class="nav d-flex flex-gap--small">
+ <li>
+ <a id="eventsTab" class="button button--lg" x-bind:class="currentTab === 'events' ? 'button--primary' : 'button--secondary'" aria-current="page" href="#" x-on:click.prevent="currentTab = 'events'">Events</a>
</li>
- <li class="nav-item">
- <a id="groupsTab" class="nav-link" x-bind:class="currentTab === 'groups' && 'active'" href="#" x-on:click.prevent="currentTab = 'groups'">Groups</a>
+ <li>
+ <a id="groupsTab" class="button button--lg" x-bind:class="currentTab === 'groups' ? 'button--primary' : 'button--secondary'" href="#" x-on:click.prevent="currentTab = 'groups'">Groups</a>
</li>
</ul>