Merge branch 'master' into gh

This commit is contained in:
lesion 2023-02-07 17:46:58 +01:00
commit 4367960a62
No known key found for this signature in database
GPG key ID: 352918250B012177
53 changed files with 1486 additions and 989 deletions

View file

@ -1,8 +1,11 @@
All notable changes to this project will be documented in this file.
###
- models initialization refactored, better dev xperience as backend hmr is working
### 1.6.2 - 12 jan '23
- add swipe gesture to move to next/prev event
- fix refresh collections, fix #219
- add russian translation (thanks @drunkod)
- refactor search / filter / selection fix #225, 227, #224
- models initialization refactored, better dev experience, fix backend HMR
### 1.6.1 - 15 dec '22
- allow edit tags in admin panel, fix #170

View file

@ -4,7 +4,7 @@
ref='cal'
v-model='selectedDate'
title-position='left'
:is-dark="settings['theme.is_dark']"
:is-dark="is_dark"
:columns="!$vuetify.breakpoint.smAndDown ? 2 : 1"
@input='click'
@update:from-page='updatePage'
@ -15,20 +15,14 @@
aria-label='Calendar'
is-expanded
is-inline)
//- template(v-slot="{ inputValue, inputEvents }")
v-btn#calendarButton(v-on='inputEvents' text tile :color='selectedDate ? "primary" : "" ') {{inputValue || $t('common.calendar')}}
v-icon(v-if='selectedDate' v-text='mdiClose' right small icon @click.prevent.stop='selectedDate = null')
v-icon(v-else v-text='mdiChevronDown' right small icon)
.calh.d-flex.justify-center.align-center(slot='placeholder')
v-progress-circular(indeterminate)
//- v-btn#calendarButton(text tile) {{$t('common.calendar')}}
//- v-icon(v-text='mdiChevronDown' right small icon)
</template>
</template>
<script>
import { mapState } from 'vuex'
import { mapState, mapGetters } from 'vuex'
import dayjs from 'dayjs'
import { mdiChevronDown, mdiClose } from '@mdi/js'
import { attributesFromEvents } from '../assets/helper'
@ -46,6 +40,7 @@ export default {
},
computed: {
...mapState(['settings', 'events']),
...mapGetters(['is_dark']),
attributes () {
return attributesFromEvents(this.events)
}
@ -66,6 +61,16 @@ export default {
</script>
<style>
.vc-container.vc-is-dark {
--gray-900: #111;
--gray-700: #333;
}
.vc-container {
--gray-400: #999 !important;
--rounded-lg: 4px !important;
}
.vc-opacity-0 {
opacity: 0.3 !important;
}

View file

@ -20,7 +20,7 @@ v-col(cols=12)
@input="date => change('date', date)"
:attributes='attributes'
:locale='$i18n.locale'
:is-dark="settings['theme.is_dark']"
:is-dark="is_dark"
is-inline
is-expanded
:min-date='type !== "recurrent" && new Date()')
@ -95,7 +95,7 @@ v-col(cols=12)
</template>
<script>
import dayjs from 'dayjs'
import { mapState, mapActions } from 'vuex'
import { mapState, mapActions, mapGetters } from 'vuex'
import List from '@/components/List'
import { attributesFromEvents } from '../assets/helper'
import { mdiClockTimeFourOutline, mdiClockTimeEightOutline, mdiClose } from '@mdi/js'
@ -123,6 +123,7 @@ export default {
},
computed: {
...mapState(['settings', 'events']),
...mapGetters(['is_dark']),
fromDate () {
if (this.value.from) {
if (this.value.multidate) {

View file

@ -1,7 +1,7 @@
<template lang="pug">
v-card.h-event.event.d-flex(itemscope itemtype="https://schema.org/Event")
nuxt-link(:to='`/event/${event.slug || event.id}`' itemprop="url")
MyPicture(v-if='!settings.hide_thumbs' :event='event' thumb :lazy='lazy')
MyPicture(v-if='!hide_thumbs' :event='event' thumb :lazy='lazy')
v-icon.float-right.mr-1(v-if='event.parentId' color='success' v-text='mdiRepeat')
.title.p-name(itemprop="name") {{ event.title }}
@ -17,12 +17,12 @@ v-card.h-event.event.d-flex(itemscope itemtype="https://schema.org/Event")
</template>
<script>
import { mapState } from 'vuex'
import { mapGetters } from 'vuex'
import MyPicture from '~/components/MyPicture'
import { mdiRepeat, mdiCalendar, mdiMapMarker } from '@mdi/js'
export default {
data() {
data({ $store }) {
return { mdiRepeat, mdiMapMarker, mdiCalendar }
},
components: {
@ -32,6 +32,6 @@ export default {
event: { type: Object, default: () => ({}) },
lazy: Boolean
},
computed: mapState(['settings'])
computed: mapGetters(['hide_thumbs'])
}
</script>

View file

@ -8,7 +8,7 @@
v-text-field(hide-details outlined
:placeholder='$t("common.search")'
@input="v => setFilter(['query', v])" clearable :clear-icon='mdiClose')
template(v-slot:append)
template(v-slot:append v-if='settings.allow_recurrent_event || settings.allow_multidate_event')
v-icon(v-text='mdiCog' v-bind='attrs' v-on='on')
v-card(outlined :rounded='"0"')
v-card-text

31
components/ThemeView.vue Normal file
View file

@ -0,0 +1,31 @@
<template lang="pug">
div.p-0.m-0.d-flex.justify-end
v-icon.ml-5(@click='toggleDark' v-text='mdiContrastCircle')
v-icon.ml-5(@click='toggleHideThumbs' v-text='hide_thumbs ? mdiViewList : mdiViewModule')
</template>
<script>
import { mapActions, mapGetters } from 'vuex'
import { mdiViewModule, mdiViewList, mdiContrastCircle } from '@mdi/js'
export default {
name: 'ThemeView',
data () {
return { mdiViewModule, mdiViewList, mdiContrastCircle }
},
computed: {
...mapGetters(['hide_thumbs', 'is_dark']),
},
methods: {
...mapActions(['setLocalSetting']),
async toggleDark() {
this.$vuetify.theme.dark = !this.$vuetify.theme.dark
this.setLocalSetting({ key: 'theme.is_dark', value: !this.is_dark })
},
async toggleHideThumbs() {
this.setLocalSetting({ key: 'hide_thumbs', value: !this.hide_thumbs })
}
}
}
</script>

View file

@ -139,7 +139,7 @@ export default {
if (!matches && search) {
this.places.unshift({ create: true, name: ev.target.value.trim() })
}
}, 100),
}, 200),
loadCoordinatesResultIcon(item) {
if (this.geocoding_provider_type == "Nominatim") {
if ( this.nominatim_class.includes(item.class)) {

View file

@ -117,9 +117,9 @@ const Ce = /* @__PURE__ */ new Set();
function Ae(t, e) {
t && t.i && (Ce.delete(t), t.i(e));
}
function Me(t, e, i, n) {
const { fragment: l, on_mount: o, on_destroy: r, after_update: f } = t.$$;
l && l.m(e, i), n || Q(() => {
function Me(t, e, i, l) {
const { fragment: n, on_mount: o, on_destroy: r, after_update: f } = t.$$;
n && n.m(e, i), l || Q(() => {
const c = o.map(W).filter(_e);
r ? r.push(...c) : O(c), t.$$.on_mount = [];
}), f.forEach(Q);
@ -131,7 +131,7 @@ function Ne(t, e) {
function Te(t, e) {
t.$$.dirty[0] === -1 && (H.push(t), Se(), t.$$.dirty.fill(0)), t.$$.dirty[e / 31 | 0] |= 1 << e % 31;
}
function ye(t, e, i, n, l, o, r, f = [-1]) {
function ye(t, e, i, l, n, o, r, f = [-1]) {
const c = I;
R(t);
const s = t.$$ = {
@ -139,7 +139,7 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
ctx: null,
props: o,
update: L,
not_equal: l,
not_equal: n,
bound: ee(),
on_mount: [],
on_destroy: [],
@ -156,8 +156,8 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
let k = !1;
if (s.ctx = i ? i(t, e.props || {}, (m, _, ...C) => {
const w = C.length ? C[0] : _;
return s.ctx && l(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = n ? n(s.ctx) : !1, e.target) {
return s.ctx && n(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = l ? l(s.ctx) : !1, e.target) {
if (e.hydrate) {
const m = $e(e.target);
s.fragment && s.fragment.l(m), m.forEach(x);
@ -190,8 +190,8 @@ typeof HTMLElement == "function" && (X = class extends HTMLElement {
$on(t, e) {
const i = this.$$.callbacks[t] || (this.$$.callbacks[t] = []);
return i.push(e), () => {
const n = i.indexOf(e);
n !== -1 && i.splice(n, 1);
const l = i.indexOf(e);
l !== -1 && i.splice(l, 1);
};
}
$set(t) {
@ -211,13 +211,13 @@ function F(t, e = "long") {
function V(t) {
return t.multidate ? F(t.start_datetime) + " - " + F(t.end_datetime) : F(t.start_datetime) + (t.end_datetime ? "-" + F(t.end_datetime, "short") : "");
}
function ne(t, e, i) {
const n = t.slice();
return n[12] = e[i], n;
}
function le(t, e, i) {
const n = t.slice();
return n[15] = e[i], n;
const l = t.slice();
return l[12] = e[i], l;
}
function ne(t, e, i) {
const l = t.slice();
return l[15] = e[i], l;
}
function re(t) {
let e;
@ -225,11 +225,11 @@ function re(t) {
c() {
e = g("link"), a(e, "rel", "stylesheet"), a(e, "href", t[4]);
},
m(i, n) {
v(i, e, n);
m(i, l) {
v(i, e, l);
},
p(i, n) {
n & 16 && a(e, "href", i[4]);
p(i, l) {
l & 16 && a(e, "href", i[4]);
},
d(i) {
i && x(e);
@ -237,51 +237,51 @@ function re(t) {
};
}
function oe(t) {
let e, i, n = t[1] && t[3] === "true" && ae(t), l = t[5], o = [];
for (let r = 0; r < l.length; r += 1)
o[r] = ue(ne(t, l, r));
let e, i, l = t[1] && t[3] === "true" && ae(t), n = t[5], o = [];
for (let r = 0; r < n.length; r += 1)
o[r] = ue(le(t, n, r));
return {
c() {
e = g("div"), n && n.c(), i = z();
e = g("div"), l && l.c(), i = z();
for (let r = 0; r < o.length; r += 1)
o[r].c();
a(e, "id", "gancioEvents"), T(e, "dark", t[2] === "dark"), T(e, "light", t[2] === "light"), T(e, "sidebar", t[3] === "true"), T(e, "nosidebar", t[3] !== "true");
},
m(r, f) {
v(r, e, f), n && n.m(e, null), u(e, i);
v(r, e, f), l && l.m(e, null), u(e, i);
for (let c = 0; c < o.length; c += 1)
o[c].m(e, null);
},
p(r, f) {
if (r[1] && r[3] === "true" ? n ? n.p(r, f) : (n = ae(r), n.c(), n.m(e, i)) : n && (n.d(1), n = null), f & 41) {
l = r[5];
if (r[1] && r[3] === "true" ? l ? l.p(r, f) : (l = ae(r), l.c(), l.m(e, i)) : l && (l.d(1), l = null), f & 41) {
n = r[5];
let c;
for (c = 0; c < l.length; c += 1) {
const s = ne(r, l, c);
for (c = 0; c < n.length; c += 1) {
const s = le(r, n, c);
o[c] ? o[c].p(s, f) : (o[c] = ue(s), o[c].c(), o[c].m(e, null));
}
for (; c < o.length; c += 1)
o[c].d(1);
o.length = l.length;
o.length = n.length;
}
f & 4 && T(e, "dark", r[2] === "dark"), f & 4 && T(e, "light", r[2] === "light"), f & 8 && T(e, "sidebar", r[3] === "true"), f & 8 && T(e, "nosidebar", r[3] !== "true");
},
d(r) {
r && x(e), n && n.d(), pe(o, r);
r && x(e), l && l.d(), pe(o, r);
}
};
}
function ae(t) {
let e, i, n, l, o, r, f;
let e, i, l, n, o, r, f;
return {
c() {
e = g("a"), i = g("div"), n = g("div"), l = j(t[1]), o = z(), r = g("img"), a(n, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
e = g("a"), i = g("div"), l = g("div"), n = j(t[1]), o = z(), r = g("img"), a(l, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
},
m(c, s) {
v(c, e, s), u(e, i), u(i, n), u(n, l), u(i, o), u(i, r);
v(c, e, s), u(e, i), u(i, l), u(l, n), u(i, o), u(i, r);
},
p(c, s) {
s & 2 && N(l, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
s & 2 && N(n, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
},
d(c) {
c && x(e);
@ -293,50 +293,50 @@ function se(t) {
function i(o, r) {
return o[12].media.length ? Ge : Le;
}
let n = i(t), l = n(t);
let l = i(t), n = l(t);
return {
c() {
e = g("div"), l.c(), a(e, "class", "img");
e = g("div"), n.c(), a(e, "class", "img");
},
m(o, r) {
v(o, e, r), l.m(e, null);
v(o, e, r), n.m(e, null);
},
p(o, r) {
n === (n = i(o)) && l ? l.p(o, r) : (l.d(1), l = n(o), l && (l.c(), l.m(e, null)));
l === (l = i(o)) && n ? n.p(o, r) : (n.d(1), n = l(o), n && (n.c(), n.m(e, null)));
},
d(o) {
o && x(e), l.d();
o && x(e), n.d();
}
};
}
function Le(t) {
let e, i, n;
let e, i, l;
return {
c() {
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, n = t[0] + "/fallbackimage.png") || a(e, "src", n), a(e, "loading", "lazy");
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, l = t[0] + "/fallbackimage.png") || a(e, "src", l), a(e, "loading", "lazy");
},
m(l, o) {
v(l, e, o);
m(n, o) {
v(n, e, o);
},
p(l, o) {
o & 32 && i !== (i = l[12].title) && a(e, "alt", i), o & 1 && !G(e.src, n = l[0] + "/fallbackimage.png") && a(e, "src", n);
p(n, o) {
o & 32 && i !== (i = n[12].title) && a(e, "alt", i), o & 1 && !G(e.src, l = n[0] + "/fallbackimage.png") && a(e, "src", l);
},
d(l) {
l && x(e);
d(n) {
n && x(e);
}
};
}
function Ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", n = t[12].media[0].name), G(e.src, l = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", l), a(e, "loading", "lazy");
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", l = t[12].media[0].name), G(e.src, n = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", n), a(e, "loading", "lazy");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && n !== (n = o[12].media[0].name) && a(e, "alt", n), r & 33 && !G(e.src, l = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", l);
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && l !== (l = o[12].media[0].name) && a(e, "alt", l), r & 33 && !G(e.src, n = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", n);
},
d(o) {
o && x(e);
@ -344,50 +344,50 @@ function Ge(t) {
};
}
function ce(t) {
let e, i = t[12].tags, n = [];
for (let l = 0; l < i.length; l += 1)
n[l] = fe(le(t, i, l));
let e, i = t[12].tags, l = [];
for (let n = 0; n < i.length; n += 1)
l[n] = fe(ne(t, i, n));
return {
c() {
e = g("div");
for (let l = 0; l < n.length; l += 1)
n[l].c();
for (let n = 0; n < l.length; n += 1)
l[n].c();
a(e, "class", "tags");
},
m(l, o) {
v(l, e, o);
for (let r = 0; r < n.length; r += 1)
n[r].m(e, null);
m(n, o) {
v(n, e, o);
for (let r = 0; r < l.length; r += 1)
l[r].m(e, null);
},
p(l, o) {
p(n, o) {
if (o & 32) {
i = l[12].tags;
i = n[12].tags;
let r;
for (r = 0; r < i.length; r += 1) {
const f = le(l, i, r);
n[r] ? n[r].p(f, o) : (n[r] = fe(f), n[r].c(), n[r].m(e, null));
const f = ne(n, i, r);
l[r] ? l[r].p(f, o) : (l[r] = fe(f), l[r].c(), l[r].m(e, null));
}
for (; r < n.length; r += 1)
n[r].d(1);
n.length = i.length;
for (; r < l.length; r += 1)
l[r].d(1);
l.length = i.length;
}
},
d(l) {
l && x(e), pe(n, l);
d(n) {
n && x(e), pe(l, n);
}
};
}
function fe(t) {
let e, i, n = t[15] + "", l;
let e, i, l = t[15] + "", n;
return {
c() {
e = g("span"), i = j("#"), l = j(n), a(e, "class", "tag");
e = g("span"), i = j("#"), n = j(l), a(e, "class", "tag");
},
m(o, r) {
v(o, e, r), u(e, i), u(e, l);
v(o, e, r), u(e, i), u(e, n);
},
p(o, r) {
r & 32 && n !== (n = o[15] + "") && N(l, n);
r & 32 && l !== (l = o[15] + "") && N(n, l);
},
d(o) {
o && x(e);
@ -395,16 +395,16 @@ function fe(t) {
};
}
function ue(t) {
let e, i, n, l, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
let e, i, l, n, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
return {
c() {
e = g("a"), $ && $.c(), i = z(), n = g("div"), l = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(l, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(n, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
e = g("a"), $ && $.c(), i = z(), l = g("div"), n = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(n, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(l, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
},
m(p, M) {
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(n, Y), E && E.m(n, null), u(e, Z);
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(l, Y), E && E.m(l, null), u(e, Z);
},
p(p, M) {
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(n, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(l, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
},
d(p) {
p && x(e), $ && $.d(), E && E.d();
@ -412,21 +412,21 @@ function ue(t) {
};
}
function He(t) {
let e, i, n = t[4] && re(t), l = t[5].length && oe(t);
let e, i, l = t[4] && re(t), n = t[5].length && oe(t);
return {
c() {
n && n.c(), e = z(), l && l.c(), i = ve(), this.c = L;
l && l.c(), e = z(), n && n.c(), i = ve(), this.c = L;
},
m(o, r) {
n && n.m(o, r), v(o, e, r), l && l.m(o, r), v(o, i, r);
l && l.m(o, r), v(o, e, r), n && n.m(o, r), v(o, i, r);
},
p(o, [r]) {
o[4] ? n ? n.p(o, r) : (n = re(o), n.c(), n.m(e.parentNode, e)) : n && (n.d(1), n = null), o[5].length ? l ? l.p(o, r) : (l = oe(o), l.c(), l.m(i.parentNode, i)) : l && (l.d(1), l = null);
o[4] ? l ? l.p(o, r) : (l = re(o), l.c(), l.m(e.parentNode, e)) : l && (l.d(1), l = null), o[5].length ? n ? n.p(o, r) : (n = oe(o), n.c(), n.m(i.parentNode, i)) : n && (n.d(1), n = null);
},
i: L,
o: L,
d(o) {
n && n.d(o), o && x(e), l && l.d(o), o && x(i);
l && l.d(o), o && x(e), n && n.d(o), o && x(i);
}
};
}
@ -438,12 +438,12 @@ function de(t) {
return "center center";
}
function Re(t, e, i) {
let { baseurl: n = "" } = e, { title: l = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
let { baseurl: l = "" } = e, { title: n = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
function w(d) {
if (!_)
return;
const S = [];
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${n}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${l}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
i(5, C = h);
}).catch((h) => {
console.error("Error loading Gancio API -> ", h);
@ -452,12 +452,12 @@ function Re(t, e, i) {
return we(() => {
_ = !0, w();
}), t.$$set = (d) => {
"baseurl" in d && i(0, n = d.baseurl), "title" in d && i(1, l = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
"baseurl" in d && i(0, l = d.baseurl), "title" in d && i(1, n = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
}, t.$$.update = () => {
t.$$.dirty & 975 && w();
}, [
n,
l,
n,
c,
k,
m,
@ -570,13 +570,13 @@ class Ie extends X {
}
customElements.define("gancio-events", Ie);
function he(t) {
let e, i, n, l, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
let e, i, l, n, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
return {
c() {
e = g("a"), h && h.c(), i = z(), n = g("div"), l = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(n, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
e = g("a"), h && h.c(), i = z(), l = g("div"), n = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(l, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
},
m(b, A) {
v(b, e, A), h && h.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d);
v(b, e, A), h && h.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d);
},
p(b, A) {
b[1].media.length ? h ? h.p(b, A) : (h = ge(b), h.c(), h.m(e, i)) : h && (h.d(1), h = null), A & 2 && o !== (o = b[1].title + "") && N(r, o), A & 2 && s !== (s = V(b[1]) + "") && N(k, s), A & 2 && w !== (w = b[1].place.name + "") && N(d, w), A & 3 && S !== (S = b[0] + "/event/" + (b[1].slug || b[1].id)) && a(e, "href", S);
@ -587,16 +587,16 @@ function he(t) {
};
}
function ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", n = t[1].media[0].name), a(e, "style", l = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", l = t[1].media[0].name), a(e, "style", n = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && n !== (n = o[1].media[0].name) && a(e, "alt", n), r & 2 && l !== (l = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", l);
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && l !== (l = o[1].media[0].name) && a(e, "alt", l), r & 2 && n !== (n = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", n);
},
d(o) {
o && x(e);
@ -609,16 +609,16 @@ function Oe(t) {
c() {
i && i.c(), e = ve(), this.c = L;
},
m(n, l) {
i && i.m(n, l), v(n, e, l);
m(l, n) {
i && i.m(l, n), v(l, e, n);
},
p(n, [l]) {
n[1] ? i ? i.p(n, l) : (i = he(n), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
p(l, [n]) {
l[1] ? i ? i.p(l, n) : (i = he(l), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
},
i: L,
o: L,
d(n) {
i && i.d(n), n && x(e);
d(l) {
i && i.d(l), l && x(e);
}
};
}
@ -630,21 +630,21 @@ function me(t) {
return "center center";
}
function Ue(t, e, i) {
let { baseurl: n = "https://demo.gancio.org" } = e, { id: l } = e, o = !1, r;
let { baseurl: l = "https://demo.gancio.org" } = e, { id: n } = e, o = !1, r;
function f(s, k) {
o && fetch(`${k}/api/event/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
o && fetch(`${k}/api/event/detail/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
}
we(() => {
o = !0, f(l, n);
o = !0, f(n, l);
});
function c(s) {
return `${n}/media/thumb/${s.media[0].url}`;
return `${l}/media/thumb/${s.media[0].url}`;
}
return t.$$set = (s) => {
"baseurl" in s && i(0, n = s.baseurl), "id" in s && i(3, l = s.id);
"baseurl" in s && i(0, l = s.baseurl), "id" in s && i(3, n = s.id);
}, t.$$.update = () => {
t.$$.dirty & 9 && f(l, n);
}, [n, r, c, l];
t.$$.dirty & 9 && f(n, l);
}, [l, r, c, n];
}
class qe extends X {
constructor(e) {

View file

@ -8,6 +8,13 @@ nav_order: 10
All notable changes to this project will be documented in this file.
### 1.6.2 - 12 jan '23
- add swipe gesture to move to next/prev event
- fix refresh collections, fix #219
- add russian translation (thanks @drunkod)
- refactor search / filter / selection fix #225, 227, #224
- models initialization refactored, better dev experience, fix backend HMR
### 1.6.1 - 15 dec '22
- allow edit tags in admin panel, fix #170
- fix header / fallback image upload, fix #222

View file

@ -4,7 +4,9 @@
<v-main>
<Snackbar/>
<Confirm/>
<nuxt :keep-alive='$route.name === "index"'/>
<v-fade-transition hide-on-leave>
<nuxt />
</v-fade-transition>
</v-main>
<Footer/>
@ -17,7 +19,7 @@ import Appbar from '../components/Appbar.vue'
import Snackbar from '../components/Snackbar'
import Footer from '../components/Footer'
import Confirm from '../components/Confirm'
import { mapState } from 'vuex'
import { mapState, mapGetters } from 'vuex'
export default {
head () {
@ -30,9 +32,12 @@ export default {
},
name: 'Default',
components: { Appbar, Snackbar, Footer, Confirm },
computed: mapState(['settings']),
computed: {
...mapState(['settings']),
...mapGetters(['is_dark'])
},
created () {
this.$vuetify.theme.dark = this.settings['theme.is_dark']
this.$vuetify.theme.dark = this.is_dark
}
}
</script>

View file

@ -301,7 +301,8 @@
"allow_multidate_event": "Permet activitats de diversos dies",
"delete_tag_confirm": "Segur que vols eliminar l'etiqueta \"{tag}\"? S'esborrarà del sistema i de {n} activitats.",
"edit_tag": "Canvia l'etiqueta",
"tilelayer_provider_attribution": "Atribució"
"tilelayer_provider_attribution": "Atribució",
"geolocation_description": "<b>1. Defineix una proveïdora de geocodificació</b>.<br>Actualment, de totes les llistades en <a href=\"https://wiki.openstreetmap.org/wiki/Nominatim#Alternatives_.2F_Third-party_providers\">la wiki d'OpenStreetMap</a>, són compatibles amb Gancio <a href=\"https://github.com/osm-search/Nominatim\">Nominatim</a> i <a href=\"https://github.com/komoot/photon\">Photon</a>.<br>Pots fer servir les instaŀlacions d'aquestes proveïdores copiant l'adreça de la instaŀlació al camp de 'Proveïdora de geolocodificació'<ul><li>https://nominatim.openstreetmap.org/search (<a href=\"https://operations.osmfoundation.org/policies/nominatim/\">Condicions del servei</a>)</li><li>https://photon.komoot.io/api/ (<a href=\"https://photon.komoot.io/\">Condicions del servei</a>)</li></ul><br><b>2. Defineix una proveïdora per mapes base.</b><br>Pots trobar-ne una llista aquí: <a href=\"https://leaflet-extras.github.io/leaflet-providers/preview/\">https://leaflet-extras.github.io/leaflet-providers/preview/</a>"
},
"auth": {
"not_confirmed": "Encara no s'ha confirmat…",

View file

@ -64,7 +64,7 @@
"embed": "Incorporar",
"embed_title": "Publica este evento en tu página web",
"embed_help": "Copiando el siguiente código en tu página web, el evento será incluido como puedes ver aquí al lado",
"feed": "RSS Feed",
"feed": "Canal RSS",
"feed_url_copied": "Copiada feed url, pegala en tu lector de feeds",
"follow_me_title": "Sigue las actualizaciones en el fediverso",
"follow": "Sigue",
@ -183,7 +183,8 @@
"address_description": "¿Cuál es la dirección?",
"alt_text_description": "Descripción para personas con baja visión",
"download_flyer": "Descargar folleto",
"remove_media_confirmation": "¿Confirmas la eliminación de la imagen?"
"remove_media_confirmation": "¿Confirmas la eliminación de la imagen?",
"show_multidate": "eventos de varios días"
},
"admin": {
"place_description": "En el caso de que un lugar sea incorrecto o cambie de dirección, puedes cambiarlo. <br/> Todos los eventos presentes y pasados asociados con este lugar cambiarán de dirección.",

View file

@ -174,7 +174,8 @@
"remove_media_confirmation": "Confirmas a eliminación da imaxe?",
"download_flyer": "Descargar folleto",
"address_description": "Cal é o enderezo?",
"address_description_osm": "Cal é o enderezo? (Contribuíntes a <a href='http://osm.org/copyright'>OpenStreetMap</a>)"
"address_description_osm": "Cal é o enderezo? (Contribuíntes a <a href='http://osm.org/copyright'>OpenStreetMap</a>)",
"show_multidate": "eventos con varias datas"
},
"admin": {
"place_description": "Se escribiches mal o lugar ou enderezo, podes cambialo.<br/>Cambiará o enderezo de tódolos eventos actuais e pasados asociados a este lugar.",

View file

@ -136,7 +136,7 @@
"saved": "Evento salvato",
"added_anon": "Evento aggiunto, verrà confermato quanto prima.",
"updated": "Evento aggiornato",
"where_description": "Dov'è il gancio? Se il posto non è presente potrai crearlo.",
"where_description": "Dov'è l'evento? Se il posto non è presente potrai crearlo.",
"address_description": "A che indirizzo?",
"address_description_osm": "A che indirizzo? (<a href='http://osm.org/copyright'>OpenStreetMap</a>)",
"coordinates_search_description": "Puoi ricercare il posto per nome, o incollare la coppia di coordinate.",

14
locales/loader.js Normal file
View file

@ -0,0 +1,14 @@
export default async (context, locale) => {
try {
if (process.server) {
return context.$axios.$get(`locale/${locale}`)
} else {
// cannot use $axios here as plugins have not yet been loaded
return fetch(`${window.location.origin}/api/locale/${locale}`).then(ret => ret.json())
}
} catch (e) {
console.error(`Error loading locale ${locale}`, e)
}
return localeMessages
}

View file

@ -57,7 +57,8 @@ module.exports = {
'@nuxtjs/i18n',
'@nuxtjs/axios',
'@nuxtjs/auth',
'@nuxtjs/sitemap'
'@nuxtjs/sitemap',
['cookie-universal-nuxt', { alias: 'cookies' }],
],
sitemap: {
@ -88,6 +89,7 @@ module.exports = {
code: key,
name: locales[key],
file: `${key}.json`,
file: 'loader.js',
iso: key
})),
vueI18n: {
@ -97,9 +99,7 @@ module.exports = {
langDir: 'locales',
lazy: true,
strategy: 'no_prefix',
baseUrl: config.baseurl,
skipSettingLocaleOnNavigate: true,
skipNuxtState: true
},
serverMiddleware: ['server/routes'],

View file

@ -1,6 +1,6 @@
{
"name": "gancio",
"version": "1.6.1",
"version": "1.6.2",
"description": "A shared agenda for local communities",
"author": "lesion",
"scripts": {
@ -27,6 +27,7 @@
"locales/",
"store/",
".nuxt/",
"gancio_plugins",
"yarn.lock"
],
"engines": {
@ -44,11 +45,13 @@
"body-parser": "^1.20.0",
"cookie-parser": "^1.4.6",
"cookie-session": "^2.0.0",
"cookie-universal-nuxt": "^2.2.2",
"cors": "^2.8.5",
"dayjs": "^1.11.7",
"dompurify": "^2.4.1",
"email-templates": "^10.0.1",
"express": "^4.18.1",
"express-rate-limit": "^6.7.0",
"http-signature": "^1.3.6",
"https-proxy-agent": "^5.0.1",
"ical.js": "^1.5.0",
@ -60,6 +63,7 @@
"linkifyjs": "4.0.2",
"lodash": "^4.17.21",
"mariadb": "^3.0.1",
"memory-cache": "^0.2.0",
"microformat-node": "^2.0.1",
"minify-css-string": "^1.0.0",
"mkdirp": "^1.0.4",

View file

@ -113,7 +113,7 @@ export default {
data.edit = true
let event
try {
event = await $axios.$get('/event/' + data.id)
event = await $axios.$get('/event/detail/' + data.id)
if (!$auth.user.is_admin && $auth.user.id !== event.userId) {
error({ statusCode: 401, message: 'Not allowed' })
return {}

View file

@ -17,7 +17,7 @@ export default {
layout: 'iframe',
async asyncData ({ $axios, params, error }) {
try {
const event = await $axios.$get(`/event/${params.event_id}`)
const event = await $axios.$get(`/event/detail/${params.event_id}`)
return { event }
} catch (e) {
error({ statusCode: 404, message: 'Event not found' })

View file

@ -65,7 +65,7 @@ v-container#event.pa-0.pa-sm-2
v-list-item-title(v-text="$t('common.embed')")
//- calendar
v-list-item(:href='`/api/event/${event.slug || event.id}.ics`')
v-list-item(:href='`/api/event/detail/${event.slug || event.id}.ics`')
v-list-item-icon
v-icon(v-text='mdiCalendarExport')
v-list-item-content
@ -185,7 +185,7 @@ export default {
},
async asyncData ({ $axios, params, error }) {
try {
const event = await $axios.$get(`/event/${params.slug}`)
const event = await $axios.$get(`/event/detail/${params.slug}`)
return { event }
} catch (e) {
error({ statusCode: 404, message: 'Event not found' })

View file

@ -1,5 +1,10 @@
<template lang="pug">
v-container.px-2.px-sm-6.pt-0
//- View
#themeview.mt-sm-4.mt-2
ThemeView
//- Announcements
#announcements.mt-2.mt-sm-4(v-if='announcements.length')
Announcement(v-for='announcement in announcements' :key='`a_${announcement.id}`' :announcement='announcement')
@ -15,18 +20,22 @@ import debounce from 'lodash/debounce'
import dayjs from 'dayjs'
import Event from '@/components/Event'
import Announcement from '@/components/Announcement'
import ThemeView from '@/components/ThemeView'
import { mdiMagnify, mdiCloseCircle } from '@mdi/js'
export default {
name: 'Index',
components: { Event, Announcement },
components: { Event, Announcement, ThemeView },
middleware: 'setup',
async fetch () {
return this.getEvents()
fetch () {
return this.getEvents({
start: this.start,
end: this.end
})
},
activated() {
if (this.$fetchState.timestamp <= Date.now() - 60000) {
this.$fetch();
this.$fetch()
}
},
data ({ $store }) {
@ -34,14 +43,11 @@ export default {
mdiMagnify, mdiCloseCircle,
isCurrentMonth: true,
now: dayjs().unix(),
date: dayjs.tz().format('YYYY-MM-DD'),
start: dayjs().startOf('month').unix(),
end: null,
searching: false,
tmpEvents: [],
selectedDay: null,
storeUnsubscribe: null
storeUnsubscribe: null,
}
},
head () {
@ -80,7 +86,7 @@ export default {
}
}
},
mounted () {
created () {
this.$root.$on('dayclick', this.dayChange)
this.$root.$on('monthchange', this.monthChange)
this.storeUnsubscribe = this.$store.subscribeAction( { after: (action, state) => {
@ -88,7 +94,8 @@ export default {
if (this.filter.query && this.filter.query.length > 2) {
this.search()
} else {
this.updateEvents()
this.tmpEvents = []
this.$fetch()
}
}
}})
@ -109,34 +116,26 @@ export default {
show_multidate: this.filter.show_multidate,
query: this.filter.query
})
}, 100),
updateEvents () {
return this.getEvents({
start: this.start,
end: this.end
})
},
}, 200),
async monthChange ({ year, month }) {
this.$nuxt.$loading.start()
this.$nextTick( async () => {
let isCurrentMonth
// unselect current selected day
this.selectedDay = null
// unselect current selected day
this.selectedDay = null
// check if current month is selected
if (month - 1 === dayjs.tz().month() && year === dayjs.tz().year()) {
this.isCurrentMonth = true
this.start = dayjs().startOf('month').unix()
this.date = dayjs.tz().format('YYYY-MM-DD')
} else {
this.isCurrentMonth = false
this.date = ''
this.start = dayjs().year(year).month(month - 1).startOf('month').unix() // .startOf('week').unix()
}
this.end = dayjs().year(year).month(month).endOf('month').unix() // .endOf('week').unix()
await this.updateEvents()
this.$nuxt.$loading.finish()
})
// check if current month is selected
if (month - 1 === dayjs.tz().month() && year === dayjs.tz().year()) {
isCurrentMonth = true
this.start = dayjs().startOf('month').unix()
} else {
isCurrentMonth = false
this.start = dayjs().year(year).month(month - 1).startOf('month').unix() // .startOf('week').unix()
}
this.end = dayjs().year(year).month(month).endOf('month').unix() // .endOf('week').unix()
await this.$fetch()
this.$nuxt.$loading.finish()
this.$nextTick( () => this.isCurrentMonth = isCurrentMonth)
},
dayChange (day) {

View file

@ -1,5 +1,8 @@
export default function ({ $axios, store }) {
if (process.client) {
$axios.defaults.baseURL = window.location.origin + '/api'
$axios.setBaseURL(window.location.origin + '/api')
} else {
const config = require('../server/config')
$axios.setBaseURL(config.baseurl + '/api')
}
}

View file

@ -58,7 +58,7 @@ export default ({ app, store }) => {
return ''
})
Vue.filter('from', timestamp => dayjs.unix(timestamp).tz().fromNow())
Vue.filter('from', timestamp => dayjs.unix(timestamp).tz().locale(app.i18n.locale || store.state.settings.instance_locale).fromNow())
Vue.filter('recurrentDetail', event => {
const parent = event.parent

View file

@ -1,36 +1,8 @@
export default async ({ app, store, res, $vuetify }) => {
export default async ({ app, $vuetify }) => {
$vuetify.lang.current = app.i18n.locale
app.i18n.onLanguageSwitched = (oldLocale, newLocale) => {
$vuetify.lang.current = newLocale
}
// const messages = {}
// if (process.server) {
// if (res.locals) {
// store.commit('setLocale', res.locals.acceptedLocale)
// if (res.locals.user_locale) {
// store.commit('setUserLocale', res.locals.user_locale)
// }
// }
// }
// messages[store.state.locale] = await import(/* webpackChunkName: "lang-[request]" */`../locales/${store.state.locale}.json`)
// always include en fallback locale
// if (store.state.locale !== 'en') {
// messages.en = await import('../locales/en.json')
// }
// if (store.state.user_locale) {
// merge(messages[store.state.locale], store.state.user_locale)
// }
// Set i18n instance on app
// app.i18n = new VueI18n({
// locale: store.state.locale,
// fallbackLocale: 'en',
// messages
// })
}

View file

@ -689,7 +689,7 @@ const eventController = {
...pagination,
replacements
}).catch(e => {
log.error('[EVENT]', e)
log.error('[EVENT]' + String(e))
return []
})

View file

@ -81,14 +81,13 @@ const exportController = {
ics (_req, res, events, alarms = []) {
const settings = res.locals.settings
const eventsMap = events.map(e => {
const tmpStart = moment.unix(e.start_datetime)
const tmpEnd = moment.unix(e.end_datetime)
const start = tmpStart.utc(true).format('YYYY-M-D-H-m').split('-').map(Number)
const end = tmpEnd.utc(true).format('YYYY-M-D-H-m').split('-').map(Number)
return {
const ret = {
uid: `${e.id}@${settings.hostname}`,
start,
end,
title: `[${settings.title}] ${e.title}`,
description: htmlToText(e.description),
htmlContent: e.description,
@ -98,6 +97,14 @@ const exportController = {
categories: e.tags.map(t => t.tag),
alarms
}
if (e.end_datetime) {
const tmpEnd = moment.unix(e.end_datetime)
const end = tmpEnd.utc(true).format('YYYY-M-D-H-m').split('-').map(Number)
ret.end = end
}
return ret
})
res.type('text/calendar; charset=UTF-8')
ics.createEvents(eventsMap, (err, value) => {

View file

@ -0,0 +1,122 @@
const log = require('../../log')
const nominatim = require('../../services/geocoding/nominatim')
const photon = require('../../services/geocoding/photon')
const axios = require('axios')
const { version } = require('../../../package.json')
let d = 0 // departure time
let h = 0 // hit geocoding provider time (aka Latency)
const geocodingController = {
/**
* Limit provider api usage.
* From https://operations.osmfoundation.org/policies/nominatim/
* [Requirements] No heavy uses (an absolute maximum of 1 request per second).
* [Websites and Apps]
* - Note that the usage limits above apply per website/application: the sum of traffic by all your users should not exceed the limits.
* - If at all possible, set up a proxy and also enable caching of requests.
*/
providerRateLimit (req, res, next, providerCache) {
let a = Date.now(); // arrival time
let dprev = d
d = dprev + 1000 + h
// console.log('a: ' + a)
// console.log('dprev: ' + dprev)
// console.log('d: ' + d)
// if the same request was already cached skip the delay mechanism
if (providerCache.get(req.params.place_details)) {
if (a < d) {
log.warn('More than 1 request per second to geocoding api. This from ' + req.ip + ' . The response data is served from memory-cache.')
}
// reset departure time because there is no need to ask provider
d = dprev
return next()
}
if (d === 0 || a > d) {
// no-queue or old-queue
// console.log('No queue or Old queue')
// arrival time + 10ms estimated computing time
d = a + 10
next()
} else {
// fresh queue
// console.log('Fresh queue')
let wait = d - a
// console.log('Waiting '+ wait)
log.warn('More than 1 request per second to geocoding api. This from ' + req.ip + ' . Applying ToS padding before asking to provider. The response data is now cached.')
setTimeout(() => {
next()
}, wait)
}
},
async nominatimRateLimit(req, res, next) {
geocodingController.providerRateLimit(req, res, next, nominatim.cache)
},
async photonRateLimit(req, res, next) {
geocodingController.providerRateLimit(req, res, next, photon.cache)
},
async checkInCache (req, res, details, providerCache) {
const ret = await providerCache.get(details)
if (ret) {
return ret
} else {
return
}
},
async queryProvider(req, res, details, provider) {
let RTTstart = Date.now()
// console.log('Asking Provider: ' + RTTstart)
const ret = await axios.get(`${provider.endpoint(req, res)}`, {
params: provider.getParams(req, res),
headers: { 'User-Agent': `gancio ${version}` }
})
if (ret) {
let RTTend = Date.now()
// console.log('Asking Provider: ' + RTTend)
// Save the hit time (aka Latency)
// console.log('Saving latency h: ' + h)
h = (RTTend - RTTstart) / 2
}
// Cache the response data
provider.cache.put(details, ret.data, 1000 * 60 * 60 * 24);
// console.log(cache.keys())
// console.log(cache.exportJson())
return ret.data
},
async _nominatim (req, res) {
const details = req.params.place_details
const ret = await geocodingController.checkInCache(req, res, details, nominatim.cache) ||
await geocodingController.queryProvider(req, res, details, nominatim)
return res.json(ret)
},
async _photon (req, res) {
const details = req.params.place_details
const ret = await geocodingController.checkInCache(req, res, details, photon.cache) ||
await geocodingController.queryProvider(req, res, details, photon)
return res.json(ret)
},
}
module.exports = geocodingController

View file

@ -0,0 +1,36 @@
const merge = require('lodash/merge')
const config = require('../../config')
const path = require('path')
const fs = require('fs')
const log = require('../../log')
const localeController = {
async get (req, res) {
const locale = req.params.locale
const locales = require('../../../locales/index')
// check if this locale exists
if (!locales[locale]) {
return res.sendStatus(404)
}
const defaultLocaleMessages = require(`../../../locales/${locale}.json`)
// check if we have a user custom messages
let customLocaleMessages = {}
const customLocalePath = path.resolve(config.user_locale, `${locale}.json`)
if (config.user_locale && fs.existsSync(customLocalePath)) {
try {
customLocaleMessages = require(customLocalePath)
} catch (e) {
log.error(`Error reading custom locale messages: ${e}`)
}
}
const ret = merge(defaultLocaleMessages, customLocaleMessages)
return res.json(ret)
}
}
module.exports = localeController

View file

@ -3,13 +3,8 @@ const { Place, Event } = require('../models/models')
const eventController = require('./event')
const exportController = require('./export')
const { version } = require('../../../package.json')
const log = require('../../log')
const { Op, where, col, fn, cast } = require('sequelize')
const NOMINATIM_URL = 'https://nominatim.openstreetmap.org/search'
const PHOTON_URL = 'https://photon.komoot.io/api/'
const axios = require('axios')
module.exports = {
@ -75,45 +70,6 @@ module.exports = {
// TOFIX: don't know why limit does not work
return res.json(places.slice(0, 10))
},
async _nominatim (req, res) {
const details = req.params.place_details
const countrycodes = res.locals.settings.geocoding_countrycodes || []
const geocoding_provider = res.locals.settings.geocoding_provider || NOMINATIM_URL
// ?limit=3&format=json&namedetails=1&addressdetails=1&q=
const ret = await axios.get(`${geocoding_provider}`, {
params: {
countrycodes: countrycodes.join(','),
q: details,
limit: 3,
format: 'json',
addressdetails: 1,
namedetails: 1,
},
headers: { 'User-Agent': `gancio ${version}` }
})
return res.json(ret.data)
},
async _photon (req, res) {
const details = req.params.place_details
const geocoding_provider = res.locals.settings.geocoding_provider || PHOTON_URL
const ret = await axios.get(`${geocoding_provider}`, {
params: {
q: details,
limit: 3,
},
headers: { 'User-Agent': `gancio ${version}` }
})
// console.log(ret)
return res.json(ret.data)
},
}
}

View file

@ -84,32 +84,39 @@ const pluginController = {
}
},
_loadPlugin (pluginFile) {
try {
const plugin = require(pluginFile)
const name = plugin.configuration.name
console.log(`Found plugin '${name}'`)
pluginController.plugins.push(plugin)
if (settingsController.settings['plugin_' + name]) {
const pluginSetting = settingsController.settings['plugin_' + name]
if (pluginSetting.enable) {
pluginController.loadPlugin(name)
}
} else {
settingsController.set('plugin_' + name, { enable: false })
}
} catch (e) {
log.warn(`Unable to load plugin ${pluginFile}: ${String(e)}`)
}
},
_load() {
// load custom plugins
const plugins_path = config.plugins_path || path.resolve(process.env.cwd || '', 'plugins')
log.info(`Loading plugin ${plugins_path}`)
if (fs.existsSync(plugins_path)) {
const plugins = fs.readdirSync(plugins_path)
.map(e => path.resolve(plugins_path, e, 'index.js'))
.filter(index => fs.existsSync(index))
plugins.forEach(pluginFile => {
try {
const plugin = require(pluginFile)
const name = plugin.configuration.name
console.log(`Found plugin '${name}'`)
pluginController.plugins.push(plugin)
if (settingsController.settings['plugin_' + name]) {
const pluginSetting = settingsController.settings['plugin_' + name]
if (pluginSetting.enable) {
pluginController.loadPlugin(name)
}
} else {
settingsController.set('plugin_' + name, { enable: false })
}
} catch (e) {
log.warn(`Unable to load plugin ${pluginFile}: ${String(e)}`)
}
})
const system_plugins_path = path.resolve(__dirname || '', '../../../gancio_plugins')
const custom_plugins_path = config.plugins_path || path.resolve(process.env.cwd || '', 'plugins')
const plugins_paths = custom_plugins_path === system_plugins_path ? [custom_plugins_path] : [custom_plugins_path, system_plugins_path]
log.info(`Loading plugins from ${plugins_paths.join(' and ')}`)
for (const plugins_path of plugins_paths) {
if (fs.existsSync(plugins_path)) {
fs.readdirSync(plugins_path)
.map(e => path.resolve(plugins_path, e, 'index.js'))
.filter(index => fs.existsSync(index))
.forEach(pluginController._loadPlugin)
}
}
}
}

View file

@ -19,6 +19,9 @@ const resourceController = require('./controller/resource')
const oauthController = require('./controller/oauth')
const announceController = require('./controller/announce')
const pluginController = require('./controller/plugins')
const geocodingController = require('./controller/geocoding')
const localeController = require('./controller/locale')
const { DDOSProtectionApiRateLimiter, SPAMProtectionApiRateLimiter } = require('./limiter')
const helpers = require('../helpers')
const storage = require('./storage')
@ -29,6 +32,10 @@ module.exports = () => {
api.use(express.urlencoded({ extended: false }))
api.use(express.json())
if (process.env.NODE_ENV !== 'test') {
api.use(DDOSProtectionApiRateLimiter)
}
if (config.status !== 'READY') {
@ -65,13 +72,12 @@ module.exports = () => {
api.get('/ping', (_req, res) => res.sendStatus(200))
api.get('/user', isAuth, (req, res) => res.json(req.user))
api.post('/user/recover', userController.forgotPassword)
api.post('/user/recover', SPAMProtectionApiRateLimiter, userController.forgotPassword)
api.post('/user/check_recover_code', userController.checkRecoverCode)
api.post('/user/recover_password', userController.updatePasswordWithRecoverCode)
api.post('/user/recover_password', SPAMProtectionApiRateLimiter, userController.updatePasswordWithRecoverCode)
// register and add users
api.post('/user/register', userController.register)
api.post('/user/register', SPAMProtectionApiRateLimiter, userController.register)
api.post('/user', isAdmin, userController.create)
// update user
@ -127,7 +133,7 @@ module.exports = () => {
*/
// allow anyone to add an event (anon event has to be confirmed, TODO: flood protection)
api.post('/event', eventController.isAnonEventAllowed, upload.single('image'), eventController.add)
api.post('/event', eventController.isAnonEventAllowed, SPAMProtectionApiRateLimiter, upload.single('image'), eventController.add)
// api.get('/event/search', eventController.search)
@ -141,8 +147,8 @@ module.exports = () => {
api.get('/event/meta', eventController.searchMeta)
// add event notification TODO
api.post('/event/notification', eventController.addNotification)
api.delete('/event/notification/:code', eventController.delNotification)
// api.post('/event/notification', eventController.addNotification)
// api.delete('/event/notification/:code', eventController.delNotification)
api.post('/settings', isAdmin, settingsController.setRequest)
api.get('/settings', isAdmin, settingsController.getAll)
@ -160,7 +166,7 @@ module.exports = () => {
api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm)
// get event
api.get('/event/:event_slug.:format?', cors, eventController.get)
api.get('/event/detail/:event_slug.:format?', cors, eventController.get)
// export events (rss/ics)
api.get('/export/:type', cors, exportController.export)
@ -170,10 +176,12 @@ module.exports = () => {
api.get('/places', isAdmin, placeController.getAll)
api.get('/place/:placeName', cors, placeController.getEvents)
api.get('/place', cors, placeController.search)
api.get('/placeOSM/Nominatim/:place_details', cors, placeController._nominatim)
api.get('/placeOSM/Photon/:place_details', cors, placeController._photon)
api.put('/place', isAdmin, placeController.updatePlace)
// - GEOCODING
api.get('/placeOSM/Nominatim/:place_details', helpers.isGeocodingEnabled, geocodingController.nominatimRateLimit, geocodingController._nominatim)
api.get('/placeOSM/Photon/:place_details', helpers.isGeocodingEnabled, geocodingController.photonRateLimit, geocodingController._photon)
// - TAGS
api.get('/tags', isAdmin, tagController.getAll)
api.get('/tag', cors, tagController.search)
@ -213,7 +221,10 @@ module.exports = () => {
// OAUTH
api.get('/clients', isAuth, oauthController.getClients)
api.get('/client/:client_id', isAuth, oauthController.getClient)
api.post('/client', oauthController.createClient)
api.post('/client', SPAMProtectionApiRateLimiter, oauthController.createClient)
// CUSTOM LOCALE
api.get('/locale/:locale', localeController.get)
}
api.use((_req, res) => res.sendStatus(404))

32
server/api/limiter.js Normal file
View file

@ -0,0 +1,32 @@
const rateLimit = require('express-rate-limit')
const log = require('../log')
const next = (req, res, next) => next()
const instanceApiRateLimiter = {
DDOSProtectionApiRateLimiter: (process.env.NODE_ENV === 'test' ? next : rateLimit({
windowMs: 60 * 1000, // 5 minutes
max: 100, // Limit each IP to 100 requests per `window` (here, per 5 minutes)
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (request, response, next, options) => {
log.warn(`DDOS protection api rate limiter: > 100req/minute/ip ${request.ip}`)
return response.status(options.statusCode).send(options.message)
}
})),
SPAMProtectionApiRateLimiter: (process.env.NODE_ENV === 'test' ? next : rateLimit({
windowMs: 5 * 60 * 1000, // 10 minutes
max: 3, // Limit each IP to 3 requests per `window` (here, per 15 minutes)
standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
legacyHeaders: false, // Disable the `X-RateLimit-*` headers
handler: (request, response, next, options) => {
log.warn(`SPAM protection api rate limiter: 3req/5min/ip ${request.ip}`)
return response.status(options.statusCode).send(options.message)
}
}))
}
module.exports = instanceApiRateLimiter

View file

@ -69,7 +69,7 @@ module.exports = (sequelize, DataTypes) => {
url: `${config.baseurl}/event/${this.slug || this.id}`,
type: 'Event',
startTime: dayjs.unix(this.start_datetime).tz().locale(locale).format(),
endTime: this.end_datetime ? dayjs.unix(this.end_datetime).tz().locale(locale).format() : null,
...( this.end_datetime ? { endTime : dayjs.unix(this.end_datetime).tz().locale(locale).format() } : {} ),
location: {
name: this.place.name,
address: this.place.address,

View file

@ -1,2 +1,20 @@
// export default models
// Announcement: require('./announcement'),
// APUser: require('./ap_user'),
// Collection: require('./collection'),
// Event: require('./event'),
// EventNotification: require('./eventnotification'),
// Filter: require('./filter'),
// Instance: require('./instance'),
// Notification: require('./notification'),
// OAuthClient: require('./oauth_client'),
// OAuthCode: require('./oauth_code'),
// OAuthToken: require('./oauth_token'),
// Place: require('./place'),
// Resource: require('./resource'),
// Setting: require('./setting'),
// Tag: require('./tag'),
// User: require('./user'),
module.exports = {}

View file

@ -33,7 +33,7 @@ async function modify (args) {
async function create (args) {
await _initializeDB()
const User = require('../api/models/user')
const { User } = require('../api/models/models')
const user = await User.create({
email: args.email,
is_active: true,
@ -46,7 +46,7 @@ async function create (args) {
async function remove (args) {
await _initializeDB()
const User = require('../api/models/user')
const { User } = require('../api/models/models')
const user = await User.findOne({
where: { email: args.email }
})
@ -58,7 +58,7 @@ async function remove (args) {
async function list () {
await _initializeDB()
const User = require('../api/models/user')
const { User } = require('../api/models/models')
const users = await User.findAll()
console.log()
users.forEach(u => console.log(`${u.id}\tadmin: ${u.is_admin}\tenabled: ${u.is_active}\temail: ${u.email}`))

View file

@ -1,4 +1,4 @@
const Event = require('../api/models/event')
const { Event } = require('../api/models/models')
const config = require('../config')
const log = require('../log')

View file

@ -2,10 +2,8 @@ const express = require('express')
const router = express.Router()
const cors = require('cors')
const Users = require('./users')
const Event = require('../api/models/event')
const User = require('../api/models/user')
const Tag = require('../api/models/tag')
const Place = require('../api/models/place')
const { Event, User, Tag, Place } = require('../api/models/models')
const settingsController = require('../api/controller/settings')
const Helpers = require('./helpers')

View file

@ -1,32 +0,0 @@
const express = require('express')
const router = express.Router()
const cors = require('cors')
const settingsController = require('../api/controller/settings')
const config = require('../config')
const version = require('../../package.json').version
router.use(cors())
router.get('/', (req, res) => {
const ret = {
version: '1.0',
server: {
baseUrl: config.baseurl,
name: config.title,
software: 'Gancio',
version
},
protocols: ['activitypub'],
openRegistrations: settingsController.settings.allow_registration,
usage: {
users: {
total: 10
}
},
localPost: 3,
localComments: 0
}
res.json(ret)
})
module.exports = router

View file

@ -1,6 +1,4 @@
const Event = require('../api/models/event')
const Resource = require('../api/models/resource')
const APUser = require('../api/models/ap_user')
const { Event, Resource, APUser } = require('../api/models/models')
const log = require('../log')
const helpers = require('../helpers')

View file

@ -1,7 +1,5 @@
const Event = require('../api/models/event')
const Place = require('../api/models/place')
const APUser = require('../api/models/ap_user')
const Tag = require('../api/models/tag')
const { Event, Place, APUser, Tag } = require('../api/models/models')
const escape = require('lodash/escape')
const config = require('../config')
const log = require('../log')

View file

@ -1,8 +1,6 @@
const express = require('express')
const router = express.Router()
const Event = require('../api/models/event')
const Resource = require('../api/models/resource')
const User = require('../api/models/user')
const { Event, Resource, User } = require('../api/models/models')
const cors = require('cors')
const settingsController = require('../api/controller/settings')
@ -65,7 +63,9 @@ router.get('/nodeinfo/:nodeinfo_version', async (req, res) => {
metadata: {
nodeDescription: settings.description,
nodeName: settings.title,
nodeLabel: settings.instance_place
nodeLabel: settings.instance_place,
nodeTimezone: settings.instance_timezone,
nodeActor: settings.instance_name
},
openRegistrations: settings.allow_registration,
protocols: ['activitypub'],

View file

@ -1,6 +1,5 @@
const ical = require('ical.js')
const settingsController = require('./api/controller/settings')
const acceptLanguage = require('accept-language')
const express = require('express')
const dayjs = require('dayjs')
const timezone = require('dayjs/plugin/timezone')
@ -15,7 +14,6 @@ const axios = require('axios')
const crypto = require('crypto')
const Microformats = require('microformat-node')
const get = require('lodash/get')
const cloneDeep = require('lodash/cloneDeep')
const DOMPurify = require('dompurify')
const { JSDOM } = require('jsdom')
@ -119,9 +117,9 @@ module.exports = {
log.warn(err)
} else {
res.status(404).send('Not found (but nice try 😊)')
// }
}
}
}})
})
})
router.use('/fallbackimage.png', (req, res, next) => {
@ -287,5 +285,13 @@ module.exports = {
return res.redirect((accepted === 'application/rss+xml' ? '/feed/rss' : '/feed/ics') + req.path)
}
next()
},
async isGeocodingEnabled(req, res, next) {
if (res.locals.settings.allow_geolocation) {
next()
} else {
res.sendStatus(403)
}
}
}

View file

@ -1,5 +1,4 @@
const Place = require('../api/models/place')
const Event = require('../api/models/event')
const { Event, Place } = require('../api/models/models')
const Sequelize = require('sequelize')
const log = require('../log')

View file

@ -1,5 +1,5 @@
const Tag = require('../api/models/tag')
const Event = require('../api/models/event')
const { Event, Tag } = require('../api/models/models')
const Sequelize = require('sequelize')
const log = require('../log')
@ -13,7 +13,7 @@ module.exports = {
})
if (!tags.length) { return }
log.info(`Remove ${tags.length} unrelated tags`)
log.info(`Remove ${tags.length} orphan tags (${tags.join(', ')})`)
await Tag.destroy({
where: { tag: { [Sequelize.Op.in]: tags.map(p => p.tag) } }

View file

@ -0,0 +1,28 @@
const cache = require('memory-cache')
const providerCache = new cache.Cache()
const nominatim = {
commonName: 'Nominatim',
DEFAULT_ENDPOINT: 'https://nominatim.openstreetmap.org/search',
endpoint: (req, res) => {
return res.locals.settings.geocoding_provider || nominatim.DEFAULT_ENDPOINT
},
cache: providerCache,
getParams (req, res) {
const countrycodes = res.locals.settings.geocoding_countrycodes || []
const details = req.params.place_details
return {
countrycodes: countrycodes.join(','),
q: details,
limit: 3,
format: 'json',
addressdetails: 1,
namedetails: 1,
}
},
}
module.exports = nominatim

View file

@ -0,0 +1,23 @@
const cache = require('memory-cache')
const providerCache = new cache.Cache()
const photon = {
commonName: 'Photon',
DEFAULT_ENDPOINT: 'https://photon.komoot.io/api/',
endpoint: (req, res) => {
return res.locals.settings.geocoding_provider || photon.DEFAULT_ENDPOINT
},
cache: providerCache,
getParams (req, res) {
const details = req.params.place_details
return {
q: details,
limit: 3,
}
}
}
module.exports = photon

View file

@ -1,5 +1,4 @@
const log = require('./log')
const eventController = require('./api/controller/event')
const placeHelpers = require('./helpers/place')
const tagHelpers = require('./helpers/tag')
// const notifier = require('./notifier')
@ -54,6 +53,7 @@ class TaskManager {
}
start (interval = loopInterval) {
const eventController = require('./api/controller/event')
// create and clean recurrent events
this.add(new Task({

View file

@ -117,9 +117,9 @@ const Ce = /* @__PURE__ */ new Set();
function Ae(t, e) {
t && t.i && (Ce.delete(t), t.i(e));
}
function Me(t, e, i, n) {
const { fragment: l, on_mount: o, on_destroy: r, after_update: f } = t.$$;
l && l.m(e, i), n || Q(() => {
function Me(t, e, i, l) {
const { fragment: n, on_mount: o, on_destroy: r, after_update: f } = t.$$;
n && n.m(e, i), l || Q(() => {
const c = o.map(W).filter(_e);
r ? r.push(...c) : O(c), t.$$.on_mount = [];
}), f.forEach(Q);
@ -131,7 +131,7 @@ function Ne(t, e) {
function Te(t, e) {
t.$$.dirty[0] === -1 && (H.push(t), Se(), t.$$.dirty.fill(0)), t.$$.dirty[e / 31 | 0] |= 1 << e % 31;
}
function ye(t, e, i, n, l, o, r, f = [-1]) {
function ye(t, e, i, l, n, o, r, f = [-1]) {
const c = I;
R(t);
const s = t.$$ = {
@ -139,7 +139,7 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
ctx: null,
props: o,
update: L,
not_equal: l,
not_equal: n,
bound: ee(),
on_mount: [],
on_destroy: [],
@ -156,8 +156,8 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
let k = !1;
if (s.ctx = i ? i(t, e.props || {}, (m, _, ...C) => {
const w = C.length ? C[0] : _;
return s.ctx && l(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = n ? n(s.ctx) : !1, e.target) {
return s.ctx && n(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = l ? l(s.ctx) : !1, e.target) {
if (e.hydrate) {
const m = $e(e.target);
s.fragment && s.fragment.l(m), m.forEach(x);
@ -190,8 +190,8 @@ typeof HTMLElement == "function" && (X = class extends HTMLElement {
$on(t, e) {
const i = this.$$.callbacks[t] || (this.$$.callbacks[t] = []);
return i.push(e), () => {
const n = i.indexOf(e);
n !== -1 && i.splice(n, 1);
const l = i.indexOf(e);
l !== -1 && i.splice(l, 1);
};
}
$set(t) {
@ -211,13 +211,13 @@ function F(t, e = "long") {
function V(t) {
return t.multidate ? F(t.start_datetime) + " - " + F(t.end_datetime) : F(t.start_datetime) + (t.end_datetime ? "-" + F(t.end_datetime, "short") : "");
}
function ne(t, e, i) {
const n = t.slice();
return n[12] = e[i], n;
}
function le(t, e, i) {
const n = t.slice();
return n[15] = e[i], n;
const l = t.slice();
return l[12] = e[i], l;
}
function ne(t, e, i) {
const l = t.slice();
return l[15] = e[i], l;
}
function re(t) {
let e;
@ -225,11 +225,11 @@ function re(t) {
c() {
e = g("link"), a(e, "rel", "stylesheet"), a(e, "href", t[4]);
},
m(i, n) {
v(i, e, n);
m(i, l) {
v(i, e, l);
},
p(i, n) {
n & 16 && a(e, "href", i[4]);
p(i, l) {
l & 16 && a(e, "href", i[4]);
},
d(i) {
i && x(e);
@ -237,51 +237,51 @@ function re(t) {
};
}
function oe(t) {
let e, i, n = t[1] && t[3] === "true" && ae(t), l = t[5], o = [];
for (let r = 0; r < l.length; r += 1)
o[r] = ue(ne(t, l, r));
let e, i, l = t[1] && t[3] === "true" && ae(t), n = t[5], o = [];
for (let r = 0; r < n.length; r += 1)
o[r] = ue(le(t, n, r));
return {
c() {
e = g("div"), n && n.c(), i = z();
e = g("div"), l && l.c(), i = z();
for (let r = 0; r < o.length; r += 1)
o[r].c();
a(e, "id", "gancioEvents"), T(e, "dark", t[2] === "dark"), T(e, "light", t[2] === "light"), T(e, "sidebar", t[3] === "true"), T(e, "nosidebar", t[3] !== "true");
},
m(r, f) {
v(r, e, f), n && n.m(e, null), u(e, i);
v(r, e, f), l && l.m(e, null), u(e, i);
for (let c = 0; c < o.length; c += 1)
o[c].m(e, null);
},
p(r, f) {
if (r[1] && r[3] === "true" ? n ? n.p(r, f) : (n = ae(r), n.c(), n.m(e, i)) : n && (n.d(1), n = null), f & 41) {
l = r[5];
if (r[1] && r[3] === "true" ? l ? l.p(r, f) : (l = ae(r), l.c(), l.m(e, i)) : l && (l.d(1), l = null), f & 41) {
n = r[5];
let c;
for (c = 0; c < l.length; c += 1) {
const s = ne(r, l, c);
for (c = 0; c < n.length; c += 1) {
const s = le(r, n, c);
o[c] ? o[c].p(s, f) : (o[c] = ue(s), o[c].c(), o[c].m(e, null));
}
for (; c < o.length; c += 1)
o[c].d(1);
o.length = l.length;
o.length = n.length;
}
f & 4 && T(e, "dark", r[2] === "dark"), f & 4 && T(e, "light", r[2] === "light"), f & 8 && T(e, "sidebar", r[3] === "true"), f & 8 && T(e, "nosidebar", r[3] !== "true");
},
d(r) {
r && x(e), n && n.d(), pe(o, r);
r && x(e), l && l.d(), pe(o, r);
}
};
}
function ae(t) {
let e, i, n, l, o, r, f;
let e, i, l, n, o, r, f;
return {
c() {
e = g("a"), i = g("div"), n = g("div"), l = j(t[1]), o = z(), r = g("img"), a(n, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
e = g("a"), i = g("div"), l = g("div"), n = j(t[1]), o = z(), r = g("img"), a(l, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
},
m(c, s) {
v(c, e, s), u(e, i), u(i, n), u(n, l), u(i, o), u(i, r);
v(c, e, s), u(e, i), u(i, l), u(l, n), u(i, o), u(i, r);
},
p(c, s) {
s & 2 && N(l, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
s & 2 && N(n, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
},
d(c) {
c && x(e);
@ -293,50 +293,50 @@ function se(t) {
function i(o, r) {
return o[12].media.length ? Ge : Le;
}
let n = i(t), l = n(t);
let l = i(t), n = l(t);
return {
c() {
e = g("div"), l.c(), a(e, "class", "img");
e = g("div"), n.c(), a(e, "class", "img");
},
m(o, r) {
v(o, e, r), l.m(e, null);
v(o, e, r), n.m(e, null);
},
p(o, r) {
n === (n = i(o)) && l ? l.p(o, r) : (l.d(1), l = n(o), l && (l.c(), l.m(e, null)));
l === (l = i(o)) && n ? n.p(o, r) : (n.d(1), n = l(o), n && (n.c(), n.m(e, null)));
},
d(o) {
o && x(e), l.d();
o && x(e), n.d();
}
};
}
function Le(t) {
let e, i, n;
let e, i, l;
return {
c() {
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, n = t[0] + "/fallbackimage.png") || a(e, "src", n), a(e, "loading", "lazy");
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, l = t[0] + "/fallbackimage.png") || a(e, "src", l), a(e, "loading", "lazy");
},
m(l, o) {
v(l, e, o);
m(n, o) {
v(n, e, o);
},
p(l, o) {
o & 32 && i !== (i = l[12].title) && a(e, "alt", i), o & 1 && !G(e.src, n = l[0] + "/fallbackimage.png") && a(e, "src", n);
p(n, o) {
o & 32 && i !== (i = n[12].title) && a(e, "alt", i), o & 1 && !G(e.src, l = n[0] + "/fallbackimage.png") && a(e, "src", l);
},
d(l) {
l && x(e);
d(n) {
n && x(e);
}
};
}
function Ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", n = t[12].media[0].name), G(e.src, l = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", l), a(e, "loading", "lazy");
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", l = t[12].media[0].name), G(e.src, n = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", n), a(e, "loading", "lazy");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && n !== (n = o[12].media[0].name) && a(e, "alt", n), r & 33 && !G(e.src, l = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", l);
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && l !== (l = o[12].media[0].name) && a(e, "alt", l), r & 33 && !G(e.src, n = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", n);
},
d(o) {
o && x(e);
@ -344,50 +344,50 @@ function Ge(t) {
};
}
function ce(t) {
let e, i = t[12].tags, n = [];
for (let l = 0; l < i.length; l += 1)
n[l] = fe(le(t, i, l));
let e, i = t[12].tags, l = [];
for (let n = 0; n < i.length; n += 1)
l[n] = fe(ne(t, i, n));
return {
c() {
e = g("div");
for (let l = 0; l < n.length; l += 1)
n[l].c();
for (let n = 0; n < l.length; n += 1)
l[n].c();
a(e, "class", "tags");
},
m(l, o) {
v(l, e, o);
for (let r = 0; r < n.length; r += 1)
n[r].m(e, null);
m(n, o) {
v(n, e, o);
for (let r = 0; r < l.length; r += 1)
l[r].m(e, null);
},
p(l, o) {
p(n, o) {
if (o & 32) {
i = l[12].tags;
i = n[12].tags;
let r;
for (r = 0; r < i.length; r += 1) {
const f = le(l, i, r);
n[r] ? n[r].p(f, o) : (n[r] = fe(f), n[r].c(), n[r].m(e, null));
const f = ne(n, i, r);
l[r] ? l[r].p(f, o) : (l[r] = fe(f), l[r].c(), l[r].m(e, null));
}
for (; r < n.length; r += 1)
n[r].d(1);
n.length = i.length;
for (; r < l.length; r += 1)
l[r].d(1);
l.length = i.length;
}
},
d(l) {
l && x(e), pe(n, l);
d(n) {
n && x(e), pe(l, n);
}
};
}
function fe(t) {
let e, i, n = t[15] + "", l;
let e, i, l = t[15] + "", n;
return {
c() {
e = g("span"), i = j("#"), l = j(n), a(e, "class", "tag");
e = g("span"), i = j("#"), n = j(l), a(e, "class", "tag");
},
m(o, r) {
v(o, e, r), u(e, i), u(e, l);
v(o, e, r), u(e, i), u(e, n);
},
p(o, r) {
r & 32 && n !== (n = o[15] + "") && N(l, n);
r & 32 && l !== (l = o[15] + "") && N(n, l);
},
d(o) {
o && x(e);
@ -395,16 +395,16 @@ function fe(t) {
};
}
function ue(t) {
let e, i, n, l, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
let e, i, l, n, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
return {
c() {
e = g("a"), $ && $.c(), i = z(), n = g("div"), l = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(l, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(n, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
e = g("a"), $ && $.c(), i = z(), l = g("div"), n = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(n, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(l, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
},
m(p, M) {
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(n, Y), E && E.m(n, null), u(e, Z);
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(l, Y), E && E.m(l, null), u(e, Z);
},
p(p, M) {
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(n, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(l, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
},
d(p) {
p && x(e), $ && $.d(), E && E.d();
@ -412,21 +412,21 @@ function ue(t) {
};
}
function He(t) {
let e, i, n = t[4] && re(t), l = t[5].length && oe(t);
let e, i, l = t[4] && re(t), n = t[5].length && oe(t);
return {
c() {
n && n.c(), e = z(), l && l.c(), i = ve(), this.c = L;
l && l.c(), e = z(), n && n.c(), i = ve(), this.c = L;
},
m(o, r) {
n && n.m(o, r), v(o, e, r), l && l.m(o, r), v(o, i, r);
l && l.m(o, r), v(o, e, r), n && n.m(o, r), v(o, i, r);
},
p(o, [r]) {
o[4] ? n ? n.p(o, r) : (n = re(o), n.c(), n.m(e.parentNode, e)) : n && (n.d(1), n = null), o[5].length ? l ? l.p(o, r) : (l = oe(o), l.c(), l.m(i.parentNode, i)) : l && (l.d(1), l = null);
o[4] ? l ? l.p(o, r) : (l = re(o), l.c(), l.m(e.parentNode, e)) : l && (l.d(1), l = null), o[5].length ? n ? n.p(o, r) : (n = oe(o), n.c(), n.m(i.parentNode, i)) : n && (n.d(1), n = null);
},
i: L,
o: L,
d(o) {
n && n.d(o), o && x(e), l && l.d(o), o && x(i);
l && l.d(o), o && x(e), n && n.d(o), o && x(i);
}
};
}
@ -438,12 +438,12 @@ function de(t) {
return "center center";
}
function Re(t, e, i) {
let { baseurl: n = "" } = e, { title: l = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
let { baseurl: l = "" } = e, { title: n = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
function w(d) {
if (!_)
return;
const S = [];
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${n}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${l}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
i(5, C = h);
}).catch((h) => {
console.error("Error loading Gancio API -> ", h);
@ -452,12 +452,12 @@ function Re(t, e, i) {
return we(() => {
_ = !0, w();
}), t.$$set = (d) => {
"baseurl" in d && i(0, n = d.baseurl), "title" in d && i(1, l = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
"baseurl" in d && i(0, l = d.baseurl), "title" in d && i(1, n = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
}, t.$$.update = () => {
t.$$.dirty & 975 && w();
}, [
n,
l,
n,
c,
k,
m,
@ -570,13 +570,13 @@ class Ie extends X {
}
customElements.define("gancio-events", Ie);
function he(t) {
let e, i, n, l, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
let e, i, l, n, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
return {
c() {
e = g("a"), h && h.c(), i = z(), n = g("div"), l = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(n, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
e = g("a"), h && h.c(), i = z(), l = g("div"), n = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(l, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
},
m(b, A) {
v(b, e, A), h && h.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d);
v(b, e, A), h && h.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d);
},
p(b, A) {
b[1].media.length ? h ? h.p(b, A) : (h = ge(b), h.c(), h.m(e, i)) : h && (h.d(1), h = null), A & 2 && o !== (o = b[1].title + "") && N(r, o), A & 2 && s !== (s = V(b[1]) + "") && N(k, s), A & 2 && w !== (w = b[1].place.name + "") && N(d, w), A & 3 && S !== (S = b[0] + "/event/" + (b[1].slug || b[1].id)) && a(e, "href", S);
@ -587,16 +587,16 @@ function he(t) {
};
}
function ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", n = t[1].media[0].name), a(e, "style", l = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", l = t[1].media[0].name), a(e, "style", n = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && n !== (n = o[1].media[0].name) && a(e, "alt", n), r & 2 && l !== (l = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", l);
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && l !== (l = o[1].media[0].name) && a(e, "alt", l), r & 2 && n !== (n = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", n);
},
d(o) {
o && x(e);
@ -609,16 +609,16 @@ function Oe(t) {
c() {
i && i.c(), e = ve(), this.c = L;
},
m(n, l) {
i && i.m(n, l), v(n, e, l);
m(l, n) {
i && i.m(l, n), v(l, e, n);
},
p(n, [l]) {
n[1] ? i ? i.p(n, l) : (i = he(n), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
p(l, [n]) {
l[1] ? i ? i.p(l, n) : (i = he(l), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
},
i: L,
o: L,
d(n) {
i && i.d(n), n && x(e);
d(l) {
i && i.d(l), l && x(e);
}
};
}
@ -630,21 +630,21 @@ function me(t) {
return "center center";
}
function Ue(t, e, i) {
let { baseurl: n = "https://demo.gancio.org" } = e, { id: l } = e, o = !1, r;
let { baseurl: l = "https://demo.gancio.org" } = e, { id: n } = e, o = !1, r;
function f(s, k) {
o && fetch(`${k}/api/event/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
o && fetch(`${k}/api/event/detail/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
}
we(() => {
o = !0, f(l, n);
o = !0, f(n, l);
});
function c(s) {
return `${n}/media/thumb/${s.media[0].url}`;
return `${l}/media/thumb/${s.media[0].url}`;
}
return t.$$set = (s) => {
"baseurl" in s && i(0, n = s.baseurl), "id" in s && i(3, l = s.id);
"baseurl" in s && i(0, l = s.baseurl), "id" in s && i(3, n = s.id);
}, t.$$.update = () => {
t.$$.dirty & 9 && f(l, n);
}, [n, r, c, l];
t.$$.dirty & 9 && f(n, l);
}, [l, r, c, n];
}
class qe extends X {
constructor(e) {

View file

@ -1,6 +1,10 @@
import dayjs from 'dayjs'
export const state = () => ({
localSettings : {
hide_thumbs: null,
'theme.is_dark': null
},
settings: {
instance_timezone: 'Europe/Rome',
instance_name: '',
@ -21,17 +25,29 @@ export const state = () => ({
enable_trusted_instances: true,
trusted_instances: [],
trusted_instances_label: '',
footerLinks: []
footerLinks: [],
hide_thumbs: false,
'theme.is_dark': true,
hide_calendar: false
},
filter: {
query: '',
show_recurrent: null,
show_multidate: null
show_multidate: null,
},
announcements: [],
events: []
})
export const getters = {
hide_thumbs (state) {
return (state.localSettings['hide_thumbs'] === null) ? state.settings.hide_thumbs : state.localSettings.hide_thumbs
},
is_dark (state) {
return (state.localSettings['theme.is_dark'] === null) ? state.settings['theme.is_dark'] : state.localSettings['theme.is_dark']
}
}
export const mutations = {
setSettings (state, settings) {
state.settings = settings
@ -39,11 +55,14 @@ export const mutations = {
setSetting (state, setting) {
state.settings[setting.key] = setting.value
},
setLocalSetting(state, setting) {
state.localSettings[setting.key] = setting.value
},
setAnnouncements (state, announcements) {
state.announcements = announcements
},
setEvents (state, events) {
state.events = events
state.events = Object.freeze(events)
},
setFilter (state, { type, value }) {
state.filter[type] = value
@ -53,11 +72,17 @@ export const mutations = {
export const actions = {
// this method is called server side only for each request for nuxt
// we use it to get configuration from db, set locale, etc...
nuxtServerInit ({ commit }, { _req, res }) {
commit('setSettings', res.locals.settings)
nuxtServerInit ({ commit }, { res, app }) {
if (res.locals && res.locals.settings) {
commit('setSettings', res.locals.settings)
}
commit('setFilter', { type: 'show_recurrent',
value: res.locals.settings.allow_recurrent_event && res.locals.settings.recurrent_event_visible })
commit('setLocalSetting', { key: 'hide_thumbs', value: app.$cookies.get('hide_thumbs') })
commit('setLocalSetting', { key: 'theme.is_dark', value: app.$cookies.get('theme.is_dark') })
if (res.locals.status === 'READY') {
commit('setAnnouncements', res.locals.announcements)
}
@ -73,6 +98,13 @@ export const actions = {
await this.$axios.$post('/settings', setting)
commit('setSetting', setting)
},
async setLocalSetting ({ commit }, setting) {
this.$cookies.set(setting.key, setting.value, {
path: '/',
maxAge: 60 * 60 * 24 * 7
})
commit('setLocalSetting', setting)
},
setFilter ({ commit }, [type, value]) {
commit('setFilter', { type, value })
},
@ -84,6 +116,5 @@ export const actions = {
show_multidate: state.filter.show_multidate
})
commit('setEvents', events)
return events
}
}

View file

@ -415,5 +415,33 @@ describe('Collection', () => {
expect(response.body.length).toBe(1)
})
})
describe('Geocoding', () => {
test('should not be enabled by default', async () => {
await request(app)
.post('/api/settings')
.send({ key: 'allow_geolocation', value: false })
.auth(token.access_token, { type: 'bearer' })
.expect(200)
const response = await request(app).get('/api/placeOSM/Nominatim/test')
.expect(403)
expect(response.body).toBeDefined()
})
test('should geocode when enabled', async () => {
await request(app)
.post('/api/settings')
.send({ key: 'allow_geolocation', value: true })
.auth(token.access_token, { type: 'bearer' })
.expect(200)
const response = await request(app).get('/api/placeOSM/Nominatim/test')
.expect(200)
expect(response.body).toBeDefined()
})
})

View file

@ -11,7 +11,7 @@
function update(id, baseurl) {
if (mounted) {
fetch(`${baseurl}/api/event/${id}`)
fetch(`${baseurl}/api/event/detail/${id}`)
.then((res) => res.json())
.then((e) => (event = e))
}

View file

@ -117,9 +117,9 @@ const Ce = /* @__PURE__ */ new Set();
function Ae(t, e) {
t && t.i && (Ce.delete(t), t.i(e));
}
function Me(t, e, i, n) {
const { fragment: l, on_mount: o, on_destroy: r, after_update: f } = t.$$;
l && l.m(e, i), n || Q(() => {
function Me(t, e, i, l) {
const { fragment: n, on_mount: o, on_destroy: r, after_update: f } = t.$$;
n && n.m(e, i), l || Q(() => {
const c = o.map(W).filter(_e);
r ? r.push(...c) : O(c), t.$$.on_mount = [];
}), f.forEach(Q);
@ -131,7 +131,7 @@ function Ne(t, e) {
function Te(t, e) {
t.$$.dirty[0] === -1 && (H.push(t), Se(), t.$$.dirty.fill(0)), t.$$.dirty[e / 31 | 0] |= 1 << e % 31;
}
function ye(t, e, i, n, l, o, r, f = [-1]) {
function ye(t, e, i, l, n, o, r, f = [-1]) {
const c = I;
R(t);
const s = t.$$ = {
@ -139,7 +139,7 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
ctx: null,
props: o,
update: L,
not_equal: l,
not_equal: n,
bound: ee(),
on_mount: [],
on_destroy: [],
@ -156,8 +156,8 @@ function ye(t, e, i, n, l, o, r, f = [-1]) {
let k = !1;
if (s.ctx = i ? i(t, e.props || {}, (m, _, ...C) => {
const w = C.length ? C[0] : _;
return s.ctx && l(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = n ? n(s.ctx) : !1, e.target) {
return s.ctx && n(s.ctx[m], s.ctx[m] = w) && (!s.skip_bound && s.bound[m] && s.bound[m](w), k && Te(t, m)), _;
}) : [], s.update(), k = !0, O(s.before_update), s.fragment = l ? l(s.ctx) : !1, e.target) {
if (e.hydrate) {
const m = $e(e.target);
s.fragment && s.fragment.l(m), m.forEach(x);
@ -190,8 +190,8 @@ typeof HTMLElement == "function" && (X = class extends HTMLElement {
$on(t, e) {
const i = this.$$.callbacks[t] || (this.$$.callbacks[t] = []);
return i.push(e), () => {
const n = i.indexOf(e);
n !== -1 && i.splice(n, 1);
const l = i.indexOf(e);
l !== -1 && i.splice(l, 1);
};
}
$set(t) {
@ -211,13 +211,13 @@ function F(t, e = "long") {
function V(t) {
return t.multidate ? F(t.start_datetime) + " - " + F(t.end_datetime) : F(t.start_datetime) + (t.end_datetime ? "-" + F(t.end_datetime, "short") : "");
}
function ne(t, e, i) {
const n = t.slice();
return n[12] = e[i], n;
}
function le(t, e, i) {
const n = t.slice();
return n[15] = e[i], n;
const l = t.slice();
return l[12] = e[i], l;
}
function ne(t, e, i) {
const l = t.slice();
return l[15] = e[i], l;
}
function re(t) {
let e;
@ -225,11 +225,11 @@ function re(t) {
c() {
e = g("link"), a(e, "rel", "stylesheet"), a(e, "href", t[4]);
},
m(i, n) {
v(i, e, n);
m(i, l) {
v(i, e, l);
},
p(i, n) {
n & 16 && a(e, "href", i[4]);
p(i, l) {
l & 16 && a(e, "href", i[4]);
},
d(i) {
i && x(e);
@ -237,51 +237,51 @@ function re(t) {
};
}
function oe(t) {
let e, i, n = t[1] && t[3] === "true" && ae(t), l = t[5], o = [];
for (let r = 0; r < l.length; r += 1)
o[r] = ue(ne(t, l, r));
let e, i, l = t[1] && t[3] === "true" && ae(t), n = t[5], o = [];
for (let r = 0; r < n.length; r += 1)
o[r] = ue(le(t, n, r));
return {
c() {
e = g("div"), n && n.c(), i = z();
e = g("div"), l && l.c(), i = z();
for (let r = 0; r < o.length; r += 1)
o[r].c();
a(e, "id", "gancioEvents"), T(e, "dark", t[2] === "dark"), T(e, "light", t[2] === "light"), T(e, "sidebar", t[3] === "true"), T(e, "nosidebar", t[3] !== "true");
},
m(r, f) {
v(r, e, f), n && n.m(e, null), u(e, i);
v(r, e, f), l && l.m(e, null), u(e, i);
for (let c = 0; c < o.length; c += 1)
o[c].m(e, null);
},
p(r, f) {
if (r[1] && r[3] === "true" ? n ? n.p(r, f) : (n = ae(r), n.c(), n.m(e, i)) : n && (n.d(1), n = null), f & 41) {
l = r[5];
if (r[1] && r[3] === "true" ? l ? l.p(r, f) : (l = ae(r), l.c(), l.m(e, i)) : l && (l.d(1), l = null), f & 41) {
n = r[5];
let c;
for (c = 0; c < l.length; c += 1) {
const s = ne(r, l, c);
for (c = 0; c < n.length; c += 1) {
const s = le(r, n, c);
o[c] ? o[c].p(s, f) : (o[c] = ue(s), o[c].c(), o[c].m(e, null));
}
for (; c < o.length; c += 1)
o[c].d(1);
o.length = l.length;
o.length = n.length;
}
f & 4 && T(e, "dark", r[2] === "dark"), f & 4 && T(e, "light", r[2] === "light"), f & 8 && T(e, "sidebar", r[3] === "true"), f & 8 && T(e, "nosidebar", r[3] !== "true");
},
d(r) {
r && x(e), n && n.d(), pe(o, r);
r && x(e), l && l.d(), pe(o, r);
}
};
}
function ae(t) {
let e, i, n, l, o, r, f;
let e, i, l, n, o, r, f;
return {
c() {
e = g("a"), i = g("div"), n = g("div"), l = j(t[1]), o = z(), r = g("img"), a(n, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
e = g("a"), i = g("div"), l = g("div"), n = j(t[1]), o = z(), r = g("img"), a(l, "class", "title"), a(r, "id", "logo"), a(r, "alt", "logo"), G(r.src, f = t[0] + "/logo.png") || a(r, "src", f), a(i, "class", "content"), a(e, "href", t[0]), a(e, "target", "_blank"), a(e, "id", "header");
},
m(c, s) {
v(c, e, s), u(e, i), u(i, n), u(n, l), u(i, o), u(i, r);
v(c, e, s), u(e, i), u(i, l), u(l, n), u(i, o), u(i, r);
},
p(c, s) {
s & 2 && N(l, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
s & 2 && N(n, c[1]), s & 1 && !G(r.src, f = c[0] + "/logo.png") && a(r, "src", f), s & 1 && a(e, "href", c[0]);
},
d(c) {
c && x(e);
@ -293,50 +293,50 @@ function se(t) {
function i(o, r) {
return o[12].media.length ? Ge : Le;
}
let n = i(t), l = n(t);
let l = i(t), n = l(t);
return {
c() {
e = g("div"), l.c(), a(e, "class", "img");
e = g("div"), n.c(), a(e, "class", "img");
},
m(o, r) {
v(o, e, r), l.m(e, null);
v(o, e, r), n.m(e, null);
},
p(o, r) {
n === (n = i(o)) && l ? l.p(o, r) : (l.d(1), l = n(o), l && (l.c(), l.m(e, null)));
l === (l = i(o)) && n ? n.p(o, r) : (n.d(1), n = l(o), n && (n.c(), n.m(e, null)));
},
d(o) {
o && x(e), l.d();
o && x(e), n.d();
}
};
}
function Le(t) {
let e, i, n;
let e, i, l;
return {
c() {
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, n = t[0] + "/fallbackimage.png") || a(e, "src", n), a(e, "loading", "lazy");
e = g("img"), a(e, "style", "aspect-ratio=1.7778;"), a(e, "alt", i = t[12].title), G(e.src, l = t[0] + "/fallbackimage.png") || a(e, "src", l), a(e, "loading", "lazy");
},
m(l, o) {
v(l, e, o);
m(n, o) {
v(n, e, o);
},
p(l, o) {
o & 32 && i !== (i = l[12].title) && a(e, "alt", i), o & 1 && !G(e.src, n = l[0] + "/fallbackimage.png") && a(e, "src", n);
p(n, o) {
o & 32 && i !== (i = n[12].title) && a(e, "alt", i), o & 1 && !G(e.src, l = n[0] + "/fallbackimage.png") && a(e, "src", l);
},
d(l) {
l && x(e);
d(n) {
n && x(e);
}
};
}
function Ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", n = t[12].media[0].name), G(e.src, l = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", l), a(e, "loading", "lazy");
e = g("img"), a(e, "style", i = "object-position: " + de(t[12]) + "; aspect-ratio=1.7778;"), a(e, "alt", l = t[12].media[0].name), G(e.src, n = t[0] + "/media/thumb/" + t[12].media[0].url) || a(e, "src", n), a(e, "loading", "lazy");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && n !== (n = o[12].media[0].name) && a(e, "alt", n), r & 33 && !G(e.src, l = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", l);
r & 32 && i !== (i = "object-position: " + de(o[12]) + "; aspect-ratio=1.7778;") && a(e, "style", i), r & 32 && l !== (l = o[12].media[0].name) && a(e, "alt", l), r & 33 && !G(e.src, n = o[0] + "/media/thumb/" + o[12].media[0].url) && a(e, "src", n);
},
d(o) {
o && x(e);
@ -344,50 +344,50 @@ function Ge(t) {
};
}
function ce(t) {
let e, i = t[12].tags, n = [];
for (let l = 0; l < i.length; l += 1)
n[l] = fe(le(t, i, l));
let e, i = t[12].tags, l = [];
for (let n = 0; n < i.length; n += 1)
l[n] = fe(ne(t, i, n));
return {
c() {
e = g("div");
for (let l = 0; l < n.length; l += 1)
n[l].c();
for (let n = 0; n < l.length; n += 1)
l[n].c();
a(e, "class", "tags");
},
m(l, o) {
v(l, e, o);
for (let r = 0; r < n.length; r += 1)
n[r].m(e, null);
m(n, o) {
v(n, e, o);
for (let r = 0; r < l.length; r += 1)
l[r].m(e, null);
},
p(l, o) {
p(n, o) {
if (o & 32) {
i = l[12].tags;
i = n[12].tags;
let r;
for (r = 0; r < i.length; r += 1) {
const f = le(l, i, r);
n[r] ? n[r].p(f, o) : (n[r] = fe(f), n[r].c(), n[r].m(e, null));
const f = ne(n, i, r);
l[r] ? l[r].p(f, o) : (l[r] = fe(f), l[r].c(), l[r].m(e, null));
}
for (; r < n.length; r += 1)
n[r].d(1);
n.length = i.length;
for (; r < l.length; r += 1)
l[r].d(1);
l.length = i.length;
}
},
d(l) {
l && x(e), pe(n, l);
d(n) {
n && x(e), pe(l, n);
}
};
}
function fe(t) {
let e, i, n = t[15] + "", l;
let e, i, l = t[15] + "", n;
return {
c() {
e = g("span"), i = j("#"), l = j(n), a(e, "class", "tag");
e = g("span"), i = j("#"), n = j(l), a(e, "class", "tag");
},
m(o, r) {
v(o, e, r), u(e, i), u(e, l);
v(o, e, r), u(e, i), u(e, n);
},
p(o, r) {
r & 32 && n !== (n = o[15] + "") && N(l, n);
r & 32 && l !== (l = o[15] + "") && N(n, l);
},
d(o) {
o && x(e);
@ -395,16 +395,16 @@ function fe(t) {
};
}
function ue(t) {
let e, i, n, l, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
let e, i, l, n, o = V(t[12]) + "", r, f, c, s = t[12].title + "", k, m, _, C, w = t[12].place.name + "", d, S, h, b = t[12].place.address + "", A, Y, Z, U, q, $ = t[3] !== "true" && se(t), E = t[12].tags.length && ce(t);
return {
c() {
e = g("a"), $ && $.c(), i = z(), n = g("div"), l = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(l, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(n, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
e = g("a"), $ && $.c(), i = z(), l = g("div"), n = g("div"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("span"), C = j("@"), d = j(w), S = z(), h = g("span"), A = j(b), Y = z(), E && E.c(), Z = z(), a(n, "class", "subtitle"), a(c, "class", "title"), a(h, "class", "subtitle"), a(_, "class", "place"), a(l, "class", "content"), a(e, "href", U = t[0] + "/event/" + (t[12].slug || t[12].id)), a(e, "class", "event"), a(e, "title", q = t[12].title), a(e, "target", "_blank");
},
m(p, M) {
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(n, Y), E && E.m(n, null), u(e, Z);
v(p, e, M), $ && $.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d), u(_, S), u(_, h), u(h, A), u(l, Y), E && E.m(l, null), u(e, Z);
},
p(p, M) {
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(n, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
p[3] !== "true" ? $ ? $.p(p, M) : ($ = se(p), $.c(), $.m(e, i)) : $ && ($.d(1), $ = null), M & 32 && o !== (o = V(p[12]) + "") && N(r, o), M & 32 && s !== (s = p[12].title + "") && N(k, s), M & 32 && w !== (w = p[12].place.name + "") && N(d, w), M & 32 && b !== (b = p[12].place.address + "") && N(A, b), p[12].tags.length ? E ? E.p(p, M) : (E = ce(p), E.c(), E.m(l, null)) : E && (E.d(1), E = null), M & 33 && U !== (U = p[0] + "/event/" + (p[12].slug || p[12].id)) && a(e, "href", U), M & 32 && q !== (q = p[12].title) && a(e, "title", q);
},
d(p) {
p && x(e), $ && $.d(), E && E.d();
@ -412,21 +412,21 @@ function ue(t) {
};
}
function He(t) {
let e, i, n = t[4] && re(t), l = t[5].length && oe(t);
let e, i, l = t[4] && re(t), n = t[5].length && oe(t);
return {
c() {
n && n.c(), e = z(), l && l.c(), i = ve(), this.c = L;
l && l.c(), e = z(), n && n.c(), i = ve(), this.c = L;
},
m(o, r) {
n && n.m(o, r), v(o, e, r), l && l.m(o, r), v(o, i, r);
l && l.m(o, r), v(o, e, r), n && n.m(o, r), v(o, i, r);
},
p(o, [r]) {
o[4] ? n ? n.p(o, r) : (n = re(o), n.c(), n.m(e.parentNode, e)) : n && (n.d(1), n = null), o[5].length ? l ? l.p(o, r) : (l = oe(o), l.c(), l.m(i.parentNode, i)) : l && (l.d(1), l = null);
o[4] ? l ? l.p(o, r) : (l = re(o), l.c(), l.m(e.parentNode, e)) : l && (l.d(1), l = null), o[5].length ? n ? n.p(o, r) : (n = oe(o), n.c(), n.m(i.parentNode, i)) : n && (n.d(1), n = null);
},
i: L,
o: L,
d(o) {
n && n.d(o), o && x(e), l && l.d(o), o && x(i);
l && l.d(o), o && x(e), n && n.d(o), o && x(i);
}
};
}
@ -438,12 +438,12 @@ function de(t) {
return "center center";
}
function Re(t, e, i) {
let { baseurl: n = "" } = e, { title: l = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
let { baseurl: l = "" } = e, { title: n = "" } = e, { maxlength: o = !1 } = e, { tags: r = "" } = e, { places: f = "" } = e, { theme: c = "light" } = e, { show_recurrent: s = !1 } = e, { sidebar: k = "true" } = e, { external_style: m = "" } = e, _ = !1, C = [];
function w(d) {
if (!_)
return;
const S = [];
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${n}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
o && S.push(`max=${o}`), r && S.push(`tags=${r}`), f && S.push(`places=${f}`), S.push(`show_recurrent=${s ? "true" : "false"}`), fetch(`${l}/api/events?${S.join("&")}`).then((h) => h.json()).then((h) => {
i(5, C = h);
}).catch((h) => {
console.error("Error loading Gancio API -> ", h);
@ -452,12 +452,12 @@ function Re(t, e, i) {
return we(() => {
_ = !0, w();
}), t.$$set = (d) => {
"baseurl" in d && i(0, n = d.baseurl), "title" in d && i(1, l = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
"baseurl" in d && i(0, l = d.baseurl), "title" in d && i(1, n = d.title), "maxlength" in d && i(6, o = d.maxlength), "tags" in d && i(7, r = d.tags), "places" in d && i(8, f = d.places), "theme" in d && i(2, c = d.theme), "show_recurrent" in d && i(9, s = d.show_recurrent), "sidebar" in d && i(3, k = d.sidebar), "external_style" in d && i(4, m = d.external_style);
}, t.$$.update = () => {
t.$$.dirty & 975 && w();
}, [
n,
l,
n,
c,
k,
m,
@ -570,13 +570,13 @@ class Ie extends X {
}
customElements.define("gancio-events", Ie);
function he(t) {
let e, i, n, l, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
let e, i, l, n, o = t[1].title + "", r, f, c, s = V(t[1]) + "", k, m, _, C, w = t[1].place.name + "", d, S, h = t[1].media.length && ge(t);
return {
c() {
e = g("a"), h && h.c(), i = z(), n = g("div"), l = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(n, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
e = g("a"), h && h.c(), i = z(), l = g("div"), n = g("strong"), r = j(o), f = z(), c = g("div"), k = j(s), m = z(), _ = g("div"), C = j("@"), d = j(w), a(_, "class", "place"), a(l, "class", "container"), a(e, "href", S = t[0] + "/event/" + (t[1].slug || t[1].id)), a(e, "class", "card"), a(e, "target", "_blank");
},
m(b, A) {
v(b, e, A), h && h.m(e, null), u(e, i), u(e, n), u(n, l), u(l, r), u(n, f), u(n, c), u(c, k), u(n, m), u(n, _), u(_, C), u(_, d);
v(b, e, A), h && h.m(e, null), u(e, i), u(e, l), u(l, n), u(n, r), u(l, f), u(l, c), u(c, k), u(l, m), u(l, _), u(_, C), u(_, d);
},
p(b, A) {
b[1].media.length ? h ? h.p(b, A) : (h = ge(b), h.c(), h.m(e, i)) : h && (h.d(1), h = null), A & 2 && o !== (o = b[1].title + "") && N(r, o), A & 2 && s !== (s = V(b[1]) + "") && N(k, s), A & 2 && w !== (w = b[1].place.name + "") && N(d, w), A & 3 && S !== (S = b[0] + "/event/" + (b[1].slug || b[1].id)) && a(e, "href", S);
@ -587,16 +587,16 @@ function he(t) {
};
}
function ge(t) {
let e, i, n, l;
let e, i, l, n;
return {
c() {
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", n = t[1].media[0].name), a(e, "style", l = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
e = g("img"), G(e.src, i = t[2](t[1])) || a(e, "src", i), a(e, "alt", l = t[1].media[0].name), a(e, "style", n = "object-position: " + me(t[1]) + "; aspect-ratio=1.7778;");
},
m(o, r) {
v(o, e, r);
},
p(o, r) {
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && n !== (n = o[1].media[0].name) && a(e, "alt", n), r & 2 && l !== (l = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", l);
r & 2 && !G(e.src, i = o[2](o[1])) && a(e, "src", i), r & 2 && l !== (l = o[1].media[0].name) && a(e, "alt", l), r & 2 && n !== (n = "object-position: " + me(o[1]) + "; aspect-ratio=1.7778;") && a(e, "style", n);
},
d(o) {
o && x(e);
@ -609,16 +609,16 @@ function Oe(t) {
c() {
i && i.c(), e = ve(), this.c = L;
},
m(n, l) {
i && i.m(n, l), v(n, e, l);
m(l, n) {
i && i.m(l, n), v(l, e, n);
},
p(n, [l]) {
n[1] ? i ? i.p(n, l) : (i = he(n), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
p(l, [n]) {
l[1] ? i ? i.p(l, n) : (i = he(l), i.c(), i.m(e.parentNode, e)) : i && (i.d(1), i = null);
},
i: L,
o: L,
d(n) {
i && i.d(n), n && x(e);
d(l) {
i && i.d(l), l && x(e);
}
};
}
@ -630,21 +630,21 @@ function me(t) {
return "center center";
}
function Ue(t, e, i) {
let { baseurl: n = "https://demo.gancio.org" } = e, { id: l } = e, o = !1, r;
let { baseurl: l = "https://demo.gancio.org" } = e, { id: n } = e, o = !1, r;
function f(s, k) {
o && fetch(`${k}/api/event/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
o && fetch(`${k}/api/event/detail/${s}`).then((m) => m.json()).then((m) => i(1, r = m));
}
we(() => {
o = !0, f(l, n);
o = !0, f(n, l);
});
function c(s) {
return `${n}/media/thumb/${s.media[0].url}`;
return `${l}/media/thumb/${s.media[0].url}`;
}
return t.$$set = (s) => {
"baseurl" in s && i(0, n = s.baseurl), "id" in s && i(3, l = s.id);
"baseurl" in s && i(0, l = s.baseurl), "id" in s && i(3, n = s.id);
}, t.$$.update = () => {
t.$$.dirty & 9 && f(l, n);
}, [n, r, c, l];
t.$$.dirty & 9 && f(n, l);
}, [l, r, c, n];
}
class qe extends X {
constructor(e) {

1020
yarn.lock

File diff suppressed because it is too large Load diff