Skip to content

Commit

Permalink
feat(dashboard): improve events list (#759)
Browse files Browse the repository at this point in the history
* feat(dashboard): improve events list

* feat(dashboard): refactor events

* fix: build

* feat: time ago tooltip
  • Loading branch information
crashmax-dev committed Sep 23, 2024
1 parent 0f16b6b commit 5eca37c
Show file tree
Hide file tree
Showing 21 changed files with 318 additions and 191 deletions.
3 changes: 1 addition & 2 deletions frontend/dashboard/src/components/dashboard/chat.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ import { useProfile, useTwitchGetUsers } from '@/api/index.js'
import { useTheme } from '@/composables/use-theme.js'
const { data: profile } = useProfile()
const { theme: chatTheme, toggleTheme } = useTheme('twirTwitchChatTheme')
const { theme: chatTheme, toggleTheme } = useTheme()
const openFrankerFaceZ = ref(false)
const selectedTwitchId = computed(() => profile.value?.selectedDashboardId ?? '')
Expand Down
28 changes: 21 additions & 7 deletions frontend/dashboard/src/components/dashboard/events.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<script lang="ts" setup>
import { IconSettings } from '@tabler/icons-vue'
import { IconExternalLink, IconSettings } from '@tabler/icons-vue'
import { EventType } from '@twir/api/messages/dashboard/dashboard'
import { useIntervalFn, useLocalStorage } from '@vueuse/core'
import { NButton, NPopselect, NScrollbar, NText } from 'naive-ui'
import { NButton, NPopselect, NScrollbar, NText, NTooltip } from 'naive-ui'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import Card from './card.vue'
import Ban from './events/ban.vue'
Expand All @@ -25,6 +26,7 @@ const props = defineProps<{
popup?: boolean
}>()
const { t } = useI18n()
const { data: events, isLoading, refetch } = useDashboardEvents()
useIntervalFn(refetch, 1000)
Expand Down Expand Up @@ -89,20 +91,32 @@ const { data } = useProfile()
function openPopup() {
if (!data.value) return
const height = 800
const width = 500
const top = Math.max(0, (screen.height - height) / 2)
const left = Math.max(0, (screen.width - width) / 2)
window.open(
`${window.location.origin}/dashboard/popup/widgets/eventslist?apiKey=${data.value?.apiKey}`,
`${window.location.origin}/dashboard/popup/widgets/eventslist?apiKey=${data.value.apiKey}`,
'_blank',
'width=400,height=600,popup=true',
`height=${height},width=${width},top=${top},left=${left},status=0,location=0,menubar=0,toolbar=0`,
)
}
</script>

<template>
<Card :content-style="{ padding: isLoading ? '10px' : '0px', height: '80%' }" :popup="props.popup">
<template #header-extra>
<NButton :disabled="!data" secondary size="small" type="info" class="uppercase" @click="openPopup">
Popup
</NButton>
<NTooltip trigger="hover" placement="bottom">
<template #trigger>
<NButton size="small" text @click="openPopup">
<IconExternalLink />
</NButton>
</template>

{{ t('sharedButtons.popout') }}
</NTooltip>

<NPopselect
v-model:value="enabledEvents" multiple :options="enabledEventsOptions"
trigger="click"
Expand Down
35 changes: 22 additions & 13 deletions frontend/dashboard/src/components/dashboard/events/ban.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
<script lang="ts" setup>
import { IconBan, IconClockCancel } from '@tabler/icons-vue'
import { computed } from 'vue'
import { IconUserCancel } from '@tabler/icons-vue';
import Base from './base.vue'
import UserLink from './user-link.vue'
import Base from './base.vue';
import { resolveUserName } from '@/helpers';
defineProps<{
userName: string,
const props = defineProps<{
userName: string
userLogin: string
createdAt: string,
createdAt: string
reason: string
moderatorUserName: string
moderatorUserLogin: string
endsIn: string
}>();
}>()
const iconBan = computed(() => {
if (props.endsIn === 'permanent') return IconBan
return IconClockCancel
})
</script>

<template>
<Base :icon="IconUserCancel" :created-at="createdAt">
<Base
:icon="iconBan"
:icon-color="['#ff4f4d', '#ffaaa8']"
:created-at="createdAt"
>
<template #leftContent>
<div class="flex flex-col">
<span>
{{ resolveUserName(moderatorUserLogin, moderatorUserName) }}
<b class="text-xs">banned</b> {{ resolveUserName(userLogin, userName) }}
for {{ endsIn }} {{ endsIn != 'permanent' ? 'minutes' : '' }}</span>
<UserLink :name="moderatorUserLogin" :display-name="moderatorUserName" />{{ '' }}
<span class="font-bold">banned</span>{{ '' }}
<UserLink :name="userLogin" :display-name="userName" />
for {{ endsIn }} {{ endsIn !== 'permanent' ? 'minutes' : '' }}</span>
<span class="text-xs">{{ reason }}</span>
</div>
</template>
Expand Down
75 changes: 61 additions & 14 deletions frontend/dashboard/src/components/dashboard/events/base.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,82 @@
<script lang="ts" setup>
import type { SVGProps } from '@tabler/icons-vue';
import { UseTimeAgo } from '@vueuse/components';
import type { FunctionalComponent } from 'vue';
import { UseTimeAgo } from '@vueuse/components'
import { computed } from 'vue'
defineProps<{
import type { SVGProps } from '@tabler/icons-vue'
import type { FunctionalComponent } from 'vue'
import { useTheme } from '@/composables/use-theme.js'
const props = defineProps<{
icon: FunctionalComponent<SVGProps, Record<string, any>, any>
iconColor?: string;
iconColor?: [light: string, dark: string]
createdAt: string
}>();
}>()
defineSlots<{
leftContent: any,
rightContent: any,
}>();
leftContent: any
rightContent: any
}>()
const locale = navigator.language
const theme = useTheme()
const color = computed(() => {
if (!props.iconColor) return
return props.iconColor.at(Number(theme.theme.value === 'dark'))
})
const date = computed(() => new Date(Number(props.createdAt)))
</script>

<template>
<div class="flex min-h-[50px] gap-2.5 px-1 select-text border-b-[color:var(--n-border-color)] border-b border-solid">
<div class="flex min-h-[50px] gap-2.5 px-2.5 select-text border-b-[color:var(--n-border-color)] border-b border-solid">
<div class="flex justify-between items-center w-full">
<div class="flex gap-2.5 items-center">
<component :is="icon" class="flex items-center h-9 w-9" :style="{ color: iconColor }" />
<component
:is="icon"
class="flex items-center min-h-9 min-w-9"
:style="{ color }"
/>
<div class="flex flex-col">
<slot name="leftContent" />
</div>
</div>

<div class="flex items-end text-xs h-full px-2.5 flex-shrink-0">
<UseTimeAgo v-slot="{ timeAgo }" :time="new Date(Number(createdAt))" :update-interval="1000" show-second>
{{ timeAgo }}
<div class="flex items-end text-xs h-full py-2 flex-shrink-0">
<UseTimeAgo
v-slot="{ timeAgo }"
:time="date"
:update-interval="1000"
show-second
>
<span class="tooltip" :data-utc="date.toLocaleString(locale)">
{{ timeAgo }}
</span>
</UseTimeAgo>
</div>
</div>
</div>
</template>

<style scoped>
.tooltip {
position: relative;
}
.tooltip:after {
content: attr(data-utc);
position: absolute;
top: 0px;
right: 0;
left: -100px;
display: none;
text-align: center;
background-color: #000;
border-radius: 4px;
padding: 2px;
white-space: nowrap;
}
.tooltip:hover:after {
display: block;
}
</style>
18 changes: 10 additions & 8 deletions frontend/dashboard/src/components/dashboard/events/chatClear.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
<script lang="ts" setup>
import { IconEraser } from '@tabler/icons-vue';
import { IconEraser } from '@tabler/icons-vue'
import Base from './base.vue';
import Base from './base.vue'
defineProps<{
createdAt: string,
}>();
createdAt: string
}>()
</script>

<template>
<Base :icon="IconEraser" :created-at="createdAt">
<Base
:icon="IconEraser"
:icon-color="['#ff4f4d', '#ffaaa8']"
:created-at="createdAt"
>
<template #leftContent>
<div class="flex flex-col">
<span>Chat Cleared</span>
</div>
Chat cleared
</template>
</Base>
</template>
22 changes: 13 additions & 9 deletions frontend/dashboard/src/components/dashboard/events/donate.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
<script lang="ts" setup>
import { IconCurrencyDollar } from '@tabler/icons-vue';
import { IconCurrencyDollar } from '@tabler/icons-vue'
import Base from './base.vue';
import Base from './base.vue'
defineProps<{
userName: string,
createdAt: string,
amount: string,
currency: string,
userName: string
createdAt: string
amount: string
currency: string
message: string
}>();
}>()
</script>

<template>
<Base :icon="IconCurrencyDollar" :created-at="createdAt">
<Base
:icon="IconCurrencyDollar"
:icon-color="['#00a865', '#5cffbe']"
:created-at="createdAt"
>
<template #leftContent>
<div class="flex flex-col">
<span>{{ userName }} <b class="text-xs">donated</b> {{ amount }}{{ currency }}</span>
<span>{{ userName }} <span class="font-bold">donated</span> {{ amount }}{{ currency }}</span>
<span class="text-xs">{{ message }}</span>
</div>
</template>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,28 @@
<script lang="ts" setup>
import { IconMoodPlus } from '@tabler/icons-vue';
import { IconMoodPlus } from '@tabler/icons-vue'
import Base from './base.vue';
import { resolveUserName } from '@/helpers/index.js';
import Base from './base.vue'
import UserLink from './user-link.vue'
defineProps<{
createdAt: string,
userName: string,
userDisplayName: string,
createdAt: string
userName: string
userDisplayName: string
message: string
}>();
}>()
</script>

<template>
<Base :icon="IconMoodPlus" :created-at="createdAt">
<Base
:icon="IconMoodPlus"
:icon-color="['#772ce8', '#9147ff']"
:created-at="createdAt"
>
<template #leftContent>
<div class="flex flex-col">
<span>
{{ resolveUserName(userName, userDisplayName) }}
<b class="text-sx">first time joined chat</b>
<UserLink :name="userName" :display-name="userDisplayName" />{{ '' }}
<span class="font-bold">first time message</span>
</span>
<span class="text-sx">{{ message }}</span>
</div>
Expand Down
22 changes: 12 additions & 10 deletions frontend/dashboard/src/components/dashboard/events/follow.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
<script lang="ts" setup>
import { IconHeartFilled } from '@tabler/icons-vue';
import { IconHeartFilled } from '@tabler/icons-vue'
import Base from './base.vue';
import { resolveUserName } from '@/helpers/index.js';
import Base from './base.vue'
import UserLink from './user-link.vue'
defineProps<{
userName: string,
userDisplayName: string,
userName: string
userDisplayName: string
createdAt: string
}>();
}>()
</script>

<template>
<Base :icon="IconHeartFilled" :created-at="createdAt">
<Base
:icon="IconHeartFilled"
:icon-color="['#c516a5', '#ff38db']"
:created-at="createdAt"
>
<template #leftContent>
{{ resolveUserName(userName, userDisplayName) }}
<UserLink :name="userName" :display-name="userDisplayName" />
</template>
</Base>
</template>
Loading

0 comments on commit 5eca37c

Please sign in to comment.