Lots of little QOL style fixes, remove minimized event panels
This commit is contained in:
parent
2b9dff2983
commit
a6aded4e8e
9 changed files with 203 additions and 198 deletions
73
README.md
73
README.md
|
@ -1,3 +1,74 @@
|
||||||
# EventMapper
|
# EventMapper
|
||||||
|
|
||||||
TODO: Readme
|
EventMapper, an easily-deployable, nearly-static digital guide application made in JavaScript.
|
||||||
|
|
||||||
|
## Specifications
|
||||||
|
|
||||||
|
### Data Folder Structure
|
||||||
|
```
|
||||||
|
/events
|
||||||
|
[FLOOR].json
|
||||||
|
/rooms
|
||||||
|
[FLOOR].json
|
||||||
|
floors.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Floor
|
||||||
|
Used to represent a floor in a building. It is a parent to both its [Rooms](#room) and [Events](#events).
|
||||||
|
This object gets represented in the app as a map poly, and in a set of buttons among other floors.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "[FLOOR ID]",
|
||||||
|
"poly": [
|
||||||
|
[x, y], // An array of vertex positions.
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"lang": {
|
||||||
|
"[IETF LANGUAGE TAG]": {
|
||||||
|
"name": "[SHORT SINGLE-LINE STRING]",
|
||||||
|
"description": "[SINGLE-LINE STRING]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This will be stored in an array in `floors.json` to be accessed by clients.
|
||||||
|
|
||||||
|
### Room
|
||||||
|
Used to represent a space in which events can happen. It is a child to a [Floor](#floor), and a parent to [Events](#event).
|
||||||
|
This object gets represented in the app as a map poly.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "[FLOOR]_[ROOM ID]",
|
||||||
|
"poly": [
|
||||||
|
[x, y], // An array of vertex positions.
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"lang": {
|
||||||
|
"[IETF LANGUAGE TAG]": {
|
||||||
|
"name": "[SINGLE-LINE STRING]",
|
||||||
|
"description": "[SINGLE-LINE STRING]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This will be stored in an array in `rooms/[FLOOR].json` to be accessed by clients.
|
||||||
|
|
||||||
|
### Event
|
||||||
|
Used to represent a point in time when an activity or festivity happens. It is a child to both a [Floor](#floor) and a [Room](#room), reflected in its ID.
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "[FLOOR]_[ROOM]_[EVENT ID]",
|
||||||
|
"when": {
|
||||||
|
"start": "[ISO 8601 DATE]",
|
||||||
|
"end": "[ISO 8601 DATE]"
|
||||||
|
},
|
||||||
|
"lang": {
|
||||||
|
"[IETF LANGUAGE TAG]": {
|
||||||
|
"name": "[SINGLE-LINE STRING]",
|
||||||
|
"description": "[MULTI-LINE STRING]",
|
||||||
|
"url": "[URL]"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
This will be stored in an array in `events/[FLOOR].json` to be accessed by clients.
|
|
@ -1,8 +1,4 @@
|
||||||
export class GameObjManager {
|
export class GameObjManager {
|
||||||
opts = {
|
|
||||||
floorMinZoom: 1,
|
|
||||||
roomMinZoom: 2,
|
|
||||||
};
|
|
||||||
map;
|
map;
|
||||||
|
|
||||||
mainmanager;
|
mainmanager;
|
||||||
|
@ -10,12 +6,8 @@ export class GameObjManager {
|
||||||
floorObject;
|
floorObject;
|
||||||
roomObjects = new Map([]);
|
roomObjects = new Map([]);
|
||||||
|
|
||||||
constructor(map, opts) {
|
constructor(map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
this.opts = {
|
|
||||||
...this.opts,
|
|
||||||
opts,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generateFloor() {
|
generateFloor() {
|
||||||
|
@ -58,13 +50,32 @@ export class GameObjManager {
|
||||||
this.map.kp.add(this.floorObject);
|
this.map.kp.add(this.floorObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
zoomToBounds(boundingBox) {
|
||||||
|
// Get screen size
|
||||||
|
const width = this.map.kp.width();
|
||||||
|
const height = this.map.kp.height();
|
||||||
|
|
||||||
|
// Get bbox size
|
||||||
|
const bBoxWidth = boundingBox.width * 1.5;
|
||||||
|
const bBoxHeight = boundingBox.height * 1.5;
|
||||||
|
|
||||||
|
// Compare bounds
|
||||||
|
const scaledWidth = width / bBoxWidth;
|
||||||
|
const scaledHeight = height / bBoxHeight;
|
||||||
|
|
||||||
|
// Whichever one is biggest
|
||||||
|
const scale = Math.min(scaledWidth, scaledHeight);
|
||||||
|
|
||||||
|
this.map.zoomToAbs(
|
||||||
|
Math.log2(scale), // log scale
|
||||||
|
boundingBox.center()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
zoomToFloor() {
|
zoomToFloor() {
|
||||||
const objectBounds = this.floorObject.renderArea().bbox();
|
const objectBounds = this.floorObject.renderArea().bbox();
|
||||||
|
|
||||||
this.map.zoomToAbs(
|
this.zoomToBounds(objectBounds);
|
||||||
this.map.opts.minZoomLevel + this.opts.floorMinZoom,
|
|
||||||
objectBounds.center()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomToRoom(id) {
|
zoomToRoom(id) {
|
||||||
|
@ -73,10 +84,7 @@ export class GameObjManager {
|
||||||
|
|
||||||
const objectBounds = selectedObject.renderArea().bbox();
|
const objectBounds = selectedObject.renderArea().bbox();
|
||||||
|
|
||||||
this.map.zoomToAbs(
|
this.zoomToBounds(objectBounds);
|
||||||
this.map.opts.minZoomLevel + this.opts.roomMinZoom,
|
|
||||||
objectBounds.center()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generateRooms() {
|
generateRooms() {
|
||||||
|
|
|
@ -15,12 +15,10 @@ export default new Map([
|
||||||
events_in: (name) => `Events (${name})`,
|
events_in: (name) => `Events (${name})`,
|
||||||
event_in: (location) => `In ${location}`,
|
event_in: (location) => `In ${location}`,
|
||||||
view_events_in: (name) => `Return to events in ${name}`,
|
view_events_in: (name) => `Return to events in ${name}`,
|
||||||
minimize: "Hide events panel",
|
minimize: "Toggle event panel docking",
|
||||||
maximize: "Show events panel",
|
|
||||||
event_inspector_header: (name) => `Event ${name}`,
|
event_inspector_header: (name) => `Event ${name}`,
|
||||||
event_inspector_back: "Return to events panel",
|
event_inspector_back: "Return to events panel",
|
||||||
event_inspector_minimize: "Hide event inspector",
|
event_inspector_minimize: "Toggle event inspector docking",
|
||||||
event_inspector_maximize: "Show event inspector",
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -2,7 +2,7 @@ export class KaplayMap {
|
||||||
kp;
|
kp;
|
||||||
opts = {
|
opts = {
|
||||||
minZoomLevel: 1,
|
minZoomLevel: 1,
|
||||||
maxZoomLevel: 5,
|
maxZoomLevel: 6,
|
||||||
dblClickDuration: 0.2, // s
|
dblClickDuration: 0.2, // s
|
||||||
dblClickForgiveness: 100, // px
|
dblClickForgiveness: 100, // px
|
||||||
};
|
};
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class EventMapperManager {
|
||||||
this.uimanager = new UIManager(mapUi);
|
this.uimanager = new UIManager(mapUi);
|
||||||
this.uimanager.mainmanager = this;
|
this.uimanager.mainmanager = this;
|
||||||
|
|
||||||
this.gameobjmanager = new GameObjManager(this.map, {});
|
this.gameobjmanager = new GameObjManager(this.map);
|
||||||
this.gameobjmanager.mainmanager = this;
|
this.gameobjmanager.mainmanager = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,17 +60,24 @@ export class EventMapperManager {
|
||||||
|
|
||||||
let hash = location.hash;
|
let hash = location.hash;
|
||||||
if (hash.includes("#")) hash = hash.replace("#", "");
|
if (hash.includes("#")) hash = hash.replace("#", "");
|
||||||
|
else return;
|
||||||
|
|
||||||
const floorFocus = this.convertIdFocus(hash, "floor");
|
const floorFocus = this.convertIdFocus(hash, "floor");
|
||||||
const roomFocus = this.convertIdFocus(hash, "room");
|
const roomFocus = this.convertIdFocus(hash, "room");
|
||||||
const eventFocus = this.convertIdFocus(hash, "event");
|
const eventFocus = this.convertIdFocus(hash, "event");
|
||||||
|
|
||||||
|
this.uimanager.setLoading(true);
|
||||||
if (floorFocus != this.convertFocus(prevID, "floor"))
|
if (floorFocus != this.convertFocus(prevID, "floor"))
|
||||||
await this.selectFloor(floorFocus);
|
await this.selectFloor(floorFocus);
|
||||||
|
this.uimanager.setLoading(true);
|
||||||
|
this.uimanager.setLoading(false);
|
||||||
if (roomFocus != this.convertFocus(prevID, "room"))
|
if (roomFocus != this.convertFocus(prevID, "room"))
|
||||||
await this.selectRoom(roomFocus);
|
await this.selectRoom(roomFocus);
|
||||||
|
this.uimanager.setLoading(true);
|
||||||
|
this.uimanager.setLoading(false);
|
||||||
if (eventFocus != this.convertFocus(prevID, "event"))
|
if (eventFocus != this.convertFocus(prevID, "event"))
|
||||||
await this.selectEvent(eventFocus);
|
await this.selectEvent(eventFocus);
|
||||||
|
this.uimanager.setLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
async selectFloor(id) {
|
async selectFloor(id) {
|
||||||
|
|
|
@ -49,7 +49,9 @@ export class UIManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
setEventsMinimized(state) {
|
setEventsMinimized(state) {
|
||||||
if (state) {
|
if (state == null) {
|
||||||
|
this.uiElements.eventsContainer.classList.toggle("minimized");
|
||||||
|
} else if (state) {
|
||||||
this.uiElements.eventsContainer.classList.add("minimized");
|
this.uiElements.eventsContainer.classList.add("minimized");
|
||||||
} else {
|
} else {
|
||||||
this.uiElements.eventsContainer.classList.remove("minimized");
|
this.uiElements.eventsContainer.classList.remove("minimized");
|
||||||
|
@ -57,7 +59,10 @@ export class UIManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
setEventsInspector(state) {
|
setEventsInspector(state) {
|
||||||
this.setEventsMinimized(false);
|
if (
|
||||||
|
state != this.uiElements.eventsContainer.classList.contains("inspector")
|
||||||
|
)
|
||||||
|
this.setEventsMinimized(false);
|
||||||
if (state) {
|
if (state) {
|
||||||
this.uiElements.eventsContainer.classList.add("inspector");
|
this.uiElements.eventsContainer.classList.add("inspector");
|
||||||
} else {
|
} else {
|
||||||
|
@ -81,9 +86,6 @@ export class UIManager {
|
||||||
|
|
||||||
// Floors
|
// Floors
|
||||||
this.uiElements.floors = this.ui.querySelector("#floors");
|
this.uiElements.floors = this.ui.querySelector("#floors");
|
||||||
this.uiElements.floorsHeading = this.ui.querySelector(
|
|
||||||
"#floors .widget-heading"
|
|
||||||
);
|
|
||||||
this.uiElements.floorButtons =
|
this.uiElements.floorButtons =
|
||||||
this.uiElements.floors.querySelector("#floor-buttons");
|
this.uiElements.floors.querySelector("#floor-buttons");
|
||||||
|
|
||||||
|
@ -102,10 +104,6 @@ export class UIManager {
|
||||||
this.uiElements.events.querySelector("#events-header #room-description");
|
this.uiElements.events.querySelector("#events-header #room-description");
|
||||||
this.uiElements.eventList =
|
this.uiElements.eventList =
|
||||||
this.uiElements.events.querySelector("#event-list");
|
this.uiElements.events.querySelector("#event-list");
|
||||||
this.uiElements.eventsMinimized =
|
|
||||||
this.uiElements.eventsContainer.querySelector("#events-minimized");
|
|
||||||
this.uiElements.eventsMinimizedBackButton =
|
|
||||||
this.uiElements.eventsMinimized.querySelector("#back");
|
|
||||||
|
|
||||||
this.uiElements.eventsInspector =
|
this.uiElements.eventsInspector =
|
||||||
this.uiElements.eventsContainer.querySelector("#events-inspector");
|
this.uiElements.eventsContainer.querySelector("#events-inspector");
|
||||||
|
@ -117,29 +115,16 @@ export class UIManager {
|
||||||
this.uiElements.eventsInspectorHeader.querySelector("#event-length");
|
this.uiElements.eventsInspectorHeader.querySelector("#event-length");
|
||||||
this.uiElements.eventsInspectorRoomTime =
|
this.uiElements.eventsInspectorRoomTime =
|
||||||
this.uiElements.eventsInspector.querySelector("#room-time");
|
this.uiElements.eventsInspector.querySelector("#room-time");
|
||||||
this.uiElements.eventsInspectorMinimized =
|
|
||||||
this.uiElements.eventsContainer.querySelector(
|
|
||||||
"#events-inspector-minimized"
|
|
||||||
);
|
|
||||||
this.uiElements.eventsInspectorBackButton =
|
this.uiElements.eventsInspectorBackButton =
|
||||||
this.uiElements.eventsInspector.querySelector("#back");
|
this.uiElements.eventsInspector.querySelector("#back");
|
||||||
this.uiElements.eventsInspectorBody =
|
this.uiElements.eventsInspectorBody =
|
||||||
this.uiElements.eventsInspector.querySelector("#event-body");
|
this.uiElements.eventsInspector.querySelector("#event-body");
|
||||||
this.uiElements.eventsInspectorMinimizedBackButton =
|
|
||||||
this.uiElements.eventsInspectorMinimized.querySelector("#back");
|
|
||||||
|
|
||||||
this.uiElements.minimizeButton = this.uiElements.events.querySelector(
|
this.uiElements.minimizeButton =
|
||||||
"#footer #footer-buttons #minimize"
|
this.uiElements.events.querySelector("#minimize");
|
||||||
);
|
|
||||||
this.uiElements.maximizeButton =
|
|
||||||
this.uiElements.eventsMinimized.querySelector("#maximize");
|
|
||||||
|
|
||||||
this.uiElements.eventsInspectorMinimizeButton =
|
this.uiElements.eventsInspectorMinimizeButton =
|
||||||
this.uiElements.eventsInspector.querySelector(
|
this.uiElements.eventsInspector.querySelector("#minimize");
|
||||||
"#footer #footer-buttons #minimize"
|
|
||||||
);
|
|
||||||
this.uiElements.eventsInspectorMaximizeButton =
|
|
||||||
this.uiElements.eventsInspectorMinimized.querySelector("#maximize");
|
|
||||||
|
|
||||||
// Loading
|
// Loading
|
||||||
this.uiElements.loading = this.ui.querySelector("#loading");
|
this.uiElements.loading = this.ui.querySelector("#loading");
|
||||||
|
@ -166,21 +151,11 @@ export class UIManager {
|
||||||
__initInspector() {
|
__initInspector() {
|
||||||
this.uiElements.eventsInspectorMinimizeButton.addEventListener(
|
this.uiElements.eventsInspectorMinimizeButton.addEventListener(
|
||||||
"click",
|
"click",
|
||||||
() => this.setEventsMinimized(true)
|
() => this.setEventsMinimized()
|
||||||
);
|
|
||||||
this.uiElements.eventsInspectorMaximizeButton.addEventListener(
|
|
||||||
"click",
|
|
||||||
() => this.setEventsMinimized(false)
|
|
||||||
);
|
);
|
||||||
this.uiElements.eventsInspectorBackButton.addEventListener("click", () => {
|
this.uiElements.eventsInspectorBackButton.addEventListener("click", () => {
|
||||||
window.location.hash = this.mainmanager.getCurrentFocus("room");
|
window.location.hash = this.mainmanager.getCurrentFocus("room");
|
||||||
});
|
});
|
||||||
this.uiElements.eventsInspectorMinimizedBackButton.addEventListener(
|
|
||||||
"click",
|
|
||||||
() => {
|
|
||||||
window.location.hash = this.mainmanager.getCurrentFocus("room");
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateInspector() {
|
updateInspector() {
|
||||||
|
@ -191,12 +166,8 @@ export class UIManager {
|
||||||
|
|
||||||
this.uiElements.eventsInspectorBackButton.title =
|
this.uiElements.eventsInspectorBackButton.title =
|
||||||
currentLocalization.event_inspector_back;
|
currentLocalization.event_inspector_back;
|
||||||
this.uiElements.eventsInspectorMinimizedBackButton.title =
|
|
||||||
currentLocalization.event_inspector_back;
|
|
||||||
this.uiElements.eventsInspectorMinimizeButton.title =
|
this.uiElements.eventsInspectorMinimizeButton.title =
|
||||||
currentLocalization.event_inspector_minimize;
|
currentLocalization.event_inspector_minimize;
|
||||||
this.uiElements.eventsInspectorMaximizeButton.title =
|
|
||||||
currentLocalization.event_inspector_maximize;
|
|
||||||
|
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const eventDateStart = new Date(currentEvent.when.start);
|
const eventDateStart = new Date(currentEvent.when.start);
|
||||||
|
@ -283,16 +254,10 @@ export class UIManager {
|
||||||
this.uiElements.eventsBackButton.addEventListener("click", () => {
|
this.uiElements.eventsBackButton.addEventListener("click", () => {
|
||||||
window.location.hash = this.mainmanager.getCurrentFocus("floor");
|
window.location.hash = this.mainmanager.getCurrentFocus("floor");
|
||||||
});
|
});
|
||||||
this.uiElements.eventsMinimizedBackButton.addEventListener("click", () => {
|
|
||||||
window.location.hash = this.mainmanager.getCurrentFocus("floor");
|
|
||||||
});
|
|
||||||
|
|
||||||
this.uiElements.minimizeButton.addEventListener("click", () => {
|
this.uiElements.minimizeButton.addEventListener("click", () =>
|
||||||
this.uiElements.eventsContainer.classList.add("minimized");
|
this.setEventsMinimized()
|
||||||
});
|
);
|
||||||
this.uiElements.maximizeButton.addEventListener("click", () => {
|
|
||||||
this.uiElements.eventsContainer.classList.remove("minimized");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__updateEventsSoft() {
|
__updateEventsSoft() {
|
||||||
|
@ -314,7 +279,6 @@ export class UIManager {
|
||||||
const focusedRoom = this.mainmanager.getCurrentFocusObject("room");
|
const focusedRoom = this.mainmanager.getCurrentFocusObject("room");
|
||||||
|
|
||||||
this.uiElements.minimizeButton.title = currentLocalization.minimize;
|
this.uiElements.minimizeButton.title = currentLocalization.minimize;
|
||||||
this.uiElements.maximizeButton.title = currentLocalization.maximize;
|
|
||||||
// Figure out header
|
// Figure out header
|
||||||
|
|
||||||
if (this.mainmanager.getIsFocused("room")) {
|
if (this.mainmanager.getIsFocused("room")) {
|
||||||
|
@ -329,9 +293,6 @@ export class UIManager {
|
||||||
this.uiElements.eventsBackButton.disabled = false;
|
this.uiElements.eventsBackButton.disabled = false;
|
||||||
this.uiElements.eventsBackButton.title =
|
this.uiElements.eventsBackButton.title =
|
||||||
currentLocalization.view_events_in(focusedFloor.name);
|
currentLocalization.view_events_in(focusedFloor.name);
|
||||||
this.uiElements.eventsMinimizedBackButton.disabled = false;
|
|
||||||
this.uiElements.eventsMinimizedBackButton.title =
|
|
||||||
currentLocalization.view_events_in(focusedFloor.name);
|
|
||||||
} else {
|
} else {
|
||||||
if (currentEvents.size < 1) {
|
if (currentEvents.size < 1) {
|
||||||
this.uiElements.eventsRoomName.textContent = focusedFloor.name;
|
this.uiElements.eventsRoomName.textContent = focusedFloor.name;
|
||||||
|
@ -343,8 +304,6 @@ export class UIManager {
|
||||||
focusedFloor.description;
|
focusedFloor.description;
|
||||||
this.uiElements.eventsBackButton.disabled = true;
|
this.uiElements.eventsBackButton.disabled = true;
|
||||||
this.uiElements.eventsBackButton.title = "";
|
this.uiElements.eventsBackButton.title = "";
|
||||||
this.uiElements.eventsMinimizedBackButton.disabled = true;
|
|
||||||
this.uiElements.eventsMinimizedBackButton.title = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all children
|
// Remove all children
|
||||||
|
@ -455,8 +414,6 @@ export class UIManager {
|
||||||
const mainFocus = this.mainmanager.getCurrentFocus("floor");
|
const mainFocus = this.mainmanager.getCurrentFocus("floor");
|
||||||
// Remove all children
|
// Remove all children
|
||||||
this.uiElements.floorButtons.replaceChildren();
|
this.uiElements.floorButtons.replaceChildren();
|
||||||
this.uiElements.floorsHeading.textContent =
|
|
||||||
currentLocalization.floors_header;
|
|
||||||
|
|
||||||
// Put them back
|
// Put them back
|
||||||
currentFloors.forEach(({ name }, id) => {
|
currentFloors.forEach(({ name }, id) => {
|
||||||
|
@ -486,9 +443,6 @@ export class UIManager {
|
||||||
const currentFloors = this.mainmanager.getAllFocusObject("floor");
|
const currentFloors = this.mainmanager.getAllFocusObject("floor");
|
||||||
const mainFocus = this.mainmanager.getCurrentFocus("floor");
|
const mainFocus = this.mainmanager.getCurrentFocus("floor");
|
||||||
|
|
||||||
this.uiElements.floorsHeading.textContent =
|
|
||||||
currentLocalization.floors_header;
|
|
||||||
|
|
||||||
currentFloors.forEach((_, id) => {
|
currentFloors.forEach((_, id) => {
|
||||||
const child = this.uiElements.floorButtons.querySelector("#floor-" + id);
|
const child = this.uiElements.floorButtons.querySelector("#floor-" + id);
|
||||||
if (id === mainFocus) child.classList.add("selected");
|
if (id === mainFocus) child.classList.add("selected");
|
||||||
|
|
|
@ -15,7 +15,7 @@ h1.widget-heading {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
letter-spacing: 0.25em;
|
/* letter-spacing: 0.25em; */
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
/* border-bottom: 1px solid currentColor;
|
/* border-bottom: 1px solid currentColor;
|
||||||
padding-bottom: 2px; */
|
padding-bottom: 2px; */
|
||||||
|
@ -136,15 +136,13 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #floors #floor-buttons .floor-button {
|
#map-ui #floors #floor-buttons .floor-button {
|
||||||
text-align: left;
|
display: inline-block;
|
||||||
width: 200px;
|
width: 36px;
|
||||||
padding: 12px;
|
height: 36px;
|
||||||
height: unset;
|
padding: 4px;
|
||||||
}
|
}
|
||||||
#map-ui #floors #floor-buttons .floor-button.selected {
|
#map-ui #floors #floor-buttons .floor-button.selected {
|
||||||
padding-left: 9px;
|
|
||||||
border: 1px solid #fff;
|
border: 1px solid #fff;
|
||||||
border-left: 4px solid #fff;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container {
|
#map-ui #events-container {
|
||||||
|
@ -156,51 +154,57 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events,
|
#map-ui #events-container #events,
|
||||||
#map-ui #events-container #events-minimized,
|
#map-ui #events-container #events-inspector {
|
||||||
#map-ui #events-container #events-inspector,
|
|
||||||
#map-ui #events-container #events-inspector-minimized {
|
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
display: inline-block;
|
display: inline-flex;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
gap: 8px;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
left: 16px;
|
||||||
bottom: 16px;
|
bottom: 16px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
left: -100%;
|
translate: 0 calc(100% + 32px);
|
||||||
background-color: #202020;
|
background-color: #202020;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
box-shadow: 0 0 8px 0 #0008;
|
box-shadow: 0 0 8px 0 #0008;
|
||||||
transition: left 0.5s;
|
transition: translate 0.25s, bottom 0.25s, width 0.25s, border-radius 0.25s;
|
||||||
}
|
max-height: calc(50vh - 16px);
|
||||||
|
flex-direction: column;
|
||||||
#map-ui #events-container #events,
|
|
||||||
#map-ui #events-container #events-inspector {
|
|
||||||
width: 400px;
|
width: 400px;
|
||||||
max-width: calc(100% - 32px);
|
max-width: calc(100% - 32px);
|
||||||
|
z-index: 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container:not(.empty):not(.inspector):not(.minimized) #events {
|
#map-ui #events-container:not(.inspector) #events,
|
||||||
left: 16px;
|
#map-ui #events-container.inspector #events-inspector {
|
||||||
|
translate: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container:not(.empty):not(.inspector).minimized #events-minimized {
|
#map-ui #events-container:not(.inspector) #events,
|
||||||
left: 16px;
|
#map-ui #events-container.inspector #events-inspector {
|
||||||
|
translate: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container:not(.empty):not(.minimized).inspector #events-inspector {
|
#map-ui #events-container:not(.inspector).minimized #events,
|
||||||
left: 16px;
|
#map-ui #events-container.inspector.minimized #events-inspector {
|
||||||
|
bottom: 0;
|
||||||
|
translate: 0 calc(100% - 52px);
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container:not(.empty).minimized.inspector #events-inspector-minimized {
|
#map-ui #events-container.empty #events,
|
||||||
left: 16px;
|
#map-ui #events-container.empty #events-inspector {
|
||||||
|
translate: 0 calc(100% + 32px);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* #map-ui #floors.empty ~ #events-container #events,
|
#map-ui #events-container.minimized #events #room-description,
|
||||||
#map-ui #floors.empty ~ #events-container #events-inspector,
|
#map-ui #events-container.minimized #events-inspector #event-length {
|
||||||
#map-ui #floors.empty ~ #events-container #events-minimized,
|
display: none;
|
||||||
#map-ui #floors.empty ~ #events-container #events-inspector-minimized {
|
}
|
||||||
left: -100% !important;
|
|
||||||
} */
|
#map-ui #events-container.minimized #room-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events #footer #footer-buttons,
|
#map-ui #events-container #events #footer #footer-buttons,
|
||||||
#map-ui #events-container #events-inspector #footer #footer-buttons {
|
#map-ui #events-container #events-inspector #footer #footer-buttons {
|
||||||
|
@ -214,28 +218,15 @@ a {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events #events-header,
|
#map-ui #events-container #events-header {
|
||||||
#map-ui #events-container #events-inspector #events-header {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 36px auto;
|
align-items: start;
|
||||||
|
grid-template-columns: 36px auto 36px;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
margin-bottom: 8px;
|
|
||||||
/* align-items: center; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events #event-list {
|
#map-ui #events-container.minimized #events-header {
|
||||||
/* min-height: 100px; */
|
align-items: center;
|
||||||
max-height: calc(50% - 16px);
|
|
||||||
margin: 8px 0;
|
|
||||||
padding: 8px;
|
|
||||||
background-color: #0002;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
/* transition: height 0.25s,
|
|
||||||
min-height 0.25s,
|
|
||||||
padding 0.25s,
|
|
||||||
margin 0.25s; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events.empty #event-list {
|
#map-ui #events-container #events.empty #event-list {
|
||||||
|
@ -248,19 +239,23 @@ a {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#map-ui #events-container #events #event-list,
|
||||||
#map-ui #events-container #events-inspector #event-body {
|
#map-ui #events-container #events-inspector #event-body {
|
||||||
/* min-height: 100px; */
|
width: 100%;
|
||||||
max-height: calc(50% - 16px);
|
overflow-y: auto;
|
||||||
margin: 8px 0;
|
overflow-x: hidden;
|
||||||
|
box-sizing: border-box;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
background-color: #0002;
|
background-color: #0002;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 4px;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#map-ui #events-container #events #events-header button,
|
#map-ui #events-container #events #events-header button,
|
||||||
#map-ui #events-container #footer #footer-buttons button,
|
#map-ui #events-container #footer #footer-buttons button,
|
||||||
#map-ui #events-container #events-inspector #events-header button:not(.link),
|
#map-ui #events-container #events-inspector #events-header button:not(.link) {
|
||||||
#map-ui #events-container #events-minimized button,
|
|
||||||
#map-ui #events-container #events-inspector-minimized button {
|
|
||||||
width: 36px;
|
width: 36px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,4 +287,14 @@ a {
|
||||||
-webkit-mask-image: radial-gradient(circle, #fff0 0%, #fff0 33%, #ffff 33%, #ffff 66%, #fff0 66%, #fff0 100%);
|
-webkit-mask-image: radial-gradient(circle, #fff0 0%, #fff0 33%, #ffff 33%, #ffff 66%, #fff0 66%, #fff0 100%);
|
||||||
mask-image: radial-gradient(circle, #fff0 0%, #fff0 33%, #ffff 33%, #ffff 66%, #fff0 66%, #fff0 100%);
|
mask-image: radial-gradient(circle, #fff0 0%, #fff0 33%, #ffff 33%, #ffff 66%, #fff0 66%, #fff0 100%);
|
||||||
animation: load 0.5s linear infinite;
|
animation: load 0.5s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
#map-ui #events-container #events,
|
||||||
|
#map-ui #events-container #events-inspector {
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 33vh;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -19,7 +19,6 @@
|
||||||
<button class="zoom-button" id="zoom-out" disabled>-</button>
|
<button class="zoom-button" id="zoom-out" disabled>-</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="floors" class="empty">
|
<div id="floors" class="empty">
|
||||||
<h1 class="widget-heading"></h1>
|
|
||||||
<div id="floor-buttons">
|
<div id="floor-buttons">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -32,19 +31,11 @@
|
||||||
<h1 class="widget-heading" id="room-name"></h1>
|
<h1 class="widget-heading" id="room-name"></h1>
|
||||||
<p class="widget-description" id="room-description"></p>
|
<p class="widget-description" id="room-description"></p>
|
||||||
</div>
|
</div>
|
||||||
|
<button id="minimize">_</button>
|
||||||
</div>
|
</div>
|
||||||
<div id="event-list">
|
<div id="event-list">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
|
||||||
<div id="footer-buttons">
|
|
||||||
<button id="minimize">_</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="events-minimized">
|
|
||||||
<button id="maximize">‾</button>
|
|
||||||
<button id="back" disabled>↑</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div id="events-inspector">
|
<div id="events-inspector">
|
||||||
<div id="events-header">
|
<div id="events-header">
|
||||||
|
@ -53,19 +44,11 @@
|
||||||
<h1 class="widget-heading" id="room-name"></h1>
|
<h1 class="widget-heading" id="room-name"></h1>
|
||||||
<p class="widget-description subtitle" id="event-length"></p>
|
<p class="widget-description subtitle" id="event-length"></p>
|
||||||
</div>
|
</div>
|
||||||
|
<button id="minimize">_</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="widget-description" id="room-time"></p>
|
<p class="widget-description" id="room-time"></p>
|
||||||
<div id="event-body">
|
<div id="event-body">
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
|
||||||
<div id="footer-buttons">
|
|
||||||
<button id="minimize">_</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="events-inspector-minimized">
|
|
||||||
<button id="maximize">‾</button>
|
|
||||||
<button id="back">←</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="loading">
|
<div id="loading">
|
||||||
|
|
|
@ -19,21 +19,14 @@ app.get('/data/:lang/events/:floor', async (req, res) => {
|
||||||
else
|
else
|
||||||
return res.status(400).send("Bad Request");
|
return res.status(400).send("Bad Request");
|
||||||
|
|
||||||
// Get localization
|
|
||||||
let l10nReq = await fetch(new URL(`localization/${req.params.lang}.json`, config.data_url));
|
|
||||||
let l10n;
|
|
||||||
if (l10nReq.ok)
|
|
||||||
l10n = await l10nReq.json();
|
|
||||||
else
|
|
||||||
return res.status(404).send("Localization not found!");
|
|
||||||
|
|
||||||
// Merge events and localization
|
// Merge events and localization
|
||||||
|
const lang = req.params.lang;
|
||||||
const merged = events.map(event => {
|
const merged = events.map(event => {
|
||||||
const localizationKey = l10n.__events[event.id];
|
event.name = event.lang[lang]?.name ?? "";
|
||||||
return {
|
event.description = event.lang[lang]?.description ?? "";
|
||||||
...event,
|
event.url = event.lang[lang]?.url ?? "";
|
||||||
...localizationKey
|
delete event.lang;
|
||||||
};
|
return event;
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.send(merged);
|
return res.send(merged);
|
||||||
|
@ -48,21 +41,13 @@ app.get('/data/:lang/floors', async (req, res) => {
|
||||||
else
|
else
|
||||||
return res.status(400).send("Bad Request");
|
return res.status(400).send("Bad Request");
|
||||||
|
|
||||||
// Get localization
|
|
||||||
let l10nReq = await fetch(new URL(`localization/${req.params.lang}.json`, config.data_url));
|
|
||||||
let l10n;
|
|
||||||
if (l10nReq.ok)
|
|
||||||
l10n = await l10nReq.json();
|
|
||||||
else
|
|
||||||
return res.status(404).send("Localization not found!");
|
|
||||||
|
|
||||||
// Merge layers and localization
|
// Merge layers and localization
|
||||||
|
const lang = req.params.lang;
|
||||||
const merged = layers.map(layer => {
|
const merged = layers.map(layer => {
|
||||||
const localizationKey = l10n.__layers[layer.id];
|
layer.name = layer.lang[lang]?.name ?? "";
|
||||||
return {
|
layer.description = layer.lang[lang]?.description ?? "";
|
||||||
...layer,
|
delete layer.lang;
|
||||||
...localizationKey
|
return layer;
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.send(merged);
|
return res.send(merged);
|
||||||
|
@ -77,21 +62,13 @@ app.get('/data/:lang/rooms/:floor', async (req, res) => {
|
||||||
else
|
else
|
||||||
return res.status(400).send("Bad Request");
|
return res.status(400).send("Bad Request");
|
||||||
|
|
||||||
// Get localization
|
|
||||||
let l10nReq = await fetch(new URL(`localization/${req.params.lang}.json`, config.data_url));
|
|
||||||
let l10n;
|
|
||||||
if (l10nReq.ok)
|
|
||||||
l10n = await l10nReq.json();
|
|
||||||
else
|
|
||||||
return res.status(404).send("Localization not found!");
|
|
||||||
|
|
||||||
// Merge rooms and localization
|
// Merge rooms and localization
|
||||||
|
const lang = req.params.lang;
|
||||||
const merged = rooms.map(room => {
|
const merged = rooms.map(room => {
|
||||||
const localizationKey = l10n.__rooms[room.id];
|
room.name = room.lang[lang]?.name ?? "";
|
||||||
return {
|
room.description = room.lang[lang]?.description ?? "";
|
||||||
...room,
|
delete room.lang;
|
||||||
...localizationKey
|
return room;
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.send(merged);
|
return res.send(merged);
|
||||||
|
@ -101,4 +78,6 @@ app.listen(config.port, () => {
|
||||||
const listeningURL = new URL("http://localhost/");
|
const listeningURL = new URL("http://localhost/");
|
||||||
listeningURL.port = config.port;
|
listeningURL.port = config.port;
|
||||||
console.log(`Example app listening on ${listeningURL.toString()}`)
|
console.log(`Example app listening on ${listeningURL.toString()}`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export default app;
|
Loading…
Reference in a new issue