added Chat-History to matches
All checks were successful
CSGOWTF/csgowtf/pipeline/head This commit looks good

This commit is contained in:
2022-02-03 14:55:22 +01:00
parent 2b4b0d082c
commit 7114ca2479
8 changed files with 239 additions and 41 deletions

View File

@@ -0,0 +1,139 @@
<template>
<div class="chat-history mt-2">
<table class="table table-borderless">
<tbody>
<tr v-for="(m, id) in data.chat" :key="id">
<td>
{{ ConvertTickToTime(m.tick) }}
</td>
<td>
<img :class="'team-color-' + m.color"
:src="constructAvatarUrl(m.avatar)"
alt="Player avatar"
class="avatar">
</td>
<td class="name"
@click="GoToPlayer(m.steamid64)"
:class="m.startSide === 1 ? 'text-info' : 'text-warning'">
<i v-if="m.tracked" class="fa fa-dot-circle-o text-success tracked" title="Tracked user"></i>
{{ m.player }}
<i class="fa fa-external-link"></i>
</td>
<td>
</td>
<td class="message">
{{ m.message }}
</td>
</tr>
</tbody>
</table>
</div>
</template>
<script>
import {useStore} from "vuex";
import {onMounted, reactive} from "vue";
import {GetChatHistory, constructAvatarUrl, GoToPlayer, ConvertTickToTime} from "@/utils";
export default {
name: "MatchChatHistory",
setup() {
const store = useStore()
const data = reactive({
chat: [],
})
const getChatHistory = async () => {
const resData = await GetChatHistory(store, store.state.matchDetails.match_id)
if (resData !== null) {
data.chat = await setPlayer(sortChatHistory(resData))
}
}
const sortChatHistory = (res = {}) => {
let arr = []
if (res !== {}) {
Object.keys(res).forEach(i => {
res[i].forEach(o => {
let obj = Object.assign({
player: i,
tick: o.tick,
all_chat: o.all_chat,
message: o.message
})
arr.push(obj)
})
})
}
arr.sort((a, b) => a.tick - b.tick)
return arr
}
const setPlayer = async (chat) => {
let arr = []
for (const o of chat) {
for (const p of store.state.matchDetails.stats) {
console.log(p)
if (o.player === p.player.steamid64) {
const obj = Object.assign({
player: p.player.name,
steamid64: p.player.steamid64,
avatar: p.player.avatar,
color: p.color,
startSide: p.team_id,
tracked: p.player.tracked,
tick: o.tick,
all_chat: o.all_chat,
message: o.message
})
arr.push(obj)
}
}
}
return arr
}
onMounted(() => {
getChatHistory()
})
return {data, constructAvatarUrl, GoToPlayer, ConvertTickToTime}
}
}
</script>
<style lang="scss" scoped>
table td {
padding: .5rem;
}
.avatar {
width: 75%;
height: 75%;
border-radius: 50%;
}
.name {
cursor: pointer;
text-align: left;
width: 200px;
max-width: 200px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
.tracked {
font-size: .8rem;
}
.fa-external-link {
color: white;
font-size: .8rem;
vertical-align: top;
}
}
.message {
width: 40ch;
max-width: 40ch;
}
</style>

View File

@@ -63,7 +63,7 @@
</template> </template>
<script> <script>
import {constructAvatarUrl, DisplayRank, FormatVacDate, GetHLTV_1, GoToPlayer} from "../utils"; import {constructAvatarUrl, DisplayRank, FormatVacDate, GetHLTV_1, GoToPlayer} from "@/utils";
import {useStore} from "vuex"; import {useStore} from "vuex";
export default { export default {
@@ -203,39 +203,6 @@ export default {
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.team-color-blue,
.team-color-orange,
.team-color-green,
.team-color-purple,
.team-color-yellow,
.team-color-grey {
outline: 3px solid;
}
.team-color-grey {
outline-color: var(--csgo-grey);
}
.team-color-orange {
outline-color: var(--csgo-orange);
}
.team-color-blue {
outline-color: var(--csgo-blue);
}
.team-color-yellow {
outline-color: var(--csgo-yellow);
}
.team-color-purple {
outline-color: var(--csgo-purple);
}
.team-color-green {
outline-color: var(--csgo-green);
}
.player__vac, .player__vac,
.vac-placeholder { .vac-placeholder {
width: 20px; width: 20px;

View File

@@ -74,17 +74,17 @@ const routes = [
score: lazyLoadComponent('FlashChart') score: lazyLoadComponent('FlashChart')
} }
}, },
{
path: 'utility',
components: {
score: lazyLoadComponent('UtilityChart')
}
},
{ {
path: 'damage', path: 'damage',
components: { components: {
score: lazyLoadComponent('DamageSite') score: lazyLoadComponent('DamageSite')
} }
},
{
path: 'chat-history',
components: {
score: lazyLoadComponent('MatchChatHistory')
}
} }
] ]
}, },

View File

@@ -24,6 +24,39 @@
animation: placeholder-wave-alt 2.5s linear infinite; animation: placeholder-wave-alt 2.5s linear infinite;
} }
.team-color-blue,
.team-color-orange,
.team-color-green,
.team-color-purple,
.team-color-yellow,
.team-color-grey {
outline: 3px solid;
}
.team-color-grey {
outline-color: var(--csgo-grey);
}
.team-color-orange {
outline-color: var(--csgo-orange);
}
.team-color-blue {
outline-color: var(--csgo-blue);
}
.team-color-yellow {
outline-color: var(--csgo-yellow);
}
.team-color-purple {
outline-color: var(--csgo-purple);
}
.team-color-green {
outline-color: var(--csgo-green);
}
@keyframes placeholder-wave-alt { @keyframes placeholder-wave-alt {
100% { 100% {
mask-position: -200% 0%; mask-position: -200% 0%;

View File

@@ -299,6 +299,45 @@ export const GetWeaponDmg = async (store, match_id) => {
return response return response
} }
// /match/<id>/chat GET returns chat history for match <id>
export const GetChatHistory = async (store, match_id) => {
let response = null
await axios
.get(`${API_URL}/match/${match_id}/chat`)
.then((res) => {
if (res.status === STATUS.OK)
response = res.data
})
.catch((err) => {
let message = ''
switch (err.response.status) {
case STATUS.BAD_REQUEST:
message = 'Bad request'
break
case STATUS.NOT_FOUND:
message = 'Weapon damage not found'
break
case STATUS.INTERNAL_SERVER_ERROR:
message = 'Unable to get weapon damage'
break
default:
message = 'An unknown error occurred'
}
store.commit({
type: 'changeInfoState',
data: {
statuscode: err.response.status,
message: message,
type: 'error'
}
})
})
return response
}
// /matches GET returns last 20 matches in DB // /matches GET returns last 20 matches in DB
export const GetMatches = async (store) => { export const GetMatches = async (store) => {
let response = null let response = null

View File

@@ -1,5 +1,14 @@
import {DateTime, Duration} from "luxon/build/es6/luxon"; import {DateTime, Duration} from "luxon/build/es6/luxon";
export const ConvertTickToTime = (tick, rate = 64) => {
const time = Duration.fromObject({hours: 0, minutes: 0, seconds: tick / rate || 0})
if (time.hours > 1)
return time.toFormat('hh:mm:ss')
else if (time.hours < 1)
return time.toFormat('mm:ss')
}
export const FormatDuration = (d) => { export const FormatDuration = (d) => {
const duration = Duration.fromObject({hours: 0, minutes: 0, seconds: d}).normalize().toObject() const duration = Duration.fromObject({hours: 0, minutes: 0, seconds: d}).normalize().toObject()

View File

@@ -4,7 +4,8 @@ import {
FormatFullDate, FormatFullDate,
FormatFullDuration, FormatFullDuration,
FormatVacDate, FormatVacDate,
MatchNotParsedTime MatchNotParsedTime,
ConvertTickToTime
} from "./DateTime"; } from "./DateTime";
import {GoToLink, GoToMatch, GoToPlayer} from "./GoTo"; import {GoToLink, GoToMatch, GoToPlayer} from "./GoTo";
import {SaveLastVisitedToLocalStorage} from "./LocalStorage"; import {SaveLastVisitedToLocalStorage} from "./LocalStorage";
@@ -19,6 +20,7 @@ import {
GetWeaponDmg, GetWeaponDmg,
LoadMoreMatches, LoadMoreMatches,
LoadMoreMatchesExplore, LoadMoreMatchesExplore,
GetChatHistory,
TrackMe TrackMe
} from "./ApiRequests"; } from "./ApiRequests";
import { import {
@@ -40,6 +42,8 @@ import {
export { export {
MatchNotParsedTime, MatchNotParsedTime,
GetChatHistory,
ConvertTickToTime,
FormatDate, FormatDate,
FormatFullDuration, FormatFullDuration,
FormatFullDate, FormatFullDate,

View File

@@ -129,6 +129,13 @@
replace>Damage replace>Damage
</router-link> </router-link>
</li> </li>
<li :title="!data.matchDetails.parsed ? 'This demo has not been parsed' : ''"
class="list-item nav-item">
<router-link :class="!data.matchDetails.parsed ? 'disabled' : ''" :disabled="!data.matchDetails.parsed"
:to="'/match/' + data.matchDetails.match_id + '/chat-history'" class="nav-link"
replace>Chat-History
</router-link>
</li>
</ul> </ul>
</div> </div>
</div> </div>