diff --git a/marko/components/right-menu/index.marko b/marko/components/right-menu/index.marko
new file mode 100644
index 0000000..97132f3
--- /dev/null
+++ b/marko/components/right-menu/index.marko
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/marko/components/right-menu/style.less b/marko/components/right-menu/style.less
new file mode 100644
index 0000000..0340a63
--- /dev/null
+++ b/marko/components/right-menu/style.less
@@ -0,0 +1,26 @@
+.right-menu {
+ position: fixed;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ width: 28ch;
+
+ padding: 0.333em;
+ padding-bottom: 1em;
+
+ text-align: left;
+
+ user-select: none;
+ overflow-x: hidden;
+ overflow-y: auto;
+
+ .showhide {
+ display: none;
+ }
+}
+
+@media screen and (max-width: 800px) {
+ .right-menu {
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/marko/global/base.less b/marko/global/base.less
index b302f07..e4a07cf 100644
--- a/marko/global/base.less
+++ b/marko/global/base.less
@@ -10,6 +10,11 @@ body {
width: calc(100% - 32ch);
margin-right: 0;
}
+ @media screen and (min-width: 700px) {
+ main.with-right {
+ width: calc(100% - 60ch)
+ }
+ }
a {
text-decoration: none;
diff --git a/marko/page/logs/components/filter-menu/component.js b/marko/page/logs/components/filter-menu/component.js
new file mode 100644
index 0000000..36bb547
--- /dev/null
+++ b/marko/page/logs/components/filter-menu/component.js
@@ -0,0 +1,129 @@
+module.exports = class {
+ onCreate(input) {
+ this.state = {
+ characters: [],
+ channels: [],
+ eventNames: [],
+ filters: [],
+ search: "",
+ activeMap: {
+ events: {},
+ characters: {},
+ channels: {},
+ },
+ }
+ }
+
+ onInput(input) {
+ this.update(input)
+ }
+
+ onMount(input) {
+ this.getEl("search").addEventListener("keydown", ev => {
+ if (this.waiting) {
+ return
+ }
+
+ if (this.timeout != null) {
+ clearTimeout(this.timeout)
+ }
+
+ if (ev.key === "Enter") {
+ this.emit("add", "search", ev.target.value)
+ this.getEl("search").value = ""
+ }
+
+ this.timeout = setTimeout(() => {
+ this.timeout = null
+ this.state.search = ev.target.value
+
+ this.update(this.input)
+ }, 200)
+ })
+ }
+
+ update(input) {
+ if (input.filter) {
+ this.updateActive(input)
+ }
+
+ const search = this.state.search.toLocaleLowerCase()
+
+ this.state.characters = input.characters.filter(c => !this.state.activeMap.characters[c.id]).filter(c => this.matches(c.name, search)).sort((a,b) => a.name.localeCompare(b.name))
+ this.state.channels = input.channels.filter(c => !this.state.activeMap.channels[c.name]).filter(c => this.matches(c.name, search)).sort((a,b) => a.name.localeCompare(b.name))
+ this.state.eventNames = input.eventNames.filter(e => !this.state.activeMap.events[e]).filter(e => this.matches(e, search)).sort((a,b) => a.localeCompare(b))
+ }
+
+ updateActive({filter, characters, channels, eventNames}) {
+ const filters = []
+ const activeMap = {
+ events: {},
+ characters: {},
+ channels: {},
+ }
+
+ if (filter.search != null) {
+ filters.push({
+ type: "search",
+ key: "search",
+ icon: "T",
+ color: "color-text",
+ text: filter.search,
+ })
+ }
+
+ for (const character of (filter.characters || [])) {
+ activeMap.characters[character] = true
+
+ filters.push({
+ type: "characters",
+ key: character,
+ icon: "C",
+ color: "color-tag-character",
+ id: character,
+ text: (characters.find(c => c.id === character) || {name: "Unknown ("+character+")"}).name,
+ })
+ }
+
+ for (const channel of (filter.channels || [])) {
+ activeMap.channels[channel] = true
+
+ filters.push({
+ type: "channels",
+ key: channel.replace(/'/g, "__"),
+ icon: "#",
+ color: "color-tag-location",
+ id: channel,
+ text: channel,
+ })
+ }
+
+ for (const event of (filter.events || [])) {
+ activeMap.events[event] = true
+
+ filters.push({
+ type: "events",
+ key: event.replace(/['\s\.]/g, "__"),
+ icon: "E",
+ color: "color-tag-event",
+ id: event,
+ text: event,
+ })
+ }
+
+ this.state.filters = filters
+ this.state.activeMap = activeMap
+ }
+
+ matches(str, search) {
+ if (search == "") {
+ return true
+ }
+
+ if (search.length > str.length) {
+ return false
+ }
+
+ return str.toLowerCase().indexOf(search) !== -1
+ }
+}
\ No newline at end of file
diff --git a/marko/page/logs/components/filter-menu/index.marko b/marko/page/logs/components/filter-menu/index.marko
new file mode 100644
index 0000000..7c51505
--- /dev/null
+++ b/marko/page/logs/components/filter-menu/index.marko
@@ -0,0 +1,36 @@
+
\ No newline at end of file
diff --git a/marko/page/logs/components/filter-menu/style.less b/marko/page/logs/components/filter-menu/style.less
new file mode 100644
index 0000000..cef6bc2
--- /dev/null
+++ b/marko/page/logs/components/filter-menu/style.less
@@ -0,0 +1,24 @@
+div.right-menu.filter-menu {
+ input {
+ background: none;
+ border: none;
+ outline: none;
+ width: 95%;
+ margin-top: 1em;
+ margin-left: 2.5%;
+ border: 1px solid rgba(119, 119, 119, 0.25);
+ font-size: 1.1em;
+ box-sizing: border-box;
+
+ color: #999;
+ }
+ input:focus {
+ color: #FC1;
+ }
+
+ div.filter-section {
+ max-height: calc(25vh - 3em);
+ overflow-y: auto;
+ overflow-x: hidden;
+ }
+}
\ No newline at end of file
diff --git a/marko/page/logs/components/logs-menu/component.js b/marko/page/logs/components/logs-menu/component.js
index 13fd610..c9bce8c 100644
--- a/marko/page/logs/components/logs-menu/component.js
+++ b/marko/page/logs/components/logs-menu/component.js
@@ -13,54 +13,7 @@ module.exports = class {
return
}
- const filters = []
- const {characters, channels, events, search} = input.filter
-
- if (search != null) {
- filters.push({
- type: "search",
- key: "search",
- icon: "T",
- color: "color-text",
- text: search,
- })
- }
-
- for (const character of (characters || [])) {
- filters.push({
- type: "characters",
- key: character,
- icon: "C",
- color: "color-tag-character",
- id: character,
- text: (input.characters.find(c => c.id === character) || {name: "Unknown ("+character+")"}).name,
- })
- }
-
- for (const channel of (channels || [])) {
- filters.push({
- type: "channels",
- key: channel.replace(/'/g, "__"),
- icon: "#",
- color: "color-tag-location",
- id: channel,
- text: channel,
- })
- }
-
- for (const event of (events || [])) {
- filters.push({
- type: "events",
- key: event.replace(/['\s\.]/g, "__"),
- icon: "E",
- color: "color-tag-event",
- id: event,
- text: event,
- })
- }
-
- this.state.filters = filters
- this.state.filtered = (filters.length > 0)
+ this.state.filtered = input.filter.search || input.filter.channels || input.filter.characters || input.filter.events
}
select(value) {
diff --git a/marko/page/logs/components/logs-menu/index.marko b/marko/page/logs/components/logs-menu/index.marko
index 8051914..16c6ff0 100644
--- a/marko/page/logs/components/logs-menu/index.marko
+++ b/marko/page/logs/components/logs-menu/index.marko
@@ -4,8 +4,4 @@
Add Log
-
- Filters
- ${filter.text}
- Add Filter
\ No newline at end of file
diff --git a/marko/page/logs/components/logs-table-row/style.less b/marko/page/logs/components/logs-table-row/style.less
index 3fde21f..1756092 100644
--- a/marko/page/logs/components/logs-table-row/style.less
+++ b/marko/page/logs/components/logs-table-row/style.less
@@ -10,11 +10,17 @@ tr.logs-table-row {
}
td.expand {
- width: 2%;
+ width: 0%;
}
- td.channel, td.date, td.eventĀ {
- width: 12%;
+ td.date {
+ width: 16%;
+ }
+ td.channel {
+ width: 14%;
+ }
+ td.eventĀ {
+ width: 18%;
}
td.character {
diff --git a/marko/page/logs/components/logs-table/style.less b/marko/page/logs/components/logs-table/style.less
index 9f8091e..da8e81b 100644
--- a/marko/page/logs/components/logs-table/style.less
+++ b/marko/page/logs/components/logs-table/style.less
@@ -9,7 +9,7 @@ table.logs-table {
text-decoration: underline;
}
- @media screen and (max-width: 900px) {
+ @media screen and (max-width: 1200px) {
td.event, th.event {
display: none;
}
diff --git a/marko/page/logs/components/page/component.js b/marko/page/logs/components/page/component.js
index 61aa792..cd3b24a 100644
--- a/marko/page/logs/components/page/component.js
+++ b/marko/page/logs/components/page/component.js
@@ -19,11 +19,18 @@ module.exports = class {
addFilter(type, filter) {
if (type === "search") {
- this.state.filter = Object.assign({}, this.state.filter, {search: filter})
+ if (filter.trim().length > 0) {
+ this.state.filter = Object.assign({}, this.state.filter, {search: filter})
+ } else {
+ this.state.filter = Object.assign({}, this.state.filter, {search: null})
+ }
+
} else {
this.state.filter = Object.assign({}, this.state.filter, {[type]: (this.state.filter[type] || []).filter(f => f !== filter).concat(filter)})
}
+ this.updateQuery(this.state.filter)
+
this.refresh()
}
@@ -41,6 +48,31 @@ module.exports = class {
this.refresh()
}
}
+
+ this.updateQuery(this.state.filter)
+ }
+
+ updateQuery(filter) {
+ const queries = []
+
+ if (filter.characters) {
+ queries.push("characters=" + filter.characters.join(","))
+ }
+ if (filter.channels) {
+ queries.push("channels=" + filter.channels.map(c => encodeURIComponent(c)).join(","))
+ }
+ if (filter.events) {
+ queries.push("events=" + filter.events.map(e => encodeURIComponent(e)).join(","))
+ }
+ if (filter.search) {
+ queries.push("search=" + encodeURIComponent(filter.search))
+ }
+
+ if (queries.length > 0) {
+ history.replaceState("", "", `/logs/?${queries.join("&")}`)
+ } else {
+ history.replaceState("", "", "/logs/")
+ }
}
refresh() {
diff --git a/marko/page/logs/components/page/index.marko b/marko/page/logs/components/page/index.marko
index 2c438f8..774aed1 100644
--- a/marko/page/logs/components/page/index.marko
+++ b/marko/page/logs/components/page/index.marko
@@ -1,7 +1,7 @@
-
-
+
+
+
-
diff --git a/marko/page/logs/list.marko b/marko/page/logs/list.marko
index 99741c2..1793abd 100644
--- a/marko/page/logs/list.marko
+++ b/marko/page/logs/list.marko
@@ -1,6 +1,11 @@
<@body>
-
-
+
@body>
\ No newline at end of file
diff --git a/routes/logs/index.js b/routes/logs/index.js
index 2272189..b73620a 100644
--- a/routes/logs/index.js
+++ b/routes/logs/index.js
@@ -3,6 +3,7 @@ const router = express.Router()
const {logHeaderApi, eventNames} = require("../../rpdata/api/LogHeader")
const {charactersApi} = require("../../rpdata/api/Character")
+const {channelApi} = require("../../rpdata/api/Channel")
const listTemplate = require("../../marko/page/logs/list.marko")
@@ -27,6 +28,8 @@ router.get("/", async(req, res) => {
filter: filter,
logs: logHeaderApi.list(filter),
characters: charactersApi.listHeaders(),
+ channels: channelApi.list(),
+ eventNames: logHeaderApi.eventNames(),
selected: {index: true},
})
} catch(err) {