From 9824b0ffeb89200ac371e29e893b12e1f5735670 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Fri, 1 Mar 2024 19:37:48 +0100 Subject: [PATCH 01/24] feat: First draft --- config/routes.php | 2 + frontend/src/components/MainMenu.vue | 14 ++++ frontend/src/main.js | 1 + frontend/src/router/index.js | 5 ++ frontend/src/store/index.js | 13 ++++ frontend/src/views/Quickwins.vue | 55 ++++++++++++++ package-lock.json | 8 +- src/Controller/Api/TagsController.php | 28 +++++++ src/Event/MessageEvent.php | 2 + src/Model/Entity/Tag.php | 28 +++++++ src/Model/Entity/TaggedMessage.php | 37 ++++++++++ src/Model/Table/MessagesTable.php | 2 +- src/Model/Table/TaggedMessagesTable.php | 98 +++++++++++++++++++++++++ src/Model/Table/TagsTable.php | 61 +++++++++++++++ tests/Fixture/TagedMessagesFixture.php | 23 ++++++ tests/Fixture/TagsFixture.php | 28 +++++++ 16 files changed, 400 insertions(+), 5 deletions(-) create mode 100644 frontend/src/views/Quickwins.vue create mode 100644 src/Controller/Api/TagsController.php create mode 100644 src/Model/Entity/Tag.php create mode 100644 src/Model/Entity/TaggedMessage.php create mode 100644 src/Model/Table/TaggedMessagesTable.php create mode 100644 src/Model/Table/TagsTable.php create mode 100644 tests/Fixture/TagedMessagesFixture.php create mode 100644 tests/Fixture/TagsFixture.php diff --git a/config/routes.php b/config/routes.php index 086db5e1..aefaed35 100644 --- a/config/routes.php +++ b/config/routes.php @@ -59,6 +59,7 @@ $builder->connect('/', ['controller' => 'Home', 'action' => 'index']); $builder->connect('/shop', ['controller' => 'Home', 'action' => 'index']); $builder->connect('/collection', ['controller' => 'Home', 'action' => 'index']); + $builder->connect('/quickwins', ['controller' => 'Home', 'action' => 'index']); $builder->connect('/profile', ['controller' => 'Home', 'action' => 'index']); $builder->connect('/settings', ['controller' => 'Home', 'action' => 'index']); @@ -77,6 +78,7 @@ $builder->post('/shop/purchase', ['prefix' => 'Api', 'controller' => 'Shop', 'action' => 'purchase']); $builder->get('/collection', ['prefix' => 'Api', 'controller' => 'Collection', 'action' => 'get']); + $builder->get('/taggedMessages', ['prefix' => 'Api', 'controller' => 'Tags', 'action' => 'get']); }); }); diff --git a/frontend/src/components/MainMenu.vue b/frontend/src/components/MainMenu.vue index 22166d76..add284a2 100644 --- a/frontend/src/components/MainMenu.vue +++ b/frontend/src/components/MainMenu.vue @@ -31,6 +31,13 @@ > Collection + + #QuickWins + @@ -104,6 +111,13 @@ > Collection + + Collection +
diff --git a/frontend/src/main.js b/frontend/src/main.js index 750fa147..4128ceaa 100644 --- a/frontend/src/main.js +++ b/frontend/src/main.js @@ -84,6 +84,7 @@ import './assets/main.css' store.dispatch('getUsers'), store.dispatch('getProducts'), store.dispatch('getCollection'), + store.dispatch('getTaggedMessages'), ]) app diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js index ce703880..f8f58670 100644 --- a/frontend/src/router/index.js +++ b/frontend/src/router/index.js @@ -19,6 +19,11 @@ const router = createRouter({ name: 'collection', component: () => import('@/views/Collection.vue') }, + { + path: '/quickwins', + name: 'quickwins', + component: () => import('@/views/Quickwins.vue') + }, { path: '/profile', name: 'profile', diff --git a/frontend/src/store/index.js b/frontend/src/store/index.js index 71d06fae..3693163b 100644 --- a/frontend/src/store/index.js +++ b/frontend/src/store/index.js @@ -10,6 +10,7 @@ const store = createStore({ users: [], products: [], collection: [], + taggedMessages: [], filter: { range: helper.getRangeFilter(), order: helper.getOrderFilter(), @@ -22,6 +23,7 @@ const store = createStore({ users: state => state.users, products: state => state.products, collection: state => state.collection, + taggedMessages: state => state.taggedMessages, filter: state => state.filter, range: state => state.filter.range, order: state => state.filter.order, @@ -71,6 +73,14 @@ const store = createStore({ console.log(error) } }, + async getTaggedMessages({ commit }) { + try { + const response = await api.get('taggedMessages') + commit('SET_TAGGEDMESSAGES', response.data) + } catch (error) { + console.log(error) + } + }, async toggleSentNotifications({ commit, getters }) { commit('TOGGLE_SENT_NOTIFICATIONS') try { @@ -110,6 +120,9 @@ const store = createStore({ SET_COLLECTION(state, collection) { state.collection = collection }, + SET_TAGGEDMESSAGES(state, taggedMessages) { + state.taggedMessages = taggedMessages + }, TOGGLE_SENT_NOTIFICATIONS(state) { state.user.notifications.sent = !state.user.notifications.sent }, diff --git a/frontend/src/views/Quickwins.vue b/frontend/src/views/Quickwins.vue new file mode 100644 index 00000000..5bd2e4c4 --- /dev/null +++ b/frontend/src/views/Quickwins.vue @@ -0,0 +1,55 @@ + + + diff --git a/package-lock.json b/package-lock.json index c2d9bf1f..48768c6a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,10 +6,10 @@ "": { "name": "gib-potato", "dependencies": { - "@sentry/vite-plugin": "^2.14.0", - "@sentry/vue": "^7.100.1", + "@sentry/vite-plugin": "^2.14.1", + "@sentry/vue": "^7.102.0", "axios": "^1.6.7", - "vue": "^3.4.18", + "vue": "^3.4.19", "vue-router": "^4.2.5", "vue-select": "^4.0.0-beta.6", "vuex": "^4.1.0" @@ -24,7 +24,7 @@ "postcss": "^8.4.35", "prettier": "^3.2.5", "tailwindcss": "^3.4.1", - "vite": "^5.1.1" + "vite": "^5.1.3" } }, "node_modules/@aashutoshrathi/word-wrap": { diff --git a/src/Controller/Api/TagsController.php b/src/Controller/Api/TagsController.php new file mode 100644 index 00000000..423e452e --- /dev/null +++ b/src/Controller/Api/TagsController.php @@ -0,0 +1,28 @@ +fetchTable('TaggedMessages'); + $collection = $taggedMessagesTable->find() + ->orderBy(['created' => 'DESC']) + ->all(); + + return $this->response + ->withStatus(200) + ->withType('json') + ->withStringBody(json_encode($collection)); + } +} diff --git a/src/Event/MessageEvent.php b/src/Event/MessageEvent.php index 142c1be1..99571c25 100644 --- a/src/Event/MessageEvent.php +++ b/src/Event/MessageEvent.php @@ -37,6 +37,7 @@ public function __construct(array $event) $this->receivers = $event['receivers']; $this->channel = $event['channel']; $this->text = $event['text']; + // TODO: create reaction service $this->reaction = $event['reaction']; $this->timestamp = $event['timestamp']; $this->eventTimestamp = $event['event_timestamp']; @@ -87,6 +88,7 @@ public function process(): void toUsers: $toUsers, event: $this, ); + // TODO: create tag service $notificationService->notifyUsers( fromUser: $fromUser, toUsers: $toUsers, diff --git a/src/Model/Entity/Tag.php b/src/Model/Entity/Tag.php new file mode 100644 index 00000000..1ca6a416 --- /dev/null +++ b/src/Model/Entity/Tag.php @@ -0,0 +1,28 @@ + + */ + protected array $_accessible = [ + 'name' => true, + ]; +} diff --git a/src/Model/Entity/TaggedMessage.php b/src/Model/Entity/TaggedMessage.php new file mode 100644 index 00000000..37ac4bd3 --- /dev/null +++ b/src/Model/Entity/TaggedMessage.php @@ -0,0 +1,37 @@ + + */ + protected array $_accessible = [ + 'tag_id' => true, + 'message_id' => true, + 'created' => true, + 'message' => true, + 'tag' => true, + ]; +} diff --git a/src/Model/Table/MessagesTable.php b/src/Model/Table/MessagesTable.php index 6cd207d4..cd2151dd 100644 --- a/src/Model/Table/MessagesTable.php +++ b/src/Model/Table/MessagesTable.php @@ -42,7 +42,7 @@ public function initialize(array $config): void $this->setTable('messages'); $this->setDisplayField('id'); $this->setPrimaryKey('id'); - + $this->addBehavior('Timestamp'); $this->belongsTo('Users', [ diff --git a/src/Model/Table/TaggedMessagesTable.php b/src/Model/Table/TaggedMessagesTable.php new file mode 100644 index 00000000..93fb3d14 --- /dev/null +++ b/src/Model/Table/TaggedMessagesTable.php @@ -0,0 +1,98 @@ + newEntities(array $data, array $options = []) + * @method \App\Model\Entity\TaggedMessage get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args) + * @method \App\Model\Entity\TaggedMessage findOrCreate($search, ?callable $callback = null, array $options = []) + * @method \App\Model\Entity\TaggedMessage patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) + * @method array<\App\Model\Entity\TaggedMessage> patchEntities(iterable $entities, array $data, array $options = []) + * @method \App\Model\Entity\TaggedMessage|false save(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method \App\Model\Entity\TaggedMessage saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage>|false saveMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage> saveManyOrFail(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage>|false deleteMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage> deleteManyOrFail(iterable $entities, array $options = []) + * + * @mixin \Cake\ORM\Behavior\TimestampBehavior + */ +class TaggedMessagesTable extends Table +{ + /** + * Initialize method + * + * @param array $config The configuration for the Table. + * @return void + */ + public function initialize(array $config): void + { + parent::initialize($config); + + $this->setTable('tagged_messages'); + $this->setDisplayField('id'); + $this->setPrimaryKey('id'); + + $this->addBehavior('Timestamp'); + + $this->belongsTo('Tags', [ + 'foreignKey' => 'tag_id', + 'joinType' => 'INNER', + ]); + $this->belongsTo('Messages', [ + 'foreignKey' => 'message_id', + 'joinType' => 'INNER', + ]); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator): Validator + { + $validator + ->uuid('tag_id') + ->notEmptyString('tag_id'); + + $validator + ->uuid('message_id') + ->notEmptyString('message_id'); + + $validator + ->scalar('message') + ->allowEmptyString('message'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules): RulesChecker + { + $rules->add($rules->existsIn(['tag_id'], 'Tags'), ['errorField' => 'tag_id']); + $rules->add($rules->existsIn(['message_id'], 'Messages'), ['errorField' => 'message_id']); + + return $rules; + } +} diff --git a/src/Model/Table/TagsTable.php b/src/Model/Table/TagsTable.php new file mode 100644 index 00000000..440234e9 --- /dev/null +++ b/src/Model/Table/TagsTable.php @@ -0,0 +1,61 @@ + newEntities(array $data, array $options = []) + * @method \App\Model\Entity\Tag get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args) + * @method \App\Model\Entity\Tag findOrCreate($search, ?callable $callback = null, array $options = []) + * @method \App\Model\Entity\Tag patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) + * @method array<\App\Model\Entity\Tag> patchEntities(iterable $entities, array $data, array $options = []) + * @method \App\Model\Entity\Tag|false save(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method \App\Model\Entity\Tag saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag>|false saveMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag> saveManyOrFail(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag>|false deleteMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag> deleteManyOrFail(iterable $entities, array $options = []) + */ +class TagsTable extends Table +{ + /** + * Initialize method + * + * @param array $config The configuration for the Table. + * @return void + */ + public function initialize(array $config): void + { + parent::initialize($config); + + $this->setTable('tags'); + $this->setDisplayField('name'); + $this->setPrimaryKey('id'); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator): Validator + { + $validator + ->scalar('name') + ->maxLength('name', 255) + ->requirePresence('name', 'create') + ->notEmptyString('name'); + + return $validator; + } +} diff --git a/tests/Fixture/TagedMessagesFixture.php b/tests/Fixture/TagedMessagesFixture.php new file mode 100644 index 00000000..b432c603 --- /dev/null +++ b/tests/Fixture/TagedMessagesFixture.php @@ -0,0 +1,23 @@ +records = []; + parent::init(); + } +} diff --git a/tests/Fixture/TagsFixture.php b/tests/Fixture/TagsFixture.php new file mode 100644 index 00000000..9b02b7c1 --- /dev/null +++ b/tests/Fixture/TagsFixture.php @@ -0,0 +1,28 @@ +records = [ + [ + 'id' => '92d4083d-718f-4dd5-907e-5503bc1cac1b', + 'name' => '#quickwin', + ], + ]; + parent::init(); + } +} From 89d6e21f77729e77a75513b7c09d5f5024ad8fc1 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 08:15:50 +0100 Subject: [PATCH 02/24] Store tagged messages --- frontend/src/views/Quickwins.vue | 3 - src/Event/MessageEvent.php | 8 ++- src/Model/Entity/Tag.php | 28 -------- src/Model/Entity/TaggedMessage.php | 10 ++- src/Model/Table/TaggedMessagesTable.php | 27 +++----- src/Model/Table/TagsTable.php | 61 ----------------- src/Service/AwardService.php | 6 +- src/Service/TaggedMessageService.php | 51 ++++++++++++++ tests/Fixture/TaggedMessagesFixture.php | 30 +++++++++ tests/TestCase/Model/Table/.gitkeep | 0 .../Model/Table/TaggedMessagesTableTest.php | 66 +++++++++++++++++++ 11 files changed, 169 insertions(+), 121 deletions(-) delete mode 100644 src/Model/Entity/Tag.php delete mode 100644 src/Model/Table/TagsTable.php create mode 100644 src/Service/TaggedMessageService.php create mode 100644 tests/Fixture/TaggedMessagesFixture.php delete mode 100644 tests/TestCase/Model/Table/.gitkeep create mode 100644 tests/TestCase/Model/Table/TaggedMessagesTableTest.php diff --git a/frontend/src/views/Quickwins.vue b/frontend/src/views/Quickwins.vue index 5bd2e4c4..940c2931 100644 --- a/frontend/src/views/Quickwins.vue +++ b/frontend/src/views/Quickwins.vue @@ -19,9 +19,7 @@

- Posted {{ new Date(item.created).toLocaleDateString('en-us', { year:"numeric", month:"short", day:"numeric"}) }} -

@@ -46,7 +44,6 @@ export default { const store = useStore() return { - user: computed(() => store.getters.user), taggedMessages: computed(() => store.getters.taggedMessages), } }, diff --git a/src/Event/MessageEvent.php b/src/Event/MessageEvent.php index 99571c25..66041c4e 100644 --- a/src/Event/MessageEvent.php +++ b/src/Event/MessageEvent.php @@ -8,6 +8,7 @@ use App\Service\AwardService; use App\Service\NotificationService; use App\Service\UserService; +use App\Service\TaggedMessageService; class MessageEvent extends AbstractEvent { @@ -37,7 +38,6 @@ public function __construct(array $event) $this->receivers = $event['receivers']; $this->channel = $event['channel']; $this->text = $event['text']; - // TODO: create reaction service $this->reaction = $event['reaction']; $this->timestamp = $event['timestamp']; $this->eventTimestamp = $event['event_timestamp']; @@ -54,6 +54,7 @@ public function process(): void $userService = new UserService(); $awardService = new AwardService(); $notificationService = new NotificationService(); + $taggedMessagesService = new TaggedMessageService(); $fromUser = $userService->getOrCreateUser($this->sender); $validator = new Validation( @@ -88,7 +89,10 @@ public function process(): void toUsers: $toUsers, event: $this, ); - // TODO: create tag service + $taggedMessagesService->storeMessageIfTagged( + fromUser: $fromUser, + event: $this, + ); $notificationService->notifyUsers( fromUser: $fromUser, toUsers: $toUsers, diff --git a/src/Model/Entity/Tag.php b/src/Model/Entity/Tag.php deleted file mode 100644 index 1ca6a416..00000000 --- a/src/Model/Entity/Tag.php +++ /dev/null @@ -1,28 +0,0 @@ - - */ - protected array $_accessible = [ - 'name' => true, - ]; -} diff --git a/src/Model/Entity/TaggedMessage.php b/src/Model/Entity/TaggedMessage.php index 37ac4bd3..ef5648ba 100644 --- a/src/Model/Entity/TaggedMessage.php +++ b/src/Model/Entity/TaggedMessage.php @@ -9,12 +9,10 @@ * TaggedMessage Entity * * @property string $id - * @property string $tag_id - * @property string $message_id * @property \Cake\I18n\DateTime $created + * @property string|null $sender_user_id * * @property \App\Model\Entity\Message $message - * @property \App\Model\Entity\Tag $tag */ class TaggedMessage extends Entity { @@ -28,10 +26,10 @@ class TaggedMessage extends Entity * @var array */ protected array $_accessible = [ - 'tag_id' => true, - 'message_id' => true, 'created' => true, 'message' => true, - 'tag' => true, + 'sender_user_id' => true, ]; + + public const TAG = '#quickwin'; } diff --git a/src/Model/Table/TaggedMessagesTable.php b/src/Model/Table/TaggedMessagesTable.php index 93fb3d14..517e3410 100644 --- a/src/Model/Table/TaggedMessagesTable.php +++ b/src/Model/Table/TaggedMessagesTable.php @@ -11,9 +11,6 @@ /** * TaggedMessages Model * - * @property \App\Model\Table\TagsTable&\Cake\ORM\Association\BelongsTo $Tags - * @property \App\Model\Table\MessagesTable&\Cake\ORM\Association\BelongsTo $Messages - * * @method \App\Model\Entity\TaggedMessage newEmptyEntity() * @method \App\Model\Entity\TaggedMessage newEntity(array $data, array $options = []) * @method array<\App\Model\Entity\TaggedMessage> newEntities(array $data, array $options = []) @@ -48,12 +45,9 @@ public function initialize(array $config): void $this->addBehavior('Timestamp'); - $this->belongsTo('Tags', [ - 'foreignKey' => 'tag_id', - 'joinType' => 'INNER', - ]); - $this->belongsTo('Messages', [ - 'foreignKey' => 'message_id', + $this->belongsTo('Users', [ + 'className' => 'Users', + 'foreignKey' => 'sender_user_id', 'joinType' => 'INNER', ]); } @@ -66,18 +60,14 @@ public function initialize(array $config): void */ public function validationDefault(Validator $validator): Validator { - $validator - ->uuid('tag_id') - ->notEmptyString('tag_id'); - - $validator - ->uuid('message_id') - ->notEmptyString('message_id'); - $validator ->scalar('message') ->allowEmptyString('message'); + $validator + ->uuid('sender_user_id') + ->notEmptyString('sender_user_id'); + return $validator; } @@ -90,8 +80,7 @@ public function validationDefault(Validator $validator): Validator */ public function buildRules(RulesChecker $rules): RulesChecker { - $rules->add($rules->existsIn(['tag_id'], 'Tags'), ['errorField' => 'tag_id']); - $rules->add($rules->existsIn(['message_id'], 'Messages'), ['errorField' => 'message_id']); + $rules->add($rules->existsIn(['sender_user_id'], 'Users'), ['errorField' => 'sender_user_id']); return $rules; } diff --git a/src/Model/Table/TagsTable.php b/src/Model/Table/TagsTable.php deleted file mode 100644 index 440234e9..00000000 --- a/src/Model/Table/TagsTable.php +++ /dev/null @@ -1,61 +0,0 @@ - newEntities(array $data, array $options = []) - * @method \App\Model\Entity\Tag get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args) - * @method \App\Model\Entity\Tag findOrCreate($search, ?callable $callback = null, array $options = []) - * @method \App\Model\Entity\Tag patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) - * @method array<\App\Model\Entity\Tag> patchEntities(iterable $entities, array $data, array $options = []) - * @method \App\Model\Entity\Tag|false save(\Cake\Datasource\EntityInterface $entity, array $options = []) - * @method \App\Model\Entity\Tag saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = []) - * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag>|false saveMany(iterable $entities, array $options = []) - * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag> saveManyOrFail(iterable $entities, array $options = []) - * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag>|false deleteMany(iterable $entities, array $options = []) - * @method iterable<\App\Model\Entity\Tag>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\Tag> deleteManyOrFail(iterable $entities, array $options = []) - */ -class TagsTable extends Table -{ - /** - * Initialize method - * - * @param array $config The configuration for the Table. - * @return void - */ - public function initialize(array $config): void - { - parent::initialize($config); - - $this->setTable('tags'); - $this->setDisplayField('name'); - $this->setPrimaryKey('id'); - } - - /** - * Default validation rules. - * - * @param \Cake\Validation\Validator $validator Validator instance. - * @return \Cake\Validation\Validator - */ - public function validationDefault(Validator $validator): Validator - { - $validator - ->scalar('name') - ->maxLength('name', 255) - ->requirePresence('name', 'create') - ->notEmptyString('name'); - - return $validator; - } -} diff --git a/src/Service/AwardService.php b/src/Service/AwardService.php index bffed8fc..15cb48df 100644 --- a/src/Service/AwardService.php +++ b/src/Service/AwardService.php @@ -38,7 +38,7 @@ public function gib( * @param \App\Model\Entity\User $fromUser User who did gib the potato. * @param \App\Model\Entity\User $toUser User who will receive the potato. * @param \App\Event\MessageEvent|\App\Event\ReactionAddedEvent $event The event. - * @return void + * @return string created message id */ private function gibToUser( User $fromUser, @@ -61,11 +61,13 @@ private function gibToUser( ], ]); $messagesTable->saveOrFail($message); - + metrics()->increment( key: 'gibpotato.potatoes.given_out', value: $event->amount, unit: MetricsUnit::custom('potato'), ); + + return $message->id; } } diff --git a/src/Service/TaggedMessageService.php b/src/Service/TaggedMessageService.php new file mode 100644 index 00000000..7240ce2f --- /dev/null +++ b/src/Service/TaggedMessageService.php @@ -0,0 +1,51 @@ + $toUsers Users who will receive the potato. + * @param \App\Event\MessageEvent|\App\Event\ReactionAddedEvent $event The event. + * @return void + */ + public function storeMessageIfTagged( + User $fromUser, + MessageEvent|ReactionAddedEvent $event, + ): void { + if (!str_contains($event->text, TaggedMessage::TAG)) { + return; + } + + $taggedMessagesTable = $this->fetchTable('TaggedMessages'); + + $message = $taggedMessagesTable->newEntity([ + 'sender_user_id' => $fromUser->id, + 'message' => $event->text, + ], [ + 'accessibleFields' => [ + 'sender_user_id' => true, + 'message' => true, + ], + ]); + $taggedMessagesTable->saveOrFail($message); + + metrics()->increment( + key: 'gibpotato.message.tagged', + value: 1, + unit: MetricsUnit::custom('tags'), + ); + } +} diff --git a/tests/Fixture/TaggedMessagesFixture.php b/tests/Fixture/TaggedMessagesFixture.php new file mode 100644 index 00000000..763e55f5 --- /dev/null +++ b/tests/Fixture/TaggedMessagesFixture.php @@ -0,0 +1,30 @@ +records = [ + [ + 'id' => 'c19d0b39-840e-47db-aaaa-f5e132b8a35c', + 'created' => 1709324293, + 'message' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', + 'sender_user_id' => '4a1ecef4-effc-4784-bf76-5feb9a2b741a', + ], + ]; + parent::init(); + } +} diff --git a/tests/TestCase/Model/Table/.gitkeep b/tests/TestCase/Model/Table/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/TestCase/Model/Table/TaggedMessagesTableTest.php b/tests/TestCase/Model/Table/TaggedMessagesTableTest.php new file mode 100644 index 00000000..b53a45b9 --- /dev/null +++ b/tests/TestCase/Model/Table/TaggedMessagesTableTest.php @@ -0,0 +1,66 @@ + + */ + protected array $fixtures = [ + 'app.TaggedMessages', + 'app.Tags', + 'app.Messages', + ]; + + /** + * setUp method + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + $config = $this->getTableLocator()->exists('TaggedMessages') ? [] : ['className' => TaggedMessagesTable::class]; + $this->TaggedMessages = $this->getTableLocator()->get('TaggedMessages', $config); + } + + /** + * tearDown method + * + * @return void + */ + protected function tearDown(): void + { + unset($this->TaggedMessages); + + parent::tearDown(); + } + + /** + * Test validationDefault method + * + * @return void + * @uses \App\Model\Table\TaggedMessagesTable::validationDefault() + */ + public function testValidationDefault(): void + { + $this->markTestIncomplete('Not implemented yet.'); + } +} From 0be61b32689030915d23cc092671f1992c83fb4c Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 08:17:43 +0100 Subject: [PATCH 03/24] revert gitkeep --- tests/TestCase/Table/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/TestCase/Table/.gitkeep diff --git a/tests/TestCase/Table/.gitkeep b/tests/TestCase/Table/.gitkeep new file mode 100644 index 00000000..e69de29b From 7f8fe25d4674671ae4c353a915f5ae1d4dc50340 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 17:26:13 +0100 Subject: [PATCH 04/24] Models --- src/Model/Entity/TaggedMessage.php | 6 +++++- src/Model/Table/TaggedMessagesTable.php | 6 ++++++ tests/Fixture/TaggedMessagesFixture.php | 7 ++++--- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Model/Entity/TaggedMessage.php b/src/Model/Entity/TaggedMessage.php index ef5648ba..e305a280 100644 --- a/src/Model/Entity/TaggedMessage.php +++ b/src/Model/Entity/TaggedMessage.php @@ -10,9 +10,11 @@ * * @property string $id * @property \Cake\I18n\DateTime $created + * @property string|null $message * @property string|null $sender_user_id + * @property string $permalink * - * @property \App\Model\Entity\Message $message + * @property \App\Model\Entity\User $user */ class TaggedMessage extends Entity { @@ -29,6 +31,8 @@ class TaggedMessage extends Entity 'created' => true, 'message' => true, 'sender_user_id' => true, + 'permalink' => true, + 'user' => true, ]; public const TAG = '#quickwin'; diff --git a/src/Model/Table/TaggedMessagesTable.php b/src/Model/Table/TaggedMessagesTable.php index 517e3410..04422283 100644 --- a/src/Model/Table/TaggedMessagesTable.php +++ b/src/Model/Table/TaggedMessagesTable.php @@ -68,6 +68,12 @@ public function validationDefault(Validator $validator): Validator ->uuid('sender_user_id') ->notEmptyString('sender_user_id'); + $validator + ->scalar('permalink') + ->maxLength('permalink', 255) + ->requirePresence('permalink', 'create') + ->notEmptyString('permalink'); + return $validator; } diff --git a/tests/Fixture/TaggedMessagesFixture.php b/tests/Fixture/TaggedMessagesFixture.php index 763e55f5..eb7cfb9a 100644 --- a/tests/Fixture/TaggedMessagesFixture.php +++ b/tests/Fixture/TaggedMessagesFixture.php @@ -19,10 +19,11 @@ public function init(): void { $this->records = [ [ - 'id' => 'c19d0b39-840e-47db-aaaa-f5e132b8a35c', - 'created' => 1709324293, + 'id' => 'a428fd32-6965-4fc8-8495-42da264c86d8', + 'created' => 1709364434, 'message' => 'Lorem ipsum dolor sit amet, aliquet feugiat. Convallis morbi fringilla gravida, phasellus feugiat dapibus velit nunc, pulvinar eget sollicitudin venenatis cum nullam, vivamus ut a sed, mollitia lectus. Nulla vestibulum massa neque ut et, id hendrerit sit, feugiat in taciti enim proin nibh, tempor dignissim, rhoncus duis vestibulum nunc mattis convallis.', - 'sender_user_id' => '4a1ecef4-effc-4784-bf76-5feb9a2b741a', + 'sender_user_id' => '9c7fb3a8-8d6f-4e50-b927-9944a39e0841', + 'permalink' => 'Lorem ipsum dolor sit amet', ], ]; parent::init(); From 8116f0a58034d971c098639c9ce52e76b446e0b4 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 17:32:52 +0100 Subject: [PATCH 05/24] Add migration --- .../20240302162526_TaggedMessages.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 config/Migrations/20240302162526_TaggedMessages.php diff --git a/config/Migrations/20240302162526_TaggedMessages.php b/config/Migrations/20240302162526_TaggedMessages.php new file mode 100644 index 00000000..8e13148e --- /dev/null +++ b/config/Migrations/20240302162526_TaggedMessages.php @@ -0,0 +1,90 @@ +table('tagged_messages', ['id' => false, 'primary_key' => ['id']]) + ->addColumn('id', 'uuid', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->addColumn('message', 'string', [ + 'default' => null, + 'limit' => 4096, + 'null' => false, + ]) + ->addColumn('permalink', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addColumn('sender_user_id', 'uuid', [ + 'default' => null, + 'limit' => null, + 'null' => false, + ]) + ->addColumn('created', 'datetime', [ + 'default' => null, + 'limit' => null, + 'null' => true, + ]) + ->addIndex( + [ + 'sender_user_id', + ] + ) + ->addIndex( + [ + 'receiver_user_id', + ] + ) + ->addIndex( + [ + 'permalink', + ] + ) + ->create(); + + $this->table('messages') + ->addColumn('permalink', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]) + ->addIndex( + [ + 'permalink', + ] + ) + ->update(); + } + + /** + * Down Method. + * + * More information on this method is available here: + * https://book.cakephp.org/phinx/0/en/migrations.html#the-down-method + * @return void + */ + public function down(): void + { + $this->table('tagged_messages')->drop()->save(); + + $this->table('messages') + ->removeIndexByName('permalink') + ->removeColumn('permalink') + ->update(); + } +} From b9918298b94d760855784d1aa228fe72dd4ec37f Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 19:27:32 +0100 Subject: [PATCH 06/24] Posting message to channel --- src/Event/MessageEvent.php | 9 ++++++- src/Model/Entity/Message.php | 3 ++- src/Service/AwardService.php | 4 +-- src/Service/NotificationService.php | 39 ++++++++++++++++++++++++++++ src/Service/TaggedMessageService.php | 20 ++++++++------ 5 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/Event/MessageEvent.php b/src/Event/MessageEvent.php index 66041c4e..c1c48d7b 100644 --- a/src/Event/MessageEvent.php +++ b/src/Event/MessageEvent.php @@ -89,10 +89,17 @@ public function process(): void toUsers: $toUsers, event: $this, ); - $taggedMessagesService->storeMessageIfTagged( + $quickwinId = $taggedMessagesService->storeMessageIfTagged( fromUser: $fromUser, event: $this, ); + if ($quickwinId !== false) { + $notificationService->notifyChannelNewQuickwin( + fromUser: $fromUser, + taggedMessageId: $quickwinId, + event: $this + ); + } $notificationService->notifyUsers( fromUser: $fromUser, toUsers: $toUsers, diff --git a/src/Model/Entity/Message.php b/src/Model/Entity/Message.php index ca20c7b6..20966304 100644 --- a/src/Model/Entity/Message.php +++ b/src/Model/Entity/Message.php @@ -13,6 +13,7 @@ * @property string $receiver_user_id * @property int $amount * @property string $type + * @property string $permalink * @property \Cake\I18n\DateTime|null $created * * @property \App\Model\Entity\User $user @@ -33,5 +34,5 @@ class Message extends Entity ]; public const TYPE_POTATO = 'potato'; - public const MAX_AMOUNT = 5; + public const MAX_AMOUNT = 50; } diff --git a/src/Service/AwardService.php b/src/Service/AwardService.php index 15cb48df..c8f0c813 100644 --- a/src/Service/AwardService.php +++ b/src/Service/AwardService.php @@ -52,12 +52,14 @@ private function gibToUser( 'receiver_user_id' => $toUser->id, 'amount' => $event->amount, 'type' => str_replace(':', '', $event->reaction), + 'permalink' => $event->permalink, ], [ 'accessibleFields' => [ 'sender_user_id' => true, 'receiver_user_id' => true, 'amount' => true, 'type' => true, + 'permalink' => true, ], ]); $messagesTable->saveOrFail($message); @@ -67,7 +69,5 @@ private function gibToUser( value: $event->amount, unit: MetricsUnit::custom('potato'), ); - - return $message->id; } } diff --git a/src/Service/NotificationService.php b/src/Service/NotificationService.php index 20f6d9b0..1a44f6b6 100644 --- a/src/Service/NotificationService.php +++ b/src/Service/NotificationService.php @@ -8,6 +8,7 @@ use App\Http\SlackClient; use App\Model\Entity\User; use Cake\ORM\Locator\LocatorAwareTrait; +use Cake\Routing\Router; class NotificationService { @@ -80,4 +81,42 @@ public function notifyUsers( ); } } + + /** + * @param \App\Model\Entity\User $fromUser User who did gib the potato + * @param string $taggedMessageId id of the tagged message + * @param \App\Event\MessageEvent $event The event. + * @return void + */ + public function notifyChannelNewQuickwin( + User $fromUser, + string $taggedMessageId, + MessageEvent $event, + ): void { + $blocks = [ + [ + 'type' => 'section', + 'text' => [ + 'type' => 'mrkdwn', + 'text' => "<@{$fromUser->slack_user_id}> posted a new <" . $event->permalink . "|#quickwin>!", + ], + ], + [ + 'type' => 'divider', + ], + [ + 'type' => 'section', + 'text' => [ + 'type' => 'mrkdwn', + 'text' => '<' . Router::url('/quickwins', true) . '?id=' . $taggedMessageId . '|Visit Hall of Fame>', + ], + ], + + ]; + + $this->slackClient->postBlocks( + channel: env('POTATO_CHANNEL'), + blocks: json_encode($blocks), + ); + } } diff --git a/src/Service/TaggedMessageService.php b/src/Service/TaggedMessageService.php index 7240ce2f..fa8e37c9 100644 --- a/src/Service/TaggedMessageService.php +++ b/src/Service/TaggedMessageService.php @@ -4,7 +4,7 @@ namespace App\Service; use App\Event\MessageEvent; -use App\Event\ReactionAddedEvent; +use App\Service\NotificationService; use App\Model\Entity\User; use App\Model\Entity\TaggedMessage; use Cake\ORM\Locator\LocatorAwareTrait; @@ -18,34 +18,38 @@ class TaggedMessageService /** * @param \App\Model\Entity\User $fromUser User who did gib the potato. * @param array<\App\Model\Entity\User> $toUsers Users who will receive the potato. - * @param \App\Event\MessageEvent|\App\Event\ReactionAddedEvent $event The event. - * @return void + * @param \App\Event\MessageEvent $event The event. + * @return bool|string false if not tagged, tagged_message_id if tagged */ public function storeMessageIfTagged( User $fromUser, - MessageEvent|ReactionAddedEvent $event, - ): void { + MessageEvent $event, + ): bool|string { if (!str_contains($event->text, TaggedMessage::TAG)) { - return; + return false; } $taggedMessagesTable = $this->fetchTable('TaggedMessages'); - $message = $taggedMessagesTable->newEntity([ + $taggedMessage = $taggedMessagesTable->newEntity([ 'sender_user_id' => $fromUser->id, 'message' => $event->text, + 'permalink' => $event->permalink, ], [ 'accessibleFields' => [ 'sender_user_id' => true, 'message' => true, + 'permalink' => true, ], ]); - $taggedMessagesTable->saveOrFail($message); + $taggedMessagesTable->saveOrFail($taggedMessage); metrics()->increment( key: 'gibpotato.message.tagged', value: 1, unit: MetricsUnit::custom('tags'), ); + + return $taggedMessage->id; } } From 812b8018f6713f9bf104c36a7fcbd16efb78184c Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 20:55:13 +0100 Subject: [PATCH 07/24] Refactor TagsController to include reaction count for tagged messages --- src/Controller/Api/TagsController.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Controller/Api/TagsController.php b/src/Controller/Api/TagsController.php index 423e452e..37a2ba97 100644 --- a/src/Controller/Api/TagsController.php +++ b/src/Controller/Api/TagsController.php @@ -16,10 +16,22 @@ class TagsController extends ApiController public function get(): Response { $taggedMessagesTable = $this->fetchTable('TaggedMessages'); - $collection = $taggedMessagesTable->find() - ->orderBy(['created' => 'DESC']) + $messages = $this->fetchTable('Messages'); + + $collection = $taggedMessagesTable->find(); + $collection->contain(['Users']); + + $collection->orderBy(['TaggedMessages.created' => 'DESC']) + ->enableAutoFields(true) ->all(); + foreach ($collection as $taggedMessage) { + $reactionCount = $messages->find() + ->where(['permalink' => $taggedMessage->permalink]) + ->count(); + $taggedMessage->reaction_count = $reactionCount; + } + return $this->response ->withStatus(200) ->withType('json') From 5df650f077417b406984694aef4d529a1aa7ac24 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 21:12:16 +0100 Subject: [PATCH 08/24] Add user avatars to Quickwins.vue and replace user IDs with user names in TagsController.php --- frontend/src/views/Quickwins.vue | 3 +++ src/Controller/Api/TagsController.php | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/frontend/src/views/Quickwins.vue b/frontend/src/views/Quickwins.vue index 940c2931..6e56548b 100644 --- a/frontend/src/views/Quickwins.vue +++ b/frontend/src/views/Quickwins.vue @@ -11,6 +11,9 @@ :index="index" class="relative" > +
+ +

{{ item.message }}

diff --git a/src/Controller/Api/TagsController.php b/src/Controller/Api/TagsController.php index 37a2ba97..06816ace 100644 --- a/src/Controller/Api/TagsController.php +++ b/src/Controller/Api/TagsController.php @@ -25,11 +25,32 @@ public function get(): Response ->enableAutoFields(true) ->all(); + $collectedUsersInMessages = []; foreach ($collection as $taggedMessage) { $reactionCount = $messages->find() ->where(['permalink' => $taggedMessage->permalink]) ->count(); $taggedMessage->reaction_count = $reactionCount; + // extract all user ids from message: "<@U042CECCR7A> has tagged you in a message" + preg_match_all('/<@([A-Z0-9]+)>/', $taggedMessage->message, $matches); + $collectedUsersInMessages += $matches[1]; + $taggedMessage->tagged_users = $matches[1]; + } + + $usersTable = $this->fetchTable('Users'); + $users = $usersTable->find() + ->where(['Users.slack_user_id IN' => array_unique($collectedUsersInMessages)]) + ->all(); + + foreach ($collection as $taggedMessage) { + foreach ($users as $markedUsers) { + // replace all user ids with user names + $taggedMessage->message = str_replace( + "<@{$markedUsers->slack_user_id}>", + "<@{$markedUsers->slack_name}>", + $taggedMessage->message + ); + } } return $this->response From f103f668ba0b7562e84c336fd2e4175b8bc9abfa Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 21:52:13 +0100 Subject: [PATCH 09/24] Added formatted message --- frontend/src/components/FormattedMessage.vue | 18 +++++++++++++ frontend/src/views/Quickwins.vue | 28 +++++++++++--------- 2 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 frontend/src/components/FormattedMessage.vue diff --git a/frontend/src/components/FormattedMessage.vue b/frontend/src/components/FormattedMessage.vue new file mode 100644 index 00000000..3cd5543c --- /dev/null +++ b/frontend/src/components/FormattedMessage.vue @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/frontend/src/views/Quickwins.vue b/frontend/src/views/Quickwins.vue index 6e56548b..d5d129a6 100644 --- a/frontend/src/views/Quickwins.vue +++ b/frontend/src/views/Quickwins.vue @@ -11,20 +11,20 @@ :index="index" class="relative" > -
- -
-
- -

{{ item.message }}

- +
+ +
+
+ {{item.user.slack_name}} + {{ new Date(item.created).toLocaleDateString('en-us', { year:"numeric", month:"short", day:"numeric"}) }} +
+ + + 🥔 + +
-
-

- Posted {{ new Date(item.created).toLocaleDateString('en-us', { year:"numeric", month:"short", day:"numeric"}) }} -

-
import { computed } from 'vue' import { useStore } from 'vuex' +import FormattedMessage from '../components/FormattedMessage.vue'; export default { name: 'Quickwins', + components: { + FormattedMessage, + }, setup() { const store = useStore() From 94528c138b967b1b93633cf9aed0e656ebd157f9 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 21:54:46 +0100 Subject: [PATCH 10/24] Update MAX_AMOUNT constant value in Message entity --- src/Model/Entity/Message.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Model/Entity/Message.php b/src/Model/Entity/Message.php index 20966304..660009f9 100644 --- a/src/Model/Entity/Message.php +++ b/src/Model/Entity/Message.php @@ -34,5 +34,5 @@ class Message extends Entity ]; public const TYPE_POTATO = 'potato'; - public const MAX_AMOUNT = 50; + public const MAX_AMOUNT = 5; } From bb6a2a650a7495f1d55ba94cdea3d8c71fa3bed4 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Sat, 2 Mar 2024 21:56:19 +0100 Subject: [PATCH 11/24] csfix --- config/Migrations/20240302162526_TaggedMessages.php | 2 ++ src/Controller/Api/TagsController.php | 6 +++--- src/Event/MessageEvent.php | 4 ++-- src/Model/Table/MessagesTable.php | 2 +- src/Model/Table/TaggedMessagesTable.php | 2 -- src/Service/AwardService.php | 2 +- src/Service/NotificationService.php | 4 ++-- src/Service/TaggedMessageService.php | 7 +++---- 8 files changed, 14 insertions(+), 15 deletions(-) diff --git a/config/Migrations/20240302162526_TaggedMessages.php b/config/Migrations/20240302162526_TaggedMessages.php index 8e13148e..c632696d 100644 --- a/config/Migrations/20240302162526_TaggedMessages.php +++ b/config/Migrations/20240302162526_TaggedMessages.php @@ -10,6 +10,7 @@ class TaggedMessages extends AbstractMigration * * More information on this method is available here: * https://book.cakephp.org/phinx/0/en/migrations.html#the-up-method + * * @return void */ public function up(): void @@ -76,6 +77,7 @@ public function up(): void * * More information on this method is available here: * https://book.cakephp.org/phinx/0/en/migrations.html#the-down-method + * * @return void */ public function down(): void diff --git a/src/Controller/Api/TagsController.php b/src/Controller/Api/TagsController.php index 06816ace..a36cbb3c 100644 --- a/src/Controller/Api/TagsController.php +++ b/src/Controller/Api/TagsController.php @@ -17,10 +17,10 @@ public function get(): Response { $taggedMessagesTable = $this->fetchTable('TaggedMessages'); $messages = $this->fetchTable('Messages'); - + $collection = $taggedMessagesTable->find(); $collection->contain(['Users']); - + $collection->orderBy(['TaggedMessages.created' => 'DESC']) ->enableAutoFields(true) ->all(); @@ -52,7 +52,7 @@ public function get(): Response ); } } - + return $this->response ->withStatus(200) ->withType('json') diff --git a/src/Event/MessageEvent.php b/src/Event/MessageEvent.php index c1c48d7b..e2464e47 100644 --- a/src/Event/MessageEvent.php +++ b/src/Event/MessageEvent.php @@ -7,8 +7,8 @@ use App\Event\Validation\Validation; use App\Service\AwardService; use App\Service\NotificationService; -use App\Service\UserService; use App\Service\TaggedMessageService; +use App\Service\UserService; class MessageEvent extends AbstractEvent { @@ -96,7 +96,7 @@ public function process(): void if ($quickwinId !== false) { $notificationService->notifyChannelNewQuickwin( fromUser: $fromUser, - taggedMessageId: $quickwinId, + taggedMessageId: $quickwinId, event: $this ); } diff --git a/src/Model/Table/MessagesTable.php b/src/Model/Table/MessagesTable.php index cd2151dd..6cd207d4 100644 --- a/src/Model/Table/MessagesTable.php +++ b/src/Model/Table/MessagesTable.php @@ -42,7 +42,7 @@ public function initialize(array $config): void $this->setTable('messages'); $this->setDisplayField('id'); $this->setPrimaryKey('id'); - + $this->addBehavior('Timestamp'); $this->belongsTo('Users', [ diff --git a/src/Model/Table/TaggedMessagesTable.php b/src/Model/Table/TaggedMessagesTable.php index 04422283..f4d6ca3b 100644 --- a/src/Model/Table/TaggedMessagesTable.php +++ b/src/Model/Table/TaggedMessagesTable.php @@ -3,7 +3,6 @@ namespace App\Model\Table; -use Cake\ORM\Query\SelectQuery; use Cake\ORM\RulesChecker; use Cake\ORM\Table; use Cake\Validation\Validator; @@ -24,7 +23,6 @@ * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage> saveManyOrFail(iterable $entities, array $options = []) * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage>|false deleteMany(iterable $entities, array $options = []) * @method iterable<\App\Model\Entity\TaggedMessage>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\TaggedMessage> deleteManyOrFail(iterable $entities, array $options = []) - * * @mixin \Cake\ORM\Behavior\TimestampBehavior */ class TaggedMessagesTable extends Table diff --git a/src/Service/AwardService.php b/src/Service/AwardService.php index c8f0c813..39adb84d 100644 --- a/src/Service/AwardService.php +++ b/src/Service/AwardService.php @@ -63,7 +63,7 @@ private function gibToUser( ], ]); $messagesTable->saveOrFail($message); - + metrics()->increment( key: 'gibpotato.potatoes.given_out', value: $event->amount, diff --git a/src/Service/NotificationService.php b/src/Service/NotificationService.php index 1a44f6b6..253cfa36 100644 --- a/src/Service/NotificationService.php +++ b/src/Service/NotificationService.php @@ -98,7 +98,7 @@ public function notifyChannelNewQuickwin( 'type' => 'section', 'text' => [ 'type' => 'mrkdwn', - 'text' => "<@{$fromUser->slack_user_id}> posted a new <" . $event->permalink . "|#quickwin>!", + 'text' => "<@{$fromUser->slack_user_id}> posted a new <" . $event->permalink . '|#quickwin>!', ], ], [ @@ -111,7 +111,7 @@ public function notifyChannelNewQuickwin( 'text' => '<' . Router::url('/quickwins', true) . '?id=' . $taggedMessageId . '|Visit Hall of Fame>', ], ], - + ]; $this->slackClient->postBlocks( diff --git a/src/Service/TaggedMessageService.php b/src/Service/TaggedMessageService.php index fa8e37c9..d1d7c418 100644 --- a/src/Service/TaggedMessageService.php +++ b/src/Service/TaggedMessageService.php @@ -4,9 +4,8 @@ namespace App\Service; use App\Event\MessageEvent; -use App\Service\NotificationService; -use App\Model\Entity\User; use App\Model\Entity\TaggedMessage; +use App\Model\Entity\User; use Cake\ORM\Locator\LocatorAwareTrait; use Sentry\Metrics\MetricsUnit; use function Sentry\metrics; @@ -19,7 +18,7 @@ class TaggedMessageService * @param \App\Model\Entity\User $fromUser User who did gib the potato. * @param array<\App\Model\Entity\User> $toUsers Users who will receive the potato. * @param \App\Event\MessageEvent $event The event. - * @return bool|string false if not tagged, tagged_message_id if tagged + * @return string|bool false if not tagged, tagged_message_id if tagged */ public function storeMessageIfTagged( User $fromUser, @@ -28,7 +27,7 @@ public function storeMessageIfTagged( if (!str_contains($event->text, TaggedMessage::TAG)) { return false; } - + $taggedMessagesTable = $this->fetchTable('TaggedMessages'); $taggedMessage = $taggedMessagesTable->newEntity([ From d7b7829006a3573b87009059543a9cee2539da19 Mon Sep 17 00:00:00 2001 From: Daniel Griesser Date: Mon, 4 Mar 2024 09:16:24 +0100 Subject: [PATCH 12/24] Add top note --- frontend/src/views/Quickwins.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/views/Quickwins.vue b/frontend/src/views/Quickwins.vue index d5d129a6..3023c16e 100644 --- a/frontend/src/views/Quickwins.vue +++ b/frontend/src/views/Quickwins.vue @@ -1,8 +1,13 @@ \ No newline at end of file + From 61e7d32d4c57e7902db37a787d727e916c339eb9 Mon Sep 17 00:00:00 2001 From: Michael Hoffmann Date: Thu, 14 Mar 2024 08:44:34 +0100 Subject: [PATCH 24/24] CS --- src/Controller/Api/QuickWinsController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Controller/Api/QuickWinsController.php b/src/Controller/Api/QuickWinsController.php index 78116d7f..7fef406f 100644 --- a/src/Controller/Api/QuickWinsController.php +++ b/src/Controller/Api/QuickWinsController.php @@ -26,7 +26,7 @@ public function get(): Response foreach ($quickWins as $quickWin) { // extract all user ids from message: "<@U042CECCR7A> has tagged you in a message" preg_match_all('/<@([A-Z0-9]+)>/', $quickWin->message, $matches); - foreach($matches[1] as $match) { + foreach ($matches[1] as $match) { $collectedUsersInMessages[] = $match; } }