From d393b5478c0278956d5c0cbd26e0e86d9428cc1f Mon Sep 17 00:00:00 2001 From: julian laplace Date: Wed, 26 Oct 2022 23:03:51 +0200 Subject: filters --- public/assets/js/lib/views/stream/hootfilters.js | 63 ++++++++++- public/assets/js/lib/views/stream/hootstream.js | 129 ++++++++++++++++++----- public/assets/js/lib/views/stream/index.js | 15 ++- public/assets/js/util/format.js | 3 + views/hootstream/filters.ejs | 23 ++-- views/partials/scripts.ejs | 1 + 6 files changed, 187 insertions(+), 47 deletions(-) diff --git a/public/assets/js/lib/views/stream/hootfilters.js b/public/assets/js/lib/views/stream/hootfilters.js index bb060af..c58baa4 100644 --- a/public/assets/js/lib/views/stream/hootfilters.js +++ b/public/assets/js/lib/views/stream/hootfilters.js @@ -1,10 +1,34 @@ var HootFilters = View.extend({ el: "#hootfilters", - events: {}, + events: { + "change .filter input": "filter", + "click [name=sort]": "sort", + }, initialize: function (opt) { this.__super__.initialize.call(this); + this.parent = opt.parent; + this.$images = this.$("[name=images]"); + this.$music = this.$("[name=music]"); + this.$files = this.$("[name=files]"); + this.$hoots = this.$("[name=hoots]"); + this.$sortOrder = this.$(".sort"); + this.$sort = this.$("[name=sort]"); + this.state = { + images: true, + music: true, + files: true, + hoots: true, + sort: "name", + order: "asc", + }; + this.$images.prop("checked", this.state.images); + this.$music.prop("checked", this.state.music); + this.$files.prop("checked", this.state.files); + this.$hoots.prop("checked", this.state.hoots); + this.$sort.filter(`[value=${this.state.sort}]`).prop("checked", true); + this.update(this.state); }, show: function () { @@ -15,5 +39,42 @@ var HootFilters = View.extend({ this.$el.hide(); }, + update: function (state) { + this.state = state; + // console.log(this.state.sort, this.state.order); + this.$sortOrder.toggleClass( + "sortDesc", + this.state.sort === "date" + ? this.state.order === "asc" + : this.state.order === "desc" + ); + }, + load: function () {}, + + filter: function (event) { + const { name, checked } = event.target; + // console.log(name, checked); + this.update({ + ...this.state, + [name]: checked, + }); + this.parent.onFilter(this.state); + }, + + sort: function (event) { + const { name, value } = event.target; + console.log(name, value); + this.update({ + ...this.state, + sort: value, + order: + value === this.state.sort + ? this.state.order === "desc" + ? "asc" + : "desc" + : "asc", + }); + this.parent.onFilter(this.state); + }, }); diff --git a/public/assets/js/lib/views/stream/hootstream.js b/public/assets/js/lib/views/stream/hootstream.js index 70d2b2a..a67f4b8 100644 --- a/public/assets/js/lib/views/stream/hootstream.js +++ b/public/assets/js/lib/views/stream/hootstream.js @@ -1,5 +1,3 @@ -const IMAGE_REGEXP = /(.gif|.jpg|.jpeg|.png)$/gi; - var HootStream = View.extend({ el: "#hootstream", @@ -47,28 +45,109 @@ var HootStream = View.extend({ // this.parent.onKeyword(keyword) }, - load: function (data) { - this.$hootevents.empty(); - const { order, threadLookup } = this.agglutinate(data); - // console.log(data, threadLookup, order); - const $els = order.map( - function (item) { - // console.log(item.type, item.thread_id); - return item.type === "thread" - ? this.renderThread({ - ...threadLookup[item.thread_id], + load: function (data, filters) { + this.state = { + ...this.agglutinate(data), + data, + filters, + }; + this.build(filters); + }, + + build: function (filters) { + const { data, order, threadLookup } = this.state; + const threads = Object.values(threadLookup); + + let sortedOrder; + + if (filters.sort === "name") { + sortedOrder = threads + .reduce((names, values) => { + if (values.thread.length) { + return names.concat([ + [values.thread[0].title, values.thread[0].id], + ]); + } + return names; + }, []) + .sort( + filters.order === "asc" + ? (a, b) => a[0].localeCompare(b[0]) + : (a, b) => b[0].localeCompare(a[0]) + ) + .map(([, thread_id]) => ({ + type: "thread", + thread_id, + })); + } else if (filters.sort === "date") { + sortedOrder = filters.order === "desc" ? order : [...order].reverse(); + } else { + sortedOrder = order; + } + // console.log(sortedOrder, threadLookup); + + const $els = sortedOrder + .filter(({ type, thread_id }) => { + if (filters.hoots && (type === "hoot" || type === "lastlog")) { + return true; + } + const thread = threadLookup[thread_id]; + if (filters.hoots && thread.comments?.length) { + return true; + } + if ( + filters.music && + thread.files?.some((file) => AUDIO_REGEXP.test(file.filename)) + ) { + return true; + } + if ( + filters.images && + thread.files?.some((file) => IMAGE_REGEXP.test(file.filename)) + ) { + return true; + } + return false; + }) + .map( + function ({ type, thread_id, data: itemData }) { + // console.log(type, thread_id); + if (type === "thread") { + const thread = threadLookup[thread_id]; + const threadData = { + ...thread, + files: + filters.images || filters.music + ? thread.files.filter((file) => { + if (AUDIO_REGEXP.test(file.filename)) { + return filters.music; + } + if (IMAGE_REGEXP.test(file.filename)) { + return filters.images; + } + return filters.files; + }) + : [], + comments: filters.hoots ? thread.comments : [], query: data.query, - }).reduce( - ($el, $item) => $el.append($item), - $("
") - ) - : item.type === "hoot" - ? this.renderHoot(item.data) - : item.type === "lastlog" - ? this.renderLastlog(item.data) - : "Unknown item"; - }.bind(this) - ); + }; + if (threadData.files.length || threadData.comments.length) { + return this.renderThread(threadData).reduce( + ($el, $item) => $el.append($item), + $("
") + ); + } else { + return $(); + } + } + return type === "hoot" + ? this.renderHoot(itemData) + : type === "lastlog" + ? this.renderLastlog(itemData) + : "Unknown item"; + }.bind(this) + ); + this.$hootevents.empty(); this.$hootevents.append($els); audio.init(); }, @@ -142,7 +221,7 @@ var HootStream = View.extend({ console.error(thread, comments, files, images); return ["
Missing thread!
"]; } - thread = thread.shift(); + thread = thread[0]; const isViewingKeyword = query.keyword === thread.keyword; const isViewingThread = query.thread === thread.id; // console.log(thread, comments, files, images); @@ -153,7 +232,7 @@ var HootStream = View.extend({ 0.0, 1.0 ); - console.log(thread); + // console.log(thread); return [ "
", this.renderHoot({ diff --git a/public/assets/js/lib/views/stream/index.js b/public/assets/js/lib/views/stream/index.js index 76dbfa8..8ef9208 100644 --- a/public/assets/js/lib/views/stream/index.js +++ b/public/assets/js/lib/views/stream/index.js @@ -3,12 +3,9 @@ var StreamView = View.extend({ initialize: function (opt) { // opt.parent = parent - // this.hootbox = new HootBox({ parent: this }); this.hootform = new HootForm({ parent: this }); this.hootstream = new HootStream({ parent: this }); - // this.threadbox = new ThreadBox({ parent: this }); - // this.lastlog = new LastLog({ parent: this }); - // this.countdown = new Countdown({ parent: this }); + this.hootfilters = new HootFilters({ parent: this }); }, load: function ({ ...target }) { @@ -20,11 +17,7 @@ var StreamView = View.extend({ populate: function (data) { $("body").removeClass("loading"); this.data = data; - this.hootstream.load(data); - // this.hootbox.load(data.hootbox); - // this.hootbox.hide(); - // this.threadbox.load(data); - // this.lastlog.load(data.lastlog); + this.hootstream.load(data, this.hootfilters.state); if (data.mail.count) { $(".alert") .show() @@ -49,6 +42,10 @@ var StreamView = View.extend({ this.populate(this.data); }, + onFilter: function (filters) { + this.hootstream.build(filters); + }, + success: function () { window.location.href = "/index"; }, diff --git a/public/assets/js/util/format.js b/public/assets/js/util/format.js index c477a9a..224678e 100644 --- a/public/assets/js/util/format.js +++ b/public/assets/js/util/format.js @@ -6,6 +6,9 @@ var is_mobile = is_iphone || is_ipad || is_android; var is_desktop = !is_mobile; document.body.classList.add(is_desktop ? "desktop" : "mobile"); +const AUDIO_REGEXP = /(mp3|wav|aif|aiff|ogg|opus|flac)$/i; +const IMAGE_REGEXP = /(.gif|.jpg|.jpeg|.png)$/i; + function choice(a) { return a[randint(a.length)]; } diff --git a/views/hootstream/filters.ejs b/views/hootstream/filters.ejs index 27177aa..34ac4b9 100644 --- a/views/hootstream/filters.ejs +++ b/views/hootstream/filters.ejs @@ -1,29 +1,28 @@
-
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 6cfaf4d..bf65bff 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -35,6 +35,7 @@ + -- cgit v1.2.3-70-g09d2