Merge branch 'master' into gh
This commit is contained in:
commit
b66feb92e2
47 changed files with 998 additions and 781 deletions
8
.snyk
Normal file
8
.snyk
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
||||||
|
version: v1.25.0
|
||||||
|
ignore: {}
|
||||||
|
# patches apply the minimum changes required to fix a vulnerability
|
||||||
|
patch:
|
||||||
|
SNYK-JS-LODASH-567746:
|
||||||
|
- express-oauth-server > oauth2-server > lodash:
|
||||||
|
patched: '2022-06-06T14:57:24.390Z'
|
|
@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- new Tag page!
|
- new Tag page!
|
||||||
- new Place page!
|
- new Place page!
|
||||||
- new search flow
|
- new search flow
|
||||||
- new meta-tag-place / group / cohort page!
|
- new meta-tag-place / group / collection page!
|
||||||
- allow footer links reordering
|
- allow footer links reordering
|
||||||
- new Docker image
|
- new Docker image
|
||||||
- add GANCIO_DB_PORT environment
|
- add GANCIO_DB_PORT environment
|
||||||
|
@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file.
|
||||||
- add dynamic sitemap.xml !
|
- add dynamic sitemap.xml !
|
||||||
- calendar attributes refactoring (a dot each day, colors represents n. events)
|
- calendar attributes refactoring (a dot each day, colors represents n. events)
|
||||||
- fix event mime type response
|
- fix event mime type response
|
||||||
|
- new **undocumented** gancio CLI accounts management (list / create / remove / modify accounts)
|
||||||
|
|
||||||
|
|
||||||
### 1.4.4 - 10 may '22
|
### 1.4.4 - 10 may '22
|
||||||
|
|
|
@ -42,9 +42,10 @@ li {
|
||||||
.v-dialog {
|
.v-dialog {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
&.v-dialog--fullscreen {
|
}
|
||||||
max-width: 100%;
|
|
||||||
}
|
.v-dialog .v-dialog--fullscreen {
|
||||||
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.theme--dark.v-list {
|
.theme--dark.v-list {
|
||||||
|
|
|
@ -47,7 +47,6 @@ v-col(cols=12)
|
||||||
:disabled='!value.from'
|
:disabled='!value.from'
|
||||||
:prepend-icon="mdiClockTimeFourOutline"
|
:prepend-icon="mdiClockTimeFourOutline"
|
||||||
:rules="[$validators.required('event.from')]"
|
:rules="[$validators.required('event.from')]"
|
||||||
readonly
|
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="on")
|
v-on="on")
|
||||||
v-time-picker(
|
v-time-picker(
|
||||||
|
@ -72,7 +71,6 @@ v-col(cols=12)
|
||||||
:value="dueHour"
|
:value="dueHour"
|
||||||
:disabled='!fromHour'
|
:disabled='!fromHour'
|
||||||
:prepend-icon="mdiClockTimeEightOutline"
|
:prepend-icon="mdiClockTimeEightOutline"
|
||||||
readonly
|
|
||||||
v-bind="attrs"
|
v-bind="attrs"
|
||||||
v-on="on")
|
v-on="on")
|
||||||
v-time-picker(
|
v-time-picker(
|
||||||
|
@ -103,7 +101,7 @@ export default {
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
mdiClockTimeFourOutline, mdiClockTimeEightOutline,
|
mdiClockTimeFourOutline, mdiClockTimeEightOutline,
|
||||||
allowedMinutes: [0, 15, 30, 45],
|
allowedMinutes: [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55],
|
||||||
menuFromHour: false,
|
menuFromHour: false,
|
||||||
menuDueHour: false,
|
menuDueHour: false,
|
||||||
type: 'normal',
|
type: 'normal',
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
v-card-text.body.pt-0.pb-0
|
v-card-text.body.pt-0.pb-0
|
||||||
time.dt-start.subtitle-1(:datetime='event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")' itemprop="startDate" :content="event.start_datetime|unixFormat('YYYY-MM-DDTHH:mm')") <v-icon v-text='mdiCalendar'></v-icon> {{ event|when }}
|
time.dt-start.subtitle-1(:datetime='event.start_datetime|unixFormat("YYYY-MM-DD HH:mm")' itemprop="startDate" :content="event.start_datetime|unixFormat('YYYY-MM-DDTHH:mm')") <v-icon v-text='mdiCalendar'></v-icon> {{ event|when }}
|
||||||
.d-none.dt-end(itemprop="endDate" :content="event.end_datetime|unixFormat('YYYY-MM-DDTHH:mm')") {{event.end_datetime|unixFormat('YYYY-MM-DD HH:mm')}}
|
.d-none.dt-end(itemprop="endDate" :content="event.end_datetime|unixFormat('YYYY-MM-DDTHH:mm')") {{event.end_datetime|unixFormat('YYYY-MM-DD HH:mm')}}
|
||||||
nuxt-link.place.d-block.p-location.pl-0(text color='primary' :to='`/p/${event.place.name}`' itemprop="location" :content="event.place.name") <v-icon v-text='mdiMapMarker'></v-icon> {{event.place.name}}
|
nuxt-link.place.d-block.p-location.pl-0(text color='primary' :to='`/place/${event.place.name}`' itemprop="location" :content="event.place.name") <v-icon v-text='mdiMapMarker'></v-icon> {{event.place.name}}
|
||||||
.d-none(itemprop='location.address') {{event.place.address}}
|
.d-none(itemprop='location.address') {{event.place.address}}
|
||||||
|
|
||||||
v-card-actions.pt-0.actions.justify-space-between
|
v-card-actions.pt-0.actions.justify-space-between
|
||||||
|
|
|
@ -1,55 +1,55 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
v-app-bar(app aria-label='Menu' height=64)
|
v-app-bar(app aria-label='Menu' height=64)
|
||||||
|
|
||||||
//- logo, title and description
|
//- logo, title and description
|
||||||
v-list-item.pa-0(:to='$route.name==="index"?"/about":"/"')
|
v-list-item(:to='$route.name==="index"?"/about":"/"')
|
||||||
v-list-item-avatar.ma-xs-1(tile)
|
v-list-item-avatar.ma-xs-1(tile)
|
||||||
img(src='/logo.png' height='40')
|
img(src='/logo.png' height='40')
|
||||||
v-list-item-content.d-flex
|
v-list-item-content
|
||||||
v-list-item-title.d-flex
|
v-list-item-title.d-flex
|
||||||
h2 {{settings.title}}
|
h2 {{settings.title}}
|
||||||
v-list-item-subtitle.d-none.d-sm-flex {{settings.description}}
|
v-list-item-subtitle.d-none.d-sm-flex {{settings.description}}
|
||||||
|
|
||||||
v-spacer
|
v-spacer
|
||||||
v-btn(v-if='$auth.loggedIn || settings.allow_anon_event' icon nuxt to='/add' :aria-label='$t("common.add_event")' :title='$t("common.add_event")')
|
v-btn(v-if='$auth.loggedIn || settings.allow_anon_event' icon nuxt to='/add' :aria-label='$t("common.add_event")' :title='$t("common.add_event")')
|
||||||
v-icon(large color='primary' v-text='mdiPlus')
|
v-icon(large color='primary' v-text='mdiPlus')
|
||||||
|
|
||||||
v-btn(icon nuxt to='/export' :title='$t("common.share")' :aria-label='$t("common.share")')
|
v-btn(icon nuxt to='/export' :title='$t("common.share")' :aria-label='$t("common.share")')
|
||||||
v-icon(v-text='mdiShareVariant')
|
v-icon(v-text='mdiShareVariant')
|
||||||
|
|
||||||
v-btn(v-if='!$auth.loggedIn' icon nuxt to='/login' :title='$t("common.login")' :aria-label='$t("common.login")')
|
v-btn(v-if='!$auth.loggedIn' icon nuxt to='/login' :title='$t("common.login")' :aria-label='$t("common.login")')
|
||||||
v-icon(v-text='mdiLogin')
|
v-icon(v-text='mdiLogin')
|
||||||
|
|
||||||
client-only
|
client-only
|
||||||
v-menu(v-if='$auth.loggedIn' offset-y eager)
|
v-menu(v-if='$auth.loggedIn' offset-y eager)
|
||||||
template(v-slot:activator="{ on, attrs }")
|
template(v-slot:activator="{ on, attrs }")
|
||||||
v-btn(icon v-bind='attrs' v-on='on' title='Menu' aria-label='Menu')
|
v-btn(icon v-bind='attrs' v-on='on' title='Menu' aria-label='Menu')
|
||||||
v-icon(v-text='mdiDotsVertical')
|
|
||||||
v-list
|
|
||||||
v-list-item(nuxt to='/settings')
|
|
||||||
v-list-item-icon
|
|
||||||
v-icon(v-text='mdiCog')
|
|
||||||
v-list-item-content
|
|
||||||
v-list-item-title {{$t('common.settings')}}
|
|
||||||
|
|
||||||
v-list-item(v-if='$auth.user.is_admin' nuxt to='/admin')
|
|
||||||
v-list-item-icon
|
|
||||||
v-icon(v-text='mdiAccount')
|
|
||||||
v-list-item-content
|
|
||||||
v-list-item-title {{$t('common.admin')}}
|
|
||||||
|
|
||||||
v-list-item(@click='logout')
|
|
||||||
v-list-item-icon
|
|
||||||
v-icon(v-text='mdiLogout')
|
|
||||||
v-list-item-content
|
|
||||||
v-list-item-title {{$t('common.logout')}}
|
|
||||||
template(#placeholder)
|
|
||||||
v-btn(v-if='$auth.loggedIn' icon aria-label='Menu' title='Menu')
|
|
||||||
v-icon(v-text='mdiDotsVertical')
|
v-icon(v-text='mdiDotsVertical')
|
||||||
|
v-list
|
||||||
|
v-list-item(nuxt to='/settings')
|
||||||
|
v-list-item-icon
|
||||||
|
v-icon(v-text='mdiCog')
|
||||||
|
v-list-item-content
|
||||||
|
v-list-item-title {{$t('common.settings')}}
|
||||||
|
|
||||||
|
v-list-item(v-if='$auth.user.is_admin' nuxt to='/admin')
|
||||||
|
v-list-item-icon
|
||||||
|
v-icon(v-text='mdiAccount')
|
||||||
|
v-list-item-content
|
||||||
|
v-list-item-title {{$t('common.admin')}}
|
||||||
|
|
||||||
|
v-list-item(@click='logout')
|
||||||
|
v-list-item-icon
|
||||||
|
v-icon(v-text='mdiLogout')
|
||||||
|
v-list-item-content
|
||||||
|
v-list-item-title {{$t('common.logout')}}
|
||||||
|
template(#placeholder)
|
||||||
|
v-btn(v-if='$auth.loggedIn' icon aria-label='Menu' title='Menu')
|
||||||
|
v-icon(v-text='mdiDotsVertical')
|
||||||
|
|
||||||
|
|
||||||
v-btn(icon target='_blank' :href='`${settings.baseurl}/feed/rss`' title='RSS' aria-label='RSS')
|
v-btn(icon target='_blank' :href='`${settings.baseurl}/feed/rss`' title='RSS' aria-label='RSS')
|
||||||
v-icon(color='orange' v-text='mdiRss')
|
v-icon(color='orange' v-text='mdiRss')
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -1,42 +1,48 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
v-container.pt-0.pt-md-2
|
v-row
|
||||||
v-switch.mt-0(
|
v-col(cols=12)
|
||||||
v-if='settings.allow_recurrent_event'
|
v-switch(
|
||||||
v-model='showRecurrent'
|
v-if='settings.allow_recurrent_event'
|
||||||
inset color='primary'
|
v-model='show_recurrent'
|
||||||
hide-details
|
@change='change'
|
||||||
:label="$t('event.show_recurrent')")
|
inset color='primary'
|
||||||
v-autocomplete(
|
hide-details
|
||||||
v-model='meta'
|
:label="$t('event.show_recurrent')")
|
||||||
:label='$t("common.search")'
|
v-col.mb-4(cols=12)
|
||||||
:filter='filter'
|
v-autocomplete.p-0(
|
||||||
cache-items
|
v-model='meta'
|
||||||
hide-details
|
:label='$t("common.search")'
|
||||||
color='primary'
|
:filter='filter'
|
||||||
hide-selected
|
cache-items
|
||||||
small-chips
|
hide-details
|
||||||
:items='items'
|
color='primary'
|
||||||
@change='change'
|
hide-selected
|
||||||
hide-no-data
|
small-chips
|
||||||
@input.native='search'
|
@focus='search'
|
||||||
item-text='label'
|
:menu-props="{ maxWidth: '400' }"
|
||||||
return-object
|
:items='items'
|
||||||
chips
|
@change='change'
|
||||||
multiple)
|
hide-no-data
|
||||||
template(v-slot:selection="{ attrs, item }")
|
@input.native='search'
|
||||||
v-chip(v-bind="attrs"
|
item-text='label'
|
||||||
close
|
return-object
|
||||||
@click:close='remove(item)'
|
chips
|
||||||
:close-icon='mdiCloseCircle')
|
multiple)
|
||||||
v-avatar(left)
|
template(v-slot:selection="{ attrs, item }")
|
||||||
v-icon(v-text="item.type === 'place' ? mdiMapMarker : mdiTag")
|
v-chip(v-bind="attrs"
|
||||||
span {{ item.label }}
|
small
|
||||||
template(v-slot:item='{ item }')
|
close
|
||||||
v-list-item-avatar
|
@click:close='remove(item)'
|
||||||
v-icon(v-text="item.type === 'place' ? mdiMapMarker : mdiTag")
|
:close-icon='mdiCloseCircle')
|
||||||
v-list-item-content
|
v-avatar(left)
|
||||||
v-list-item-title(v-text='item.label')
|
v-icon(small v-text="item.type === 'place' ? mdiMapMarker : mdiTag")
|
||||||
v-list-item-subtitle(v-if='item.type ==="place"' v-text='item.address')
|
span {{ item.label }}
|
||||||
|
template(v-slot:item='{ item }')
|
||||||
|
v-list-item-avatar
|
||||||
|
v-icon(v-text="item.type === 'place' ? mdiMapMarker : mdiTag")
|
||||||
|
v-list-item-content
|
||||||
|
v-list-item-title(v-text='item.label')
|
||||||
|
v-list-item-subtitle(v-if='item.type ==="place"' v-text='item.address')
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -47,26 +53,17 @@ import debounce from 'lodash/debounce'
|
||||||
export default {
|
export default {
|
||||||
name: 'Search',
|
name: 'Search',
|
||||||
props: {
|
props: {
|
||||||
filters: { type: Object, default: () => ({}) }
|
filters: { type: Object, default: () => ({ }) }
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
mdiTag, mdiMapMarker, mdiCloseCircle,
|
mdiTag, mdiMapMarker, mdiCloseCircle,
|
||||||
meta: [],
|
meta: [],
|
||||||
items: [],
|
items: [],
|
||||||
|
show_recurrent: this.filters.show_recurrent || false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: mapState(['settings']),
|
||||||
...mapState(['settings']),
|
|
||||||
showRecurrent: {
|
|
||||||
get () {
|
|
||||||
return this.filters.show_recurrent
|
|
||||||
},
|
|
||||||
set (v) {
|
|
||||||
this.change(v)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
methods: {
|
methods: {
|
||||||
filter (item, queryText, itemText) {
|
filter (item, queryText, itemText) {
|
||||||
return itemText.toLocaleLowerCase().indexOf(queryText.toLocaleLowerCase()) > -1 ||
|
return itemText.toLocaleLowerCase().indexOf(queryText.toLocaleLowerCase()) > -1 ||
|
||||||
|
@ -76,14 +73,14 @@ export default {
|
||||||
this.items = await this.$axios.$get(`/event/meta?search=${search.target.value}`)
|
this.items = await this.$axios.$get(`/event/meta?search=${search.target.value}`)
|
||||||
}, 100),
|
}, 100),
|
||||||
remove (item) {
|
remove (item) {
|
||||||
this.meta = this.meta.filter(m => m.type !== item.type || m.type === 'place' ? m.id !== item.id : m.tag !== item.tag)
|
this.meta = this.meta.filter(m => m.type !== item.type || m.type === 'place' ? m.id !== item.id : m.label !== item.label)
|
||||||
this.change()
|
this.change()
|
||||||
},
|
},
|
||||||
change (show_recurrent) {
|
change () {
|
||||||
const filters = {
|
const filters = {
|
||||||
tags: this.meta.filter(t => t.type === 'tag').map(t => t.label),
|
tags: this.meta.filter(t => t.type === 'tag').map(t => t.label),
|
||||||
places: this.meta.filter(p => p.type === 'place').map(p => p.id),
|
places: this.meta.filter(p => p.type === 'place').map(p => p.id),
|
||||||
show_recurrent: typeof show_recurrent !== 'undefined' ? show_recurrent : this.filters.show_recurrent
|
show_recurrent: this.show_recurrent
|
||||||
}
|
}
|
||||||
this.$emit('update', filters)
|
this.$emit('update', filters)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@ v-row
|
||||||
@input.native='search'
|
@input.native='search'
|
||||||
persistent-hint
|
persistent-hint
|
||||||
:items="places"
|
:items="places"
|
||||||
|
@focus='search'
|
||||||
@change='selectPlace')
|
@change='selectPlace')
|
||||||
template(v-slot:item="{ item, attrs, on }")
|
template(v-slot:item="{ item, attrs, on }")
|
||||||
v-list-item(v-bind='attrs' v-on='on')
|
v-list-item(v-bind='attrs' v-on='on')
|
||||||
v-list-item-content(two-line v-if='item.create')
|
v-list-item-content(two-line v-if='item.create && search')
|
||||||
v-list-item-title <v-icon color='primary' v-text='mdiPlus' :aria-label='$t("common.add")'></v-icon> {{item.name}}
|
v-list-item-title <v-icon color='primary' v-text='mdiPlus' :aria-label='$t("common.add")'></v-icon> {{item.name}}
|
||||||
v-list-item-content(two-line v-else)
|
v-list-item-content(two-line v-else)
|
||||||
v-list-item-title(v-text='item.name')
|
v-list-item-title(v-text='item.name')
|
||||||
|
@ -73,7 +74,7 @@ export default {
|
||||||
search: debounce(async function(ev) {
|
search: debounce(async function(ev) {
|
||||||
const search = ev.target.value.trim().toLowerCase()
|
const search = ev.target.value.trim().toLowerCase()
|
||||||
this.places = await this.$axios.$get(`place?search=${search}`)
|
this.places = await this.$axios.$get(`place?search=${search}`)
|
||||||
if (!search) { return this.places }
|
if (!search && this.places.length) { return this.places }
|
||||||
const matches = this.places.find(p => search === p.name.toLocaleLowerCase())
|
const matches = this.places.find(p => search === p.name.toLocaleLowerCase())
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
this.places.unshift({ create: true, name: ev.target.value.trim() })
|
this.places.unshift({ create: true, name: ev.target.value.trim() })
|
||||||
|
|
|
@ -1,44 +1,47 @@
|
||||||
<template lang='pug'>
|
<template lang='pug'>
|
||||||
v-container
|
v-container
|
||||||
v-card-title {{$t('common.cohort')}}
|
v-card-title {{$t('common.collections')}}
|
||||||
v-spacer
|
v-spacer
|
||||||
v-text-field(v-model='search'
|
v-text-field(v-model='search'
|
||||||
:append-icon='mdiMagnify' outlined rounded
|
:append-icon='mdiMagnify' outlined rounded
|
||||||
label='Search'
|
label='Search'
|
||||||
single-line hide-details)
|
single-line hide-details)
|
||||||
v-card-subtitle(v-html="$t('admin.cohort_description')")
|
v-card-subtitle(v-html="$t('admin.collections_description')")
|
||||||
|
|
||||||
v-btn(color='primary' text @click='newCohort') <v-icon v-text='mdiPlus'></v-icon> {{$t('common.new')}}
|
v-btn(color='primary' text @click='newCollection') <v-icon v-text='mdiPlus'></v-icon> {{$t('admin.new_collection')}}
|
||||||
|
|
||||||
v-dialog(v-model='dialog' width='800' destroy-on-close :fullscreen='$vuetify.breakpoint.xsOnly')
|
v-dialog(v-model='dialog' width='800' destroy-on-close :fullscreen='$vuetify.breakpoint.xsOnly')
|
||||||
v-card(color='secondary')
|
v-card(color='secondary')
|
||||||
v-card-title {{$t('admin.edit_cohort')}}
|
v-card-title {{$t('admin.edit_collection')}}
|
||||||
v-card-text
|
v-card-text
|
||||||
v-form(v-model='valid' ref='form')
|
v-form(v-model='valid' ref='form')
|
||||||
v-text-field(
|
v-text-field(
|
||||||
v-if='!cohort.id'
|
v-if='!collection.id'
|
||||||
:rules="[$validators.required('common.name')]"
|
:rules="[$validators.required('common.name')]"
|
||||||
:label="$t('common.name')"
|
:label="$t('common.name')"
|
||||||
v-model='cohort.name'
|
v-model='collection.name'
|
||||||
:placeholder='$t("common.name")')
|
:placeholder='$t("common.name")')
|
||||||
template(v-slot:append-outer v-if='!cohort.id')
|
template(v-slot:append-outer v-if='!collection.id')
|
||||||
v-btn(text @click='saveCohort' color='primary' :loading='loading'
|
v-btn(text @click='saveCollection' color='primary' :loading='loading'
|
||||||
:disabled='!valid || loading || !!cohort.id') {{$t('common.save')}}
|
:disabled='!valid || loading || !!collection.id') {{$t('common.save')}}
|
||||||
h3(v-else class='text-h5' v-text='cohort.name')
|
h3(v-else class='text-h5' v-text='collection.name')
|
||||||
|
|
||||||
v-row
|
v-row
|
||||||
v-col(cols=5)
|
v-col(cols=5)
|
||||||
v-autocomplete(v-model='filterTags'
|
v-autocomplete(v-model='filterTags'
|
||||||
cache-items
|
cache-items
|
||||||
:prepend-icon="mdiTagMultiple"
|
:prepend-icon="mdiTagMultiple"
|
||||||
|
|
||||||
chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint
|
chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint
|
||||||
:disabled="!cohort.id"
|
:disabled="!collection.id"
|
||||||
placeholder='Tutte'
|
placeholder='Tutte'
|
||||||
@input.native='searchTags'
|
@input.native='searchTags'
|
||||||
|
@focus='searchTags'
|
||||||
:delimiters="[',', ';']"
|
:delimiters="[',', ';']"
|
||||||
:items="tags"
|
:items="tags"
|
||||||
:label="$t('common.tags')")
|
:label="$t('common.tags')")
|
||||||
|
template(v-slot:selection="{ item, on, attrs, selected, parent}")
|
||||||
|
v-chip(v-bind="attrs" close :close-icon='mdiCloseCircle' @click:close='parent.selectItem(item)'
|
||||||
|
:input-value="selected" label small) {{item}}
|
||||||
|
|
||||||
v-col(cols=5)
|
v-col(cols=5)
|
||||||
v-autocomplete(v-model='filterPlaces'
|
v-autocomplete(v-model='filterPlaces'
|
||||||
|
@ -49,11 +52,16 @@ v-container
|
||||||
clearable
|
clearable
|
||||||
return-object
|
return-object
|
||||||
item-text='name'
|
item-text='name'
|
||||||
:disabled="!cohort.id"
|
:disabled="!collection.id"
|
||||||
@input.native="searchPlaces"
|
@input.native="searchPlaces"
|
||||||
|
@focus='searchPlaces'
|
||||||
:delimiters="[',', ';']"
|
:delimiters="[',', ';']"
|
||||||
:items="places"
|
:items="places"
|
||||||
:label="$t('common.places')")
|
:label="$t('common.places')")
|
||||||
|
template(v-slot:selection="{ item, on, attrs, selected, parent}")
|
||||||
|
v-chip(v-bind="attrs" close :close-icon='mdiCloseCircle' @click:close='parent.selectItem(item)'
|
||||||
|
:input-value="selected" label small) {{item.name}}
|
||||||
|
|
||||||
//- template(v-slot:item="{ item, attrs, on }")
|
//- template(v-slot:item="{ item, attrs, on }")
|
||||||
//- v-list-item(v-bind='attrs' v-on='on')
|
//- v-list-item(v-bind='attrs' v-on='on')
|
||||||
//- v-list-item-content(two-line)
|
//- v-list-item-content(two-line)
|
||||||
|
@ -61,7 +69,7 @@ v-container
|
||||||
//- v-list-item-subtitle(v-text='item.address')
|
//- v-list-item-subtitle(v-text='item.address')
|
||||||
|
|
||||||
v-col(cols=2)
|
v-col(cols=2)
|
||||||
v-btn(color='primary' text @click='addFilter' :disabled='!cohort.id || !filterPlaces.length && !filterTags.length') add <v-icon v-text='mdiPlus'></v-icon>
|
v-btn(color='primary' text @click='addFilter' :disabled='!collection.id || !filterPlaces.length && !filterTags.length') add <v-icon v-text='mdiPlus'></v-icon>
|
||||||
|
|
||||||
|
|
||||||
v-data-table(
|
v-data-table(
|
||||||
|
@ -76,28 +84,25 @@ v-container
|
||||||
v-chip.ma-1(small v-for='tag in item.tags' v-text='tag' :key='tag')
|
v-chip.ma-1(small v-for='tag in item.tags' v-text='tag' :key='tag')
|
||||||
template(v-slot:item.places='{item}')
|
template(v-slot:item.places='{item}')
|
||||||
v-chip.ma-1(small v-for='place in item.places' v-text='place.name' :key='place.id' )
|
v-chip.ma-1(small v-for='place in item.places' v-text='place.name' :key='place.id' )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
v-card-actions
|
v-card-actions
|
||||||
v-spacer
|
v-spacer
|
||||||
v-btn(text @click='dialog=false' color='warning') {{$t('common.close')}}
|
v-btn(text @click='dialog=false' color='warning') {{$t('common.close')}}
|
||||||
//- v-btn(text @click='saveCohort' color='primary' :loading='loading'
|
|
||||||
//- :disable='!valid || loading') {{$t('common.save')}}
|
|
||||||
|
|
||||||
v-card-text
|
v-card-text
|
||||||
v-data-table(
|
v-data-table(
|
||||||
:headers='cohortHeaders'
|
:headers='collectionHeaders'
|
||||||
:items='cohorts'
|
:items='collections'
|
||||||
:hide-default-footer='cohorts.length<5'
|
:hide-default-footer='collections.length<5'
|
||||||
:footer-props='{ prevIcon: mdiChevronLeft, nextIcon: mdiChevronRight }'
|
:footer-props='{ prevIcon: mdiChevronLeft, nextIcon: mdiChevronRight }'
|
||||||
:search='search')
|
:search='search')
|
||||||
template(v-slot:item.filters='{item}')
|
template(v-slot:item.filters='{item}')
|
||||||
span {{cohortFilters(item)}}
|
span {{collectionFilters(item)}}
|
||||||
template(v-slot:item.actions='{item}')
|
template(v-slot:item.actions='{item}')
|
||||||
v-btn(@click='editCohort(item)' color='primary' icon)
|
v-btn(@click='editCollection(item)' color='primary' icon)
|
||||||
v-icon(v-text='mdiPencil')
|
v-icon(v-text='mdiPencil')
|
||||||
v-btn(@click='removeCohort(item)' color='error' icon)
|
v-btn(@click='removeCollection(item)' color='error' icon)
|
||||||
v-icon(v-text='mdiDeleteForever')
|
v-icon(v-text='mdiDeleteForever')
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
@ -114,16 +119,16 @@ export default {
|
||||||
dialog: false,
|
dialog: false,
|
||||||
valid: false,
|
valid: false,
|
||||||
search: '',
|
search: '',
|
||||||
cohort: { name: '', id: null },
|
collection: { name: '', id: null },
|
||||||
filterTags: [],
|
filterTags: [],
|
||||||
filterPlaces: [],
|
filterPlaces: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
places: [],
|
places: [],
|
||||||
cohorts: [],
|
collections: [],
|
||||||
filters: [],
|
filters: [],
|
||||||
tagName: '',
|
tagName: '',
|
||||||
placeName: '',
|
placeName: '',
|
||||||
cohortHeaders: [
|
collectionHeaders: [
|
||||||
{ value: 'name', text: 'Name' },
|
{ value: 'name', text: 'Name' },
|
||||||
{ value: 'filters', text: 'Filters' },
|
{ value: 'filters', text: 'Filters' },
|
||||||
{ value: 'actions', text: 'Actions', align: 'right' }
|
{ value: 'actions', text: 'Actions', align: 'right' }
|
||||||
|
@ -136,7 +141,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async fetch () {
|
async fetch () {
|
||||||
this.cohorts = await this.$axios.$get('/cohorts?withFilters=true')
|
this.collections = await this.$axios.$get('/collections?withFilters=true')
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
@ -146,8 +151,8 @@ export default {
|
||||||
searchPlaces: debounce(async function (ev) {
|
searchPlaces: debounce(async function (ev) {
|
||||||
this.places = await this.$axios.$get(`/place?search=${ev.target.value}`)
|
this.places = await this.$axios.$get(`/place?search=${ev.target.value}`)
|
||||||
}, 100),
|
}, 100),
|
||||||
cohortFilters (cohort) {
|
collectionFilters (collection) {
|
||||||
return cohort.filters.map(f => {
|
return collection.filters.map(f => {
|
||||||
return '(' + f.tags?.join(', ') + f.places?.map(p => p.name).join(', ') + ')'
|
return '(' + f.tags?.join(', ') + f.places?.map(p => p.name).join(', ') + ')'
|
||||||
}).join(' - ')
|
}).join(' - ')
|
||||||
},
|
},
|
||||||
|
@ -155,27 +160,28 @@ export default {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
const tags = this.filterTags
|
const tags = this.filterTags
|
||||||
const places = this.filterPlaces.map(p => ({ id: p.id, name: p.name }))
|
const places = this.filterPlaces.map(p => ({ id: p.id, name: p.name }))
|
||||||
const filter = await this.$axios.$post('/filter', { cohortId: this.cohort.id, tags, places })
|
const filter = await this.$axios.$post('/filter', { collectionId: this.collection.id, tags, places })
|
||||||
this.$fetch()
|
this.$fetch()
|
||||||
this.filters.push(filter)
|
this.filters.push(filter)
|
||||||
this.filterTags = []
|
this.filterTags = []
|
||||||
this.filterPlaces = []
|
this.filterPlaces = []
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
async editCohort (cohort) {
|
async editCollection (collection) {
|
||||||
this.cohort = { ...cohort }
|
this.collection = { ...collection }
|
||||||
this.filters = await this.$axios.$get(`/filter/${cohort.id}`)
|
this.filters = await this.$axios.$get(`/filter/${collection.id}`)
|
||||||
this.dialog = true
|
this.dialog = true
|
||||||
},
|
},
|
||||||
newCohort () {
|
newCollection () {
|
||||||
this.cohort = { name: '', id: null },
|
this.collection = { name: '', id: null }
|
||||||
this.filters = []
|
this.filters = []
|
||||||
this.dialog = true
|
this.dialog = true
|
||||||
},
|
},
|
||||||
async saveCohort () {
|
async saveCollection () {
|
||||||
if (!this.$refs.form.validate()) return
|
if (!this.$refs.form.validate()) return
|
||||||
this.loading = true
|
this.loading = true
|
||||||
this.cohort = await this.$axios.$post('/cohorts', this.cohort)
|
this.collection.name = this.collection.name.trim()
|
||||||
|
this.collection = await this.$axios.$post('/collections', this.collection)
|
||||||
this.$fetch()
|
this.$fetch()
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
|
@ -190,12 +196,12 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async removeCohort (cohort) {
|
async removeCollection (collection) {
|
||||||
const ret = await this.$root.$confirm('admin.delete_cohort_confirm', { cohort: cohort.name })
|
const ret = await this.$root.$confirm('admin.delete_collection_confirm', { collection: collection.name })
|
||||||
if (!ret) { return }
|
if (!ret) { return }
|
||||||
try {
|
try {
|
||||||
await this.$axios.$delete(`/cohort/${cohort.id}`)
|
await this.$axios.$delete(`/collection/${collection.id}`)
|
||||||
this.cohorts = this.cohorts.filter(c => c.id !== cohort.id)
|
this.collections = this.collections.filter(c => c.id !== collection.id)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
const err = get(e, 'response.data.errors[0].message', e)
|
const err = get(e, 'response.data.errors[0].message', e)
|
||||||
this.$root.$message(this.$t(err), { color: 'error' })
|
this.$root.$message(this.$t(err), { color: 'error' })
|
|
@ -1,48 +1,48 @@
|
||||||
<template lang='pug'>
|
<template lang='pug'>
|
||||||
v-container
|
v-container
|
||||||
v-card-title {{$t('common.places')}}
|
v-card-title {{$t('common.places')}}
|
||||||
v-spacer
|
v-spacer
|
||||||
v-text-field(v-model='search'
|
v-text-field(v-model='search'
|
||||||
:append-icon='mdiMagnify' outlined rounded
|
:append-icon='mdiMagnify' outlined rounded
|
||||||
label='Search'
|
label='Search'
|
||||||
single-line hide-details)
|
single-line hide-details)
|
||||||
v-card-subtitle(v-html="$t('admin.place_description')")
|
v-card-subtitle(v-html="$t('admin.place_description')")
|
||||||
|
|
||||||
v-dialog(v-model='dialog' width='600' :fullscreen='$vuetify.breakpoint.xsOnly')
|
v-dialog(v-model='dialog' width='600' :fullscreen='$vuetify.breakpoint.xsOnly')
|
||||||
v-card(color='secondary')
|
v-card(color='secondary')
|
||||||
v-card-title {{$t('admin.edit_place')}}
|
v-card-title {{$t('admin.edit_place')}}
|
||||||
v-card-text
|
v-card-text
|
||||||
v-form(v-model='valid' ref='form' lazy-validation)
|
v-form(v-model='valid' ref='form' lazy-validation)
|
||||||
v-text-field(
|
v-text-field(
|
||||||
:rules="[$validators.required('common.name')]"
|
:rules="[$validators.required('common.name')]"
|
||||||
:label="$t('common.name')"
|
:label="$t('common.name')"
|
||||||
v-model='place.name'
|
v-model='place.name'
|
||||||
:placeholder='$t("common.name")')
|
:placeholder='$t("common.name")')
|
||||||
|
|
||||||
v-text-field(
|
v-text-field(
|
||||||
:rules="[$validators.required('common.address')]"
|
:rules="[$validators.required('common.address')]"
|
||||||
:label="$t('common.address')"
|
:label="$t('common.address')"
|
||||||
v-model='place.address'
|
v-model='place.address'
|
||||||
:placeholder='$t("common.address")')
|
:placeholder='$t("common.address")')
|
||||||
|
|
||||||
v-card-actions
|
v-card-actions
|
||||||
v-spacer
|
v-spacer
|
||||||
v-btn(@click='dialog=false' color='warning') {{$t('common.cancel')}}
|
v-btn(@click='dialog=false' color='warning') {{$t('common.cancel')}}
|
||||||
v-btn(@click='savePlace' color='primary' :loading='loading'
|
v-btn(@click='savePlace' color='primary' :loading='loading'
|
||||||
:disable='!valid || loading') {{$t('common.save')}}
|
:disable='!valid || loading') {{$t('common.save')}}
|
||||||
|
|
||||||
v-card-text
|
v-card-text
|
||||||
v-data-table(
|
v-data-table(
|
||||||
:headers='headers'
|
:headers='headers'
|
||||||
:items='places'
|
:items='places'
|
||||||
:hide-default-footer='places.length<5'
|
:hide-default-footer='places.length<5'
|
||||||
:footer-props='{ prevIcon: mdiChevronLeft, nextIcon: mdiChevronRight }'
|
:footer-props='{ prevIcon: mdiChevronLeft, nextIcon: mdiChevronRight }'
|
||||||
:search='search')
|
:search='search')
|
||||||
template(v-slot:item.actions='{item}')
|
template(v-slot:item.actions='{item}')
|
||||||
v-btn(@click='editPlace(item)' color='primary' icon)
|
v-btn(@click='editPlace(item)' color='primary' icon)
|
||||||
v-icon(v-text='mdiPencil')
|
v-icon(v-text='mdiPencil')
|
||||||
nuxt-link(:to='`/p/${item.name}`')
|
nuxt-link(:to='`/place/${item.name}`')
|
||||||
v-icon(v-text='mdiEye')
|
v-icon(v-text='mdiEye')
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
@ -79,7 +79,7 @@ export default {
|
||||||
if (!this.$refs.form.validate()) return
|
if (!this.$refs.form.validate()) return
|
||||||
this.loading = true
|
this.loading = true
|
||||||
await this.$axios.$put('/place', this.place)
|
await this.$axios.$put('/place', this.place)
|
||||||
this.updateMeta()
|
await this.$fetch()
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.dialog = false
|
this.dialog = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,8 +76,8 @@ sudo systemctl start gancio
|
||||||
> Don't be lazy and [backup]({% link install/backup.md %}) your data!
|
> Don't be lazy and [backup]({% link install/backup.md %}) your data!
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn global remove gancio
|
sudo yarn global remove gancio
|
||||||
yarn cache clean
|
sudo yarn cache clean
|
||||||
yarn global add --silent {{site.url}}/latest.tgz
|
sudo yarn global add --silent {{site.url}}/latest.tgz
|
||||||
sudo systemctl restart gancio
|
sudo systemctl restart gancio
|
||||||
```
|
```
|
||||||
|
|
|
@ -4,13 +4,15 @@
|
||||||
<Confirm/>
|
<Confirm/>
|
||||||
<Nav/>
|
<Nav/>
|
||||||
<v-main app>
|
<v-main app>
|
||||||
<div class="ml-1 mb-1 mt-1" v-if='showCohorts || showBack'>
|
<v-container fluid class='pa-0'>
|
||||||
<v-btn v-show='showBack' text color='primary' to='/'><v-icon v-text='mdiChevronLeft'/></v-btn>
|
<div v-if='showCollections || showBack'>
|
||||||
<v-btn v-for='cohort in cohorts' text color='primary' :key='cohort.id' :to='`/g/${cohort.name}`'>{{cohort.name}}</v-btn>
|
<v-btn class='ml-2 mt-2' v-if='showBack' outlined color='primary' to='/'><v-icon v-text='mdiChevronLeft'></v-icon></v-btn>
|
||||||
</div>
|
<v-btn class='ml-2 mt-2' outlined v-for='collection in collections' color='primary' :key='collection.id' :to='`/collection/${collection.name}`'>{{collection.name}}</v-btn>
|
||||||
<v-fade-transition hide-on-leave>
|
</div>
|
||||||
<nuxt />
|
<v-fade-transition hide-on-leave>
|
||||||
</v-fade-transition>
|
<nuxt />
|
||||||
|
</v-fade-transition>
|
||||||
|
</v-container>
|
||||||
</v-main>
|
</v-main>
|
||||||
<Footer/>
|
<Footer/>
|
||||||
|
|
||||||
|
@ -35,21 +37,21 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return { cohorts: [], mdiChevronLeft }
|
return { collections: [], mdiChevronLeft }
|
||||||
},
|
},
|
||||||
async fetch () {
|
async fetch () {
|
||||||
this.cohorts = await this.$axios.$get('cohorts')
|
this.collections = await this.$axios.$get('collections')
|
||||||
},
|
},
|
||||||
name: 'Default',
|
name: 'Default',
|
||||||
components: { Nav, Snackbar, Footer, Confirm },
|
components: { Nav, Snackbar, Footer, Confirm },
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['settings', 'locale']),
|
...mapState(['settings', 'locale']),
|
||||||
showBack () {
|
showBack () {
|
||||||
return ['tag-tag', 'g-cohort', 'p-place', 'search', 'announcement-id'].includes(this.$route.name)
|
return ['tag-tag', 'collection-collection', 'place-place', 'search', 'announcement-id'].includes(this.$route.name)
|
||||||
},
|
},
|
||||||
showCohorts () {
|
showCollections () {
|
||||||
if (!this.cohorts || this.cohorts.length === 0) return false
|
if (!this.collections || this.collections.length === 0) return false
|
||||||
return ['tag-tag', 'index', 'g-cohort', 'p-place'].includes(this.$route.name)
|
return ['tag-tag', 'index', 'g-collection', 'p-place'].includes(this.$route.name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created () {
|
created () {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<template lang='pug'>
|
<template lang='pug'>
|
||||||
v-container.p-4.text-center
|
v-container.pa-2.text-center
|
||||||
v-alert(v-if="error.statusCode === 404" type='error' :icon='mdiAlert') ¯\_(ツ)_/¯ {{error.message}}
|
v-alert(v-if="error.statusCode === 404" type='error' :icon='mdiAlert') ¯\_(ツ)_/¯ {{error.message}}
|
||||||
v-alert(v-else type='error' :icon='mdiAlert') An error occurred: {{error.message}}
|
v-alert.mb-2(v-else type='error' :icon='mdiAlert') An error occurred: {{error.message}}
|
||||||
nuxt-link(to='/')
|
nuxt-link(to='/')
|
||||||
v-btn Back to home
|
v-btn(outlined color='primary') Back to home
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
|
@ -87,7 +87,8 @@
|
||||||
"import": "Import",
|
"import": "Import",
|
||||||
"max_events": "N. max events",
|
"max_events": "N. max events",
|
||||||
"label": "Label",
|
"label": "Label",
|
||||||
"blobs": "Blobs"
|
"collections": "Collections",
|
||||||
|
"close": "Close"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"description": "By logging in you can publish new events.",
|
"description": "By logging in you can publish new events.",
|
||||||
|
@ -233,7 +234,10 @@
|
||||||
"smtp_test_button": "Send a test email",
|
"smtp_test_button": "Send a test email",
|
||||||
"admin_email": "Admin e-mail",
|
"admin_email": "Admin e-mail",
|
||||||
"widget": "Widget",
|
"widget": "Widget",
|
||||||
"wrong_domain_warning": "The baseurl configured in config.json <b>({baseurl})</b> differs from the one you're visiting <b>({url})</b>"
|
"wrong_domain_warning": "The baseurl configured in config.json <b>({baseurl})</b> differs from the one you're visiting <b>({url})</b>",
|
||||||
|
"new_collection": "New collection",
|
||||||
|
"collections_description": "Collections are groupings of events by tags and places. They will be displayed on the home page",
|
||||||
|
"edit_collection": "Edit Collection"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"not_confirmed": "Not confirmed yet…",
|
"not_confirmed": "Not confirmed yet…",
|
||||||
|
|
|
@ -217,7 +217,8 @@
|
||||||
"show_smtp_setup": "Paramètres d'e-mail",
|
"show_smtp_setup": "Paramètres d'e-mail",
|
||||||
"smtp_test_success": "Un e-mail de test a été envoyé à {admin_email}, veuillez vérifier votre boîte de réception",
|
"smtp_test_success": "Un e-mail de test a été envoyé à {admin_email}, veuillez vérifier votre boîte de réception",
|
||||||
"admin_email": "E-mail de l'administrateur",
|
"admin_email": "E-mail de l'administrateur",
|
||||||
"widget": "Vignette active"
|
"widget": "Vignette active",
|
||||||
|
"event_remove_ok": "Événement supprimé"
|
||||||
},
|
},
|
||||||
"oauth": {
|
"oauth": {
|
||||||
"scopes": {
|
"scopes": {
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
"import": "Importa",
|
"import": "Importa",
|
||||||
"max_events": "N. massimo eventi",
|
"max_events": "N. massimo eventi",
|
||||||
"label": "Etichetta",
|
"label": "Etichetta",
|
||||||
"blobs": "Bolle"
|
"collections": "Bolle"
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
"description": "Entrando puoi pubblicare nuovi eventi.",
|
"description": "Entrando puoi pubblicare nuovi eventi.",
|
||||||
|
@ -231,7 +231,11 @@
|
||||||
"smtp_hostname": "SMTP Hostname",
|
"smtp_hostname": "SMTP Hostname",
|
||||||
"smtp_test_success": "Una mail di test è stata inviata all'indirizzo {admin_email}, controlla la tua casella di posta",
|
"smtp_test_success": "Una mail di test è stata inviata all'indirizzo {admin_email}, controlla la tua casella di posta",
|
||||||
"smtp_test_button": "Invia una mail di prova",
|
"smtp_test_button": "Invia una mail di prova",
|
||||||
"admin_email": "E-mail dell'admin"
|
"admin_email": "E-mail dell'admin",
|
||||||
|
"new_collection": "Crea bolla",
|
||||||
|
"wrong_domain_warning": "Il \"baseurl\" configurato in config.json <b>({baseurl})</b> è diverso da quello che stai visitando <b>({url})</b>",
|
||||||
|
"collections_description": "Le bolle sono raggruppamenti di eventi per tag e posti.",
|
||||||
|
"edit_collection": "Modifica bolla"
|
||||||
},
|
},
|
||||||
"auth": {
|
"auth": {
|
||||||
"not_confirmed": "Non ancora confermato…",
|
"not_confirmed": "Non ancora confermato…",
|
||||||
|
|
|
@ -13,7 +13,7 @@ module.exports = {
|
||||||
{ charset: 'utf-8' },
|
{ charset: 'utf-8' },
|
||||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
{ name: 'viewport', content: 'width=device-width, initial-scale=1' }
|
||||||
],
|
],
|
||||||
link: [{ rel: 'icon', type: 'image/png', href: '/logo.png' }],
|
link: [{ rel: 'icon', type: 'image/png', href: config.baseurl + '/logo.png' }],
|
||||||
script: [{ src: '/gancio-events.es.js', async: true, body: true }],
|
script: [{ src: '/gancio-events.es.js', async: true, body: true }],
|
||||||
},
|
},
|
||||||
dev: isDev,
|
dev: isDev,
|
||||||
|
@ -68,6 +68,8 @@ module.exports = {
|
||||||
const Event = require('./server/api/models/event')
|
const Event = require('./server/api/models/event')
|
||||||
const events = await Event.findAll({where: { is_visible: true }})
|
const events = await Event.findAll({where: { is_visible: true }})
|
||||||
return events.map(e => `/event/${e.slug}`)
|
return events.map(e => `/event/${e.slug}`)
|
||||||
|
} else {
|
||||||
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "gancio",
|
"name": "gancio",
|
||||||
"version": "1.5.0-rc.2",
|
"version": "1.5.0-rc.5",
|
||||||
"description": "A shared agenda for local communities",
|
"description": "A shared agenda for local communities",
|
||||||
"author": "lesion",
|
"author": "lesion",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -69,14 +69,14 @@
|
||||||
"vue": "^2.6.14",
|
"vue": "^2.6.14",
|
||||||
"vue-i18n": "^8.26.7",
|
"vue-i18n": "^8.26.7",
|
||||||
"vue-template-compiler": "^2.6.14",
|
"vue-template-compiler": "^2.6.14",
|
||||||
"vuetify": "npm:@vuetify/nightly@dev",
|
"vuetify": "2.6.6",
|
||||||
"winston": "^3.7.2",
|
"winston": "^3.7.2",
|
||||||
"winston-daily-rotate-file": "^4.7.1",
|
"winston-daily-rotate-file": "^4.7.1",
|
||||||
"yargs": "^17.5.0"
|
"yargs": "^17.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxtjs/vuetify": "^1.12.3",
|
"@nuxtjs/vuetify": "^1.12.3",
|
||||||
"jest": "^28.1.0",
|
"jest": "^28.1.1",
|
||||||
"prettier": "^2.6.2",
|
"prettier": "^2.6.2",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"pug-plain-loader": "^1.1.0",
|
"pug-plain-loader": "^1.1.0",
|
||||||
|
@ -109,5 +109,6 @@
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://framagit.org/les/gancio"
|
"url": "https://framagit.org/les/gancio"
|
||||||
}
|
},
|
||||||
|
"snyk": true
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
v-tab-item
|
v-tab-item
|
||||||
Places
|
Places
|
||||||
|
|
||||||
//- Cohorts
|
//- Collections
|
||||||
v-tab {{$t('common.blobs')}}
|
v-tab {{$t('common.collections')}}
|
||||||
v-tab-item
|
v-tab-item
|
||||||
Cohorts
|
Collections
|
||||||
|
|
||||||
//- EVENTS
|
//- EVENTS
|
||||||
v-tab
|
v-tab
|
||||||
|
@ -66,7 +66,7 @@ export default {
|
||||||
Users: () => import(/* webpackChunkName: "admin" */'../components/admin/Users'),
|
Users: () => import(/* webpackChunkName: "admin" */'../components/admin/Users'),
|
||||||
Events: () => import(/* webpackChunkName: "admin" */'../components/admin/Events'),
|
Events: () => import(/* webpackChunkName: "admin" */'../components/admin/Events'),
|
||||||
Places: () => import(/* webpackChunkName: "admin" */'../components/admin/Places'),
|
Places: () => import(/* webpackChunkName: "admin" */'../components/admin/Places'),
|
||||||
Cohorts: () => import(/* webpackChunkName: "admin" */'../components/admin/Cohorts'),
|
Collections: () => import(/* webpackChunkName: "admin" */'../components/admin/Collections'),
|
||||||
Federation: () => import(/* webpackChunkName: "admin" */'../components/admin/Federation.vue'),
|
Federation: () => import(/* webpackChunkName: "admin" */'../components/admin/Federation.vue'),
|
||||||
Moderation: () => import(/* webpackChunkName: "admin" */'../components/admin/Moderation.vue'),
|
Moderation: () => import(/* webpackChunkName: "admin" */'../components/admin/Moderation.vue'),
|
||||||
Announcement: () => import(/* webpackChunkName: "admin" */'../components/admin/Announcement.vue'),
|
Announcement: () => import(/* webpackChunkName: "admin" */'../components/admin/Announcement.vue'),
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint
|
chips small-chips multiple deletable-chips hide-no-data hide-selected persistent-hint
|
||||||
cache-items
|
cache-items
|
||||||
@input.native='searchTags'
|
@input.native='searchTags'
|
||||||
:delimiters="[',', ';']"
|
:delimiters="[',', ';', '#']"
|
||||||
:items="tags"
|
:items="tags"
|
||||||
:menu-props="{ maxWidth: 400, eager: true }"
|
:menu-props="{ maxWidth: 400, eager: true }"
|
||||||
:label="$t('common.tags')")
|
:label="$t('common.tags')")
|
||||||
|
|
43
pages/collection/_collection.vue
Normal file
43
pages/collection/_collection.vue
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<v-container class='px-0' fluid>
|
||||||
|
|
||||||
|
<h1 class='d-block text-h3 font-weight-black text-center align-center text-uppercase mt-10 mb-12 mx-auto w-100 text-underline'><u>{{collection}}</u></h1>
|
||||||
|
|
||||||
|
<!-- Events -->
|
||||||
|
<div class='mb-2 mt-1 pl-1 pl-sm-2' id="events">
|
||||||
|
<Event :event='event' v-for='(event, idx) in events' :lazy='idx>2' :key='event.id'></Event>
|
||||||
|
</div>
|
||||||
|
</v-container>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import { mapState } from 'vuex'
|
||||||
|
import Event from '@/components/Event'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Collection',
|
||||||
|
components: { Event },
|
||||||
|
head () {
|
||||||
|
const title = `${this.settings.title} - ${this.collection}`
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
link: [
|
||||||
|
{ rel: 'alternate', type: 'application/rss+xml', title, href: this.settings.baseurl + `/feed/rss/collection/${this.collection}` },
|
||||||
|
{ rel: 'alternate', type: 'text/calendar', title, href: this.settings.baseurl + `/feed/ics/collection/${this.collection}` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState(['settings']),
|
||||||
|
async asyncData ({ $axios, params, error }) {
|
||||||
|
try {
|
||||||
|
const collection = params.collection
|
||||||
|
const events = await $axios.$get(`/collections/${collection}`)
|
||||||
|
return { events, collection }
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
error({ statusCode: 400, message: 'Error!' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -30,7 +30,7 @@ v-container#event.pa-0.pa-sm-2
|
||||||
|
|
||||||
.text-h6.p-location.h-adr(itemprop="location" itemscope itemtype="https://schema.org/Place")
|
.text-h6.p-location.h-adr(itemprop="location" itemscope itemtype="https://schema.org/Place")
|
||||||
v-icon(v-text='mdiMapMarker')
|
v-icon(v-text='mdiMapMarker')
|
||||||
b.vcard.ml-2.p-name(itemprop="name") {{event.place && event.place.name}}
|
nuxt-link.vcard.ml-2.p-name.text-decoration-none(itemprop="name" :to='`/place/${event.place.name}`') {{event.place && event.place.name}}
|
||||||
.text-subtitle-1.p-street-address(itemprop='address') {{event.place && event.place.address}}
|
.text-subtitle-1.p-street-address(itemprop='address') {{event.place && event.place.address}}
|
||||||
|
|
||||||
//- tags, hashtags
|
//- tags, hashtags
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
<template>
|
|
||||||
<v-container id='home' fluid>
|
|
||||||
|
|
||||||
<h1 class='d-block text-h3 font-weight-black text-center align-center text-uppercase mt-10 mb-12 mx-auto w-100 text-underline'><u>{{cohort}}</u></h1>
|
|
||||||
|
|
||||||
<!-- Events -->
|
|
||||||
<div class='mb-2 mt-1 pl-1 pl-sm-2' id="events">
|
|
||||||
<Event :event='event' v-for='(event, idx) in events' :lazy='idx>2' :key='event.id'></Event>
|
|
||||||
</div>
|
|
||||||
</v-container>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import Event from '@/components/Event'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'Tag',
|
|
||||||
components: { Event },
|
|
||||||
async asyncData ({ $axios, params, error }) {
|
|
||||||
try {
|
|
||||||
const cohort = params.cohort
|
|
||||||
const events = await $axios.$get(`/cohorts/${cohort}`)
|
|
||||||
return { events, cohort }
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e)
|
|
||||||
error({ statusCode: 400, message: 'Error!' })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,8 +1,8 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
v-container#home(fluid)
|
v-container.pa-0
|
||||||
|
|
||||||
//- Announcements
|
//- Announcements
|
||||||
#announcements.mx-1.mt-1(v-if='announcements.length')
|
#announcements.ma-2(v-if='announcements.length')
|
||||||
Announcement(v-for='announcement in announcements' :key='`a_${announcement.id}`' :announcement='announcement')
|
Announcement(v-for='announcement in announcements' :key='`a_${announcement.id}`' :announcement='announcement')
|
||||||
|
|
||||||
//- Calendar and search bar
|
//- Calendar and search bar
|
||||||
|
@ -68,7 +68,8 @@ export default {
|
||||||
{ property: 'og:image', content: this.settings.baseurl + '/logo.png' }
|
{ property: 'og:image', content: this.settings.baseurl + '/logo.png' }
|
||||||
],
|
],
|
||||||
link: [
|
link: [
|
||||||
{ rel: 'alternate', type: 'application/rss+xml', title: this.settings.title, href: this.settings.baseurl + '/feed/rss' }
|
{ rel: 'alternate', type: 'application/rss+xml', title: this.settings.title, href: this.settings.baseurl + '/feed/rss' },
|
||||||
|
{ rel: 'alternate', type: 'text/calendar', title: this.settings.title, href: this.settings.baseurl + '/feed/ics' }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<v-container id='home' fluid>
|
<v-container class='px-0' fluid>
|
||||||
|
<h1 class='d-block text-h4 font-weight-black text-center text-uppercase mt-10 mx-auto w-100 text-underline'><u>{{place.name}}</u></h1>
|
||||||
<h1 class='d-block text-h4 font-weight-black text-center text-uppercase mt-5 mx-auto w-100 text-underline'><u>{{place.name}}</u></h1>
|
|
||||||
<span class="d-block text-subtitle text-center w-100 mb-14">{{place.address}}</span>
|
<span class="d-block text-subtitle text-center w-100 mb-14">{{place.address}}</span>
|
||||||
|
|
||||||
<!-- Events -->
|
<!-- Events -->
|
||||||
|
@ -12,15 +11,27 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
import { mapState } from 'vuex'
|
||||||
import Event from '@/components/Event'
|
import Event from '@/components/Event'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Tag',
|
name: 'Place',
|
||||||
components: { Event },
|
components: { Event },
|
||||||
|
head () {
|
||||||
|
const title = `${this.settings.title} - ${this.place.name}`
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
link: [
|
||||||
|
{ rel: 'alternate', type: 'application/rss+xml', title, href: this.settings.baseurl + `/feed/rss/place/${this.place.name}` },
|
||||||
|
{ rel: 'alternate', type: 'text/calendar', title, href: this.settings.baseurl + `/feed/ics/place/${this.place.name}` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState(['settings']),
|
||||||
asyncData ({ $axios, params, error }) {
|
asyncData ({ $axios, params, error }) {
|
||||||
try {
|
try {
|
||||||
const place = params.place
|
const place = params.place
|
||||||
return $axios.$get(`/place/${place}/events`)
|
return $axios.$get(`/place/${place}`)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error({ statusCode: 400, message: 'Error!' })
|
error({ statusCode: 400, message: 'Error!' })
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<v-container id='home' fluid>
|
<v-container class='px-0' fluid>
|
||||||
|
|
||||||
<h1 class='d-block text-h3 font-weight-black text-center align-center text-uppercase mt-5 mb-16 mx-auto w-100 text-underline'><u>{{tag}}</u></h1>
|
<h1 class='d-block text-h3 font-weight-black text-center text-uppercase mt-10 mb-16 mx-auto w-100 text-underline'><u>{{tag}}</u></h1>
|
||||||
|
|
||||||
<!-- Events -->
|
<!-- Events -->
|
||||||
<div class="mb-2 mt-1 pl-1 pl-sm-2" id="events">
|
<div class="mb-2 mt-1 pl-1 pl-sm-2" id="events">
|
||||||
|
@ -11,15 +11,28 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
|
import { mapState } from 'vuex'
|
||||||
import Event from '@/components/Event'
|
import Event from '@/components/Event'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Tag',
|
name: 'Tag',
|
||||||
components: { Event },
|
components: { Event },
|
||||||
|
head ({ $route }) {
|
||||||
|
const tag = $route.params.tag
|
||||||
|
const title = `${this.settings.title} #${tag}`
|
||||||
|
return {
|
||||||
|
title,
|
||||||
|
link: [
|
||||||
|
{ rel: 'alternate', type: 'application/rss+xml', title, href: this.settings.baseurl + `/feed/rss/tag/${tag}` },
|
||||||
|
{ rel: 'alternate', type: 'text/calendar', title, href: this.settings.baseurl + `/feed/ics/tag/${tag}` }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState(['settings']),
|
||||||
async asyncData ({ $axios, params, error }) {
|
async asyncData ({ $axios, params, error }) {
|
||||||
try {
|
try {
|
||||||
const tag = params.tag
|
const tag = params.tag
|
||||||
const events = await $axios.$get(`/events?tags=${tag}`)
|
const events = await $axios.$get(`/tag/${tag}`)
|
||||||
return { events, tag }
|
return { events, tag }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error({ statusCode: 400, message: 'Error!' })
|
error({ statusCode: 400, message: 'Error!' })
|
||||||
|
|
|
@ -1,41 +1,42 @@
|
||||||
const Cohort = require('../models/cohort')
|
const Collection = require('../models/collection')
|
||||||
const Filter = require('../models/filter')
|
const Filter = require('../models/filter')
|
||||||
const Event = require('../models/event')
|
const Event = require('../models/event')
|
||||||
const Tag = require('../models/tag')
|
const Tag = require('../models/tag')
|
||||||
const Place = require('../models/place')
|
const Place = require('../models/place')
|
||||||
const log = require('../../log')
|
const log = require('../../log')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
|
const { col: Col } = require('../../helpers')
|
||||||
// const { sequelize } = require('../models/index')
|
|
||||||
|
|
||||||
|
|
||||||
const { Op, Sequelize } = require('sequelize')
|
const { Op, Sequelize } = require('sequelize')
|
||||||
|
|
||||||
const cohortController = {
|
const collectionController = {
|
||||||
|
|
||||||
async getAll (req, res) {
|
async getAll (req, res) {
|
||||||
const withFilters = req.query.withFilters
|
const withFilters = req.query.withFilters
|
||||||
let cohorts
|
let collections
|
||||||
if (withFilters) {
|
if (withFilters) {
|
||||||
cohorts = await Cohort.findAll({ include: [Filter] })
|
collections = await Collection.findAll({ include: [Filter] })
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
cohorts = await Cohort.findAll()
|
collections = await Collection.findAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.json(cohorts)
|
return res.json(collections)
|
||||||
},
|
},
|
||||||
|
|
||||||
// return events from cohort
|
// return events from collection
|
||||||
async getEvents (req, res) {
|
async getEvents (req, res) {
|
||||||
|
const format = req.params.format || 'json'
|
||||||
const name = req.params.name
|
const name = req.params.name
|
||||||
|
|
||||||
const cohort = await Cohort.findOne({ where: { name } })
|
const collection = await Collection.findOne({ where: { name } })
|
||||||
if (!cohort) {
|
if (!collection) {
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
}
|
}
|
||||||
const filters = await Filter.findAll({ where: { cohortId: cohort.id } })
|
const filters = await Filter.findAll({ where: { collectionId: collection.id } })
|
||||||
|
|
||||||
|
if (!filters.length) {
|
||||||
|
return res.json([])
|
||||||
|
}
|
||||||
const start = dayjs().unix()
|
const start = dayjs().unix()
|
||||||
const where = {
|
const where = {
|
||||||
// do not include parent recurrent event
|
// do not include parent recurrent event
|
||||||
|
@ -45,24 +46,16 @@ const cohortController = {
|
||||||
is_visible: true,
|
is_visible: true,
|
||||||
|
|
||||||
// [Op.or]: {
|
// [Op.or]: {
|
||||||
start_datetime: { [Op.gte]: start },
|
start_datetime: { [Op.gte]: start },
|
||||||
// end_datetime: { [Op.gte]: start }
|
// end_datetime: { [Op.gte]: start }
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (!show_recurrent) {
|
|
||||||
// where.parentId = null
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (end) {
|
|
||||||
// where.start_datetime = { [Op.lte]: end }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const replacements = []
|
const replacements = []
|
||||||
const ors = []
|
const ors = []
|
||||||
filters.forEach(f => {
|
filters.forEach(f => {
|
||||||
if (f.tags && f.tags.length) {
|
if (f.tags && f.tags.length) {
|
||||||
const tags = Sequelize.fn('EXISTS', Sequelize.literal('SELECT 1 FROM event_tags WHERE "event_tags"."eventId"="event".id AND "tagTag" in (?)'))
|
const tags = Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=event.id AND ${Col('tagTag')} in (?)`))
|
||||||
replacements.push(f.tags)
|
replacements.push(f.tags)
|
||||||
if (f.places && f.places.length) {
|
if (f.places && f.places.length) {
|
||||||
ors.push({ [Op.and]: [ { placeId: f.places.map(p => p.id) },tags] })
|
ors.push({ [Op.and]: [ { placeId: f.places.map(p => p.id) },tags] })
|
||||||
|
@ -74,34 +67,18 @@ const cohortController = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// if (tags && places) {
|
where[Op.and] = { [Op.or]: ors }
|
||||||
// where[Op.or] = {
|
|
||||||
// placeId: places ? places.split(',') : [],
|
|
||||||
// // '$tags.tag$': Sequelize.literal(`EXISTS (SELECT 1 FROM event_tags WHERE tagTag in ( ${Sequelize.QueryInterface.escape(tags)} ) )`)
|
|
||||||
// }
|
|
||||||
// } else if (tags) {
|
|
||||||
// where[Op.and] = Sequelize.literal(`EXISTS (SELECT 1 FROM event_tags WHERE event_tags.eventId=event.id AND tagTag in (?))`)
|
|
||||||
// replacements.push(tags)
|
|
||||||
// } else if (places) {
|
|
||||||
// where.placeId = places.split(',')
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (ors.length) {
|
|
||||||
where[Op.or] = ors
|
|
||||||
}
|
|
||||||
|
|
||||||
const events = await Event.findAll({
|
const events = await Event.findAll({
|
||||||
logging: console.log,
|
|
||||||
where,
|
where,
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'updatedAt', 'description', 'resources']
|
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'updatedAt', 'description', 'resources']
|
||||||
},
|
},
|
||||||
order: ['start_datetime'],
|
order: ['start_datetime'],
|
||||||
include: [
|
include: [
|
||||||
// { model: Resource, required: false, attributes: ['id'] },
|
|
||||||
{
|
{
|
||||||
model: Tag,
|
model: Tag,
|
||||||
order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
// order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
||||||
attributes: ['tag'],
|
attributes: ['tag'],
|
||||||
through: { attributes: [] }
|
through: { attributes: [] }
|
||||||
},
|
},
|
||||||
|
@ -125,43 +102,43 @@ const cohortController = {
|
||||||
},
|
},
|
||||||
|
|
||||||
async add (req, res) {
|
async add (req, res) {
|
||||||
const cohortDetail = {
|
const collectionDetail = {
|
||||||
name: req.body.name,
|
name: req.body.name,
|
||||||
isActor: true,
|
isActor: true,
|
||||||
isTop: true
|
isTop: true
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: validation
|
// TODO: validation
|
||||||
log.info('Create cohort: ' + req.body.name)
|
log.info('Create collection: ' + req.body.name)
|
||||||
const cohort = await Cohort.create(cohortDetail)
|
const collection = await Collection.create(collectionDetail)
|
||||||
res.json(cohort)
|
res.json(collection)
|
||||||
},
|
},
|
||||||
|
|
||||||
async remove (req, res) {
|
async remove (req, res) {
|
||||||
const cohort_id = req.params.id
|
const collection_id = req.params.id
|
||||||
log.info('Remove cohort', cohort_id)
|
log.info('Remove collection', collection_id)
|
||||||
try {
|
try {
|
||||||
const cohort = await Cohort.findByPk(cohort_id)
|
const collection = await Collection.findByPk(collection_id)
|
||||||
await cohort.destroy()
|
await collection.destroy()
|
||||||
res.sendStatus(200)
|
res.sendStatus(200)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error('Remove cohort failed:', e)
|
log.error('Remove collection failed:', e)
|
||||||
res.sendStatus(404)
|
res.sendStatus(404)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async getFilters (req, res) {
|
async getFilters (req, res) {
|
||||||
const cohortId = req.params.cohort_id
|
const collectionId = req.params.collection_id
|
||||||
const filters = await Filter.findAll({ where: { cohortId } })
|
const filters = await Filter.findAll({ where: { collectionId } })
|
||||||
return res.json(filters)
|
return res.json(filters)
|
||||||
},
|
},
|
||||||
|
|
||||||
async addFilter (req, res) {
|
async addFilter (req, res) {
|
||||||
const cohortId = req.body.cohortId
|
const collectionId = req.body.collectionId
|
||||||
const tags = req.body.tags
|
const tags = req.body.tags
|
||||||
const places = req.body.places
|
const places = req.body.places
|
||||||
try {
|
try {
|
||||||
const filter = await Filter.create({ cohortId, tags, places })
|
const filter = await Filter.create({ collectionId, tags, places })
|
||||||
return res.json(filter)
|
return res.json(filter)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error(String(e))
|
log.error(String(e))
|
||||||
|
@ -188,4 +165,4 @@ const cohortController = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = cohortController
|
module.exports = collectionController
|
|
@ -8,7 +8,7 @@ const linkifyHtml = require('linkify-html')
|
||||||
const Sequelize = require('sequelize')
|
const Sequelize = require('sequelize')
|
||||||
const dayjs = require('dayjs')
|
const dayjs = require('dayjs')
|
||||||
const helpers = require('../../helpers')
|
const helpers = require('../../helpers')
|
||||||
|
const Col = helpers.col
|
||||||
const Event = require('../models/event')
|
const Event = require('../models/event')
|
||||||
const Resource = require('../models/resource')
|
const Resource = require('../models/resource')
|
||||||
const Tag = require('../models/tag')
|
const Tag = require('../models/tag')
|
||||||
|
@ -17,6 +17,7 @@ const Notification = require('../models/notification')
|
||||||
const APUser = require('../models/ap_user')
|
const APUser = require('../models/ap_user')
|
||||||
|
|
||||||
const exportController = require('./export')
|
const exportController = require('./export')
|
||||||
|
const tagController = require('./tag')
|
||||||
|
|
||||||
const log = require('../../log')
|
const log = require('../../log')
|
||||||
|
|
||||||
|
@ -29,8 +30,8 @@ const eventController = {
|
||||||
order: [[Sequelize.col('w'), 'DESC']],
|
order: [[Sequelize.col('w'), 'DESC']],
|
||||||
where: {
|
where: {
|
||||||
[Op.or]: [
|
[Op.or]: [
|
||||||
{ name: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%' )},
|
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%' ),
|
||||||
{ address: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('address')), 'LIKE', '%' + search + '%')},
|
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('address')), 'LIKE', '%' + search + '%')
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
attributes: [['name', 'label'], 'address', 'id', [Sequelize.cast(Sequelize.fn('COUNT', Sequelize.col('events.placeId')),'INTEGER'), 'w']],
|
attributes: [['name', 'label'], 'address', 'id', [Sequelize.cast(Sequelize.fn('COUNT', Sequelize.col('events.placeId')),'INTEGER'), 'w']],
|
||||||
|
@ -91,7 +92,7 @@ const eventController = {
|
||||||
[
|
[
|
||||||
{ title: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('title')), 'LIKE', '%' + search + '%') },
|
{ title: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('title')), 'LIKE', '%' + search + '%') },
|
||||||
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%'),
|
Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), 'LIKE', '%' + search + '%'),
|
||||||
Sequelize.fn('EXISTS', Sequelize.literal('SELECT 1 FROM event_tags WHERE "event_tags"."eventId"="event".id AND "tagTag" = ?'))
|
Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=${Col('event.id')} AND LOWER(${Col('tagTag')}) = ?`))
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ const eventController = {
|
||||||
include: [
|
include: [
|
||||||
{
|
{
|
||||||
model: Tag,
|
model: Tag,
|
||||||
order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
// order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
||||||
attributes: ['tag'],
|
attributes: ['tag'],
|
||||||
through: { attributes: [] }
|
through: { attributes: [] }
|
||||||
},
|
},
|
||||||
|
@ -247,7 +248,6 @@ const eventController = {
|
||||||
order: [['start_datetime', 'DESC'], ['id', 'DESC']]
|
order: [['start_datetime', 'DESC'], ['id', 'DESC']]
|
||||||
})
|
})
|
||||||
|
|
||||||
// TODO: also check if event is mine
|
|
||||||
if (event && (event.is_visible || is_admin)) {
|
if (event && (event.is_visible || is_admin)) {
|
||||||
event = event.get()
|
event = event.get()
|
||||||
event.next = next && (next.slug || next.id)
|
event.next = next && (next.slug || next.id)
|
||||||
|
@ -278,7 +278,7 @@ const eventController = {
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
}
|
}
|
||||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||||
log.warn(`Someone unallowed is trying to confirm -> "${event.title} `)
|
log.warn(`Someone not allowed is trying to confirm -> "${event.title} `)
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,6 +304,7 @@ const eventController = {
|
||||||
const event = await Event.findByPk(id)
|
const event = await Event.findByPk(id)
|
||||||
if (!event) { return req.sendStatus(404) }
|
if (!event) { return req.sendStatus(404) }
|
||||||
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
if (!res.locals.user.is_admin && res.locals.user.id !== event.userId) {
|
||||||
|
log.warn(`Someone not allowed is trying to unconfirm -> "${event.title} `)
|
||||||
return res.sendStatus(403)
|
return res.sendStatus(403)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +318,7 @@ const eventController = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/** get all unconfirmed events */
|
/** get all unconfirmed events */
|
||||||
async getUnconfirmed (req, res) {
|
async getUnconfirmed (_req, res) {
|
||||||
try {
|
try {
|
||||||
const events = await Event.findAll({
|
const events = await Event.findAll({
|
||||||
where: {
|
where: {
|
||||||
|
@ -391,7 +392,7 @@ const eventController = {
|
||||||
if (body.place_id) {
|
if (body.place_id) {
|
||||||
place = await Place.findByPk(body.place_id)
|
place = await Place.findByPk(body.place_id)
|
||||||
} else {
|
} else {
|
||||||
place = await Place.findOne({ where: { name: body.place_name.trim() }})
|
place = await Place.findOne({ where: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('name')), Op.eq, body.place_name.trim().toLocaleLowerCase() )})
|
||||||
if (!place) {
|
if (!place) {
|
||||||
if (!body.place_address || !body.place_name) {
|
if (!body.place_address || !body.place_name) {
|
||||||
return res.status(400).send(`place_id or place_name and place_address required`)
|
return res.status(400).send(`place_id or place_name and place_address required`)
|
||||||
|
@ -427,6 +428,7 @@ const eventController = {
|
||||||
height: req.file.height,
|
height: req.file.height,
|
||||||
width: req.file.width,
|
width: req.file.width,
|
||||||
name: body.image_name || body.title || '',
|
name: body.image_name || body.title || '',
|
||||||
|
size: req.file.size || 0,
|
||||||
focalpoint: [parseFloat(focalpoint[0]), parseFloat(focalpoint[1])]
|
focalpoint: [parseFloat(focalpoint[0]), parseFloat(focalpoint[1])]
|
||||||
}]
|
}]
|
||||||
} else {
|
} else {
|
||||||
|
@ -438,11 +440,10 @@ const eventController = {
|
||||||
await event.setPlace(place)
|
await event.setPlace(place)
|
||||||
|
|
||||||
// create/assign tags
|
// create/assign tags
|
||||||
|
let tags = []
|
||||||
if (body.tags) {
|
if (body.tags) {
|
||||||
body.tags = body.tags.map(t => t.trim())
|
tags = await tagController._findOrCreate(body.tags)
|
||||||
await Tag.bulkCreate(body.tags.map(t => ({ tag: t })), { ignoreDuplicates: true })
|
await event.setTags(tags)
|
||||||
const tags = await Tag.findAll({ where: { tag: { [Op.in]: body.tags } } })
|
|
||||||
await event.addTags(tags)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// associate user to event and reverse
|
// associate user to event and reverse
|
||||||
|
@ -452,7 +453,7 @@ const eventController = {
|
||||||
}
|
}
|
||||||
|
|
||||||
event = event.get()
|
event = event.get()
|
||||||
event.tags = body.tags
|
event.tags = tags.map(t => t.tag)
|
||||||
event.place = place
|
event.place = place
|
||||||
// return created event to the client
|
// return created event to the client
|
||||||
res.json(event)
|
res.json(event)
|
||||||
|
@ -520,6 +521,7 @@ const eventController = {
|
||||||
height: req.file.height,
|
height: req.file.height,
|
||||||
width: req.file.width,
|
width: req.file.width,
|
||||||
name: body.image_name || body.title || '',
|
name: body.image_name || body.title || '',
|
||||||
|
size: req.file.size || 0,
|
||||||
focalpoint: [parseFloat(focalpoint[0].slice(0, 6)), parseFloat(focalpoint[1].slice(0, 6))]
|
focalpoint: [parseFloat(focalpoint[0].slice(0, 6)), parseFloat(focalpoint[1].slice(0, 6))]
|
||||||
}]
|
}]
|
||||||
} else if (!body.image) {
|
} else if (!body.image) {
|
||||||
|
@ -532,12 +534,14 @@ const eventController = {
|
||||||
})
|
})
|
||||||
|
|
||||||
await event.setPlace(place)
|
await event.setPlace(place)
|
||||||
await event.setTags([])
|
|
||||||
|
// create/assign tags
|
||||||
|
let tags = []
|
||||||
if (body.tags) {
|
if (body.tags) {
|
||||||
await Tag.bulkCreate(body.tags.map(t => ({ tag: t })), { ignoreDuplicates: true })
|
tags = await tagController._findOrCreate(body.tags)
|
||||||
const tags = await Tag.findAll({ where: { tag: { [Op.in]: body.tags } } })
|
await event.setTags(tags)
|
||||||
await event.addTags(tags)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const newEvent = await Event.findByPk(event.id, { include: [Tag, Place] })
|
const newEvent = await Event.findByPk(event.id, { include: [Tag, Place] })
|
||||||
res.json(newEvent)
|
res.json(newEvent)
|
||||||
|
|
||||||
|
@ -584,60 +588,85 @@ const eventController = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
async _select ({ start, end, tags, places, show_recurrent, max }) {
|
/**
|
||||||
|
* Method to search for events with pagination and filtering
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
async _select ({
|
||||||
|
start = dayjs().unix(),
|
||||||
|
end,
|
||||||
|
tags,
|
||||||
|
places,
|
||||||
|
show_recurrent,
|
||||||
|
limit,
|
||||||
|
page,
|
||||||
|
older }) {
|
||||||
|
|
||||||
const where = {
|
const where = {
|
||||||
// do not include parent recurrent event
|
// do not include _parent_ recurrent event
|
||||||
recurrent: null,
|
recurrent: null,
|
||||||
|
|
||||||
// confirmed event only
|
// confirmed event only
|
||||||
is_visible: true,
|
is_visible: true,
|
||||||
|
|
||||||
[Op.or]: {
|
[Op.or]: {
|
||||||
start_datetime: { [Op.gte]: start },
|
start_datetime: { [older ? Op.lte : Op.gte]: start },
|
||||||
end_datetime: { [Op.gte]: start }
|
end_datetime: { [older ? Op.lte : Op.gte]: start }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// include recurrent events?
|
||||||
if (!show_recurrent) {
|
if (!show_recurrent) {
|
||||||
where.parentId = null
|
where.parentId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (end) {
|
if (end) {
|
||||||
where.start_datetime = { [Op.lte]: end }
|
where.start_datetime = { [older ? Op.gte : Op.lte]: end }
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize tags
|
||||||
|
if (tags) {
|
||||||
|
tags = tags.split(',').map(t => t.trim().toLocaleLowerCase())
|
||||||
}
|
}
|
||||||
|
|
||||||
const replacements = []
|
const replacements = []
|
||||||
if (tags && places) {
|
if (tags && places) {
|
||||||
where[Op.or] = {
|
where[Op.and] = [
|
||||||
placeId: places ? places.split(',') : [],
|
{ placeId: places ? places.split(',') : []},
|
||||||
// '$tags.tag$': Sequelize.literal(`EXISTS (SELECT 1 FROM event_tags WHERE tagTag in ( ${Sequelize.QueryInterface.escape(tags)} ) )`)
|
Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=event.id AND LOWER(${Col('tagTag')}) in (?)`))
|
||||||
}
|
]
|
||||||
|
replacements.push(tags)
|
||||||
} else if (tags) {
|
} else if (tags) {
|
||||||
// where[Op.and] = Sequelize.literal(`EXISTS (SELECT 1 FROM event_tags WHERE eventId=event.id AND tagTag in (?))`)
|
where[Op.and] = Sequelize.fn('EXISTS', Sequelize.literal(`SELECT 1 FROM event_tags WHERE ${Col('event_tags.eventId')}=event.id AND LOWER(${Col('tagTag')}) in (?)`))
|
||||||
where[Op.and] = Sequelize.fn('EXISTS', Sequelize.literal('SELECT 1 FROM event_tags WHERE "event_tags"."eventId"="event".id AND "tagTag" in (?)'))
|
|
||||||
replacements.push(tags)
|
replacements.push(tags)
|
||||||
} else if (places) {
|
} else if (places) {
|
||||||
where.placeId = places.split(',')
|
where.placeId = places.split(',')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pagination = {}
|
||||||
|
if (limit) {
|
||||||
|
pagination = {
|
||||||
|
limit,
|
||||||
|
offset: limit * page,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const events = await Event.findAll({
|
const events = await Event.findAll({
|
||||||
where,
|
where,
|
||||||
attributes: {
|
attributes: {
|
||||||
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'updatedAt', 'description', 'resources']
|
exclude: ['likes', 'boost', 'userId', 'is_visible', 'createdAt', 'description', 'resources', 'recurrent', 'placeId', 'parentId']
|
||||||
},
|
},
|
||||||
order: ['start_datetime'],
|
order: [['start_datetime', older ? 'DESC' : 'ASC' ]],
|
||||||
include: [
|
include: [
|
||||||
{ model: Resource, required: false, attributes: ['id'] },
|
|
||||||
{
|
{
|
||||||
model: Tag,
|
model: Tag,
|
||||||
order: [Sequelize.literal('(SELECT COUNT("tagTag") FROM event_tags WHERE tagTag = tag) DESC')],
|
// order: [Sequelize.literal('(SELECT COUNT(tagTag) FROM event_tags WHERE tagTag = tag) DESC')],
|
||||||
attributes: ['tag'],
|
attributes: ['tag'],
|
||||||
through: { attributes: [] }
|
through: { attributes: [] }
|
||||||
},
|
},
|
||||||
{ model: Place, required: true, attributes: ['id', 'name', 'address'] }
|
{ model: Place, required: true, attributes: ['id', 'name', 'address'] }
|
||||||
],
|
],
|
||||||
limit: max,
|
...pagination,
|
||||||
replacements
|
replacements
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
log.error('[EVENT]', e)
|
log.error('[EVENT]', e)
|
||||||
|
@ -660,13 +689,15 @@ const eventController = {
|
||||||
const end = req.query.end
|
const end = req.query.end
|
||||||
const tags = req.query.tags
|
const tags = req.query.tags
|
||||||
const places = req.query.places
|
const places = req.query.places
|
||||||
const max = req.query.max
|
const limit = req.query.max
|
||||||
|
const page = req.query.page = 0
|
||||||
|
const older = req.query.older || false
|
||||||
|
|
||||||
const show_recurrent = settings.allow_recurrent_event &&
|
const show_recurrent = settings.allow_recurrent_event &&
|
||||||
typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settings.recurrent_event_visible
|
typeof req.query.show_recurrent !== 'undefined' ? req.query.show_recurrent === 'true' : settings.recurrent_event_visible
|
||||||
|
|
||||||
res.json(await eventController._select({
|
res.json(await eventController._select({
|
||||||
start, end, places, tags, show_recurrent, max
|
start, end, places, tags, show_recurrent, limit, page, older
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ const ics = require('ics')
|
||||||
const exportController = {
|
const exportController = {
|
||||||
|
|
||||||
async export (req, res) {
|
async export (req, res) {
|
||||||
const type = req.params.type
|
const format = req.params.format
|
||||||
const tags = req.query.tags
|
const tags = req.query.tags
|
||||||
const places = req.query.places
|
const places = req.query.places
|
||||||
const show_recurrent = !!req.query.show_recurrent
|
const show_recurrent = !!req.query.show_recurrent
|
||||||
|
@ -43,7 +43,7 @@ const exportController = {
|
||||||
attributes: { exclude: ['is_visible', 'recurrent', 'createdAt', 'likes', 'boost', 'userId', 'placeId'] },
|
attributes: { exclude: ['is_visible', 'recurrent', 'createdAt', 'likes', 'boost', 'userId', 'placeId'] },
|
||||||
where: {
|
where: {
|
||||||
is_visible: true,
|
is_visible: true,
|
||||||
recurrent: { [Op.eq]: null },
|
recurrent: null,
|
||||||
start_datetime: { [Op.gte]: yesterday },
|
start_datetime: { [Op.gte]: yesterday },
|
||||||
...where
|
...where
|
||||||
},
|
},
|
||||||
|
@ -58,7 +58,7 @@ const exportController = {
|
||||||
{ model: Place, attributes: ['name', 'id', 'address'] }]
|
{ model: Place, attributes: ['name', 'id', 'address'] }]
|
||||||
})
|
})
|
||||||
|
|
||||||
switch (type) {
|
switch (format) {
|
||||||
case 'rss':
|
case 'rss':
|
||||||
case 'feed':
|
case 'feed':
|
||||||
return exportController.feed(req, res, events.slice(0, 20))
|
return exportController.feed(req, res, events.slice(0, 20))
|
||||||
|
@ -69,10 +69,10 @@ const exportController = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
feed (_req, res, events) {
|
feed (_req, res, events, title = res.locals.settings.title, link = `${res.locals.settings.baseurl}/feed/rss`) {
|
||||||
const settings = res.locals.settings
|
const settings = res.locals.settings
|
||||||
res.type('application/rss+xml; charset=UTF-8')
|
res.type('application/rss+xml; charset=UTF-8')
|
||||||
res.render('feed/rss.pug', { events, settings, moment })
|
res.render('feed/rss.pug', { events, settings, moment, title, link })
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,22 +1,36 @@
|
||||||
const dayjs = require('dayjs')
|
|
||||||
const Place = require('../models/place')
|
const Place = require('../models/place')
|
||||||
const Event = require('../models/event')
|
const Event = require('../models/event')
|
||||||
const eventController = require('./event')
|
const eventController = require('./event')
|
||||||
|
const exportController = require('./export')
|
||||||
|
|
||||||
const log = require('../../log')
|
const log = require('../../log')
|
||||||
const { Op, where, col, fn, cast } = require('sequelize')
|
const { Op, where, col, fn, cast } = require('sequelize')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
async getEvents (req, res) {
|
async getEvents (req, res) {
|
||||||
const name = req.params.placeName
|
const placeName = req.params.placeName
|
||||||
const place = await Place.findOne({ where: { name }})
|
const place = await Place.findOne({ where: { name: placeName }})
|
||||||
if (!place) {
|
if (!place) {
|
||||||
log.warn(`Place ${name} not found`)
|
log.warn(`Place ${placeName} not found`)
|
||||||
return res.sendStatus(404)
|
return res.sendStatus(404)
|
||||||
}
|
}
|
||||||
const start = dayjs().unix()
|
|
||||||
const events = await eventController._select({ start, places: `${place.id}`, show_recurrent: true})
|
|
||||||
|
|
||||||
return res.json({ events, place })
|
const format = req.params.format || 'json'
|
||||||
|
log.debug(`Events for place: ${placeName}`)
|
||||||
|
const events = await eventController._select({ places: String(place.id), show_recurrent: true })
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case 'rss':
|
||||||
|
return exportController.feed(req, res, events,
|
||||||
|
`${res.locals.settings.title} - Place @${place.name}`,
|
||||||
|
`${res.locals.settings.baseurl}/feed/rss/place/${place.name}`)
|
||||||
|
case 'ics':
|
||||||
|
return exportController.ics(req, res, events)
|
||||||
|
default:
|
||||||
|
return res.json({ events, place })
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
@ -36,7 +50,7 @@ module.exports = {
|
||||||
return res.json(places)
|
return res.json(places)
|
||||||
},
|
},
|
||||||
|
|
||||||
async get (req, res) {
|
async search (req, res) {
|
||||||
const search = req.query.search.toLocaleLowerCase()
|
const search = req.query.search.toLocaleLowerCase()
|
||||||
const places = await Place.findAll({
|
const places = await Place.findAll({
|
||||||
order: [[cast(fn('COUNT', col('events.placeId')),'INTEGER'), 'DESC']],
|
order: [[cast(fn('COUNT', col('events.placeId')),'INTEGER'), 'DESC']],
|
||||||
|
@ -49,7 +63,9 @@ module.exports = {
|
||||||
attributes: ['name', 'address', 'id'],
|
attributes: ['name', 'address', 'id'],
|
||||||
include: [{ model: Event, where: { is_visible: true }, required: true, attributes: [] }],
|
include: [{ model: Event, where: { is_visible: true }, required: true, attributes: [] }],
|
||||||
group: ['place.id'],
|
group: ['place.id'],
|
||||||
raw: true
|
raw: true,
|
||||||
|
limit: 10,
|
||||||
|
subQuery: false
|
||||||
})
|
})
|
||||||
|
|
||||||
// TOFIX: don't know why limit does not work
|
// TOFIX: don't know why limit does not work
|
||||||
|
|
|
@ -1,31 +1,60 @@
|
||||||
const dayjs = require('dayjs')
|
|
||||||
const Tag = require('../models/tag')
|
const Tag = require('../models/tag')
|
||||||
const Event = require('../models/event')
|
const Event = require('../models/event')
|
||||||
const eventController = require('./event')
|
|
||||||
const Sequelize = require('sequelize')
|
const { where, fn, col, Op } = require('sequelize')
|
||||||
|
const exportController = require('./export')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
// async getEvents (req, res) {
|
|
||||||
// const name = req.params.placeName
|
|
||||||
// const place = await Place.findOne({ where: { name }})
|
|
||||||
// if (!place) {
|
|
||||||
// log.warn(`Place ${name} not found`)
|
|
||||||
// return res.sendStatus(404)
|
|
||||||
// }
|
|
||||||
// const start = dayjs().unix()
|
|
||||||
// const events = await eventController._select({ start, places: `${place.id}`, show_recurrent: true})
|
|
||||||
|
|
||||||
// return res.json({ events, place })
|
async _findOrCreate (tags) {
|
||||||
// },
|
// trim tags
|
||||||
|
const trimmedTags = tags.map(t => t.trim())
|
||||||
|
const lowercaseTags = trimmedTags.map(t => t.toLocaleLowerCase())
|
||||||
|
|
||||||
async get (req, res) {
|
// search for already existing tags (tag is the same as TaG)
|
||||||
|
const existingTags = await Tag.findAll({ where: { [Op.and]: where(fn('LOWER', col('tag')), { [Op.in]: lowercaseTags }) } })
|
||||||
|
const lowercaseExistingTags = existingTags.map(t => t.tag.toLocaleLowerCase())
|
||||||
|
const remainingTags = trimmedTags.filter(t => ! lowercaseExistingTags.includes(t.toLocaleLowerCase()))
|
||||||
|
|
||||||
|
// create remaining tags (cannot use updateOnDuplicate or manage conflicts)
|
||||||
|
return [].concat(
|
||||||
|
existingTags,
|
||||||
|
await Tag.bulkCreate(remainingTags.map(t => ({ tag: t })))
|
||||||
|
)
|
||||||
|
},
|
||||||
|
|
||||||
|
// /feed/rss/tag/:tagname
|
||||||
|
// /feed/ics/tag/:tagname
|
||||||
|
// /feed/json/tag/:tagname
|
||||||
|
// tag/:tag
|
||||||
|
async getEvents (req, res) {
|
||||||
|
const eventController = require('./event')
|
||||||
|
const format = req.params.format || 'json'
|
||||||
|
const tags = req.params.tag
|
||||||
|
const events = await eventController._select({ tags: tags.toLocaleLowerCase(), show_recurrent: true })
|
||||||
|
switch (format) {
|
||||||
|
case 'rss':
|
||||||
|
return exportController.feed(req, res, events,
|
||||||
|
`${res.locals.settings.title} - Tag #${tags}`,
|
||||||
|
`${res.locals.settings.baseurl}/feed/rss/tag/${tags}`)
|
||||||
|
case 'ics':
|
||||||
|
return exportController.ics(req, res, events)
|
||||||
|
default:
|
||||||
|
return res.json(events)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* search for tags by query string
|
||||||
|
* sorted by usage
|
||||||
|
*/
|
||||||
|
async search (req, res) {
|
||||||
const search = req.query.search
|
const search = req.query.search
|
||||||
console.error(search)
|
|
||||||
const tags = await Tag.findAll({
|
const tags = await Tag.findAll({
|
||||||
order: [[Sequelize.fn('COUNT', Sequelize.col('tag.tag')), 'DESC']],
|
order: [[fn('COUNT', col('tag.tag')), 'DESC']],
|
||||||
attributes: ['tag'],
|
attributes: ['tag'],
|
||||||
where: {
|
where: {
|
||||||
tag: Sequelize.where(Sequelize.fn('LOWER', Sequelize.col('tag')), 'LIKE', '%' + search + '%'),
|
tag: where(fn('LOWER', col('tag')), 'LIKE', '%' + search + '%'),
|
||||||
},
|
},
|
||||||
include: [{ model: Event, where: { is_visible: true }, attributes: [], through: { attributes: [] }, required: true }],
|
include: [{ model: Event, where: { is_visible: true }, attributes: [], through: { attributes: [] }, required: true }],
|
||||||
group: ['tag.tag'],
|
group: ['tag.tag'],
|
||||||
|
@ -35,13 +64,4 @@ module.exports = {
|
||||||
|
|
||||||
return res.json(tags.map(t => t.tag))
|
return res.json(tags.map(t => t.tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
// async getPlaces (req, res) {
|
|
||||||
// const search = req.params.search
|
|
||||||
// const places = await Place.findAll({ where: {
|
|
||||||
// [Op.or]: [
|
|
||||||
// { name: }
|
|
||||||
// ]
|
|
||||||
// }})
|
|
||||||
// }
|
|
||||||
}
|
}
|
|
@ -33,7 +33,7 @@ if (config.status !== 'READY') {
|
||||||
const resourceController = require('./controller/resource')
|
const resourceController = require('./controller/resource')
|
||||||
const oauthController = require('./controller/oauth')
|
const oauthController = require('./controller/oauth')
|
||||||
const announceController = require('./controller/announce')
|
const announceController = require('./controller/announce')
|
||||||
const cohortController = require('./controller/cohort')
|
const collectionController = require('./controller/collection')
|
||||||
const helpers = require('../helpers')
|
const helpers = require('../helpers')
|
||||||
const storage = require('./storage')
|
const storage = require('./storage')
|
||||||
const upload = multer({ storage })
|
const upload = multer({ storage })
|
||||||
|
@ -58,8 +58,8 @@ if (config.status !== 'READY') {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
*/
|
*/
|
||||||
api.get('/ping', (req, res) => res.sendStatus(200))
|
api.get('/ping', (_req, res) => res.sendStatus(200))
|
||||||
api.get('/user', isAuth, (req, res) => res.json(res.locals.user))
|
api.get('/user', isAuth, (_req, res) => res.json(res.locals.user))
|
||||||
|
|
||||||
|
|
||||||
api.post('/user/recover', userController.forgotPassword)
|
api.post('/user/recover', userController.forgotPassword)
|
||||||
|
@ -88,9 +88,11 @@ if (config.status !== 'READY') {
|
||||||
* @param {integer} [start] - start timestamp (default: now)
|
* @param {integer} [start] - start timestamp (default: now)
|
||||||
* @param {integer} [end] - end timestamp (optional)
|
* @param {integer} [end] - end timestamp (optional)
|
||||||
* @param {array} [tags] - List of tags
|
* @param {array} [tags] - List of tags
|
||||||
* @param {array} [places] - List of places
|
* @param {array} [places] - List of places id
|
||||||
* @param {integer} [max] - Max events
|
* @param {integer} [max] - Limit events
|
||||||
* @param {boolean} [show_recurrent] - Show also recurrent events (default: as choosen in admin settings)
|
* @param {boolean} [show_recurrent] - Show also recurrent events (default: as choosen in admin settings)
|
||||||
|
* @param {integer} [page] - Pagination
|
||||||
|
* @param {boolean} [older] - select <= start instead of >=
|
||||||
* @example ***Example***
|
* @example ***Example***
|
||||||
* [https://demo.gancio.org/api/events](https://demo.gancio.org/api/events)
|
* [https://demo.gancio.org/api/events](https://demo.gancio.org/api/events)
|
||||||
* [usage example](https://framagit.org/les/gancio/-/blob/master/webcomponents/src/GancioEvents.svelte#L18-42)
|
* [usage example](https://framagit.org/les/gancio/-/blob/master/webcomponents/src/GancioEvents.svelte#L18-42)
|
||||||
|
@ -131,9 +133,6 @@ if (config.status !== 'READY') {
|
||||||
// get tags/places
|
// get tags/places
|
||||||
api.get('/event/meta', eventController.searchMeta)
|
api.get('/event/meta', eventController.searchMeta)
|
||||||
|
|
||||||
// get unconfirmed events
|
|
||||||
api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed)
|
|
||||||
|
|
||||||
// add event notification TODO
|
// add event notification TODO
|
||||||
api.post('/event/notification', eventController.addNotification)
|
api.post('/event/notification', eventController.addNotification)
|
||||||
api.delete('/event/notification/:code', eventController.delNotification)
|
api.delete('/event/notification/:code', eventController.delNotification)
|
||||||
|
@ -142,7 +141,10 @@ if (config.status !== 'READY') {
|
||||||
api.post('/settings/logo', isAdmin, multer({ dest: config.upload_path }).single('logo'), settingsController.setLogo)
|
api.post('/settings/logo', isAdmin, multer({ dest: config.upload_path }).single('logo'), settingsController.setLogo)
|
||||||
api.post('/settings/smtp', isAdmin, settingsController.testSMTP)
|
api.post('/settings/smtp', isAdmin, settingsController.testSMTP)
|
||||||
|
|
||||||
// confirm event
|
// get unconfirmed events
|
||||||
|
api.get('/event/unconfirmed', isAdmin, eventController.getUnconfirmed)
|
||||||
|
|
||||||
|
// [un]confirm event
|
||||||
api.put('/event/confirm/:event_id', isAuth, eventController.confirm)
|
api.put('/event/confirm/:event_id', isAuth, eventController.confirm)
|
||||||
api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm)
|
api.put('/event/unconfirm/:event_id', isAuth, eventController.unconfirm)
|
||||||
|
|
||||||
|
@ -153,12 +155,13 @@ if (config.status !== 'READY') {
|
||||||
api.get('/export/:type', cors, exportController.export)
|
api.get('/export/:type', cors, exportController.export)
|
||||||
|
|
||||||
|
|
||||||
api.get('/place/:placeName/events', cors, placeController.getEvents)
|
|
||||||
api.get('/place/all', isAdmin, placeController.getAll)
|
api.get('/place/all', isAdmin, placeController.getAll)
|
||||||
api.get('/place', cors, placeController.get)
|
api.get('/place/:placeName', cors, placeController.getEvents)
|
||||||
|
api.get('/place', cors, placeController.search)
|
||||||
api.put('/place', isAdmin, placeController.updatePlace)
|
api.put('/place', isAdmin, placeController.updatePlace)
|
||||||
|
|
||||||
api.get('/tag', cors, tagController.get)
|
api.get('/tag', cors, tagController.search)
|
||||||
|
api.get('/tag/:tag', cors, tagController.getEvents)
|
||||||
|
|
||||||
// - FEDIVERSE INSTANCES, MODERATION, RESOURCES
|
// - FEDIVERSE INSTANCES, MODERATION, RESOURCES
|
||||||
api.get('/instances', isAdmin, instanceController.getAll)
|
api.get('/instances', isAdmin, instanceController.getAll)
|
||||||
|
@ -175,14 +178,14 @@ if (config.status !== 'READY') {
|
||||||
api.put('/announcements/:announce_id', isAdmin, announceController.update)
|
api.put('/announcements/:announce_id', isAdmin, announceController.update)
|
||||||
api.delete('/announcements/:announce_id', isAdmin, announceController.remove)
|
api.delete('/announcements/:announce_id', isAdmin, announceController.remove)
|
||||||
|
|
||||||
// - COHORT
|
// - COLLECTIONS
|
||||||
api.get('/cohorts/:name', cohortController.getEvents)
|
api.get('/collections/:name', cors, collectionController.getEvents)
|
||||||
api.get('/cohorts', cohortController.getAll)
|
api.get('/collections', collectionController.getAll)
|
||||||
api.post('/cohorts', isAdmin, cohortController.add)
|
api.post('/collections', isAdmin, collectionController.add)
|
||||||
api.delete('/cohort/:id', isAdmin, cohortController.remove)
|
api.delete('/collection/:id', isAdmin, collectionController.remove)
|
||||||
api.get('/filter/:cohort_id', isAdmin, cohortController.getFilters)
|
api.get('/filter/:collection_id', isAdmin, collectionController.getFilters)
|
||||||
api.post('/filter', isAdmin, cohortController.addFilter)
|
api.post('/filter', isAdmin, collectionController.addFilter)
|
||||||
api.delete('/filter/:id', isAdmin, cohortController.removeFilter)
|
api.delete('/filter/:id', isAdmin, collectionController.removeFilter)
|
||||||
|
|
||||||
// OAUTH
|
// OAUTH
|
||||||
api.get('/clients', isAuth, oauthController.getClients)
|
api.get('/clients', isAuth, oauthController.getClients)
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
const { Model, DataTypes } = require('sequelize')
|
const { Model, DataTypes } = require('sequelize')
|
||||||
const sequelize = require('./index').sequelize
|
const sequelize = require('./index').sequelize
|
||||||
|
|
||||||
class Cohort extends Model {}
|
class Collection extends Model {}
|
||||||
|
|
||||||
Cohort.init({
|
Collection.init({
|
||||||
id: {
|
id: {
|
||||||
type: DataTypes.INTEGER,
|
type: DataTypes.INTEGER,
|
||||||
autoIncrement: true,
|
autoIncrement: true,
|
||||||
|
@ -21,7 +21,7 @@ Cohort.init({
|
||||||
isTop: {
|
isTop: {
|
||||||
type: DataTypes.BOOLEAN
|
type: DataTypes.BOOLEAN
|
||||||
}
|
}
|
||||||
}, { sequelize, modelName: 'cohort', timestamps: false })
|
}, { sequelize, modelName: 'collection', timestamps: false })
|
||||||
|
|
||||||
|
|
||||||
module.exports = Cohort
|
module.exports = Collection
|
|
@ -1,5 +1,5 @@
|
||||||
const { Model, DataTypes } = require('sequelize')
|
const { Model, DataTypes } = require('sequelize')
|
||||||
const Cohort = require('./cohort')
|
const Collection = require('./collection')
|
||||||
const sequelize = require('./index').sequelize
|
const sequelize = require('./index').sequelize
|
||||||
|
|
||||||
class Filter extends Model {}
|
class Filter extends Model {}
|
||||||
|
@ -18,7 +18,7 @@ Filter.init({
|
||||||
}
|
}
|
||||||
}, { sequelize, modelName: 'filter', timestamps: false })
|
}, { sequelize, modelName: 'filter', timestamps: false })
|
||||||
|
|
||||||
Filter.belongsTo(Cohort)
|
Filter.belongsTo(Collection)
|
||||||
Cohort.hasMany(Filter)
|
Collection.hasMany(Filter)
|
||||||
|
|
||||||
module.exports = Filter
|
module.exports = Filter
|
||||||
|
|
|
@ -39,11 +39,10 @@ User.init({
|
||||||
|
|
||||||
User.prototype.comparePassword = async function (pwd) {
|
User.prototype.comparePassword = async function (pwd) {
|
||||||
if (!this.password) { return false }
|
if (!this.password) { return false }
|
||||||
const ret = await bcrypt.compare(pwd, this.password)
|
return bcrypt.compare(pwd, this.password)
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User.beforeSave(async (user, options) => {
|
User.beforeSave(async (user, _options) => {
|
||||||
if (user.changed('password')) {
|
if (user.changed('password')) {
|
||||||
const salt = await bcrypt.genSalt(10)
|
const salt = await bcrypt.genSalt(10)
|
||||||
const hash = await bcrypt.hash(user.password, salt)
|
const hash = await bcrypt.hash(user.password, salt)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
let db
|
let db
|
||||||
function _initializeDB () {
|
function _initializeDB () {
|
||||||
const config = require('../config')
|
const config = require('../config')
|
||||||
config.load()
|
|
||||||
config.log_level = 'error'
|
config.log_level = 'error'
|
||||||
db = require('../api/models/index')
|
db = require('../api/models/index')
|
||||||
return db.initialize()
|
return db.initialize()
|
||||||
|
@ -29,13 +28,12 @@ async function modify (args) {
|
||||||
async function create (args) {
|
async function create (args) {
|
||||||
await _initializeDB()
|
await _initializeDB()
|
||||||
const User = require('../api/models/user')
|
const User = require('../api/models/user')
|
||||||
console.error(args)
|
|
||||||
const user = await User.create({
|
const user = await User.create({
|
||||||
email: args.email,
|
email: args.email,
|
||||||
is_active: true,
|
is_active: true,
|
||||||
is_admin: args.admin || false
|
is_admin: args.admin || false
|
||||||
})
|
}).catch(e => console.error(String(e)))
|
||||||
console.error(user)
|
console.error(JSON.stringify(user, null, 2))
|
||||||
await db.close()
|
await db.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,4 +37,5 @@ let config = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.load()
|
||||||
module.exports = config
|
module.exports = config
|
|
@ -1,4 +1,3 @@
|
||||||
// needed by sequelize
|
// needed by sequelize
|
||||||
const config = require('./config')
|
const config = require('./config')
|
||||||
config.load()
|
|
||||||
module.exports = config.db
|
module.exports = config.db
|
||||||
|
|
|
@ -116,6 +116,14 @@ module.exports = {
|
||||||
next()
|
next()
|
||||||
},
|
},
|
||||||
|
|
||||||
|
col (field) {
|
||||||
|
if (config.db.dialect === 'postgres') {
|
||||||
|
return '"' + field.split('.').join('"."') + '"'
|
||||||
|
} else {
|
||||||
|
return field
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
async getImageFromURL (url) {
|
async getImageFromURL (url) {
|
||||||
log.debug(`getImageFromURL ${url}`)
|
log.debug(`getImageFromURL ${url}`)
|
||||||
if(!/^https?:\/\//.test(url)) {
|
if(!/^https?:\/\//.test(url)) {
|
||||||
|
@ -233,5 +241,13 @@ module.exports = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next()
|
next()
|
||||||
|
},
|
||||||
|
|
||||||
|
async feedRedirect (req, res, next) {
|
||||||
|
const accepted = req.accepts('html', 'application/rss+xml', 'text/calendar')
|
||||||
|
if (['application/rss+xml', 'text/calendar'].includes(accepted) && /^\/(tag|place|collection)\/.*/.test(req.path)) {
|
||||||
|
return res.redirect((accepted === 'application/rss+xml' ? '/feed/rss' : '/feed/ics') + req.path)
|
||||||
|
}
|
||||||
|
next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const config = require('../server/config')
|
const config = require('../server/config')
|
||||||
config.load()
|
|
||||||
|
|
||||||
const initialize = {
|
const initialize = {
|
||||||
// close connections/port/unix socket
|
// close connections/port/unix socket
|
||||||
|
|
30
server/migrations/20220617203517-collection.js
Normal file
30
server/migrations/20220617203517-collection.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
async up (queryInterface, Sequelize) {
|
||||||
|
return Promise.all(
|
||||||
|
[
|
||||||
|
await queryInterface.renameTable('cohorts', 'collections'),
|
||||||
|
await queryInterface.renameColumn('filters', 'cohortId', 'collectionId'),
|
||||||
|
await queryInterface.changeColumn('filters', 'collectionId', {
|
||||||
|
type: Sequelize.INTEGER,
|
||||||
|
allowNull: true,
|
||||||
|
references: {
|
||||||
|
model: 'collections',
|
||||||
|
key: 'id'
|
||||||
|
},
|
||||||
|
onUpdate: 'CASCADE',
|
||||||
|
onDelete: 'SET NULL'
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
},
|
||||||
|
|
||||||
|
async down (queryInterface, Sequelize) {
|
||||||
|
/**
|
||||||
|
* Add reverting commands here.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* await queryInterface.dropTable('users');
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
};
|
|
@ -34,9 +34,17 @@ if (config.status === 'READY') {
|
||||||
const federation = require('./federation')
|
const federation = require('./federation')
|
||||||
const webfinger = require('./federation/webfinger')
|
const webfinger = require('./federation/webfinger')
|
||||||
const exportController = require('./api/controller/export')
|
const exportController = require('./api/controller/export')
|
||||||
|
const tagController = require('./api/controller/tag')
|
||||||
|
const placeController = require('./api/controller/place')
|
||||||
|
const collectionController = require('./api/controller/collection')
|
||||||
|
|
||||||
|
// rss / ics feed
|
||||||
|
app.use(helpers.feedRedirect)
|
||||||
|
app.get('/feed/:format/tag/:tag', cors(), tagController.getEvents)
|
||||||
|
app.get('/feed/:format/place/:placeName', cors(), placeController.getEvents)
|
||||||
|
app.get('/feed/:format/collection/:name', cors(), collectionController.getEvents)
|
||||||
|
app.get('/feed/:format', cors(), exportController.export)
|
||||||
|
|
||||||
// rss/ics/atom feed
|
|
||||||
app.get('/feed/:type', cors(), exportController.export)
|
|
||||||
|
|
||||||
app.use('/event/:slug', helpers.APRedirect)
|
app.use('/event/:slug', helpers.APRedirect)
|
||||||
|
|
||||||
|
@ -59,7 +67,7 @@ app.use('/api', api)
|
||||||
|
|
||||||
// // Handle 500
|
// // Handle 500
|
||||||
app.use((error, _req, res, _next) => {
|
app.use((error, _req, res, _next) => {
|
||||||
log.error('[ERROR]', error)
|
log.error('[ERROR]' + error)
|
||||||
return res.status(500).send('500: Internal Server Error')
|
return res.status(500).send('500: Internal Server Error')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@ let token
|
||||||
let app
|
let app
|
||||||
beforeAll( async () => {
|
beforeAll( async () => {
|
||||||
fs.copyFileSync('./starter.sqlite', './testdb.sqlite')
|
fs.copyFileSync('./starter.sqlite', './testdb.sqlite')
|
||||||
await require('../server/initialize.server.js')()
|
await require('../server/initialize.server.js').start()
|
||||||
app = require('../server/routes.js')
|
app = require('../server/routes.js').handler
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Basic', () => {
|
describe('Basic', () => {
|
||||||
|
@ -96,7 +96,7 @@ describe('Events', () => {
|
||||||
.expect(403)
|
.expect(403)
|
||||||
|
|
||||||
await request(app).post('/api/event')
|
await request(app).post('/api/event')
|
||||||
.send({ title: 'test title', place_name: 'place name', place_address: 'address', start_datetime: new Date().getTime() * 1000 })
|
.send({ title: 'test title', place_name: 'place name', place_address: 'address', tags: ['test'], start_datetime: new Date().getTime() * 1000 })
|
||||||
.auth(token.access_token, { type: 'bearer' })
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ describe('Events', () => {
|
||||||
.send(event)
|
.send(event)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
|
|
||||||
expect(response.body.tags[0]).toBe('test tag')
|
expect(response.body.tags[0]).toBe('test tag')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -132,47 +133,97 @@ describe('Events', () => {
|
||||||
describe('Tags', () => {
|
describe('Tags', () => {
|
||||||
test('should create event with tags', async () => {
|
test('should create event with tags', async () => {
|
||||||
const event = await request(app).post('/api/event')
|
const event = await request(app).post('/api/event')
|
||||||
.send({ title: 'test tags', place_id: 2, start_datetime: new Date().getTime() * 1000, tags: ['tag1', 'tag2', 'tag3'] })
|
.send({ title: 'test tags', place_id: 2, start_datetime: new Date().getTime() * 1000, tags: ['tag1', 'Tag2', 'tAg3'] })
|
||||||
.auth(token.access_token, { type: 'bearer' })
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(event.body.tags.length).toBe(3)
|
expect(event.body.tags.length).toBe(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should create event trimming tags / ignore sensitiviness', async () => {
|
||||||
|
const event = await request(app).post('/api/event')
|
||||||
|
.send({ title: 'test trimming tags', place_id: 2, start_datetime: new Date().getTime() * 1000, tags: ['Tag1', 'taG2 '] })
|
||||||
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(event.body.tags.length).toBe(2)
|
||||||
|
expect(event.body.tags[0]).toBe('tag1')
|
||||||
|
expect(event.body.tags[1]).toBe('Tag2')
|
||||||
|
})
|
||||||
|
|
||||||
test('should return events searching for tags', async () => {
|
test('should return events searching for tags', async () => {
|
||||||
const response = await request(app).get('/api/events?tags=tag1')
|
const response = await request(app).get('/api/events?tags=tAg3')
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
console.error(response.body)
|
// console.error(response.body)
|
||||||
console.error(response.body[0].tags)
|
// console.error(response.body[0].tags)
|
||||||
expect(response.body.length).toBe(1)
|
expect(response.body.length).toBe(1)
|
||||||
expect(response.body[0].title).toBe('test tags')
|
// expect(response.body[0].title).toBe('test tags')
|
||||||
expect(response.body[0].tags.length).toBe(3)
|
expect(response.body[0].tags.length).toBe(3)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe ('Cohort', () => {
|
describe('Place', () => {
|
||||||
test('should not create a new cohort if not allowed', () => {
|
test('should get events by place', async () => {
|
||||||
return request(app).post('/api/cohorts')
|
const response = await request(app).get('/api/place/place name 2')
|
||||||
.send({ name: 'test cohort' })
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body.place.name).toBe('place name 2')
|
||||||
|
expect(response.body.events.length).toBe(2)
|
||||||
|
expect(response.body.events[0].place.name).toBe('place name 2')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('admin should get all places', async () => {
|
||||||
|
await request(app).get('/api/place/all')
|
||||||
|
.expect(403)
|
||||||
|
|
||||||
|
const response = await request(app).get('/api/place/all')
|
||||||
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
|
||||||
|
expect(response.body.length).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('should search for a place', async () => {
|
||||||
|
const response = await request(app).get('/api/place?search=place')
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body.length).toBe(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe ('Collection', () => {
|
||||||
|
test('should not create a new collection if not allowed', () => {
|
||||||
|
return request(app).post('/api/collections')
|
||||||
|
.send({ name: 'test collection' })
|
||||||
.expect(403)
|
.expect(403)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should create a new cohort', async () => {
|
test('should create a new collection', async () => {
|
||||||
const response = await request(app).post('/api/cohorts')
|
const response = await request(app).post('/api/collections')
|
||||||
.send({ name: 'test cohort' })
|
.send({ name: 'test collection' })
|
||||||
.auth(token.access_token, { type: 'bearer' })
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
expect(response.body.id).toBe(1)
|
expect(response.body.id).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('should do not have any event when no filters', async () => {
|
||||||
|
const response = await request(app).get('/api/collections/test collection')
|
||||||
|
.expect(200)
|
||||||
|
|
||||||
|
expect(response.body.length).toBe(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
test('should add a new filter', async () => {
|
test('should add a new filter', async () => {
|
||||||
await request(app)
|
await request(app)
|
||||||
.post('/api/filter')
|
.post('/api/filter')
|
||||||
.expect(403)
|
.expect(403)
|
||||||
|
|
||||||
const response = await request(app).post('/api/filter')
|
const response = await request(app).post('/api/filter')
|
||||||
.send({ cohortId: 1, places: [1] })
|
.send({ collectionId: 1, tags: ['test'] })
|
||||||
.auth(token.access_token, { type: 'bearer' })
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
|
@ -180,12 +231,12 @@ describe ('Cohort', () => {
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should get cohort events', async () => {
|
test('should get collection events', async () => {
|
||||||
const response = await request(app)
|
const response = await request(app)
|
||||||
.get('/api/cohorts/1')
|
.get(`/api/collections/test collection`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(response.body.length).toBe(2)
|
expect(response.body.length).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should remove filter', async () => {
|
test('should remove filter', async () => {
|
||||||
|
@ -209,7 +260,7 @@ describe ('Cohort', () => {
|
||||||
test('shoud filter for tags', async () => {
|
test('shoud filter for tags', async () => {
|
||||||
await request(app)
|
await request(app)
|
||||||
.post('/api/filter')
|
.post('/api/filter')
|
||||||
.send({ cohortId: 1, tags: ['test'] })
|
.send({ collectionId: 1, tags: ['test'] })
|
||||||
.auth(token.access_token, { type: 'bearer' })
|
.auth(token.access_token, { type: 'bearer' })
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
|
@ -220,8 +271,8 @@ describe ('Cohort', () => {
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(response.body.length).toBe(1)
|
expect(response.body.length).toBe(1)
|
||||||
response = await request(app)
|
response = await request(app)
|
||||||
.get('/api/cohorts/1')
|
.get(`/api/collections/test collection`)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(response.body.length).toBe(1)
|
expect(response.body.length).toBe(1)
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
doctype xml
|
doctype xml
|
||||||
rss(version='2.0' xmlns:atom="http://www.w3.org/2005/Atom")
|
rss(version='2.0' xmlns:atom="http://www.w3.org/2005/Atom")
|
||||||
channel
|
channel
|
||||||
atom:link(href=`${settings.baseurl}/feed/rss` rel="self" type="application/rss+xml")
|
atom:link(href=`${link}` rel="self" type="application/rss+xml")
|
||||||
title #{settings.title}
|
title #{title}
|
||||||
link #{settings.baseurl}
|
link #{settings.baseurl}
|
||||||
description #{settings.description}
|
description #{settings.description}
|
||||||
each event in events
|
each event in events
|
||||||
item
|
item
|
||||||
if (event.media && event.media.length)
|
if (event.media && event.media.length)
|
||||||
<enclosure url="#{settings.baseurl}/media/#{event.media[0].url}" type='image/jpeg'></enclosure>
|
<enclosure url="#{settings.baseurl}/media/#{event.media[0].url}" type='image/jpeg' length="#{event.media[0].size||1}"></enclosure>
|
||||||
title [#{moment.unix(event.start_datetime).format("YY-MM-DD")}] #{event.title} @#{event.place.name}
|
title [#{moment.unix(event.start_datetime).format("YY-MM-DD")}] #{event.title} @#{event.place.name}
|
||||||
link #{settings.baseurl}/event/#{event.slug || event.id}
|
link #{settings.baseurl}/event/#{event.slug || event.id}
|
||||||
each tag in event.tags
|
each tag in event.tags
|
||||||
category #{tag.tag}
|
category #{tag}
|
||||||
description
|
description
|
||||||
| <![CDATA[
|
| <![CDATA[
|
||||||
| <h4>#{event.title}</h4>
|
| <h4>#{event.title}</h4>
|
||||||
|
@ -20,7 +20,7 @@ rss(version='2.0' xmlns:atom="http://www.w3.org/2005/Atom")
|
||||||
| <small>(#{moment.unix(event.start_datetime).format("dddd, D MMMM HH:mm")})</small><br/>
|
| <small>(#{moment.unix(event.start_datetime).format("dddd, D MMMM HH:mm")})</small><br/>
|
||||||
if (event.media && event.media.length)
|
if (event.media && event.media.length)
|
||||||
| <img alt="#{event.media[0].name || ''}" src="#{settings.baseurl}/media/#{event.media[0].url}"/>
|
| <img alt="#{event.media[0].name || ''}" src="#{settings.baseurl}/media/#{event.media[0].url}"/>
|
||||||
| <pre>!{event.description}</pre>
|
| !{event.description}
|
||||||
| ]]>
|
| ]]>
|
||||||
pubDate= new Date(event.updatedAt).toUTCString()
|
pubDate= new Date(event.updatedAt).toUTCString()
|
||||||
guid #{settings.baseurl}/event/#{event.slug || event.id}
|
guid #{settings.baseurl}/event/#{event.slug || event.id}
|
||||||
|
|
|
@ -14,7 +14,7 @@ function wpgancio_delete_post ($post_id) {
|
||||||
$gancio_id = get_post_meta($post_id, 'wpgancio_gancio_id', TRUE);
|
$gancio_id = get_post_meta($post_id, 'wpgancio_gancio_id', TRUE);
|
||||||
if ($gancio_id) {
|
if ($gancio_id) {
|
||||||
$http = _wp_http_get_object();
|
$http = _wp_http_get_object();
|
||||||
$response = $http->request( "${instance_url}/api/event/${gancio_id}", array(
|
$http->request( "${instance_url}/api/event/${gancio_id}", array(
|
||||||
'method' => 'DELETE',
|
'method' => 'DELETE',
|
||||||
'headers' => array (
|
'headers' => array (
|
||||||
'Authorization' => 'Bearer ' . get_option('wpgancio_token')
|
'Authorization' => 'Bearer ' . get_option('wpgancio_token')
|
||||||
|
@ -30,6 +30,7 @@ function wpgancio_save_event ($post_id) {
|
||||||
return sanitize_title($tag->name);
|
return sanitize_title($tag->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge event tags with post tags
|
||||||
$tmp_tags = get_the_terms( $event, 'event-tag' );
|
$tmp_tags = get_the_terms( $event, 'event-tag' );
|
||||||
$tags = array_map('tagName', $tmp_tags);
|
$tags = array_map('tagName', $tmp_tags);
|
||||||
|
|
||||||
|
|
|
@ -80,6 +80,9 @@ function wpgancio_options_page() {
|
||||||
function wpgancio_instance_url_cb( $args ) {
|
function wpgancio_instance_url_cb( $args ) {
|
||||||
// get the value of the setting we've registered with register_setting()
|
// get the value of the setting we've registered with register_setting()
|
||||||
$instance_url = get_option( 'wpgancio_instance_url' );
|
$instance_url = get_option( 'wpgancio_instance_url' );
|
||||||
|
if (empty($instance_url)) {
|
||||||
|
$instance_url = WP_GANCIO_DEFAULT_INSTANCEURL;
|
||||||
|
}
|
||||||
// output the field
|
// output the field
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
630
yarn.lock
630
yarn.lock
|
@ -1132,28 +1132,28 @@
|
||||||
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
|
resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
|
||||||
integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
|
integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
|
||||||
|
|
||||||
"@jest/console@^28.1.0":
|
"@jest/console@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.0.tgz#db78222c3d3b0c1db82f1b9de51094c2aaff2176"
|
resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.1.tgz#305f8ca50b6e70413839f54c0e002b60a0f2fd7d"
|
||||||
integrity sha512-tscn3dlJFGay47kb4qVruQg/XWlmvU0xp3EJOjzzY+sBaI+YgwKcvAmTcyYU7xEiLLIY5HCdWRooAL8dqkFlDA==
|
integrity sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
|
||||||
"@jest/core@^28.1.0":
|
"@jest/core@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.0.tgz#784a1e6ce5358b46fcbdcfbbd93b1b713ed4ea80"
|
resolved "https://registry.yarnpkg.com/@jest/core/-/core-28.1.1.tgz#086830bec6267accf9af5ca76f794858e9f9f092"
|
||||||
integrity sha512-/2PTt0ywhjZ4NwNO4bUqD9IVJfmFVhVKGlhvSpmEfUCuxYf/3NHcKmRFI+I71lYzbTT3wMuYpETDCTHo81gC/g==
|
integrity sha512-3pYsBoZZ42tXMdlcFeCc/0j9kOlK7MYuXs2B1QbvDgMoW1K9NJ4G/VYvIbMb26iqlkTfPHo7SC2JgjDOk/mxXw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/console" "^28.1.0"
|
"@jest/console" "^28.1.1"
|
||||||
"@jest/reporters" "^28.1.0"
|
"@jest/reporters" "^28.1.1"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
ansi-escapes "^4.2.1"
|
ansi-escapes "^4.2.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
|
@ -1161,80 +1161,80 @@
|
||||||
exit "^0.1.2"
|
exit "^0.1.2"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-changed-files "^28.0.2"
|
jest-changed-files "^28.0.2"
|
||||||
jest-config "^28.1.0"
|
jest-config "^28.1.1"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-resolve "^28.1.0"
|
jest-resolve "^28.1.1"
|
||||||
jest-resolve-dependencies "^28.1.0"
|
jest-resolve-dependencies "^28.1.1"
|
||||||
jest-runner "^28.1.0"
|
jest-runner "^28.1.1"
|
||||||
jest-runtime "^28.1.0"
|
jest-runtime "^28.1.1"
|
||||||
jest-snapshot "^28.1.0"
|
jest-snapshot "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-validate "^28.1.0"
|
jest-validate "^28.1.1"
|
||||||
jest-watcher "^28.1.0"
|
jest-watcher "^28.1.1"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
rimraf "^3.0.0"
|
rimraf "^3.0.0"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
"@jest/environment@^28.1.0":
|
"@jest/environment@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.0.tgz#dedf7d59ec341b9292fcf459fd0ed819eb2e228a"
|
resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-28.1.1.tgz#c4cbf85283278d768f816ebd1a258ea6f9e39d4f"
|
||||||
integrity sha512-S44WGSxkRngzHslhV6RoAExekfF7Qhwa6R5+IYFa81mpcj0YgdBnRSmvHe3SNwOt64yXaE5GG8Y2xM28ii5ssA==
|
integrity sha512-9auVQ2GzQ7nrU+lAr8KyY838YahElTX9HVjbQPPS2XjlxQ+na18G113OoBhyBGBtD6ZnO/SrUy5WR8EzOj1/Uw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/fake-timers" "^28.1.0"
|
"@jest/fake-timers" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-mock "^28.1.0"
|
jest-mock "^28.1.1"
|
||||||
|
|
||||||
"@jest/expect-utils@^28.1.0":
|
"@jest/expect-utils@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.0.tgz#a5cde811195515a9809b96748ae8bcc331a3538a"
|
resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-28.1.1.tgz#d84c346025b9f6f3886d02c48a6177e2b0360587"
|
||||||
integrity sha512-5BrG48dpC0sB80wpeIX5FU6kolDJI4K0n5BM9a5V38MGx0pyRvUBSS0u2aNTdDzmOrCjhOg8pGs6a20ivYkdmw==
|
integrity sha512-n/ghlvdhCdMI/hTcnn4qV57kQuV9OTsZzH1TTCVARANKhl6hXJqLKUkwX69ftMGpsbpt96SsDD8n8LD2d9+FRw==
|
||||||
dependencies:
|
dependencies:
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
|
|
||||||
"@jest/expect@^28.1.0":
|
"@jest/expect@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.0.tgz#2e5a31db692597070932366a1602b5157f0f217c"
|
resolved "https://registry.yarnpkg.com/@jest/expect/-/expect-28.1.1.tgz#ea4fcc8504b45835029221c0dc357c622a761326"
|
||||||
integrity sha512-be9ETznPLaHOmeJqzYNIXv1ADEzENuQonIoobzThOYPuK/6GhrWNIJDVTgBLCrz3Am73PyEU2urQClZp0hLTtA==
|
integrity sha512-/+tQprrFoT6lfkMj4mW/mUIfAmmk/+iQPmg7mLDIFOf2lyf7EBHaS+x3RbeR0VZVMe55IvX7QRoT/2aK3AuUXg==
|
||||||
dependencies:
|
dependencies:
|
||||||
expect "^28.1.0"
|
expect "^28.1.1"
|
||||||
jest-snapshot "^28.1.0"
|
jest-snapshot "^28.1.1"
|
||||||
|
|
||||||
"@jest/fake-timers@^28.1.0":
|
"@jest/fake-timers@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.0.tgz#ea77878aabd5c5d50e1fc53e76d3226101e33064"
|
resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-28.1.1.tgz#47ce33296ab9d680c76076d51ddbe65ceb3337f1"
|
||||||
integrity sha512-Xqsf/6VLeAAq78+GNPzI7FZQRf5cCHj1qgQxCjws9n8rKw8r1UYoeaALwBvyuzOkpU3c1I6emeMySPa96rxtIg==
|
integrity sha512-BY/3+TyLs5+q87rGWrGUY5f8e8uC3LsVHS9Diz8+FV3ARXL4sNnkLlIB8dvDvRrp+LUCGM+DLqlsYubizGUjIA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@sinonjs/fake-timers" "^9.1.1"
|
"@sinonjs/fake-timers" "^9.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-mock "^28.1.0"
|
jest-mock "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
|
|
||||||
"@jest/globals@^28.1.0":
|
"@jest/globals@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.0.tgz#a4427d2eb11763002ff58e24de56b84ba79eb793"
|
resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-28.1.1.tgz#c0a7977f85e26279cc090d9adcdf82b8a34c4061"
|
||||||
integrity sha512-3m7sTg52OTQR6dPhsEQSxAvU+LOBbMivZBwOvKEZ+Rb+GyxVnXi9HKgOTYkx/S99T8yvh17U4tNNJPIEQmtwYw==
|
integrity sha512-dEgl/6v7ToB4vXItdvcltJBgny0xBE6xy6IYQrPJAJggdEinGxCDMivNv7sFzPcTITGquXD6UJwYxfJ/5ZwDSg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/environment" "^28.1.0"
|
"@jest/environment" "^28.1.1"
|
||||||
"@jest/expect" "^28.1.0"
|
"@jest/expect" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
|
|
||||||
"@jest/reporters@^28.1.0":
|
"@jest/reporters@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.0.tgz#5183a28b9b593b6000fa9b89b031c7216b58a9a0"
|
resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-28.1.1.tgz#9389f4bb3cce4d9b586f6195f83c79cd2a1c8662"
|
||||||
integrity sha512-qxbFfqap/5QlSpIizH9c/bFCDKsQlM4uAKSOvZrP+nIdrjqre3FmKzpTtYyhsaVcOSNK7TTt2kjm+4BJIjysFA==
|
integrity sha512-597Zj4D4d88sZrzM4atEGLuO7SdA/YrOv9SRXHXRNC+/FwPCWxZhBAEzhXoiJzfRwn8zes/EjS8Lo6DouGN5Gg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@bcoe/v8-coverage" "^0.2.3"
|
"@bcoe/v8-coverage" "^0.2.3"
|
||||||
"@jest/console" "^28.1.0"
|
"@jest/console" "^28.1.1"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@jridgewell/trace-mapping" "^0.3.7"
|
"@jridgewell/trace-mapping" "^0.3.7"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
|
@ -1247,8 +1247,9 @@
|
||||||
istanbul-lib-report "^3.0.0"
|
istanbul-lib-report "^3.0.0"
|
||||||
istanbul-lib-source-maps "^4.0.0"
|
istanbul-lib-source-maps "^4.0.0"
|
||||||
istanbul-reports "^3.1.3"
|
istanbul-reports "^3.1.3"
|
||||||
jest-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-worker "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
|
jest-worker "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
string-length "^4.0.1"
|
string-length "^4.0.1"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
@ -1271,51 +1272,51 @@
|
||||||
callsites "^3.0.0"
|
callsites "^3.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
|
|
||||||
"@jest/test-result@^28.1.0":
|
"@jest/test-result@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.0.tgz#fd149dee123510dd2fcadbbf5f0020f98ad7f12c"
|
resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.1.tgz#c6f18d1bbb01aa88925dd687872a75f8414b317a"
|
||||||
integrity sha512-sBBFIyoPzrZho3N+80P35A5oAkSKlGfsEFfXFWuPGBsW40UAjCkGakZhn4UQK4iQlW2vgCDMRDOob9FGKV8YoQ==
|
integrity sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/console" "^28.1.0"
|
"@jest/console" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||||
collect-v8-coverage "^1.0.0"
|
collect-v8-coverage "^1.0.0"
|
||||||
|
|
||||||
"@jest/test-sequencer@^28.1.0":
|
"@jest/test-sequencer@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.0.tgz#ce7294bbe986415b9a30e218c7e705e6ebf2cdf2"
|
resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-28.1.1.tgz#f594ee2331df75000afe0d1ae3237630ecec732e"
|
||||||
integrity sha512-tZCEiVWlWNTs/2iK9yi6o3AlMfbbYgV4uuZInSVdzZ7ftpHZhCMuhvk2HLYhCZzLgPFQ9MnM1YaxMnh3TILFiQ==
|
integrity sha512-nuL+dNSVMcWB7OOtgb0EGH5AjO4UBCt68SLP08rwmC+iRhyuJWS9MtZ/MpipxFwKAlHFftbMsydXqWre8B0+XA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
|
||||||
"@jest/transform@^28.1.0":
|
"@jest/transform@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.0.tgz#224a3c9ba4cc98e2ff996c0a89a2d59db15c74ce"
|
resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-28.1.1.tgz#83541f2a3f612077c8501f49cc4e205d4e4a6b27"
|
||||||
integrity sha512-omy2xe5WxlAfqmsTjTPxw+iXRTRnf+NtX0ToG+4S0tABeb4KsKmPUHq5UBuwunHg3tJRwgEQhEp0M/8oiatLEA==
|
integrity sha512-PkfaTUuvjUarl1EDr5ZQcCA++oXkFCP9QFUkG0yVKVmNObjhrqDy0kbMpMebfHWm3CCDHjYNem9eUSH8suVNHQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.11.6"
|
"@babel/core" "^7.11.6"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@jridgewell/trace-mapping" "^0.3.7"
|
"@jridgewell/trace-mapping" "^0.3.7"
|
||||||
babel-plugin-istanbul "^6.1.1"
|
babel-plugin-istanbul "^6.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
convert-source-map "^1.4.0"
|
convert-source-map "^1.4.0"
|
||||||
fast-json-stable-stringify "^2.0.0"
|
fast-json-stable-stringify "^2.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
pirates "^4.0.4"
|
pirates "^4.0.4"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
write-file-atomic "^4.0.1"
|
write-file-atomic "^4.0.1"
|
||||||
|
|
||||||
"@jest/types@^28.1.0":
|
"@jest/types@^28.1.1":
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.0.tgz#508327a89976cbf9bd3e1cc74641a29fd7dfd519"
|
resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.1.tgz#d059bbc80e6da6eda9f081f293299348bd78ee0b"
|
||||||
integrity sha512-xmEggMPr317MIOjjDoZ4ejCSr9Lpbt/u34+dvc99t7DS8YirW5rwZEhzKPC2BMUFkUhI48qs6qLUSGw5FuL0GA==
|
integrity sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/schemas" "^28.0.2"
|
"@jest/schemas" "^28.0.2"
|
||||||
"@types/istanbul-lib-coverage" "^2.0.0"
|
"@types/istanbul-lib-coverage" "^2.0.0"
|
||||||
|
@ -2785,15 +2786,15 @@ axios@^0.27.2:
|
||||||
follow-redirects "^1.14.9"
|
follow-redirects "^1.14.9"
|
||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
|
|
||||||
babel-jest@^28.1.0:
|
babel-jest@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.0.tgz#95a67f8e2e7c0042e7b3ad3951b8af41a533b5ea"
|
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-28.1.1.tgz#2a3a4ae50964695b2d694ccffe4bec537c5a3586"
|
||||||
integrity sha512-zNKk0yhDZ6QUwfxh9k07GII6siNGMJWVUU49gmFj5gfdqDKLqa2RArXOF2CODp4Dr7dLxN2cvAV+667dGJ4b4w==
|
integrity sha512-MEt0263viUdAkTq5D7upHPNxvt4n9uLUGa6pPz3WviNBMtOmStb1lIXS3QobnoqM+qnH+vr4EKlvhe8QcmxIYw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@types/babel__core" "^7.1.14"
|
"@types/babel__core" "^7.1.14"
|
||||||
babel-plugin-istanbul "^6.1.1"
|
babel-plugin-istanbul "^6.1.1"
|
||||||
babel-preset-jest "^28.0.2"
|
babel-preset-jest "^28.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
@ -2826,10 +2827,10 @@ babel-plugin-istanbul@^6.1.1:
|
||||||
istanbul-lib-instrument "^5.0.4"
|
istanbul-lib-instrument "^5.0.4"
|
||||||
test-exclude "^6.0.0"
|
test-exclude "^6.0.0"
|
||||||
|
|
||||||
babel-plugin-jest-hoist@^28.0.2:
|
babel-plugin-jest-hoist@^28.1.1:
|
||||||
version "28.0.2"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.0.2.tgz#9307d03a633be6fc4b1a6bc5c3a87e22bd01dd3b"
|
resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-28.1.1.tgz#5e055cdcc47894f28341f87f5e35aad2df680b11"
|
||||||
integrity sha512-Kizhn/ZL+68ZQHxSnHyuvJv8IchXD62KQxV77TBDV/xoBFBOfgRAk97GNs6hXdTTCiVES9nB2I6+7MXXrk5llQ==
|
integrity sha512-NovGCy5Hn25uMJSAU8FaHqzs13cFoOI4lhIujiepssjCKRsAo3TA734RDWSGxuFTsUJXerYOqQQodlxgmtqbzw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/template" "^7.3.3"
|
"@babel/template" "^7.3.3"
|
||||||
"@babel/types" "^7.3.3"
|
"@babel/types" "^7.3.3"
|
||||||
|
@ -2878,12 +2879,12 @@ babel-preset-current-node-syntax@^1.0.0:
|
||||||
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
|
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
|
||||||
"@babel/plugin-syntax-top-level-await" "^7.8.3"
|
"@babel/plugin-syntax-top-level-await" "^7.8.3"
|
||||||
|
|
||||||
babel-preset-jest@^28.0.2:
|
babel-preset-jest@^28.1.1:
|
||||||
version "28.0.2"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.0.2.tgz#d8210fe4e46c1017e9fa13d7794b166e93aa9f89"
|
resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-28.1.1.tgz#5b6e5e69f963eb2d70f739c607b8f723c0ee75e4"
|
||||||
integrity sha512-sYzXIdgIXXroJTFeB3S6sNDWtlJ2dllCdTEsnZ65ACrMojj3hVNFRmnJ1HZtomGi+Be7aqpY/HJ92fr8OhKVkQ==
|
integrity sha512-FCq9Oud0ReTeWtcneYf/48981aTfXYuB9gbU4rBNNJVBSQ6ssv7E6v/qvbBxtOWwZFXjLZwpg+W3q7J6vhH25g==
|
||||||
dependencies:
|
dependencies:
|
||||||
babel-plugin-jest-hoist "^28.0.2"
|
babel-plugin-jest-hoist "^28.1.1"
|
||||||
babel-preset-current-node-syntax "^1.0.0"
|
babel-preset-current-node-syntax "^1.0.0"
|
||||||
|
|
||||||
babel-walk@3.0.0-canary-5:
|
babel-walk@3.0.0-canary-5:
|
||||||
|
@ -4540,10 +4541,10 @@ dezalgo@1.0.3:
|
||||||
asap "^2.0.0"
|
asap "^2.0.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
diff-sequences@^28.0.2:
|
diff-sequences@^28.1.1:
|
||||||
version "28.0.2"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.0.2.tgz#40f8d4ffa081acbd8902ba35c798458d0ff1af41"
|
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-28.1.1.tgz#9989dc731266dc2903457a70e996f3a041913ac6"
|
||||||
integrity sha512-YtEoNynLDFCRznv/XDalsKGSZDoj0U5kLnXvY0JSq3nBboRrZXjD81+eSiwi+nzcZDwedMmcowcxNwwgFW23mQ==
|
integrity sha512-FU0iFaH/E23a+a718l8Qa/19bF9p06kgE0KipMOMadwa3SjnaElKzPaUC0vnibs6/B/9ni97s61mcejk8W1fQw==
|
||||||
|
|
||||||
diffie-hellman@^5.0.0:
|
diffie-hellman@^5.0.0:
|
||||||
version "5.0.3"
|
version "5.0.3"
|
||||||
|
@ -5110,16 +5111,16 @@ expand-template@^2.0.3:
|
||||||
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||||
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||||
|
|
||||||
expect@^28.1.0:
|
expect@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.0.tgz#10e8da64c0850eb8c39a480199f14537f46e8360"
|
resolved "https://registry.yarnpkg.com/expect/-/expect-28.1.1.tgz#ca6fff65f6517cf7220c2e805a49c19aea30b420"
|
||||||
integrity sha512-qFXKl8Pmxk8TBGfaFKRtcQjfXEnKAs+dmlxdwvukJZorwrAabT7M3h8oLOG01I2utEhkmUTi17CHaPBovZsKdw==
|
integrity sha512-/AANEwGL0tWBwzLNOvO0yUdy2D52jVdNXppOqswC49sxMN2cPWsGCQdzuIf9tj6hHoBQzNvx75JUYuQAckPo3w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/expect-utils" "^28.1.0"
|
"@jest/expect-utils" "^28.1.1"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
jest-matcher-utils "^28.1.0"
|
jest-matcher-utils "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
|
|
||||||
express-oauth-server@lesion/express-oauth-server#master:
|
express-oauth-server@lesion/express-oauth-server#master:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
|
@ -6776,180 +6777,180 @@ jest-changed-files@^28.0.2:
|
||||||
execa "^5.0.0"
|
execa "^5.0.0"
|
||||||
throat "^6.0.1"
|
throat "^6.0.1"
|
||||||
|
|
||||||
jest-circus@^28.1.0:
|
jest-circus@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.0.tgz#e229f590911bd54d60efaf076f7acd9360296dae"
|
resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-28.1.1.tgz#3d27da6a974d85a466dc0cdc6ddeb58daaa57bb4"
|
||||||
integrity sha512-rNYfqfLC0L0zQKRKsg4n4J+W1A2fbyGH7Ss/kDIocp9KXD9iaL111glsLu7+Z7FHuZxwzInMDXq+N1ZIBkI/TQ==
|
integrity sha512-75+BBVTsL4+p2w198DQpCeyh1RdaS2lhEG87HkaFX/UG0gJExVq2skG2pT7XZEGBubNj2CytcWSPan4QEPNosw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/environment" "^28.1.0"
|
"@jest/environment" "^28.1.1"
|
||||||
"@jest/expect" "^28.1.0"
|
"@jest/expect" "^28.1.1"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
co "^4.6.0"
|
co "^4.6.0"
|
||||||
dedent "^0.7.0"
|
dedent "^0.7.0"
|
||||||
is-generator-fn "^2.0.0"
|
is-generator-fn "^2.0.0"
|
||||||
jest-each "^28.1.0"
|
jest-each "^28.1.1"
|
||||||
jest-matcher-utils "^28.1.0"
|
jest-matcher-utils "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-runtime "^28.1.0"
|
jest-runtime "^28.1.1"
|
||||||
jest-snapshot "^28.1.0"
|
jest-snapshot "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
stack-utils "^2.0.3"
|
stack-utils "^2.0.3"
|
||||||
throat "^6.0.1"
|
throat "^6.0.1"
|
||||||
|
|
||||||
jest-cli@^28.1.0:
|
jest-cli@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.0.tgz#cd1d8adb9630102d5ba04a22895f63decdd7ac1f"
|
resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-28.1.1.tgz#23ddfde8940e1818585ae4a568877b33b0e51cfe"
|
||||||
integrity sha512-fDJRt6WPRriHrBsvvgb93OxgajHHsJbk4jZxiPqmZbMDRcHskfJBBfTyjFko0jjfprP544hOktdSi9HVgl4VUQ==
|
integrity sha512-+sUfVbJqb1OjBZ0OdBbI6OWfYM1i7bSfzYy6gze1F1w3OKWq8ZTEKkZ8a7ZQPq6G/G1qMh/uKqpdWhgl11NFQQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/core" "^28.1.0"
|
"@jest/core" "^28.1.1"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
exit "^0.1.2"
|
exit "^0.1.2"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
import-local "^3.0.2"
|
import-local "^3.0.2"
|
||||||
jest-config "^28.1.0"
|
jest-config "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-validate "^28.1.0"
|
jest-validate "^28.1.1"
|
||||||
prompts "^2.0.1"
|
prompts "^2.0.1"
|
||||||
yargs "^17.3.1"
|
yargs "^17.3.1"
|
||||||
|
|
||||||
jest-config@^28.1.0:
|
jest-config@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.0.tgz#fca22ca0760e746fe1ce1f9406f6b307ab818501"
|
resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-28.1.1.tgz#e90b97b984f14a6c24a221859e81b258990fce2f"
|
||||||
integrity sha512-aOV80E9LeWrmflp7hfZNn/zGA4QKv/xsn2w8QCBP0t0+YqObuCWTSgNbHJ0j9YsTuCO08ZR/wsvlxqqHX20iUA==
|
integrity sha512-tASynMhS+jVV85zKvjfbJ8nUyJS/jUSYZ5KQxLUN2ZCvcQc/OmhQl2j6VEL3ezQkNofxn5pQ3SPYWPHb0unTZA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.11.6"
|
"@babel/core" "^7.11.6"
|
||||||
"@jest/test-sequencer" "^28.1.0"
|
"@jest/test-sequencer" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
babel-jest "^28.1.0"
|
babel-jest "^28.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
ci-info "^3.2.0"
|
ci-info "^3.2.0"
|
||||||
deepmerge "^4.2.2"
|
deepmerge "^4.2.2"
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-circus "^28.1.0"
|
jest-circus "^28.1.1"
|
||||||
jest-environment-node "^28.1.0"
|
jest-environment-node "^28.1.1"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-resolve "^28.1.0"
|
jest-resolve "^28.1.1"
|
||||||
jest-runner "^28.1.0"
|
jest-runner "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-validate "^28.1.0"
|
jest-validate "^28.1.1"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
parse-json "^5.2.0"
|
parse-json "^5.2.0"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
strip-json-comments "^3.1.1"
|
strip-json-comments "^3.1.1"
|
||||||
|
|
||||||
jest-diff@^28.1.0:
|
jest-diff@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.0.tgz#77686fef899ec1873dbfbf9330e37dd429703269"
|
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-28.1.1.tgz#1a3eedfd81ae79810931c63a1d0f201b9120106c"
|
||||||
integrity sha512-8eFd3U3OkIKRtlasXfiAQfbovgFgRDb0Ngcs2E+FMeBZ4rUezqIaGjuyggJBp+llosQXNEWofk/Sz4Hr5gMUhA==
|
integrity sha512-/MUUxeR2fHbqHoMMiffe/Afm+U8U4olFRJ0hiVG2lZatPJcnGxx292ustVu7bULhjV65IYMxRdploAKLbcrsyg==
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
diff-sequences "^28.0.2"
|
diff-sequences "^28.1.1"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
|
|
||||||
jest-docblock@^28.0.2:
|
jest-docblock@^28.1.1:
|
||||||
version "28.0.2"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.0.2.tgz#3cab8abea53275c9d670cdca814fc89fba1298c2"
|
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-28.1.1.tgz#6f515c3bf841516d82ecd57a62eed9204c2f42a8"
|
||||||
integrity sha512-FH10WWw5NxLoeSdQlJwu+MTiv60aXV/t8KEwIRGEv74WARE1cXIqh1vGdy2CraHuWOOrnzTWj/azQKqW4fO7xg==
|
integrity sha512-3wayBVNiOYx0cwAbl9rwm5kKFP8yHH3d/fkEaL02NPTkDojPtheGB7HZSFY4wzX+DxyrvhXz0KSCVksmCknCuA==
|
||||||
dependencies:
|
dependencies:
|
||||||
detect-newline "^3.0.0"
|
detect-newline "^3.0.0"
|
||||||
|
|
||||||
jest-each@^28.1.0:
|
jest-each@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.0.tgz#54ae66d6a0a5b1913e9a87588d26c2687c39458b"
|
resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-28.1.1.tgz#ba5238dacf4f31d9fe23ddc2c44c01e7c23885c4"
|
||||||
integrity sha512-a/XX02xF5NTspceMpHujmOexvJ4GftpYXqr6HhhmKmExtMXsyIN/fvanQlt/BcgFoRKN4OCXxLQKth9/n6OPFg==
|
integrity sha512-A042rqh17ZvEhRceDMi784ppoXR7MWGDEKTXEZXb4svt0eShMZvijGxzKsx+yIjeE8QYmHPrnHiTSQVhN4nqaw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
|
|
||||||
jest-environment-node@^28.1.0:
|
jest-environment-node@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.0.tgz#6ed2150aa31babba0c488c5b4f4d813a585c68e6"
|
resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-28.1.1.tgz#1c86c59003a7d319fa06ea3b1bbda6c193715c67"
|
||||||
integrity sha512-gBLZNiyrPw9CSMlTXF1yJhaBgWDPVvH0Pq6bOEwGMXaYNzhzhw2kA/OijNF8egbCgDS0/veRv97249x2CX+udQ==
|
integrity sha512-2aV/eeY/WNgUUJrrkDJ3cFEigjC5fqT1+fCclrY6paqJ5zVPoM//sHmfgUUp7WLYxIdbPwMiVIzejpN56MxnNA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/environment" "^28.1.0"
|
"@jest/environment" "^28.1.1"
|
||||||
"@jest/fake-timers" "^28.1.0"
|
"@jest/fake-timers" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
jest-mock "^28.1.0"
|
jest-mock "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
|
|
||||||
jest-get-type@^28.0.2:
|
jest-get-type@^28.0.2:
|
||||||
version "28.0.2"
|
version "28.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203"
|
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-28.0.2.tgz#34622e628e4fdcd793d46db8a242227901fcf203"
|
||||||
integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==
|
integrity sha512-ioj2w9/DxSYHfOm5lJKCdcAmPJzQXmbM/Url3rhlghrPvT3tt+7a/+oXc9azkKmLvoiXjtV83bEWqi+vs5nlPA==
|
||||||
|
|
||||||
jest-haste-map@^28.1.0:
|
jest-haste-map@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.0.tgz#6c1ee2daf1c20a3e03dbd8e5b35c4d73d2349cf0"
|
resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-28.1.1.tgz#471685f1acd365a9394745bb97c8fc16289adca3"
|
||||||
integrity sha512-xyZ9sXV8PtKi6NCrJlmq53PyNVHzxmcfXNVvIRHpHmh1j/HChC4pwKgyjj7Z9us19JMw8PpQTJsFWOsIfT93Dw==
|
integrity sha512-ZrRSE2o3Ezh7sb1KmeLEZRZ4mgufbrMwolcFHNRSjKZhpLa8TdooXOOFlSwoUzlbVs1t0l7upVRW2K7RWGHzbQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/graceful-fs" "^4.1.3"
|
"@types/graceful-fs" "^4.1.3"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
anymatch "^3.0.3"
|
anymatch "^3.0.3"
|
||||||
fb-watchman "^2.0.0"
|
fb-watchman "^2.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-worker "^28.1.0"
|
jest-worker "^28.1.1"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
walker "^1.0.7"
|
walker "^1.0.8"
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "^2.3.2"
|
fsevents "^2.3.2"
|
||||||
|
|
||||||
jest-leak-detector@^28.1.0:
|
jest-leak-detector@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.0.tgz#b65167776a8787443214d6f3f54935a4c73c8a45"
|
resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-28.1.1.tgz#537f37afd610a4b3f4cab15e06baf60484548efb"
|
||||||
integrity sha512-uIJDQbxwEL2AMMs2xjhZl2hw8s77c3wrPaQ9v6tXJLGaaQ+4QrNJH5vuw7hA7w/uGT/iJ42a83opAqxGHeyRIA==
|
integrity sha512-4jvs8V8kLbAaotE+wFR7vfUGf603cwYtFf1/PYEsyX2BAjSzj8hQSVTP6OWzseTl0xL6dyHuKs2JAks7Pfubmw==
|
||||||
dependencies:
|
dependencies:
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
|
|
||||||
jest-matcher-utils@^28.1.0:
|
jest-matcher-utils@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.0.tgz#2ae398806668eeabd293c61712227cb94b250ccf"
|
resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-28.1.1.tgz#a7c4653c2b782ec96796eb3088060720f1e29304"
|
||||||
integrity sha512-onnax0n2uTLRQFKAjC7TuaxibrPSvZgKTcSCnNUz/tOjJ9UhxNm7ZmPpoQavmTDUjXvUQ8KesWk2/VdrxIFzTQ==
|
integrity sha512-NPJPRWrbmR2nAJ+1nmnfcKKzSwgfaciCCrYZzVnNoxVoyusYWIjkBMNvu0RHJe7dNj4hH3uZOPZsQA+xAYWqsw==
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
jest-diff "^28.1.0"
|
jest-diff "^28.1.1"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
|
|
||||||
jest-message-util@^28.1.0:
|
jest-message-util@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.0.tgz#7e8f0b9049e948e7b94c2a52731166774ba7d0af"
|
resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.1.tgz#60aa0b475cfc08c8a9363ed2fb9108514dd9ab89"
|
||||||
integrity sha512-RpA8mpaJ/B2HphDMiDlrAZdDytkmwFqgjDZovM21F35lHGeUeCvYmm6W+sbQ0ydaLpg5bFAUuWG1cjqOl8vqrw==
|
integrity sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/code-frame" "^7.12.13"
|
"@babel/code-frame" "^7.12.13"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/stack-utils" "^2.0.0"
|
"@types/stack-utils" "^2.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
micromatch "^4.0.4"
|
micromatch "^4.0.4"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
stack-utils "^2.0.3"
|
stack-utils "^2.0.3"
|
||||||
|
|
||||||
jest-mock@^28.1.0:
|
jest-mock@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.0.tgz#ccc7cc12a9b330b3182db0c651edc90d163ff73e"
|
resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-28.1.1.tgz#37903d269427fa1ef5b2447be874e1c62a39a371"
|
||||||
integrity sha512-H7BrhggNn77WhdL7O1apG0Q/iwl0Bdd5E1ydhCJzL3oBLh/UYxAwR3EJLsBZ9XA3ZU4PA3UNw4tQjduBTCTmLw==
|
integrity sha512-bDCb0FjfsmKweAvE09dZT59IMkzgN0fYBH6t5S45NoJfd2DHkS3ySG2K+hucortryhO3fVuXdlxWcbtIuV/Skw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
jest-pnp-resolver@^1.2.2:
|
jest-pnp-resolver@^1.2.2:
|
||||||
|
@ -6962,149 +6963,149 @@ jest-regex-util@^28.0.2:
|
||||||
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead"
|
resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead"
|
||||||
integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==
|
integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==
|
||||||
|
|
||||||
jest-resolve-dependencies@^28.1.0:
|
jest-resolve-dependencies@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.0.tgz#167becb8bee6e20b5ef4a3a728ec67aef6b0b79b"
|
resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-28.1.1.tgz#3dffaaa56f4b41bc6b61053899d1756401763a27"
|
||||||
integrity sha512-Ue1VYoSZquPwEvng7Uefw8RmZR+me/1kr30H2jMINjGeHgeO/JgrR6wxj2ofkJ7KSAA11W3cOrhNCbj5Dqqd9g==
|
integrity sha512-p8Y150xYJth4EXhOuB8FzmS9r8IGLEioiaetgdNGb9VHka4fl0zqWlVe4v7mSkYOuEUg2uB61iE+zySDgrOmgQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-snapshot "^28.1.0"
|
jest-snapshot "^28.1.1"
|
||||||
|
|
||||||
jest-resolve@^28.1.0:
|
jest-resolve@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.0.tgz#b1f32748a6cee7d1779c7ef639c0a87078de3d35"
|
resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-28.1.1.tgz#bc2eaf384abdcc1aaf3ba7c50d1adf01e59095e5"
|
||||||
integrity sha512-vvfN7+tPNnnhDvISuzD1P+CRVP8cK0FHXRwPAcdDaQv4zgvwvag2n55/h5VjYcM5UJG7L4TwE5tZlzcI0X2Lhw==
|
integrity sha512-/d1UbyUkf9nvsgdBildLe6LAD4DalgkgZcKd0nZ8XUGPyA/7fsnaQIlKVnDiuUXv/IeZhPEDrRJubVSulxrShA==
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-pnp-resolver "^1.2.2"
|
jest-pnp-resolver "^1.2.2"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-validate "^28.1.0"
|
jest-validate "^28.1.1"
|
||||||
resolve "^1.20.0"
|
resolve "^1.20.0"
|
||||||
resolve.exports "^1.1.0"
|
resolve.exports "^1.1.0"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
|
||||||
jest-runner@^28.1.0:
|
jest-runner@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.0.tgz#aefe2a1e618a69baa0b24a50edc54fdd7e728eaa"
|
resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-28.1.1.tgz#9ecdb3f27a00059986797aa6b012ba8306aa436c"
|
||||||
integrity sha512-FBpmuh1HB2dsLklAlRdOxNTTHKFR6G1Qmd80pVDvwbZXTriqjWqjei5DKFC1UlM732KjYcE6yuCdiF0WUCOS2w==
|
integrity sha512-W5oFUiDBgTsCloTAj6q95wEvYDB0pxIhY6bc5F26OucnwBN+K58xGTGbliSMI4ChQal5eANDF+xvELaYkJxTmA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/console" "^28.1.0"
|
"@jest/console" "^28.1.1"
|
||||||
"@jest/environment" "^28.1.0"
|
"@jest/environment" "^28.1.1"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
emittery "^0.10.2"
|
emittery "^0.10.2"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-docblock "^28.0.2"
|
jest-docblock "^28.1.1"
|
||||||
jest-environment-node "^28.1.0"
|
jest-environment-node "^28.1.1"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-leak-detector "^28.1.0"
|
jest-leak-detector "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-resolve "^28.1.0"
|
jest-resolve "^28.1.1"
|
||||||
jest-runtime "^28.1.0"
|
jest-runtime "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
jest-watcher "^28.1.0"
|
jest-watcher "^28.1.1"
|
||||||
jest-worker "^28.1.0"
|
jest-worker "^28.1.1"
|
||||||
source-map-support "0.5.13"
|
source-map-support "0.5.13"
|
||||||
throat "^6.0.1"
|
throat "^6.0.1"
|
||||||
|
|
||||||
jest-runtime@^28.1.0:
|
jest-runtime@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.0.tgz#4847dcb2a4eb4b0f9eaf41306897e51fb1665631"
|
resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-28.1.1.tgz#569e1dc3c36c6c4c0b29516c1c49b6ad580abdaf"
|
||||||
integrity sha512-wNYDiwhdH/TV3agaIyVF0lsJ33MhyujOe+lNTUiolqKt8pchy1Hq4+tDMGbtD5P/oNLA3zYrpx73T9dMTOCAcg==
|
integrity sha512-J89qEJWW0leOsqyi0D9zHpFEYHwwafFdS9xgvhFHtIdRghbadodI0eA+DrthK/1PebBv3Px8mFSMGKrtaVnleg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/environment" "^28.1.0"
|
"@jest/environment" "^28.1.1"
|
||||||
"@jest/fake-timers" "^28.1.0"
|
"@jest/fake-timers" "^28.1.1"
|
||||||
"@jest/globals" "^28.1.0"
|
"@jest/globals" "^28.1.1"
|
||||||
"@jest/source-map" "^28.0.2"
|
"@jest/source-map" "^28.0.2"
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
cjs-module-lexer "^1.0.0"
|
cjs-module-lexer "^1.0.0"
|
||||||
collect-v8-coverage "^1.0.0"
|
collect-v8-coverage "^1.0.0"
|
||||||
execa "^5.0.0"
|
execa "^5.0.0"
|
||||||
glob "^7.1.3"
|
glob "^7.1.3"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-mock "^28.1.0"
|
jest-mock "^28.1.1"
|
||||||
jest-regex-util "^28.0.2"
|
jest-regex-util "^28.0.2"
|
||||||
jest-resolve "^28.1.0"
|
jest-resolve "^28.1.1"
|
||||||
jest-snapshot "^28.1.0"
|
jest-snapshot "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
strip-bom "^4.0.0"
|
strip-bom "^4.0.0"
|
||||||
|
|
||||||
jest-snapshot@^28.1.0:
|
jest-snapshot@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.0.tgz#4b74fa8816707dd10fe9d551c2c258e5a67b53b6"
|
resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-28.1.1.tgz#ab825c16c8d8b5e883bd57eee6ca8748c42ab848"
|
||||||
integrity sha512-ex49M2ZrZsUyQLpLGxQtDbahvgBjlLPgklkqGM0hq/F7W/f8DyqZxVHjdy19QKBm4O93eDp+H5S23EiTbbUmHw==
|
integrity sha512-1KjqHJ98adRcbIdMizjF5DipwZFbvxym/kFO4g4fVZCZRxH/dqV8TiBFCa6rqic3p0karsy8RWS1y4E07b7P0A==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/core" "^7.11.6"
|
"@babel/core" "^7.11.6"
|
||||||
"@babel/generator" "^7.7.2"
|
"@babel/generator" "^7.7.2"
|
||||||
"@babel/plugin-syntax-typescript" "^7.7.2"
|
"@babel/plugin-syntax-typescript" "^7.7.2"
|
||||||
"@babel/traverse" "^7.7.2"
|
"@babel/traverse" "^7.7.2"
|
||||||
"@babel/types" "^7.3.3"
|
"@babel/types" "^7.3.3"
|
||||||
"@jest/expect-utils" "^28.1.0"
|
"@jest/expect-utils" "^28.1.1"
|
||||||
"@jest/transform" "^28.1.0"
|
"@jest/transform" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/babel__traverse" "^7.0.6"
|
"@types/babel__traverse" "^7.0.6"
|
||||||
"@types/prettier" "^2.1.5"
|
"@types/prettier" "^2.1.5"
|
||||||
babel-preset-current-node-syntax "^1.0.0"
|
babel-preset-current-node-syntax "^1.0.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
expect "^28.1.0"
|
expect "^28.1.1"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
jest-diff "^28.1.0"
|
jest-diff "^28.1.1"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
jest-haste-map "^28.1.0"
|
jest-haste-map "^28.1.1"
|
||||||
jest-matcher-utils "^28.1.0"
|
jest-matcher-utils "^28.1.1"
|
||||||
jest-message-util "^28.1.0"
|
jest-message-util "^28.1.1"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
semver "^7.3.5"
|
semver "^7.3.5"
|
||||||
|
|
||||||
jest-util@^28.1.0:
|
jest-util@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.0.tgz#d54eb83ad77e1dd441408738c5a5043642823be5"
|
resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.1.tgz#ff39e436a1aca397c0ab998db5a51ae2b7080d05"
|
||||||
integrity sha512-qYdCKD77k4Hwkose2YBEqQk7PzUf/NSE+rutzceduFveQREeH6b+89Dc9+wjX9dAwHcgdx4yedGA3FQlU/qCTA==
|
integrity sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
ci-info "^3.2.0"
|
ci-info "^3.2.0"
|
||||||
graceful-fs "^4.2.9"
|
graceful-fs "^4.2.9"
|
||||||
picomatch "^2.2.3"
|
picomatch "^2.2.3"
|
||||||
|
|
||||||
jest-validate@^28.1.0:
|
jest-validate@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.0.tgz#8a6821f48432aba9f830c26e28226ad77b9a0e18"
|
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-28.1.1.tgz#59b7b339b3c85b5144bd0c06ad3600f503a4acc8"
|
||||||
integrity sha512-Lly7CJYih3vQBfjLeANGgBSBJ7pEa18cxpQfQEq2go2xyEzehnHfQTjoUia8xUv4x4J80XKFIDwJJThXtRFQXQ==
|
integrity sha512-Kpf6gcClqFCIZ4ti5++XemYJWUPCFUW+N2gknn+KgnDf549iLul3cBuKVe1YcWRlaF8tZV8eJCap0eECOEE3Ug==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
camelcase "^6.2.0"
|
camelcase "^6.2.0"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
jest-get-type "^28.0.2"
|
jest-get-type "^28.0.2"
|
||||||
leven "^3.1.0"
|
leven "^3.1.0"
|
||||||
pretty-format "^28.1.0"
|
pretty-format "^28.1.1"
|
||||||
|
|
||||||
jest-watcher@^28.1.0:
|
jest-watcher@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.0.tgz#aaa7b4164a4e77eeb5f7d7b25ede5e7b4e9c9aaf"
|
resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.1.tgz#533597fb3bfefd52b5cd115cd916cffd237fb60c"
|
||||||
integrity sha512-tNHMtfLE8Njcr2IRS+5rXYA4BhU90gAOwI9frTGOqd+jX0P/Au/JfRSNqsf5nUTcWdbVYuLxS1KjnzILSoR5hA==
|
integrity sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/test-result" "^28.1.0"
|
"@jest/test-result" "^28.1.1"
|
||||||
"@jest/types" "^28.1.0"
|
"@jest/types" "^28.1.1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
ansi-escapes "^4.2.1"
|
ansi-escapes "^4.2.1"
|
||||||
chalk "^4.0.0"
|
chalk "^4.0.0"
|
||||||
emittery "^0.10.2"
|
emittery "^0.10.2"
|
||||||
jest-util "^28.1.0"
|
jest-util "^28.1.1"
|
||||||
string-length "^4.0.1"
|
string-length "^4.0.1"
|
||||||
|
|
||||||
jest-worker@^26.5.0:
|
jest-worker@^26.5.0:
|
||||||
|
@ -7116,23 +7117,24 @@ jest-worker@^26.5.0:
|
||||||
merge-stream "^2.0.0"
|
merge-stream "^2.0.0"
|
||||||
supports-color "^7.0.0"
|
supports-color "^7.0.0"
|
||||||
|
|
||||||
jest-worker@^28.1.0:
|
jest-worker@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.0.tgz#ced54757a035e87591e1208253a6e3aac1a855e5"
|
resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.1.tgz#3480c73247171dfd01eda77200f0063ab6a3bf28"
|
||||||
integrity sha512-ZHwM6mNwaWBR52Snff8ZvsCTqQsvhCxP/bT1I6T6DAnb6ygkshsyLQIMxFwHpYxht0HOoqt23JlC01viI7T03A==
|
integrity sha512-Au7slXB08C6h+xbJPp7VIb6U0XX5Kc9uel/WFc6/rcTzGiaVCBRngBExSYuXSLFPULPSYU3cJ3ybS988lNFQhQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
merge-stream "^2.0.0"
|
merge-stream "^2.0.0"
|
||||||
supports-color "^8.0.0"
|
supports-color "^8.0.0"
|
||||||
|
|
||||||
jest@^28.1.0:
|
jest@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.0.tgz#f420e41c8f2395b9a30445a97189ebb57593d831"
|
resolved "https://registry.yarnpkg.com/jest/-/jest-28.1.1.tgz#3c39a3a09791e16e9ef283597d24ab19a0df701e"
|
||||||
integrity sha512-TZR+tHxopPhzw3c3560IJXZWLNHgpcz1Zh0w5A65vynLGNcg/5pZ+VildAd7+XGOu6jd58XMY/HNn0IkZIXVXg==
|
integrity sha512-qw9YHBnjt6TCbIDMPMpJZqf9E12rh6869iZaN08/vpOGgHJSAaLLUn6H8W3IAEuy34Ls3rct064mZLETkxJ2XA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/core" "^28.1.0"
|
"@jest/core" "^28.1.1"
|
||||||
|
"@jest/types" "^28.1.1"
|
||||||
import-local "^3.0.2"
|
import-local "^3.0.2"
|
||||||
jest-cli "^28.1.0"
|
jest-cli "^28.1.1"
|
||||||
|
|
||||||
jiti@^1.12.9, jiti@^1.9.2:
|
jiti@^1.12.9, jiti@^1.9.2:
|
||||||
version "1.13.0"
|
version "1.13.0"
|
||||||
|
@ -9802,10 +9804,10 @@ pretty-error@^2.1.1:
|
||||||
lodash "^4.17.20"
|
lodash "^4.17.20"
|
||||||
renderkid "^2.0.4"
|
renderkid "^2.0.4"
|
||||||
|
|
||||||
pretty-format@^28.1.0:
|
pretty-format@^28.1.1:
|
||||||
version "28.1.0"
|
version "28.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.0.tgz#8f5836c6a0dfdb834730577ec18029052191af55"
|
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.1.tgz#f731530394e0f7fcd95aba6b43c50e02d86b95cb"
|
||||||
integrity sha512-79Z4wWOYCdvQkEoEuSlBhHJqWeZ8D8YRPiPctJFCtvuaClGpiwiQYSCUOE6IEKUbbFukKOTFIUAXE8N4EQTo1Q==
|
integrity sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@jest/schemas" "^28.0.2"
|
"@jest/schemas" "^28.0.2"
|
||||||
ansi-regex "^5.0.1"
|
ansi-regex "^5.0.1"
|
||||||
|
@ -12397,16 +12399,16 @@ vuetify-loader@^1.7.3:
|
||||||
file-loader "^6.2.0"
|
file-loader "^6.2.0"
|
||||||
loader-utils "^2.0.0"
|
loader-utils "^2.0.0"
|
||||||
|
|
||||||
|
vuetify@2.6.6:
|
||||||
|
version "2.6.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.6.6.tgz#7af178fece5ccd561639eba425fe6c0a5803b37e"
|
||||||
|
integrity sha512-H4KtxDFmDN8QiTRiGfBySyjMhVaHAJTKB0llGGKZT5jKxtnx9gvEtMWXKtVuRP0NJJP0H6xBPJHNOH7nT18qiQ==
|
||||||
|
|
||||||
vuetify@^2.6:
|
vuetify@^2.6:
|
||||||
version "2.6.3"
|
version "2.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.6.3.tgz#b33ede2da958a40c6ced0ad1f4eda737984b3967"
|
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.6.3.tgz#b33ede2da958a40c6ced0ad1f4eda737984b3967"
|
||||||
integrity sha512-Zfiz2DZnp1DvxqGaSCGqGjv4mPNAurJJ5Xwy7bzNzIySGLlRdlO8UH6aNWnSgfaAsLP3voxadSGDm6tKM8Ys7w==
|
integrity sha512-Zfiz2DZnp1DvxqGaSCGqGjv4mPNAurJJ5Xwy7bzNzIySGLlRdlO8UH6aNWnSgfaAsLP3voxadSGDm6tKM8Ys7w==
|
||||||
|
|
||||||
"vuetify@npm:@vuetify/nightly@dev":
|
|
||||||
version "2.6.0-dev-20211110.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@vuetify/nightly/-/nightly-2.6.0-dev-20211110.0.tgz#161e078b674d8350ae316a574a304caecab53849"
|
|
||||||
integrity sha512-0CSbtDP68YZM9yenPsr8b3fe9d8YHxxJvPD0jzMDM/bm6ksVT+qKeb4Wwi9h8zPIphFG2vKICG21yLByg0+5Kg==
|
|
||||||
|
|
||||||
vuex@^3.6.2:
|
vuex@^3.6.2:
|
||||||
version "3.6.2"
|
version "3.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
|
resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.6.2.tgz#236bc086a870c3ae79946f107f16de59d5895e71"
|
||||||
|
@ -12431,7 +12433,7 @@ w3c-xmlserializer@^3.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
xml-name-validator "^4.0.0"
|
xml-name-validator "^4.0.0"
|
||||||
|
|
||||||
walker@^1.0.7:
|
walker@^1.0.8:
|
||||||
version "1.0.8"
|
version "1.0.8"
|
||||||
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
|
resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
|
||||||
integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
|
integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
|
||||||
|
|
Loading…
Reference in a new issue