├── .babelrc
├── .editorconfig
├── .env.example
├── .github
└── workflows
│ └── nodejs.yml
├── .gitignore
├── .gitmodules
├── .prettierrc.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── assets
└── styles
│ ├── _components.scss
│ ├── _mixins.scss
│ ├── _placeholders.scss
│ ├── _variables.scss
│ └── utils.scss
├── components
├── Card.vue
├── DashboardCard.vue
├── DevcoinIcon.vue
├── Devcoins.vue
├── DevwarsCard.vue
├── FileChooser.vue
├── HomeCard.vue
├── LinkTabs.vue
├── Logo.vue
├── Pagination.vue
├── Popup.vue
├── SquareToggle.vue
├── Tabbed.vue
├── TabbedItem.vue
├── Table.vue
├── Tag.vue
├── common
│ ├── Button.vue
│ ├── ButtonGroup.vue
│ ├── ButtonIcon.vue
│ ├── Icon.vue
│ └── button.module.js
├── dashboard
│ ├── Activities.vue
│ ├── BadgeCard.vue
│ ├── Badges.vue
│ ├── DailyPrizes.vue
│ ├── GamesPlayed.vue
│ ├── Moderation.vue
│ ├── ProfileCard.vue
│ ├── UpcomingGames.vue
│ └── Wallet.vue
├── form
│ ├── Checkbox.vue
│ ├── Input.vue
│ ├── Progress.vue
│ ├── Select.vue
│ └── Textarea.vue
├── game
│ ├── Applications.vue
│ ├── GameEditor.vue
│ ├── GameProjectTeam.vue
│ ├── GameTeam.vue
│ ├── Highlights.vue
│ ├── LanguageSkills.vue
│ ├── LargeGameDetail.vue
│ ├── NextShowing.vue
│ ├── NowShowing.vue
│ ├── ObjectivesList.vue
│ ├── Player.vue
│ ├── Recap.vue
│ ├── RegistrationButtons.vue
│ ├── ScheduleBlock.vue
│ ├── SubScore.vue
│ ├── VoteBox.vue
│ └── WebViewer.vue
├── grid
│ ├── Column.vue
│ ├── Container.vue
│ └── Row.vue
├── layout
│ ├── Footer.vue
│ ├── Header.vue
│ ├── HeaderMobile.vue
│ └── PageBanner.vue
├── mod
│ ├── ListingFilters.vue
│ ├── ModSidebar.vue
│ ├── ObjectivesEdit.vue
│ ├── PanelHeader.vue
│ ├── game
│ │ ├── GameBrief.vue
│ │ ├── GameDetails.vue
│ │ └── GameEdit.vue
│ └── schedule
│ │ └── ScheduleSetup.vue
├── modal
│ ├── AddPlayerModal.vue
│ ├── AddRegistrantModal.vue
│ ├── ConfirmModal.vue
│ ├── CreateGameModal.vue
│ ├── CropperModal.vue
│ ├── DeleteModal.vue
│ ├── EndGameModal.vue
│ ├── GameRegistration.vue
│ ├── GameResignModal.vue
│ └── ViewObjectivesModal.vue
├── toast
│ ├── Toast.vue
│ └── Toasts.vue
└── user
│ ├── Avatar.vue
│ ├── ConnectToDiscord.vue
│ ├── ConnectToTwitch.vue
│ ├── ConnectionsSmall.vue
│ └── User.vue
├── layouts
├── default.vue
├── error.vue
└── header.vue
├── middleware
├── auth.js
├── no-competitors.js
└── update-latest-route.js
├── nuxt.config.js
├── package-lock.json
├── package.json
├── pages
├── badges.vue
├── competitor
│ ├── register.vue
│ └── registered.vue
├── contact.vue
├── dashboard
│ └── _dashboard.vue
├── docs.vue
├── forgot-password.vue
├── game
│ └── confirmation.vue
├── games
│ ├── _id.vue
│ └── index.vue
├── index.vue
├── leaderboards.vue
├── login.vue
├── mod.vue
├── mod
│ ├── dashboard.vue
│ ├── game.vue
│ ├── games.vue
│ ├── index.vue
│ ├── logs.vue
│ ├── tournament.vue
│ ├── tournament
│ │ └── details.vue
│ ├── tournaments.vue
│ └── users.vue
├── pending.vue
├── register.vue
├── reset-password.vue
├── schedule.vue
├── settings.vue
├── settings
│ ├── account.vue
│ ├── connections.vue
│ ├── notifications.vue
│ └── profile.vue
└── shop.vue
├── plugins
├── axios.js
├── directives.js
├── filters.js
├── ga.js
├── global.js
├── highlight.js
├── mixins.js
├── modal.js
└── send-back.js
├── static
├── favicon.ico
├── img
│ ├── badges
│ │ ├── ace-high.png
│ │ ├── authentic.png
│ │ ├── beginner's-luck.png
│ │ ├── biggest-fan.png
│ │ ├── cake-day.png
│ │ ├── exterminator.png
│ │ ├── feed-the-pig.png
│ │ ├── first-timer.png
│ │ ├── follow-me.png
│ │ ├── full-coverage.png
│ │ ├── high-roller.png
│ │ ├── hobbyist.png
│ │ ├── hotshot.png
│ │ ├── influential.png
│ │ ├── innovator.png
│ │ ├── making-links.png
│ │ ├── mystery.png
│ │ ├── natural-leader.png
│ │ ├── obsessed.png
│ │ ├── on-the-ball.png
│ │ ├── penny-pincher.png
│ │ ├── smarty-pants.png
│ │ ├── steamroller.png
│ │ └── victorious.png
│ ├── become-contestant-bg.jpg
│ ├── browsers
│ │ ├── chrome_48x48.png
│ │ ├── edge_48x48.png
│ │ ├── firefox_48x48.png
│ │ └── safari_48x48.png
│ ├── companies
│ │ ├── devtips-square.png
│ │ ├── discord-color.png
│ │ ├── discord-white.png
│ │ ├── hiringsolved-color.png
│ │ ├── hiringsolved-white.png
│ │ ├── microsoft-color.png
│ │ ├── microsoft-white.png
│ │ ├── scotchio-square.jpg
│ │ ├── twitch-color.png
│ │ └── twitch-white.png
│ ├── default-avatar.png
│ ├── devwars-docs-bg.jpg
│ ├── docs
│ │ └── en-lang.png
│ ├── error-sad.png
│ ├── hero-bg.jpg
│ ├── starburst.png
│ ├── team-blue.png
│ └── team-red.png
└── og
│ └── logo.png
├── store
├── badges.js
├── game.js
├── index.js
├── modal.js
├── server.js
├── toast.js
└── user.js
└── utils
├── auth.js
├── gameDurations.js
├── gameStatus.js
├── linkedAccounts.js
├── mixins.js
└── objectives.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "test": {
4 | "presets": [
5 | [
6 | "@babel/preset-env",
7 | {
8 | "targets": {
9 | "node": "current"
10 | }
11 | }
12 | ]
13 | ]
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.env.example:
--------------------------------------------------------------------------------
1 | DISCORD_CLIENT=
2 | TWITCH_CLIENT=
3 |
4 | API_URL=http://localhost:8080
5 | BASE_URL=http://localhost:3000
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | name: Node.js CI
2 |
3 | on:
4 | push:
5 | branches: [master]
6 | pull_request:
7 | branches: [master]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | strategy:
14 | matrix:
15 | node-version: [12.x]
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Use Node.js ${{ matrix.node-version }}
20 | uses: actions/setup-node@v1
21 | with:
22 | node-version: ${{ matrix.node-version }}
23 | - run: npm ci
24 | - run: git submodule update --init --recursive
25 | - run: npm run lint --if-present
26 | - run: npm run build --if-present
27 | # - run: npm test
28 | env:
29 | CI: true
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 |
3 | # dependencies
4 | node_modules
5 |
6 | # logs
7 | npm-debug.log
8 |
9 | # Nuxt build
10 | .nuxt
11 |
12 | .idea/
13 |
14 | # Nuxt generate
15 | dist
16 |
17 | # temp
18 | yarn.lock
19 |
20 | .env
21 | .vscode
22 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "client"]
2 | path = client
3 | url = https://github.com/DevWars/DevWars-API-Client
4 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "singleQuote": true,
3 | "trailingComma": "all",
4 | "arrowParens": "always",
5 | "semi": true
6 | }
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2020 DevWars, LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
DevWars TV
5 |
The Human Layer of the Stack
6 |
7 |
8 |
9 | Welcome to the [DevWars](https://DevWars.tv) TV codebase. This is the core UI and interface for the the DevWars platform.
10 |
11 | ## What is DevWars?
12 |
13 | [DevWars.tv](https://www.devwars.tv/) is a live game show for developers that is currently streamed on [Twitch](https://www.twitch.tv/devwars). People of all levels participate in an exhilarating battle to create the best website they can within 60 minutes. Teams are formed of 3 people, with the team's members each controlling a single language - HTML, CSS and JavaScript.
14 |
15 | ## Getting Started
16 |
17 | ### Prerequisites
18 |
19 | - [Nodejs](https://nodejs.org/en/): 10.0 or higher
20 | - [DevWars API](https://github.com/devwars/devwars-api/): Lastest version.
21 |
22 | ### Dependency Installation
23 |
24 | Run `npm install` to install dependent node_modules.
25 |
26 | ### Environment Variables
27 |
28 | Make a copy of the `.env.example` file in the same directory and rename the given file to `.env`. This will be loaded up into the application when it first starts running. These are required configuration settings to ensure correct function. Process through the newly created file and make the required changes if needed.
29 |
30 | ### Development
31 |
32 | Running `npm run dev` will start a development server that will automatically restart when changes occur. Additionally running `npm run build` or `npm run start` will allow running a production ready version of the platform.
33 |
34 | ## Contributors
35 |
36 | This project exists thanks to all the people who [contribute](https://github.com/DevWars/devwars.tv/graphs/contributors). We encourage you to contribute to DevWars but ensure to open a related issue first. Please check out the [contributing](CONTRIBUTING.md) to DevWars guide for guidelines about how to proceed.
37 |
38 | ## License
39 |
40 | > You can check out the full license [here](https://github.com/DevWars/devwars.tv/blob/master/LICENSE)
41 |
42 | This project is licensed under the terms of the **MIT** license.
43 |
--------------------------------------------------------------------------------
/assets/styles/_components.scss:
--------------------------------------------------------------------------------
1 | $input-padding-y: 6px;
2 | $input-label-offset: $input-padding-y * 2;
3 |
4 | %form-control {
5 | display: block;
6 | width: 100%;
7 | padding: $input-padding-y 0;
8 | font-size: $font-size-base;
9 | line-height: 1.25;
10 | color: $base-font-color;
11 | background-color: transparent;
12 | background-image: none;
13 | background-clip: padding-box;
14 | border: none;
15 | border-bottom: 1px solid $text-color-muted;
16 |
17 | &:focus {
18 | border-color: $brand-secondary;
19 | outline: none;
20 | }
21 |
22 | &::placeholder {
23 | color: $text-color-muted;
24 | }
25 |
26 | &:disabled {
27 | color: #484b5b;
28 | }
29 |
30 | // Change Autocomplete styles in Chrome
31 | &:-webkit-autofill,
32 | &:-webkit-autofill:hover,
33 | &:-webkit-autofill:focus {
34 | -webkit-text-fill-color: #fff;
35 | box-shadow: 0 0 0px 1000px transparent inset;
36 | transition: background-color 5000s ease-in-out 0s;
37 | }
38 | }
39 |
40 | %form-group {
41 | margin-bottom: 30px;
42 | }
43 |
44 | %form-label {
45 | margin-top: $input-label-offset;
46 | position: relative;
47 |
48 | label {
49 | line-height: 1;
50 | color: $text-color-muted;
51 | font-size: $font-size-base;
52 | position: absolute;
53 | pointer-events: none;
54 | left: 0;
55 | top: $input-padding-y;
56 | transition: 0.2s ease all;
57 | }
58 |
59 | input,
60 | select,
61 | textarea {
62 | &:required ~ label:after {
63 | content: ' *';
64 | color: $danger-color;
65 | opacity: 0.4;
66 | }
67 |
68 | &:invalid {
69 | color: $danger-color;
70 | }
71 |
72 | &.empty:placeholder-shown ~ label,
73 | &:focus ~ label,
74 | &.valid ~ label,
75 | &.empty:focus ~ label {
76 | top: -($input-label-offset / 0.9);
77 | font-size: $font-size-sm;
78 | }
79 |
80 | &.empty ~ label {
81 | font-size: $font-size-base;
82 | top: $input-padding-y;
83 | }
84 |
85 | &:focus ~ label {
86 | color: $brand-secondary;
87 | }
88 |
89 | &:required:focus ~ label:after {
90 | opacity: 1;
91 | }
92 | }
93 | }
94 |
95 | // Aligns element to baseline of any form element with labels
96 | %align-baseline-to-input-with-labels {
97 | margin-top: $input-label-offset + $input-padding-y / 2;
98 | }
99 |
100 | // Temporary
101 | .v--modal {
102 | &-box {
103 | height: auto !important;
104 | padding: $grid-gutter-width !important;
105 | background-color: $bg-color-3 !important;
106 | animation-duration: 250ms !important;
107 | }
108 |
109 | &-overlay {
110 | background-color: rgba(#000, 0.8) !important;
111 | }
112 |
113 | h1 {
114 | margin-bottom: $grid-gutter-width;
115 | }
116 | }
117 |
118 | .modal {
119 | &__actions {
120 | margin-top: $m-space;
121 | text-align: right;
122 |
123 | .Button:not(:last-child) {
124 | margin-right: $grid-gutter-width;
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/assets/styles/_mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin size($width, $height: $width) {
2 | height: $height;
3 | width: $width;
4 | }
5 |
6 | @mixin aspect-ratio($width, $height) {
7 | position: relative;
8 | &:before {
9 | display: block;
10 | content: '';
11 | width: 100%;
12 | padding-top: ($height / $width) * 100%;
13 | }
14 | > .aspect {
15 | position: absolute;
16 | width: 100%;
17 | height: 100%;
18 | top: 0;
19 | left: 0;
20 | right: 0;
21 | bottom: 0;
22 | border: 0;
23 | }
24 | }
25 |
26 | @mixin clear-position {
27 | position: relative;
28 | top: auto;
29 | right: auto;
30 | left: auto;
31 | bottom: auto;
32 | transform: none;
33 | }
34 |
35 | @mixin clear-aspect-ratio {
36 | &:before {
37 | display: none;
38 | }
39 | }
40 |
41 | @mixin material($depth: 1) {
42 | @if $depth == 1 {
43 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
44 | } @else if $depth == 2 {
45 | box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
46 | } @else if $depth == 3 {
47 | box-shadow: 0 10px 20px rgba(0, 0, 0, 0.19);
48 | } @else if $depth == 4 {
49 | box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25);
50 | } @else if $depth == 5 {
51 | box-shadow: 0 19px 38px rgba(0, 0, 0, 0.3);
52 | }
53 | }
54 |
55 | @mixin linear-gradient($direction, $color-stops...) {
56 | background: nth(nth($color-stops, 1), 1);
57 | background: linear-gradient($direction, $color-stops);
58 | }
59 |
60 | @mixin spacing($prop, $property, $dir, $direction) {
61 | .#{$prop}#{$dir} {
62 | &-0 {
63 | #{$property}-#{$direction}: 0 !important;
64 | }
65 | &-xs {
66 | #{$property}-#{$direction}: $xs-space !important;
67 | }
68 | &-15 {
69 | #{$property}-#{$direction}: $grid-gutter-width !important;
70 | }
71 | &-sm {
72 | #{$property}-#{$direction}: $s-space !important;
73 | }
74 | &-30 {
75 | #{$property}-#{$direction}: 30px !important;
76 | }
77 | &-md {
78 | #{$property}-#{$direction}: $m-space !important;
79 | }
80 | &-60 {
81 | #{$property}-#{$direction}: 60px !important;
82 | }
83 | &-lg {
84 | #{$property}-#{$direction}: $l-space !important;
85 | }
86 | &-xl {
87 | #{$property}-#{$direction}: $xl-space !important;
88 | }
89 | }
90 | }
91 |
92 | /* ==========================================================================
93 | XX. Unaccessible Scoped Functions
94 | ========================================================================== */
95 | @mixin breakpoint($breakpoint, $range: max) {
96 | @media (#{$range}-width: map-get($grid-breakpoints, $breakpoint)) {
97 | @content;
98 | }
99 | }
100 |
101 | @mixin col-breakpoint($point) {
102 | @if $point == lg {
103 | @media (min-width: map-get($grid-breakpoints, md)) {
104 | @content;
105 | }
106 | }
107 | @if $point == md {
108 | @media (min-width: map-get($grid-breakpoints, sm)) {
109 | @content;
110 | }
111 | }
112 | @if $point == sm {
113 | @media (min-width: map-get($grid-breakpoints, xs)) {
114 | @content;
115 | }
116 | }
117 | @if $point == xs {
118 | @media (min-width: 0px) {
119 | @content;
120 | }
121 | }
122 | }
123 |
--------------------------------------------------------------------------------
/assets/styles/_placeholders.scss:
--------------------------------------------------------------------------------
1 | %truncate {
2 | overflow: hidden;
3 | text-overflow: ellipsis;
4 | white-space: nowrap;
5 | }
6 |
7 | %clear {
8 | &:after {
9 | content: '';
10 | display: table;
11 | clear: both;
12 | }
13 | }
14 |
15 | %clear-inline {
16 | font-size: 0;
17 | > * {
18 | font-size: $font-size-base;
19 | }
20 | }
21 |
22 | %material {
23 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
24 | }
25 |
26 | %material-soft {
27 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.08);
28 | }
29 |
30 | %material-hover {
31 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
32 | transform: translateY(0%);
33 | transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
34 |
35 | &:hover {
36 | box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
37 | transform: translateY(-4px);
38 | }
39 | }
40 |
41 | %flex-justify {
42 | display: flex;
43 | justify-content: space-between;
44 | align-items: center;
45 |
46 | &:after {
47 | content: normal;
48 | }
49 | }
50 |
51 | %absolute-overlay {
52 | position: absolute;
53 | top: 0;
54 | right: 0;
55 | bottom: 0;
56 | left: 0;
57 | width: 100%;
58 | height: 100%;
59 | }
60 |
61 | %fixed-overlay {
62 | position: fixed;
63 | top: 0;
64 | right: 0;
65 | bottom: 0;
66 | left: 0;
67 | }
68 |
69 | %absolute-center {
70 | position: absolute;
71 | top: 50%;
72 | left: 50%;
73 | transform: translate(-50%, -50%);
74 | }
75 |
76 | %absolute-center-x {
77 | position: absolute;
78 | left: 50%;
79 | transform: translateX(-50%);
80 | }
81 |
82 | %absolute-center-y {
83 | position: absolute;
84 | top: 50%;
85 | transform: translateY(-50%);
86 | }
87 |
88 | %align-middle {
89 | display: inline-block;
90 | vertical-align: middle;
91 | }
92 |
93 | %fill-gutter {
94 | width: calc(100% - $grid-gutter-width);
95 | margin-left: $grid-gutter-width;
96 | margin-right: $grid-gutter-width;
97 | }
98 |
99 | %readable-width {
100 | max-width: 700px;
101 | margin-left: auto;
102 | margin-right: auto;
103 | }
104 |
105 | %brand-skew {
106 | transform: skew(-12deg);
107 | }
108 |
109 | %list-unstyled {
110 | padding-left: 0;
111 | list-style: none;
112 | }
113 |
114 | %no-gutter {
115 | padding-left: 0;
116 | padding-right: 0;
117 | }
118 |
--------------------------------------------------------------------------------
/assets/styles/utils.scss:
--------------------------------------------------------------------------------
1 | @import './variables';
2 | @import './mixins';
3 | @import './placeholders';
4 | @import './components';
5 |
--------------------------------------------------------------------------------
/components/Card.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
5 |
6 |
7 |
8 |
20 |
21 |
66 |
--------------------------------------------------------------------------------
/components/DashboardCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
32 |
33 |
59 |
--------------------------------------------------------------------------------
/components/DevcoinIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
18 |
19 |
24 |
25 |
26 |
27 |
32 |
33 |
40 |
--------------------------------------------------------------------------------
/components/Devcoins.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ amount | formatNumber }}
5 |
6 |
7 |
8 |
22 |
23 |
67 |
--------------------------------------------------------------------------------
/components/DevwarsCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
{{ desc }}
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
31 |
32 |
73 |
--------------------------------------------------------------------------------
/components/FileChooser.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
13 |
36 |
--------------------------------------------------------------------------------
/components/HomeCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
27 |
28 |
79 |
--------------------------------------------------------------------------------
/components/LinkTabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
82 |
83 |
145 |
--------------------------------------------------------------------------------
/components/Logo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
30 |
31 |
58 |
--------------------------------------------------------------------------------
/components/Pagination.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
47 |
48 |
62 |
--------------------------------------------------------------------------------
/components/Popup.vue:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
17 |
32 |
33 |
89 |
--------------------------------------------------------------------------------
/components/SquareToggle.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
29 |
30 |
58 |
--------------------------------------------------------------------------------
/components/Tabbed.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
59 |
60 |
111 |
--------------------------------------------------------------------------------
/components/TabbedItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
34 |
--------------------------------------------------------------------------------
/components/Table.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
19 |
20 |
80 |
--------------------------------------------------------------------------------
/components/Tag.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
64 |
--------------------------------------------------------------------------------
/components/common/ButtonGroup.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
24 |
--------------------------------------------------------------------------------
/components/common/ButtonIcon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
29 |
30 |
60 |
--------------------------------------------------------------------------------
/components/common/Icon.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
35 |
--------------------------------------------------------------------------------
/components/common/button.module.js:
--------------------------------------------------------------------------------
1 | function parseTag(attrs) {
2 | const aTag = attrs.tag && String(attrs.tag).toLowerCase() === 'a';
3 |
4 | if (Object.prototype.hasOwnProperty.call(attrs, 'href') || aTag) {
5 | return 'a';
6 | }
7 |
8 | if (Object.prototype.hasOwnProperty.call(attrs, 'to')) {
9 | return 'nuxt-link';
10 | }
11 |
12 | return 'button';
13 | }
14 |
15 | export default {
16 | name: 'Button',
17 |
18 | render(h) {
19 | const tag = parseTag(this.$attrs);
20 |
21 | if (tag === 'a') {
22 | return h(
23 | tag,
24 | {
25 | attrs: {
26 | href: this.$attrs.href,
27 | },
28 | },
29 | this.$slots.default,
30 | );
31 | }
32 |
33 | if (tag === 'nuxt-link') {
34 | return (
35 | {this.$slots.default}
36 | );
37 | }
38 |
39 | return h(
40 | tag,
41 | {
42 | attrs: {
43 | type: 'button',
44 | },
45 | },
46 | this.$slots.default,
47 | );
48 | },
49 | };
50 |
--------------------------------------------------------------------------------
/components/dashboard/Activities.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {{ activity.createdAt | moment('mediumDate') }}
7 |
8 |
9 |
10 | {{ activity.description }}
11 |
12 |
13 |
18 |
19 | {{ activity.coins | formatNumber }}
20 |
21 |
26 |
XP
27 |
{{ activity.xp | formatNumber }}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
53 |
54 |
105 |
--------------------------------------------------------------------------------
/components/dashboard/BadgeCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
{{ badge.name }}
10 |
11 |
12 |
Earned on {{ badge.createdAt | moment('M/DD/YYYY') }}
13 |
Not earned
14 |
15 |
16 |
17 |
18 |
43 |
44 |
85 |
--------------------------------------------------------------------------------
/components/dashboard/Badges.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{ owned.length }}
7 |
8 |
9 |
View Badges
10 |
11 |
16 |
17 |
18 |
19 |
20 |
43 |
44 |
75 |
--------------------------------------------------------------------------------
/components/dashboard/DailyPrizes.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ task.message }}
10 |
11 |
12 |
{{ task.action }}
13 |
14 |
15 |
16 |
17 |
18 | Currently no active daily tasks 😟
19 |
20 |
21 |
22 |
23 |
24 |
25 |
38 |
39 |
56 |
--------------------------------------------------------------------------------
/components/dashboard/GamesPlayed.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Date
6 | Time
7 | Duration
8 | Title
9 |
10 |
11 |
12 |
13 | {{ game.startTime | moment('mediumDate') }}
14 | {{ game.startTime | moment('H:mm') }} UTC
15 | {{ durations[game.mode] || '30' }} minutes
16 | {{ game.title }}
17 |
18 |
22 | View
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | No games played by {{ user.username }} 😟
32 |
33 |
34 |
35 |
36 |
37 |
38 |
62 |
63 |
119 |
--------------------------------------------------------------------------------
/components/dashboard/ProfileCard.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ user.username }}
5 |
6 | RANK
7 |
8 |
9 |
10 |
11 |
12 |
13 |
45 |
46 |
73 |
--------------------------------------------------------------------------------
/components/dashboard/UpcomingGames.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 | {{ isApplied(game) ? 'Entered' : 'Not Entered' }}
12 |
13 |
14 | {{ game.startTime | moment('longDate') }}
15 | @ {{ game.startTime | moment('HH:mm') }} (UTC)
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
55 |
56 |
83 |
--------------------------------------------------------------------------------
/components/dashboard/Wallet.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Shop
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
43 |
44 |
97 |
--------------------------------------------------------------------------------
/components/form/Checkbox.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
$emit('input', e.target.checked)"
8 | />
9 |
10 |
11 |
12 |
13 | {{ label }}
14 |
15 |
16 |
17 |
18 |
31 |
32 |
128 |
--------------------------------------------------------------------------------
/components/form/Input.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | [
12 | $emit('input', e.target.value),
13 | inputChange(e.target.value),
14 | ]
15 | "
16 | />
17 | {{ label }}
18 |
19 |
20 |
21 |
68 |
69 |
88 |
--------------------------------------------------------------------------------
/components/form/Progress.vue:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
13 |
36 |
37 |
74 |
--------------------------------------------------------------------------------
/components/form/Select.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | [
10 | $emit('change', e.target.value),
11 | inputChange(e.target.value),
12 | ]
13 | "
14 | @input="(e) => $emit('input', e.target.value)"
15 | >
16 |
17 |
18 | {{ label }}
19 |
20 |
21 |
22 |
23 |
24 |
56 |
57 |
115 |
--------------------------------------------------------------------------------
/components/form/Textarea.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
20 |
62 |
63 |
84 |
--------------------------------------------------------------------------------
/components/game/GameEditor.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
51 |
52 |
119 |
--------------------------------------------------------------------------------
/components/game/GameTeam.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
37 |
38 |
102 |
--------------------------------------------------------------------------------
/components/game/Highlights.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
DevWars not live?
10 |
11 | You can still watch recent recordings, check out past games, or hang out in our Discord community.
12 |
13 |
14 |
15 |
20 | Join Discord
21 |
22 |
23 | Past Recordings
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
67 |
68 |
97 |
--------------------------------------------------------------------------------
/components/game/NowShowing.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Live Now
5 |
6 |
7 |
20 |
21 |
22 |
27 | Watch on Twitch
28 |
29 |
34 | Register to Play
35 |
36 |
37 |
38 |
39 |
40 |
41 |
71 |
72 |
124 |
--------------------------------------------------------------------------------
/components/game/ObjectivesList.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
25 | {{ objective.description }}
26 |
35 |
36 |
37 |
38 |
39 |
40 |
63 |
64 |
107 |
--------------------------------------------------------------------------------
/components/game/Player.vue:
--------------------------------------------------------------------------------
1 |
2 | {}"
7 | >
8 |
13 |
14 |
15 |
20 | {{ language }}
21 |
22 |
23 |
24 |
25 |
26 |
58 |
59 |
113 |
--------------------------------------------------------------------------------
/components/game/RegistrationButtons.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | Register
10 |
11 |
12 | Resign
13 |
14 |
15 |
16 |
17 |
18 |
63 |
--------------------------------------------------------------------------------
/components/game/SubScore.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
44 |
45 |
113 |
--------------------------------------------------------------------------------
/components/game/WebViewer.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
25 |
26 |
35 |
--------------------------------------------------------------------------------
/components/grid/Column.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
33 |
34 |
59 |
--------------------------------------------------------------------------------
/components/grid/Container.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
33 |
--------------------------------------------------------------------------------
/components/grid/Row.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
33 |
--------------------------------------------------------------------------------
/components/mod/ListingFilters.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $emit('change', e)">
5 |
6 | {{ x.name }}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
37 |
38 |
64 |
--------------------------------------------------------------------------------
/components/mod/PanelHeader.vue:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
47 |
48 |
87 |
--------------------------------------------------------------------------------
/components/mod/game/GameBrief.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
19 |
20 |
21 |
22 | No players
23 |
24 |
25 |
30 |
31 |
32 |
33 |
112 |
113 |
124 |
--------------------------------------------------------------------------------
/components/modal/AddPlayerModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
38 |
39 |
40 |
92 |
--------------------------------------------------------------------------------
/components/modal/ConfirmModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
{{ description }}
5 |
6 |
7 | {{ cancelText }}
8 | {{ confirmText }}
9 |
10 |
11 |
12 |
13 |
44 |
--------------------------------------------------------------------------------
/components/modal/CreateGameModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
39 |
40 |
41 |
105 |
--------------------------------------------------------------------------------
/components/modal/CropperModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Crop Image
9 |
10 |
11 |
12 |
13 |
51 |
--------------------------------------------------------------------------------
/components/modal/DeleteModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ title }}
4 |
{{ description }}
5 |
6 |
7 | {{ cancel }}
8 | {{ confirm }}
9 |
10 |
11 |
12 |
13 |
44 |
--------------------------------------------------------------------------------
/components/modal/EndGameModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | {{ team.name | capitalize }}
10 |
11 |
12 |
13 |
14 |
35 |
--------------------------------------------------------------------------------
/components/modal/GameRegistration.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Become a competitor
5 |
6 | In order to compete in live DevWars games, you must first complete
7 | the
8 | competitor registration form .
9 |
10 |
11 |
12 | Nevermind
13 |
14 |
19 | Begin Registration
20 |
21 |
22 |
23 |
24 |
25 |
26 |
Entry confirmation
27 |
28 | You are entering to play on
29 | {{ game.startTime | moment('fullDate') }} at
30 | {{ game.startTime | moment('HH:mm') }} (UTC) . Are you sure?
31 |
32 |
33 |
34 | *Entering to compete does not guarantee you will play in a live
35 | game. You will be notified 24-48 hours before the show if you are
36 | selected to play. If you are not selected, you may still be eligible
37 | to play if you are available and a selected contestant is unable to
38 | play.
39 |
40 |
41 |
42 | Nevermind
43 | Enter
44 |
45 |
46 |
47 |
48 |
84 |
--------------------------------------------------------------------------------
/components/modal/GameResignModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Resign confirmation
4 |
Are you sure you would like to cancel?
5 |
6 |
7 | Cancel
8 | Resign
9 |
10 |
11 |
12 |
13 |
40 |
--------------------------------------------------------------------------------
/components/modal/ViewObjectivesModal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Close
7 |
8 |
9 |
10 |
11 |
25 |
--------------------------------------------------------------------------------
/components/toast/Toast.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{ toast.message }}
5 |
6 |
7 |
8 |
9 |
35 |
36 |
88 |
--------------------------------------------------------------------------------
/components/toast/Toasts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
20 |
21 |
33 |
--------------------------------------------------------------------------------
/components/user/Avatar.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
25 |
26 |
63 |
--------------------------------------------------------------------------------
/components/user/ConnectToDiscord.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | Connect Discord
10 |
11 |
17 | Disconnect Discord
18 |
19 |
20 |
21 |
22 |
61 |
62 |
67 |
--------------------------------------------------------------------------------
/components/user/ConnectToTwitch.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 | Connect Twitch
10 |
11 |
17 | Disconnect Twitch
18 |
19 |
20 |
21 |
22 |
61 |
62 |
67 |
--------------------------------------------------------------------------------
/components/user/ConnectionsSmall.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
11 |
12 |
30 |
31 |
38 |
--------------------------------------------------------------------------------
/components/user/User.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | {{ user.username }}
10 |
11 |
12 |
13 |
14 |
15 |
65 |
66 |
100 |
--------------------------------------------------------------------------------
/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
29 |
30 |
166 |
--------------------------------------------------------------------------------
/layouts/error.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | {{ error.statusCode }}
11 | {{ error.message }}
12 | {{ error.description }}
13 |
14 | Go to home
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | 404
25 | Page not found
26 |
27 | The page you are looking for does not exist. Sorry!
28 |
29 |
30 | Go to home
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | 500
41 | It's not you, It's us.
42 | This page is experiencing internal server issues.
43 |
44 | Go to home
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Oops!
55 | Looks like something went wrong.
56 |
57 | Go to home
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
80 |
81 |
107 |
--------------------------------------------------------------------------------
/layouts/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
22 |
--------------------------------------------------------------------------------
/middleware/auth.js:
--------------------------------------------------------------------------------
1 | import { isAuthorized, sameRole } from '../utils/auth';
2 | // import { isAuthorized } from '../utils/auth';
3 |
4 | export default ({ store, route, redirect, error }) => {
5 | route.meta.map((meta) => {
6 | if (meta.auth) {
7 | if (!store.state.user.user) {
8 | return redirect('/login');
9 | }
10 |
11 | const role = store.state.user.user.role || 'PENDING';
12 |
13 | if (typeof meta.auth !== 'string') {
14 | return error({
15 | statusCode: 500,
16 | message: 'meta auth should be a string',
17 | });
18 | }
19 |
20 | const ok = isAuthorized(role, meta.auth);
21 |
22 | if (!ok && meta.redirectIfNot) {
23 | return redirect(meta.redirectIfNot);
24 | }
25 | if (!ok) {
26 | return error({
27 | statusCode: 401,
28 | message: 'What you trying',
29 | });
30 | }
31 |
32 | // Redirect user if email has not been verified
33 | if (role === 'PENDING' && route.name !== 'pending') {
34 | return redirect('/pending');
35 | }
36 |
37 | if (meta.limit && !sameRole(role, meta.auth)) {
38 | if (meta.redirectIfNot) {
39 | return redirect(meta.redirectIfNot);
40 | }
41 | return redirect('/');
42 | }
43 | }
44 | if (meta.noAuth && store.state.user.user) {
45 | return redirect('/dashboard');
46 | }
47 | });
48 | };
49 |
--------------------------------------------------------------------------------
/middleware/no-competitors.js:
--------------------------------------------------------------------------------
1 | export default function({ store, redirect }) {
2 | if (store.getters['user/isCompetitor']) {
3 | return redirect('/competitor/registered');
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/middleware/update-latest-route.js:
--------------------------------------------------------------------------------
1 | export default function({ isClient, route }) {
2 | if (isClient) {
3 | // Client side we'll grab the most recent path from local storage
4 | window.localStorage.setItem('latestRoute', route.fullPath);
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "devwars.tv",
3 | "version": "0.2.1",
4 | "description": "Front-end website for DevWars",
5 | "author": "DevWars, LLC",
6 | "license": "MIT",
7 | "scripts": {
8 | "dev": "nuxt",
9 | "build": "nuxt build",
10 | "start": "nuxt start",
11 | "generate": "nuxt generate",
12 | "precommit": "npm run lint",
13 | "release": "standard-version"
14 | },
15 | "dependencies": {
16 | "@nuxtjs/axios": "^5.12.3",
17 | "@nuxtjs/dotenv": "^1.4.0",
18 | "country-list": "^2.2.0",
19 | "cropperjs": "^1.5.7",
20 | "devwars-api-client": "git+https://github.com/DevWars/devwars-api-client.git#1b9543d80ae7e482c9fe90993af5e1c894f9573d",
21 | "highlight.js": "^10.4.1",
22 | "lodash": "^4.17.19",
23 | "moment": "2.25.3",
24 | "nuxt": "^2.14",
25 | "vue-awesome": "^4.1.0",
26 | "vue-js-modal": "^1.3.35",
27 | "vue2-filters": "^0.11.0"
28 | },
29 | "devDependencies": {
30 | "@vue/test-utils": "^1.0.2",
31 | "babel-eslint": "^10.1.0",
32 | "node-sass": "^4.14.1",
33 | "sass-loader": "^9.0.3",
34 | "standard-version": "^9.0.0"
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/pages/badges.vue:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
51 |
--------------------------------------------------------------------------------
/pages/competitor/registered.vue:
--------------------------------------------------------------------------------
1 |
2 |
18 |
19 |
20 |
33 |
--------------------------------------------------------------------------------
/pages/contact.vue:
--------------------------------------------------------------------------------
1 |
2 |
56 |
57 |
58 |
109 |
110 |
117 |
--------------------------------------------------------------------------------
/pages/dashboard/_dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 |
27 |
28 |
29 |
105 |
106 |
123 |
--------------------------------------------------------------------------------
/pages/forgot-password.vue:
--------------------------------------------------------------------------------
1 |
2 |
46 |
47 |
48 |
70 |
71 |
78 |
--------------------------------------------------------------------------------
/pages/game/confirmation.vue:
--------------------------------------------------------------------------------
1 |
2 |
33 |
34 |
35 |
45 |
46 |
53 |
--------------------------------------------------------------------------------
/pages/leaderboards.vue:
--------------------------------------------------------------------------------
1 |
2 |
43 |
44 |
45 |
75 |
76 |
116 |
--------------------------------------------------------------------------------
/pages/login.vue:
--------------------------------------------------------------------------------
1 |
2 |
43 |
44 |
45 |
84 |
85 |
102 |
--------------------------------------------------------------------------------
/pages/mod.vue:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
22 |
23 |
43 |
--------------------------------------------------------------------------------
/pages/mod/dashboard.vue:
--------------------------------------------------------------------------------
1 |
2 | Welcome to the Dashboard
3 |
4 |
5 |
16 |
17 |
25 |
--------------------------------------------------------------------------------
/pages/mod/index.vue:
--------------------------------------------------------------------------------
1 |
2 | mod dashboard home
3 |
4 |
5 |
14 |
--------------------------------------------------------------------------------
/pages/mod/logs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 | Error Logs
10 |
11 |
16 | All Logs
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
76 |
77 |
96 |
--------------------------------------------------------------------------------
/pages/mod/tournament/details.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Main
5 |
10 |
11 | Prizes
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
96 |
97 |
104 |
--------------------------------------------------------------------------------
/pages/mod/tournaments.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Add Tournament
5 |
6 |
7 |
8 |
9 |
10 |
11 | Date
12 | Status
13 | Tournament Name
14 |
15 |
16 |
17 |
18 | 11/04/2018
19 |
20 | PREPARING
21 |
22 | DigitalOcean Tournament
23 |
24 | Edit
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
50 |
51 |
79 |
--------------------------------------------------------------------------------
/pages/pending.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
52 |
53 |
58 |
--------------------------------------------------------------------------------
/pages/register.vue:
--------------------------------------------------------------------------------
1 |
2 |
38 |
39 |
40 |
74 |
75 |
82 |
--------------------------------------------------------------------------------
/pages/reset-password.vue:
--------------------------------------------------------------------------------
1 |
2 |
49 |
50 |
51 |
90 |
91 |
98 |
--------------------------------------------------------------------------------
/pages/schedule.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Filter by
6 | Classic
7 | Zen Garden
8 | Blitz
9 |
10 |
11 |
12 |
17 |
18 |
19 |
20 |
37 |
--------------------------------------------------------------------------------
/pages/settings.vue:
--------------------------------------------------------------------------------
1 |
2 |
20 |
21 |
22 |
38 |
39 |
44 |
--------------------------------------------------------------------------------
/pages/settings/connections.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Connections
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
35 |
--------------------------------------------------------------------------------
/plugins/axios.js:
--------------------------------------------------------------------------------
1 | import Api from 'devwars-api-client';
2 |
3 | export default function({ $axios }, inject) {
4 | const api = new Api($axios);
5 | return inject('api', api);
6 | }
7 |
--------------------------------------------------------------------------------
/plugins/directives.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | Vue.directive('closable', {
4 | inserted(el, binding) {
5 | const { outSideFrom, handler } = binding.value;
6 | const topContainer = document.body;
7 | const container = outSideFrom
8 | ? document.querySelector(outSideFrom)
9 | : el;
10 |
11 | binding.handler = (e) => {
12 | e.stopPropagation();
13 | if (!container.contains(e.target)) {
14 | document.body.removeEventListener('touch', binding.handler);
15 | document.body.removeEventListener('click', binding.handler);
16 | handler();
17 | }
18 | };
19 |
20 | setTimeout(() => {
21 | topContainer.addEventListener('touch', binding.handler);
22 | topContainer.addEventListener('click', binding.handler);
23 | }, 0);
24 | },
25 | unbind: (el, binding) => {
26 | document.body.removeEventListener('touch', binding.handler);
27 | document.body.removeEventListener('click', binding.handler);
28 | },
29 | });
30 |
--------------------------------------------------------------------------------
/plugins/filters.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Vue2Filters from 'vue2-filters';
3 | import moment from 'moment';
4 |
5 | Vue.filter('formatNumber', (number) => {
6 | return number.toLocaleString();
7 | });
8 |
9 | Vue.filter('moment', (date, format) => {
10 | format =
11 | {
12 | mediumDate: 'MMM D, YYYY',
13 | longDate: 'MMMM D, YYYY',
14 | fullDate: 'dddd, MMMM DD, YYYY',
15 | fullDateWithTime: 'dddd, MMMM DD, YYYY @ HH:mm (UTC)',
16 | }[format] || format;
17 |
18 | return moment.utc(date).format(format);
19 | });
20 |
21 | Vue.use(Vue2Filters);
22 |
--------------------------------------------------------------------------------
/plugins/ga.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 |
3 | export default ({ app }) => {
4 | /*
5 | ** Only run on client-side and only in production mode
6 | */
7 | if (process.env.NODE_ENV !== 'production') return;
8 | /*
9 | ** Include Google Analytics Script
10 | */
11 | (function(i, s, o, g, r, a, m) {
12 | i['GoogleAnalyticsObject'] = r;
13 | (i[r] =
14 | i[r] ||
15 | function() {
16 | (i[r].q = i[r].q || []).push(arguments);
17 | }),
18 | (i[r].l = 1 * new Date());
19 | (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
20 | a.async = 1;
21 | a.src = g;
22 | m.parentNode.insertBefore(a, m);
23 | })(
24 | window,
25 | document,
26 | 'script',
27 | 'https://www.google-analytics.com/analytics.js',
28 | 'ga'
29 | );
30 | /*
31 | ** Set the current page
32 | */
33 | ga('create', 'UA-61426517-1', 'auto');
34 | /*
35 | ** Every time the route changes (fired on initialization too)
36 | */
37 | app.router.afterEach((to, from) => {
38 | /*
39 | ** We tell Google Analytics to add a `pageview`
40 | */
41 | ga('set', 'page', to.fullPath);
42 | ga('send', 'pageview');
43 | });
44 | };
45 |
--------------------------------------------------------------------------------
/plugins/global.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import Container from '@/components/grid/Container';
3 | import Row from '@/components/grid/Row';
4 | import Column from '@/components/grid/Column';
5 | import Icon from '@/components/common/Icon';
6 | import Button from '@/components/common/Button';
7 | import ButtonIcon from '@/components/common/ButtonIcon';
8 | import ButtonGroup from '@/components/common/ButtonGroup';
9 |
10 | Vue.component('Container', Container);
11 | Vue.component('Row', Row);
12 | Vue.component('Column', Column);
13 | Vue.component('Icon', Icon);
14 | Vue.component('Button', Button);
15 | Vue.component('ButtonIcon', ButtonIcon);
16 | Vue.component('ButtonGroup', ButtonGroup);
17 |
--------------------------------------------------------------------------------
/plugins/highlight.js:
--------------------------------------------------------------------------------
1 | import highlight from 'highlight.js/lib/core';
2 | import xml from 'highlight.js/lib/languages/xml';
3 | import css from 'highlight.js/lib/languages/css';
4 | import javascript from 'highlight.js/lib/languages/javascript';
5 | import 'highlight.js/styles/monokai.css';
6 |
7 | highlight.registerLanguage('html', xml);
8 | highlight.registerLanguage('css', css);
9 | highlight.registerLanguage('js', javascript);
10 |
11 | export default highlight;
12 |
--------------------------------------------------------------------------------
/plugins/mixins.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | Vue.mixin({
4 | methods: {
5 | close(args) {
6 | this.$emit('close');
7 |
8 | // Not sure what resolve is used for but prevents 500 error when missing
9 | if (!this.resolve) {
10 | return;
11 | }
12 | this.resolve(args);
13 | },
14 |
15 | $open(component, props) {
16 | return new Promise((resolve) => {
17 | props.resolve = resolve;
18 |
19 | this.$modal.show(component, props, {
20 | transition: 'zoom',
21 | });
22 | });
23 | },
24 | },
25 | });
26 |
--------------------------------------------------------------------------------
/plugins/modal.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 | import VModal from 'vue-js-modal/dist/ssr.index';
3 |
4 | Vue.use(VModal, { dynamic: true });
5 |
--------------------------------------------------------------------------------
/plugins/send-back.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue';
2 |
3 | Vue.mixin({
4 | mounted() {
5 | if (Object.prototype.hasOwnProperty.call(this.$route.query, 'back')) {
6 | this.$router.push({
7 | path: window.localStorage.getItem('latestRoute'),
8 | });
9 | }
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/favicon.ico
--------------------------------------------------------------------------------
/static/img/badges/ace-high.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/ace-high.png
--------------------------------------------------------------------------------
/static/img/badges/authentic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/authentic.png
--------------------------------------------------------------------------------
/static/img/badges/beginner's-luck.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/beginner's-luck.png
--------------------------------------------------------------------------------
/static/img/badges/biggest-fan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/biggest-fan.png
--------------------------------------------------------------------------------
/static/img/badges/cake-day.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/cake-day.png
--------------------------------------------------------------------------------
/static/img/badges/exterminator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/exterminator.png
--------------------------------------------------------------------------------
/static/img/badges/feed-the-pig.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/feed-the-pig.png
--------------------------------------------------------------------------------
/static/img/badges/first-timer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/first-timer.png
--------------------------------------------------------------------------------
/static/img/badges/follow-me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/follow-me.png
--------------------------------------------------------------------------------
/static/img/badges/full-coverage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/full-coverage.png
--------------------------------------------------------------------------------
/static/img/badges/high-roller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/high-roller.png
--------------------------------------------------------------------------------
/static/img/badges/hobbyist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/hobbyist.png
--------------------------------------------------------------------------------
/static/img/badges/hotshot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/hotshot.png
--------------------------------------------------------------------------------
/static/img/badges/influential.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/influential.png
--------------------------------------------------------------------------------
/static/img/badges/innovator.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/innovator.png
--------------------------------------------------------------------------------
/static/img/badges/making-links.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/making-links.png
--------------------------------------------------------------------------------
/static/img/badges/mystery.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/mystery.png
--------------------------------------------------------------------------------
/static/img/badges/natural-leader.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/natural-leader.png
--------------------------------------------------------------------------------
/static/img/badges/obsessed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/obsessed.png
--------------------------------------------------------------------------------
/static/img/badges/on-the-ball.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/on-the-ball.png
--------------------------------------------------------------------------------
/static/img/badges/penny-pincher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/penny-pincher.png
--------------------------------------------------------------------------------
/static/img/badges/smarty-pants.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/smarty-pants.png
--------------------------------------------------------------------------------
/static/img/badges/steamroller.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/steamroller.png
--------------------------------------------------------------------------------
/static/img/badges/victorious.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/badges/victorious.png
--------------------------------------------------------------------------------
/static/img/become-contestant-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/become-contestant-bg.jpg
--------------------------------------------------------------------------------
/static/img/browsers/chrome_48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/browsers/chrome_48x48.png
--------------------------------------------------------------------------------
/static/img/browsers/edge_48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/browsers/edge_48x48.png
--------------------------------------------------------------------------------
/static/img/browsers/firefox_48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/browsers/firefox_48x48.png
--------------------------------------------------------------------------------
/static/img/browsers/safari_48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/browsers/safari_48x48.png
--------------------------------------------------------------------------------
/static/img/companies/devtips-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/devtips-square.png
--------------------------------------------------------------------------------
/static/img/companies/discord-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/discord-color.png
--------------------------------------------------------------------------------
/static/img/companies/discord-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/discord-white.png
--------------------------------------------------------------------------------
/static/img/companies/hiringsolved-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/hiringsolved-color.png
--------------------------------------------------------------------------------
/static/img/companies/hiringsolved-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/hiringsolved-white.png
--------------------------------------------------------------------------------
/static/img/companies/microsoft-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/microsoft-color.png
--------------------------------------------------------------------------------
/static/img/companies/microsoft-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/microsoft-white.png
--------------------------------------------------------------------------------
/static/img/companies/scotchio-square.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/scotchio-square.jpg
--------------------------------------------------------------------------------
/static/img/companies/twitch-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/twitch-color.png
--------------------------------------------------------------------------------
/static/img/companies/twitch-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/companies/twitch-white.png
--------------------------------------------------------------------------------
/static/img/default-avatar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/default-avatar.png
--------------------------------------------------------------------------------
/static/img/devwars-docs-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/devwars-docs-bg.jpg
--------------------------------------------------------------------------------
/static/img/docs/en-lang.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/docs/en-lang.png
--------------------------------------------------------------------------------
/static/img/error-sad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/error-sad.png
--------------------------------------------------------------------------------
/static/img/hero-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/hero-bg.jpg
--------------------------------------------------------------------------------
/static/img/starburst.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/starburst.png
--------------------------------------------------------------------------------
/static/img/team-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/team-blue.png
--------------------------------------------------------------------------------
/static/img/team-red.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/img/team-red.png
--------------------------------------------------------------------------------
/static/og/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevWars/devwars-web/f83696555200d8417fcaf4e904572558346df3a9/static/og/logo.png
--------------------------------------------------------------------------------
/store/badges.js:
--------------------------------------------------------------------------------
1 | export const state = () => ({
2 | badges: [],
3 | });
4 |
5 | export const getters = {
6 | badges(state) {
7 | return state.badges;
8 | },
9 | };
10 |
11 | export const mutations = {
12 | badges(state, badges) {
13 | state.badges = badges;
14 | },
15 | };
16 |
17 | export const actions = {
18 | refresh({ commit }) {},
19 | };
20 |
--------------------------------------------------------------------------------
/store/index.js:
--------------------------------------------------------------------------------
1 | export const state = () => ({});
2 |
3 | export const mutations = {};
4 |
5 | export const actions = {
6 | async nuxtServerInit({ dispatch }) {
7 | await Promise.all([
8 | await dispatch('server/health'),
9 | await dispatch('user/refresh'),
10 |
11 | await dispatch('game/upcoming'),
12 | await dispatch('game/active'),
13 |
14 | // Needs to only dispatch when User is logged in
15 | await dispatch('game/applications'),
16 | ]);
17 | },
18 |
19 | navigate(_, route) {
20 | this.app.router.push(route);
21 | },
22 | };
23 |
24 | // export const strict = process.env.NODE_ENV = "development";
25 | export const strict = false;
26 |
--------------------------------------------------------------------------------
/store/modal.js:
--------------------------------------------------------------------------------
1 | export const state = () => ({
2 | name: '',
3 | data: {},
4 | });
5 |
6 | export const mutations = {
7 | modal(state, { name, data }) {
8 | state.name = name;
9 | state.data = data;
10 | },
11 | };
12 |
--------------------------------------------------------------------------------
/store/server.js:
--------------------------------------------------------------------------------
1 | export const state = () => ({
2 | server: {},
3 | });
4 |
5 | export const getters = {
6 | version(state) {
7 | return state.server.version;
8 | },
9 | status(state) {
10 | return state.server.status;
11 | },
12 | };
13 |
14 | export const mutations = {
15 | server(state, server) {
16 | state.server = server;
17 | },
18 | };
19 |
20 | export const actions = {
21 | async health({ commit }) {
22 | const server = await this.$api.health.info();
23 | commit('server', server);
24 | },
25 | };
26 |
--------------------------------------------------------------------------------
/store/toast.js:
--------------------------------------------------------------------------------
1 | import { filter } from 'lodash';
2 |
3 | export const state = () => ({
4 | id: 0,
5 | toasts: [],
6 | });
7 |
8 | export const mutations = {
9 | push(state, toast) {
10 | state.id += 1;
11 | toast.id = state.id;
12 |
13 | state.toasts.push(toast);
14 | },
15 |
16 | remove(state, toast) {
17 | state.toasts = filter(state.toasts, (t) => t.id !== toast.id);
18 | },
19 | };
20 |
21 | export const actions = {
22 | add({ commit }, toast) {
23 | commit('push', toast);
24 |
25 | // for longer messages, give the user more time to read it, otherwise it
26 | // can disappear too soon.
27 | let timeOutAmount = (toast.message.split(' ').length / 6) * 3000;
28 | if (timeOutAmount < 3000) timeOutAmount = 3000;
29 |
30 | // ensure all messages end with a full stop.
31 | toast.message =
32 | toast.message[toast.message.length - 1] === '.'
33 | ? toast.message
34 | : (toast.message += '.');
35 |
36 | setTimeout(() => commit('remove', toast), timeOutAmount);
37 | },
38 |
39 | remove({ commit }, toast) {
40 | commit('remove', toast);
41 | },
42 |
43 | async error({ dispatch }, message) {
44 | // since in most cases and future bases we want to look to include a error message with
45 | // error responses from the server. If the message contains an error object or message
46 | // object then use this before falling back on its self.
47 | if (message.error != null) {
48 | message = message.error;
49 | } else if (message.message != null) {
50 | message = message.message;
51 | }
52 |
53 | await dispatch('add', { type: 'error', message });
54 | },
55 |
56 | async warning({ dispatch }, message) {
57 | await dispatch('add', { type: 'warning', message });
58 | },
59 |
60 | async success({ dispatch }, message) {
61 | await dispatch('add', { type: 'success', message });
62 | },
63 |
64 | errors({ dispatch }, e) {
65 | if (e.response.status === 400) {
66 | e.response.data.forEach((it) => {
67 | dispatch('add', { type: 'error', message: it.message });
68 | });
69 | } else {
70 | dispatch('add', {
71 | type: 'error',
72 | message: `${e.response.status} : ${e.response.statusText}`,
73 | });
74 | }
75 | },
76 | };
77 |
--------------------------------------------------------------------------------
/utils/auth.js:
--------------------------------------------------------------------------------
1 | export const roles = {
2 | PENDING: 2,
3 | USER: 2,
4 | MODERATOR: 3,
5 | ADMIN: 4,
6 | };
7 |
8 | export const names = {
9 | PENDING: 'PENDING',
10 | USER: 'USER',
11 | MODERATOR: 'MODERATOR',
12 | ADMIN: 'ADMIN',
13 | };
14 |
15 | export const isAuthorized = (userRole, miniRole) =>
16 | roles[userRole] && roles[miniRole] && roles[userRole] >= roles[miniRole];
17 |
18 | export const sameRole = (userRole, roleLimited) =>
19 | names[userRole] === names[roleLimited];
20 |
--------------------------------------------------------------------------------
/utils/gameDurations.js:
--------------------------------------------------------------------------------
1 | export default {
2 | Classic: 60,
3 | 'Zen Garden': 30,
4 | Blitz: 15,
5 | };
6 |
--------------------------------------------------------------------------------
/utils/gameStatus.js:
--------------------------------------------------------------------------------
1 | export default function nameFromStatus(status) {
2 | return ['SCHEDULED', 'ACTIVE', 'ENDED'][status];
3 | }
4 |
--------------------------------------------------------------------------------
/utils/linkedAccounts.js:
--------------------------------------------------------------------------------
1 | export default function userHasProvider(links, provider) {
2 | if (!links.some) {
3 | return false;
4 | }
5 | return links && links.some((it) => it.provider === provider);
6 | }
7 |
--------------------------------------------------------------------------------
/utils/objectives.js:
--------------------------------------------------------------------------------
1 | import { defaultTo } from 'lodash';
2 |
3 | export const voteAnalysisForTeam = (team, otherTeam, category, game) => {
4 | let points = 0;
5 | let blueVotes = 0;
6 | let redVotes = 0;
7 |
8 | blueVotes = defaultTo(team[category], 0);
9 | redVotes = defaultTo(otherTeam[category], 0);
10 |
11 | const total = blueVotes + redVotes;
12 |
13 | if (game.season === 4) {
14 | const { teamVoteResults } = game.storage.raw;
15 | const result = teamVoteResults.find(r => {
16 | const newCategory = category === 'ui' ? 'design' : (game.mode === 'zen' ? 'responsive' : 'function');
17 | return r.teamId - 1 === team.id && r.category === newCategory;
18 | });
19 |
20 | points = result?.score ?? 0;
21 | } else {
22 | if (defaultTo(blueVotes / total, 0) > 0.55) {
23 | points += 1;
24 | }
25 | if (defaultTo(blueVotes / total, 0) > 0.8) {
26 | points += 1;
27 | }
28 | }
29 |
30 | const percent = defaultTo((blueVotes / total) * 100, 0);
31 | const win = blueVotes > redVotes;
32 |
33 | return { points, win, percent: `${percent.toFixed(0)}%` };
34 | };
35 |
--------------------------------------------------------------------------------