From da0216a6065d63593f00ef3b34d6a818b7f75eb5 Mon Sep 17 00:00:00 2001 From: lesion Date: Sat, 18 Jun 2022 01:10:27 +0200 Subject: [PATCH] s/cohort/collection --- .../admin/{Cohorts.vue => Collections.vue} | 78 ++++++++--------- locales/en.json | 8 +- locales/it.json | 8 +- pages/collection/_collection.vue | 43 ++++++++++ pages/g/_cohort.vue | 31 ------- .../controller/{cohort.js => collection.js} | 84 ++++++++----------- .../api/models/{cohort.js => collection.js} | 8 +- .../migrations/20220617203517-collection.js | 30 +++++++ 8 files changed, 157 insertions(+), 133 deletions(-) rename components/admin/{Cohorts.vue => Collections.vue} (73%) create mode 100644 pages/collection/_collection.vue delete mode 100644 pages/g/_cohort.vue rename server/api/controller/{cohort.js => collection.js} (58%) rename server/api/models/{cohort.js => collection.js} (72%) create mode 100644 server/migrations/20220617203517-collection.js diff --git a/components/admin/Cohorts.vue b/components/admin/Collections.vue similarity index 73% rename from components/admin/Cohorts.vue rename to components/admin/Collections.vue index 81b8f7ec..ea577484 100644 --- a/components/admin/Cohorts.vue +++ b/components/admin/Collections.vue @@ -1,41 +1,41 @@ @@ -118,16 +118,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' } @@ -140,7 +140,7 @@ export default { } }, async fetch () { - this.cohorts = await this.$axios.$get('/cohorts?withFilters=true') + this.collections = await this.$axios.$get('/collections?withFilters=true') }, methods: { @@ -150,8 +150,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(' - ') }, @@ -159,28 +159,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.name = this.cohort.name.trim() - 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 }, @@ -195,12 +195,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' }) diff --git a/locales/en.json b/locales/en.json index 6381d8bb..29228af6 100644 --- a/locales/en.json +++ b/locales/en.json @@ -87,7 +87,7 @@ "import": "Import", "max_events": "N. max events", "label": "Label", - "blobs": "Blobs", + "collections": "Collections", "close": "Close" }, "login": { @@ -235,9 +235,9 @@ "admin_email": "Admin e-mail", "widget": "Widget", "wrong_domain_warning": "The baseurl configured in config.json ({baseurl}) differs from the one you're visiting ({url})", - "new_blob": "New blob", - "blobs_description": "Blobs are groupings of events by tags and places. They will be displayed on the home page", - "edit_blob": "Edit Blob" + "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…", diff --git a/locales/it.json b/locales/it.json index 2328c0ae..84b2caf2 100644 --- a/locales/it.json +++ b/locales/it.json @@ -87,7 +87,7 @@ "import": "Importa", "max_events": "N. massimo eventi", "label": "Etichetta", - "blobs": "Bolle" + "collections": "Bolle" }, "login": { "description": "Entrando puoi pubblicare nuovi eventi.", @@ -232,10 +232,10 @@ "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", - "new_blob": "Crea bolla", + "new_collection": "Crea bolla", "wrong_domain_warning": "Il \"baseurl\" configurato in config.json ({baseurl}) è diverso da quello che stai visitando ({url})", - "blobs_description": "Le bolle sono raggruppamenti di eventi per tag e posti.", - "edit_blob": "Modifica bolla" + "collections_description": "Le bolle sono raggruppamenti di eventi per tag e posti.", + "edit_collection": "Modifica bolla" }, "auth": { "not_confirmed": "Non ancora confermato…", diff --git a/pages/collection/_collection.vue b/pages/collection/_collection.vue new file mode 100644 index 00000000..eb410bc6 --- /dev/null +++ b/pages/collection/_collection.vue @@ -0,0 +1,43 @@ + + \ No newline at end of file diff --git a/pages/g/_cohort.vue b/pages/g/_cohort.vue deleted file mode 100644 index fadc7b68..00000000 --- a/pages/g/_cohort.vue +++ /dev/null @@ -1,31 +0,0 @@ - - \ No newline at end of file diff --git a/server/api/controller/cohort.js b/server/api/controller/collection.js similarity index 58% rename from server/api/controller/cohort.js rename to server/api/controller/collection.js index 34f8ea60..a186a13c 100644 --- a/server/api/controller/cohort.js +++ b/server/api/controller/collection.js @@ -1,38 +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 { 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 @@ -42,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] }) @@ -71,21 +67,7 @@ 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({ where, @@ -96,7 +78,7 @@ const cohortController = { 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: [] } }, @@ -120,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)) @@ -183,4 +165,4 @@ const cohortController = { -module.exports = cohortController \ No newline at end of file +module.exports = collectionController \ No newline at end of file diff --git a/server/api/models/cohort.js b/server/api/models/collection.js similarity index 72% rename from server/api/models/cohort.js rename to server/api/models/collection.js index 93f7ecb2..16a38b87 100644 --- a/server/api/models/cohort.js +++ b/server/api/models/collection.js @@ -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 diff --git a/server/migrations/20220617203517-collection.js b/server/migrations/20220617203517-collection.js new file mode 100644 index 00000000..5262e049 --- /dev/null +++ b/server/migrations/20220617203517-collection.js @@ -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'); + */ + } +};