Skip to content

Instantly share code, notes, and snippets.

@Avanger2512
Created February 27, 2020 22:04
Show Gist options
  • Save Avanger2512/119b35c05609cceaac19451aaf04ddc7 to your computer and use it in GitHub Desktop.
Save Avanger2512/119b35c05609cceaac19451aaf04ddc7 to your computer and use it in GitHub Desktop.

Revisions

  1. Avanger2512 created this gist Feb 27, 2020.
    468 changes: 468 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,468 @@
    <template>
    <transition-group name="fade" mode="in-out">
    <template v-if="loading && tableInfo.length > 0">
    <table class="tourney-participation__table"
    key="participation-table">

    <participation-thead v-if="!fullList"></participation-thead>

    <transition-group
    tag="tbody"
    :name="animationType"
    @before-enter="beforeEnter"
    @after-leave="afterLeave">

    <participation-tr
    v-for="(item, index) in setListAscending"
    :key="websoketNeed ? item.id : item.place"
    :class="[addClassForIndex(item.place-1),
    selectedOddItem(index),
    {'tourney-participation__me' : selectedMyUser(item.login)},
    'table-row-move']"
    :winClassMod="participationTrMod"
    :tr="item">
    </participation-tr>

    </transition-group>

    </table>

    <button class="tourney-participation__all"
    type="button"
    @click="onClickMore()"
    key="participation-btn">
    <span class="tourney-participation__place">{{users}}</span>
    <span class="tourney-participation__desc">{{ lang.usersList }}</span>
    <span class="tourney-participation__pic"
    v-html="icons.arrowRight"></span>
    </button>
    </template>

    <div v-else
    key="loading">
    <template v-if="loading && tableInfo.length === 0">
    No participations
    </template>
    <template v-else>
    <tables-preload
    :sizeBig="true"
    :lineAmount="11"
    class="table-preload_participiant"/>
    </template>
    </div>
    </transition-group>
    </template>

    <script>

    import ParticipationThead from './ParticipationThead';
    import ParticipationTr from './ParticipationTr';
    import Tracking from '@/components/Tourney/Tracking/Tracking';
    import TablesPreload from '@/components/Tourney/Tables/TablesPreload/TablesPreload';

    import SVG from '@/const/svg';
    import {emitter} from '@/util/ws';

    import axios from 'axios';
    import exportedAPITourney from '@/const/api-tourney';

    export default {
    name: 'ParticipationTable',
    props: {
    tourneyId: [String, Number],
    login: String,
    fullList: {
    type: Boolean,
    default: false,
    },
    participationTrMod: {
    type: Boolean,
    default: true,
    },
    websoketNeed: {
    type: Boolean,
    default: true,
    },
    users: {
    type: String,
    }
    },
    components: {
    ParticipationThead,
    ParticipationTr,
    Tracking,
    TablesPreload

    },
    data() {
    return {
    icons: SVG,
    lang: tourneyResources,
    animationType: 'shuffle',
    updatedData: [],
    tableInfo: [],
    participationLimitHistory: 10,
    loading: false,

    }
    },
    created() {
    if (this.fullList && this.websoketNeed) {
    emitter.$emit('wsUpdateTourneyTableOnlyModal', true);
    }

    if (!this.websoketNeed) {
    this.fetchTourneyTableFinalists();
    }
    },
    mounted() {
    if (this.websoketNeed) {

    if (this.fullList) {
    emitter.$emit('wsUpdateTourneyTable', {"limit": 10, "offset": 0});
    emitter.$on('wsStandingsInitModal', this.onTableInfoInitModal);
    }

    emitter.$on('wsStandingsInit', this.onTableInfoInit);
    emitter.$on('wsStandingsBrodcastUpdate', this.onTourneyUserDataUpdated);
    this.setListAscending;

    } else {
    emitter.$on('participiationLimitUpdate', this.participiationLimitUpdate);
    emitter.$on('participiationOffsetUpdate', this.participiationOffsetUpdate);
    }
    },
    methods: {
    selectedMyUser(user) {
    (this.login === user) ? true : false
    },

    onTableInfoInit(data) {
    const MESSAGE = JSON.parse(data);

    this.tableInfo = [];

    this.addElementsToArray(MESSAGE);
    },

    onTableInfoInitModal(data) {
    const MESSAGE = JSON.parse(data);

    this.tableInfo = [];
    this.addElementsToArray(MESSAGE);

    this.$emit('tableLoading', false);
    },

    addElementsToArray(data){
    // Create new array with id for vue animation by websocket message
    for (var i = 0; i < data.length; i++) {
    this.tableInfo.push({
    id: data[i].place-1,
    place: data[i].place,
    login: data[i].login,
    score: data[i].score,
    rounds: data[i].rounds,
    prizeAmount: data[i].prizeAmount,
    });
    }

    this.loading = true;
    },

    onClickMore() {
    this.$emit('participationBtnShow', 'participation');
    },

    beforeEnter(el) {
    console.log('before animation');
    },

    afterLeave(el) {
    console.log('after animation');
    this.updatedData = [];
    },

    onTourneyUserDataUpdated(data) {
    const MESSAGE = JSON.parse(data);

    if ("messageType" in MESSAGE) {

    for (let i = 0; i < MESSAGE.wsStandingsPayloads.length; i++) {
    this.updatedData.push(MESSAGE.wsStandingsPayloads[i]);
    }

    // loop for all updated users from websocket
    for (let i = 0; i < this.updatedData.length; i++) {
    let foundIndex = this.tableInfo.findIndex(x => x.login === this.updatedData[i].login);
    let place = this.updatedData[i].place;

    // if user place changing and we start sort and animation
    // else place not changing
    if (foundIndex+1 !== place) {
    this.animationType = 'shuffle';

    this.updatedData[i].id = this.tableInfo[foundIndex].id;

    // set reactive data updated users
    this.$set(this.tableInfo, foundIndex, this.updatedData[i]);

    } else {

    if (this.updatedData[i].oldPlace === null) {
    this.animationType = 'zoom';
    } else {
    this.animationType = '';
    }

    // set unique key for re-renders of a value
    let randomIndex = Math.ceil(Math.random() * 10000);
    this.updatedData[i].id = randomIndex;

    // set reactive data updated users
    this.$set(this.tableInfo, foundIndex, this.updatedData[i]);

    }
    }
    }
    },

    selectedOddItem(data) {
    // checks whether an element is odd
    if (data % 2 !== 0) { return 'is-odd' }
    },

    fetchTourneyTableFinalists(limit=10, offset=0) {
    axios
    .get(exportedAPITourney.getFinishTourmeyTable(this.tourneyId, limit, offset))
    .then(response => {
    this.tableInfo = response.data;
    this.loading = true;

    this.$emit('tableLoading', false);
    })
    .catch(error => {
    console.log(error);
    });
    },

    participiationLimitUpdate(payload) {
    this.loading = false;
    this.participationLimitHistory = payload.limit;
    this.fetchTourneyTableFinalists(payload.limit, payload.offset);
    },

    participiationOffsetUpdate(payload) {
    this.loading = false;
    this.fetchTourneyTableFinalists(this.participationLimitHistory, payload.offset);
    },
    },
    computed: {
    setListAscending() {
    this.tableInfo.sort((a, b) => b.score - a.score);

    if (this.updatedData.length) {
    console.log('clean arr in after sort');
    this.updatedData = [];
    }
    return this.tableInfo;
    },
    }
    }
    </script>

    <style lang="less" scoped>
    @import '../../../../assets/less/variables/variables.less';

    .tourney-participation {
    @this: ~'.tourney-participation';
    width: 100%;
    position: relative;

    &__table {
    width: 100%;
    border-collapse: collapse;
    border-radius: 8px;
    background: @grey-bg-light;

    thead {
    border-radius: 8px;
    overflow: hidden;
    }

    tbody {
    border-radius: 8px;
    box-shadow: 0 0 0 1px @orange;

    .tourney-participation_mod & {
    box-shadow: none;
    }
    }

    th {
    background: @black-two;
    padding: 17px 0;
    font-size: 12px;
    color: @white-o-54;
    text-align: left;

    .tourney-participation_mod & {
    background: @grey-bg;
    }

    .tourney-participation_thead & {
    background: @grey-bg-light;
    }

    .tourney-participation_game-tab & {
    background: @grey-bg;
    }

    @media (max-width: 1023px) {
    background: @grey-bg;
    }

    &:first-child {
    border-top-left-radius: 8px;
    padding-left: 24px;

    @media (max-width: 1023px) {
    padding-left: 16px;
    }

    .tourney-participation_game-tab & {
    padding-left: 16px;
    }
    }

    &:last-child {
    border-top-right-radius: 8px;
    }

    &:nth-child(4),
    &:nth-child(5) {
    .tourney-participation_game-tab & {
    display: none;
    }
    }
    }

    td {
    position: relative;
    padding: 17px 0;
    vertical-align: middle;

    &:first-child {
    padding-left: 24px;

    @media (max-width: 1023px) {
    padding-left: 16px;
    }

    .tourney-participation_game-tab & {
    padding-left: 16px;
    }
    }

    &:last-child {
    padding-right: 24px;

    @media (max-width: 1023px) {
    padding-right: 16px;
    }

    .tourney-participation_game-tab & {
    padding-right: 16px;
    }
    }

    &:nth-child(4),
    &:nth-child(5) {
    @media (max-width: 1023px) {
    display: none;
    }

    .tourney-participation_game-tab & {
    display: none;
    }
    }
    }

    tr {
    &:not(:first-child) {
    td {
    &:not(:first-child) {
    border-top: 1px solid @orange;

    .tourney-participation_mod & {
    border-top: none;
    }


    }
    }
    .tourney-participation__vs {
    display: none;
    }
    }

    &:first-child {
    td {
    &:first-child {
    .tourney-participation_mod & {
    border-top-left-radius: 8px;
    }
    }

    &:last-child {
    .tourney-participation_mod & {
    border-top-right-radius: 8px;
    }
    }
    }
    }

    &.is-odd {
    .tourney-participation_mod & {
    background: @black-two;
    }
    }

    .tourney-participation_mod & {
    min-height: 56px;
    }
    }
    }

    .shuffle-move {
    transition: transform .8s ease-out;
    }

    .move-shuffle {
    transition: transform .8s ease-out;
    }

    .fade-enter-active, .fade-leave-active {
    transition: opacity .5s;
    }

    .fade-enter, .fade-leave-to {
    opacity: 0;
    }

    .zoom-enter-active {
    transition: opacity .85s ease-in, transform .95s ease-in-out;
    }

    .zoom-leave-active {
    transition: opacity .25s ease-out, transform .2s ease-in;
    }

    .zoom-enter, .zoom-leave-to {
    position: absolute;
    width: 100%;
    // transform: scale(.95);
    opacity: 0;
    }

    </style>