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