Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: #quickwin #162

Merged
merged 25 commits into from
Mar 14, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions config/Migrations/20240302162526_TaggedMessages.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
<?php
declare(strict_types=1);

use Migrations\AbstractMigration;

class TaggedMessages extends AbstractMigration
{
/**
* Up Method.
*
* 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
{
$this->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,
])
cleptric marked this conversation as resolved.
Show resolved Hide resolved
->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();
}
cleptric marked this conversation as resolved.
Show resolved Hide resolved

/**
* 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();
}
}
2 changes: 2 additions & 0 deletions config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']);

Expand All @@ -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']);
HazAT marked this conversation as resolved.
Show resolved Hide resolved
});
});

Expand Down
19 changes: 19 additions & 0 deletions frontend/src/components/FormattedMessage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<template>
<p class="text-sm font-normal py-2.5 text-gray-900 dark:text-white" v-html="formattedMessage">

</p>
</template>

<script>
export default {
props: ['message'],
computed: {
formattedMessage() {
return this.message
.replace(/<(@[^>]+)>/g, (_match, p1) => `<span class="bg-blue-700 p-0.5 px-1 rounded-lg">${p1}</span>`)
.replace(/ (\w+) <(http[^>]+)>/g, (_match, p1, p2) => ` <a class="underline" href="${p2}">${p1}</a> `)
.replace(/:potato:/g, '🥔');
},
},
}
</script>
14 changes: 14 additions & 0 deletions frontend/src/components/MainMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@
>
Collection
</RouterLink>
<RouterLink
to="/quickwins"
class="rounded-md px-3 py-2 text-sm font-medium text-zinc-900"
:class="{ '!bg-zinc-900 !text-zinc-50': $route.path === '/quickwins' }"
>
#QuickWins
</RouterLink>
</div>
</div>
</div>
Expand Down Expand Up @@ -104,6 +111,13 @@
>
Collection
</RouterLink>
<RouterLink
to="/quickwins"
class="block rounded-md px-3 py-2 text-base font-medium text-zinc-900"
:class="{ '!bg-zinc-900 text-zinc-50': $route.path === '/quickwins' }"
>
Collection
</RouterLink>
</div>
<div class="border-t border-zinc-900 pt-4 pb-3">
<div class="flex items-center px-5">
Expand Down
1 change: 1 addition & 0 deletions frontend/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import './assets/main.css'
store.dispatch('getUsers'),
store.dispatch('getProducts'),
store.dispatch('getCollection'),
store.dispatch('getTaggedMessages'),
])

app
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const store = createStore({
users: [],
products: [],
collection: [],
taggedMessages: [],
filter: {
range: helper.getRangeFilter(),
order: helper.getOrderFilter(),
Expand All @@ -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,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
},
Expand Down
141 changes: 141 additions & 0 deletions frontend/src/views/Quickwins.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<template>
<div class="bg-gray-700 mb-8 mx-20 border-t border-b text-white px-4 py-3" role="alert">
<p class="font-bold">How to?</p>
<p class="text-sm">Write a message in Slack - if it contains <span class="bg-blue-700 p-0.5 px-1 rounded-lg">#quickwin</span> and a 🥔 emoji it will be captured here.</p>
</div>
<div
v-if="taggedMessages.length"
class="grid grid-cols-1 gap-y-12 sm:grid-cols-2 sm:gap-x-6 lg:grid-cols-4 xl:gap-x-8 mb-32"
>

<div
v-for="(item, index) in taggedMessages"
class="h-full flex flex-col"
>
<div
:index="index"
class="relative"
>
<div class="flex items-start gap-2.5">
<img class="w-8 h-8 rounded-full" :src="item.user.slack_picture" :alt="item.user.slack_name">
<div class="flex flex-col w-full max-w-[320px] leading-1.5 p-4 border-gray-200 bg-gray-100 rounded-e-xl rounded-es-xl dark:bg-gray-700">
<div class="flex items-center space-x-2 rtl:space-x-reverse">
<span class="text-sm font-semibold text-gray-900 dark:text-white">{{item.user.slack_name}}</span>
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">{{ new Date(item.created).toLocaleDateString('en-us', { year:"numeric", month:"short", day:"numeric"}) }}</span>
</div>
<FormattedMessage :message="item.message" />
<span v-if="item.reaction_count >= 2" class="relative text-sm font-normal text-gray-500 dark:text-gray-400">
<span v-for="(i, index2) in item.reaction_count" :key="i" :class="index2 === 0 ? '' : '-ml-2'">🥔</span>
</span>
</div>
</div>
</div>
</div>
</div>
<div
v-else
class="absolute inset-0 flex items-center justify-center"
>
<h1 class="text-2xl font-extrabold">
No #quickwins recorded yet
</h1>
</div>
<div v-if="modalOpen === true" class="relative z-10">
<div class="fixed inset-0 bg-zinc-700 bg-opacity-75"></div>

<div class="fixed inset-0 z-20 overflow-y-auto">
<div class="flex min-h-full items-end justify-center p-4 text-center sm:items-center sm:p-0">
<div class="relative transform overflow-hidden rounded-lg bg-zinc-50 dark:bg-zinc-900 px-4 pt-5 pb-4 text-left shadow-xl transition-all sm:my-8 sm:w-full sm:max-w-sm sm:p-6">
<div class="relative">
<div class="relative mt-4">
<div class="flex items-center space-x-2 rtl:space-x-reverse">
<span class="text-sm font-semibold text-gray-900 dark:text-white">{{modelData.user.slack_name}}</span>
<span class="text-sm font-normal text-gray-500 dark:text-gray-400">{{ new Date(modelData.created).toLocaleDateString('en-us', { year:"numeric", month:"short", day:"numeric"}) }}</span>
</div>
<FormattedMessage :message="modelData.message" />
<button
class="mt-2 cursor-pointer inline-flex w-full justify-center rounded-md border border-zinc-300 bg-zinc-100 px-4 py-2 text-base font-medium text-zinc-900 sm:mt-0 sm:text-sm"
@click="closeModal"
>
Close
</button>
</div>

</div>
</div>
</div>

</div>
</div>
</template>

<script>
import { computed } from 'vue'
import { useStore } from 'vuex'
import FormattedMessage from '../components/FormattedMessage.vue'
import JSConfetti from 'js-confetti'

export default {
name: 'Quickwins',
components: {
FormattedMessage,
},
created() {
let that = this;

document.addEventListener('keyup', function (evt) {
if (evt.keyCode === 27) {
that.closeModal();
}
});
if (this.modalOpen === true) {
const jsConfetti = new JSConfetti()
const startTime = Date.now();
let intervalId = setInterval(() => {
jsConfetti.addConfetti({
emojis: ['🥔'],
});
if (Date.now() - startTime > 3000) {
clearInterval(intervalId);
}
}, 300)
}

},
data() {
let modelData = null
let modalOpen = false

this.taggedMessages.forEach((message) => {
if (message.id === this.$route.query?.id) {
modelData = message
modalOpen = true
}
});

return {
modalOpen,
modelData,
}
},
methods: {
openModal() {
this.modalOpen = true
},
closeModal() {
this.modalOpen = false
this.$router.replace({'query': null})
},
},

setup() {
const store = useStore()

const taggedMessages = computed(() => store.getters.taggedMessages);
return {
taggedMessages,
}
},
}

</script>
14 changes: 10 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading