mirror of
https://github.com/amineo/t2-stat-parser.git
synced 2026-01-19 17:34:43 +00:00
Deprecated webapp (old stats stack)
This commit is contained in:
parent
aed14743e6
commit
c1fcb61731
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"plugins": [
|
||||
"macros",
|
||||
"@babel/plugin-proposal-class-properties"
|
||||
]
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*]
|
||||
indent_size = 2
|
||||
indent_style = space
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
12
app/webapp/.gitignore
vendored
12
app/webapp/.gitignore
vendored
|
|
@ -1,12 +0,0 @@
|
|||
# Adonis directory for storing tmp files
|
||||
tmp
|
||||
|
||||
# Don't store build
|
||||
build
|
||||
|
||||
# Environment variables, never commit this file
|
||||
.env
|
||||
|
||||
public/hot
|
||||
public/mix-manifest.json
|
||||
public/dist
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Adonis Slim App
|
||||
|
||||
The Adonis slim app is the tinest boilerplate to create Adonisjs applications with minimal footprint and you get all the goodies of Adonis IoC container, autoloading, ace commands etc.
|
||||
|
||||
## What's next?
|
||||
|
||||
This project structure can scale as you go, simply execute the `ace` commands to create **Controllers**, **Models**, etc for you.
|
||||
|
||||
Also make sure to read the [guides](http://dev.adonisjs.com/docs/4.0/installation)
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Ace Commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The ace file is just a regular Javascript file but with no extension. You
|
||||
| can call `node ace` followed by the command name and it just works.
|
||||
|
|
||||
| Also you can use `adonis` followed by the command name, since the adonis
|
||||
| global proxy all the ace commands.
|
||||
|
|
||||
*/
|
||||
|
||||
const { Ignitor } = require('@adonisjs/ignitor')
|
||||
|
||||
new Ignitor(require('@adonisjs/fold'))
|
||||
.appRoot(__dirname)
|
||||
.fireAce()
|
||||
.catch(console.error)
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const Database = use('Database');
|
||||
|
||||
class GameController {
|
||||
// /games
|
||||
async index({ inertia }) {
|
||||
const pageTitle = `Latest Games`;
|
||||
|
||||
// const gamesQry = await Database.raw(`
|
||||
// SELECT distinct game_id,map,gametype, datestamp
|
||||
// FROM games
|
||||
// WHERE (stats->>'score' IS NOT NULL) AND (game_id <> 0)
|
||||
// ORDER BY game_id desc
|
||||
// LIMIT 2000;
|
||||
// `);
|
||||
|
||||
// const gamesQry = await Database.raw(`
|
||||
// WITH gamelist AS (
|
||||
// SELECT DISTINCT p.game_id, p.map, p.gametype, p.datestamp, count(*) OVER (PARTITION BY game_id) as count from games p
|
||||
// )
|
||||
// SELECT * from gamelist
|
||||
// WHERE (count > 1) AND (game_id <> 0)
|
||||
// ORDER BY game_id desc
|
||||
// LIMIT 2000
|
||||
// `);
|
||||
|
||||
// // filter out duplicate game_ids (https://dev.to/marinamosti/removing-duplicates-in-an-array-of-objects-in-js-with-sets-3fep)
|
||||
// const games = gamesQry.rows.reduce((game, current) => {
|
||||
|
||||
// const x = game.find(item => item.game_id === current.game_id);
|
||||
// if (!x) {
|
||||
// return game.concat([current]);
|
||||
// } else {
|
||||
// return game;
|
||||
// }
|
||||
// }, []);
|
||||
|
||||
const games = await Database.from('games').orderBy('game_id', 'desc').limit(200);
|
||||
// const CTFgames = await Database.from('games').where({gametype: 'CTFGame'}).orderBy('game_id', 'desc').limit(120);
|
||||
// const LAKgames = await Database.from('games').where({gametype: 'LakRabbitGame'}).orderBy('game_id', 'desc').limit(120);
|
||||
|
||||
// move the 0 score display logic here
|
||||
|
||||
return inertia.render('Games/Main', { pageTitle, games }, { edgeVar: 'server-variable' });
|
||||
}
|
||||
|
||||
// game/:game_id
|
||||
async game({ inertia, request }) {
|
||||
const gameInfo = await Database.from('game_detail')
|
||||
.select('game_id', 'map', 'player_name', 'player_guid', 'gametype', 'stats', 'datestamp')
|
||||
.where({ game_id: request.params.game_id })
|
||||
.orderByRaw("stats->>'scoreTG' desc");
|
||||
|
||||
const pageTitle = {
|
||||
name: gameInfo[0]['map'],
|
||||
gametype: gameInfo[0]['gametype']
|
||||
};
|
||||
|
||||
return inertia.render('Games/Game', { pageTitle, gameInfo }, { edgeVar: 'server-variable' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GameController;
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
class IndexController {
|
||||
|
||||
index({ inertia }) {
|
||||
const pageTitle = "Home!"
|
||||
return inertia.render('Index', { pageTitle }, { edgeVar: 'server-variable' })
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = IndexController
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const Database = use('Database');
|
||||
|
||||
class PlayerController {
|
||||
// Main Players List
|
||||
async index({ inertia }) {
|
||||
const pageTitle = 'All Players';
|
||||
const players = await Database.table('players')
|
||||
.distinct(
|
||||
'player_guid',
|
||||
'player_name',
|
||||
'total_games_ctfgame',
|
||||
'total_games_dmgame',
|
||||
'total_games_lakrabbitgame',
|
||||
'total_games_sctfgame',
|
||||
'updated_at'
|
||||
)
|
||||
.groupBy('player_guid')
|
||||
.orderBy('player_name', 'asc')
|
||||
.limit(1000);
|
||||
|
||||
return inertia.render('Players/Main', { pageTitle, players }, { edgeVar: 'server-variable' });
|
||||
}
|
||||
|
||||
// Player Detail
|
||||
async player({ inertia, request }) {
|
||||
const playerInfo = await Database.from('players')
|
||||
.distinct(
|
||||
'player_guid',
|
||||
'player_name',
|
||||
'total_games_ctfgame',
|
||||
'total_games_dmgame',
|
||||
'total_games_lakrabbitgame',
|
||||
'total_games_sctfgame'
|
||||
)
|
||||
.where({ player_guid: request.params.player_guid })
|
||||
.limit(50);
|
||||
|
||||
const playerStatData = await Database.from('game_detail')
|
||||
.select('game_id', 'gametype', 'stats')
|
||||
.where({ player_guid: request.params.player_guid })
|
||||
.orderBy('game_id', 'desc')
|
||||
.limit(50);
|
||||
|
||||
// Dynamically generate and sum the stats object
|
||||
let playerStatTotals = {},
|
||||
statKeys = Object.keys(playerStatData[0].stats);
|
||||
|
||||
for (let i = 0; i < statKeys.length; i++) {
|
||||
if (statKeys[i] === 'map' || statKeys[i] === 'dateStamp' || statKeys[i] === 'timeDayMonth') {
|
||||
continue;
|
||||
}
|
||||
playerStatTotals[statKeys[i]] = 0;
|
||||
}
|
||||
|
||||
// Loop through the playerStatsData query from the DB
|
||||
playerStatData.map((statLine) => {
|
||||
// look through each object in playerStatsData array
|
||||
for (let [ key, value ] of Object.entries(statLine.stats)) {
|
||||
// console.log(`${key}: ${value}`);
|
||||
// If the stat item exists, add it -- if not create a new key in playerStatTotals
|
||||
if (playerStatTotals.hasOwnProperty(key) === true) {
|
||||
playerStatTotals[key] = playerStatTotals[key] + Number(value);
|
||||
} else {
|
||||
playerStatTotals[key] = Number(value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let playerData = {
|
||||
player: playerInfo[0],
|
||||
stats: playerStatData,
|
||||
totals: playerStatTotals
|
||||
};
|
||||
|
||||
const pageTitle = playerData.player.player_name;
|
||||
return inertia.render('Players/Player', { pageTitle, playerData }, { edgeVar: 'server-variable' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PlayerController;
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// babel-plugin-macros.config.js
|
||||
module.exports = {
|
||||
twin: {
|
||||
config: './tailwind.config.js',
|
||||
styled: '@emotion/styled',
|
||||
format: 'auto',
|
||||
hasSuggestions: true,
|
||||
debug: false
|
||||
}
|
||||
}
|
||||
|
|
@ -1,243 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||
const Env = use('Env')
|
||||
|
||||
module.exports = {
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Application Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value is the name of your application and can used when you
|
||||
| need to place the application's name in a email, view or
|
||||
| other location.
|
||||
|
|
||||
*/
|
||||
|
||||
name: Env.get('APP_NAME', 'AdonisJs'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| App Key
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| App key is a randomly generated 16 or 32 characters long string required
|
||||
| to encrypted cookies, sessions and other sensitive data.
|
||||
|
|
||||
*/
|
||||
appKey: Env.getOrFail('APP_KEY'),
|
||||
|
||||
http: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allow Method Spoofing
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Method spoofing allows to make requests by spoofing the http verb.
|
||||
| Which means you can make a GET request but instruct the server to
|
||||
| treat as a POST or PUT request. If you want this feature, set the
|
||||
| below value to true.
|
||||
|
|
||||
*/
|
||||
allowMethodSpoofing: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Trust Proxy
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Trust proxy defines whether X-Forwaded-* headers should be trusted or not.
|
||||
| When your application is behind a proxy server like nginx, these values
|
||||
| are set automatically and should be trusted. Apart from setting it
|
||||
| to true or false Adonis supports handful or ways to allow proxy
|
||||
| values. Read documentation for that.
|
||||
|
|
||||
*/
|
||||
trustProxy: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Subdomains
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Offset to be used for returning subdomains for a given request.For
|
||||
| majority of applications it will be 2, until you have nested
|
||||
| sudomains.
|
||||
| cheatsheet.adonisjs.com - offset - 2
|
||||
| virk.cheatsheet.adonisjs.com - offset - 3
|
||||
|
|
||||
*/
|
||||
subdomainOffset: 2,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| JSONP Callback
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default jsonp callback to be used when callback query string is missing
|
||||
| in request url.
|
||||
|
|
||||
*/
|
||||
jsonpCallback: 'callback',
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Etag
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set etag on all HTTP response. In order to disable for selected routes,
|
||||
| you can call the `response.send` with an options object as follows.
|
||||
|
|
||||
| response.send('Hello', { ignoreEtag: true })
|
||||
|
|
||||
*/
|
||||
etag: false
|
||||
},
|
||||
|
||||
views: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Cache Views
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define whether or not to cache the compiled view. Set it to true in
|
||||
| production to optimize view loading time.
|
||||
|
|
||||
*/
|
||||
cache: Env.get('CACHE_VIEWS', true)
|
||||
},
|
||||
|
||||
static: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Dot Files
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define how to treat dot files when trying to server static resources.
|
||||
| By default it is set to ignore, which will pretend that dotfiles
|
||||
| does not exists.
|
||||
|
|
||||
| Can be one of the following
|
||||
| ignore, deny, allow
|
||||
|
|
||||
*/
|
||||
dotfiles: 'ignore',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| ETag
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable or disable etag generation
|
||||
|
|
||||
*/
|
||||
etag: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Extensions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set file extension fallbacks. When set, if a file is not found, the given
|
||||
| extensions will be added to the file name and search for. The first
|
||||
| that exists will be served. Example: ['html', 'htm'].
|
||||
|
|
||||
*/
|
||||
extensions: false
|
||||
},
|
||||
|
||||
locales: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Loader
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The loader to be used for fetching and updating locales. Below is the
|
||||
| list of available options.
|
||||
|
|
||||
| file, database
|
||||
|
|
||||
*/
|
||||
loader: 'file',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Locale
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Default locale to be used by Antl provider. You can always switch drivers
|
||||
| in runtime or use the official Antl middleware to detect the driver
|
||||
| based on HTTP headers/query string.
|
||||
|
|
||||
*/
|
||||
locale: 'en'
|
||||
},
|
||||
|
||||
logger: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Transport
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Transport to be used for logging messages. You can have multiple
|
||||
| transports using same driver.
|
||||
|
|
||||
| Available drivers are: `file` and `console`.
|
||||
|
|
||||
*/
|
||||
transport: 'console',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Console Transport
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Using `console` driver for logging. This driver writes to `stdout`
|
||||
| and `stderr`
|
||||
|
|
||||
*/
|
||||
console: {
|
||||
driver: 'console',
|
||||
name: 'adonis-app',
|
||||
level: 'info'
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| File Transport
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| File transport uses file driver and writes log messages for a given
|
||||
| file inside `tmp` directory for your app.
|
||||
|
|
||||
| For a different directory, set an absolute path for the filename.
|
||||
|
|
||||
*/
|
||||
file: {
|
||||
driver: 'file',
|
||||
name: 'adonis-app',
|
||||
filename: 'adonis.log',
|
||||
level: 'info'
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Generic Cookie Options
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The following cookie options are generic settings used by AdonisJs to create
|
||||
| cookies. However, some parts of the application like `sessions` can have
|
||||
| seperate settings for cookies inside `config/session.js`.
|
||||
|
|
||||
*/
|
||||
cookie: {
|
||||
httpOnly: true,
|
||||
sameSite: false,
|
||||
path: '/',
|
||||
maxAge: 7200
|
||||
}
|
||||
}
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| JSON Parser
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below settings are applied when the request body contains a JSON payload.
|
||||
| If you want body parser to ignore JSON payloads, then simply set `types`
|
||||
| to an empty array.
|
||||
*/
|
||||
json: {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| limit
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Defines the limit of JSON that can be sent by the client. If payload
|
||||
| is over 1mb it will not be processed.
|
||||
|
|
||||
*/
|
||||
limit: '1mb',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| strict
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| When `strict` is set to true, body parser will only parse Arrays and
|
||||
| Object. Otherwise everything parseable by `JSON.parse` is parsed.
|
||||
|
|
||||
*/
|
||||
strict: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| types
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Which content types are processed as JSON payloads. You are free to
|
||||
| add your own types here, but the request body should be parseable
|
||||
| by `JSON.parse` method.
|
||||
|
|
||||
*/
|
||||
types: [
|
||||
'application/json',
|
||||
'application/json-patch+json',
|
||||
'application/vnd.api+json',
|
||||
'application/csp-report'
|
||||
]
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Raw Parser
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
|
|
||||
|
|
||||
*/
|
||||
raw: {
|
||||
types: [
|
||||
'text/*'
|
||||
]
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Form Parser
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
|
|
||||
|
|
||||
*/
|
||||
form: {
|
||||
types: [
|
||||
'application/x-www-form-urlencoded'
|
||||
]
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Files Parser
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
|
|
||||
|
|
||||
*/
|
||||
files: {
|
||||
types: [
|
||||
'multipart/form-data'
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Max Size
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Below value is the max size of all the files uploaded to the server. It
|
||||
| is validated even before files have been processed and hard exception
|
||||
| is thrown.
|
||||
|
|
||||
| Consider setting a reasonable value here, otherwise people may upload GB's
|
||||
| of files which will keep your server busy.
|
||||
|
|
||||
| Also this value is considered when `autoProcess` is set to true.
|
||||
|
|
||||
*/
|
||||
maxSize: '20mb',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Auto Process
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether or not to auto-process files. Since HTTP servers handle files via
|
||||
| couple of specific endpoints. It is better to set this value off and
|
||||
| manually process the files when required.
|
||||
|
|
||||
| This value can contain a boolean or an array of route patterns
|
||||
| to be autoprocessed.
|
||||
*/
|
||||
autoProcess: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Process Manually
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The list of routes that should not process files and instead rely on
|
||||
| manual process. This list should only contain routes when autoProcess
|
||||
| is to true. Otherwise everything is processed manually.
|
||||
|
|
||||
*/
|
||||
processManually: []
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Temporary file name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define a function, which should return a string to be used as the
|
||||
| tmp file name.
|
||||
|
|
||||
| If not defined, Bodyparser will use `uuid` as the tmp file name.
|
||||
|
|
||||
| To be defined as. If you are defining the function, then do make sure
|
||||
| to return a value from it.
|
||||
|
|
||||
| tmpFileName () {
|
||||
| return 'some-unique-value'
|
||||
| }
|
||||
|
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
@ -1,87 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Origin
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Set a list of origins to be allowed. The value can be one of the following
|
||||
|
|
||||
| Boolean: true - Allow current request origin
|
||||
| Boolean: false - Disallow all
|
||||
| String - Comma seperated list of allowed origins
|
||||
| Array - An array of allowed origins
|
||||
| String: * - A wildcard to allow current request origin
|
||||
| Function - Receives the current origin and should return one of the above values.
|
||||
|
|
||||
*/
|
||||
origin: ['playt2.com'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Methods
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| HTTP methods to be allowed. The value can be one of the following
|
||||
|
|
||||
| String - Comma seperated list of allowed methods
|
||||
| Array - An array of allowed methods
|
||||
|
|
||||
*/
|
||||
methods: ['GET', 'PUT', 'POST', 'OPTIONS', 'HEAD'],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Headers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| List of headers to be allowed via Access-Control-Request-Headers header.
|
||||
| The value can be on of the following.
|
||||
|
|
||||
| Boolean: true - Allow current request headers
|
||||
| Boolean: false - Disallow all
|
||||
| String - Comma seperated list of allowed headers
|
||||
| Array - An array of allowed headers
|
||||
| String: * - A wildcard to allow current request headers
|
||||
| Function - Receives the current header and should return one of the above values.
|
||||
|
|
||||
*/
|
||||
headers: true,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Expose Headers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| A list of headers to be exposed via `Access-Control-Expose-Headers`
|
||||
| header. The value can be on of the following.
|
||||
|
|
||||
| Boolean: false - Disallow all
|
||||
| String: Comma seperated list of allowed headers
|
||||
| Array - An array of allowed headers
|
||||
|
|
||||
*/
|
||||
exposeHeaders: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Credentials
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define Access-Control-Allow-Credentials header. It should always be a
|
||||
| boolean.
|
||||
|
|
||||
*/
|
||||
credentials: false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| MaxAge
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define Access-Control-Max-Age
|
||||
|
|
||||
*/
|
||||
maxAge: 90
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||
const Env = use('Env')
|
||||
|
||||
/** @type {import('@adonisjs/ignitor/src/Helpers')} */
|
||||
const Helpers = use('Helpers')
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Connection
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Connection defines the default connection settings to be used while
|
||||
| interacting with SQL databases.
|
||||
|
|
||||
*/
|
||||
connection: Env.get('DB_CONNECTION', 'pg'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| PostgreSQL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here we define connection settings for PostgreSQL database.
|
||||
|
|
||||
| npm i --save pg
|
||||
|
|
||||
*/
|
||||
pg: {
|
||||
client: 'pg',
|
||||
connection: {
|
||||
host: Env.get('DB_HOST', 'localhost'),
|
||||
port: Env.get('DB_PORT', ''),
|
||||
user: Env.get('DB_USER', 'root'),
|
||||
password: Env.get('DB_PASSWORD', ''),
|
||||
database: Env.get('DB_DATABASE', 'adonis')
|
||||
},
|
||||
pool: { min: 0, max: 10 },
|
||||
debug: Env.get('DB_DEBUG', false)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/** @type {import('@adonisjs/framework/src/Env')} */
|
||||
const Env = use('Env')
|
||||
|
||||
module.exports = {
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Driver to be used for hashing values. The same driver is used by the
|
||||
| auth module too.
|
||||
|
|
||||
*/
|
||||
driver: Env.get('HASH_DRIVER', 'bcrypt'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bcrypt
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Config related to bcrypt hashing. https://www.npmjs.com/package/bcrypt
|
||||
| package is used internally.
|
||||
|
|
||||
*/
|
||||
bcrypt: {
|
||||
rounds: 10
|
||||
},
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Argon
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Config related to argon. https://www.npmjs.com/package/argon2 package is
|
||||
| used internally.
|
||||
|
|
||||
| Since argon is optional, you will have to install the dependency yourself
|
||||
|
|
||||
|============================================================================
|
||||
| npm i argon2
|
||||
|============================================================================
|
||||
|
|
||||
*/
|
||||
argon: {
|
||||
type: 1
|
||||
}
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
module.exports = {
|
||||
apps : [{
|
||||
name: process.env.APP_NAME,
|
||||
script: 'server.js',
|
||||
// Options reference: https://pm2.keymetrics.io/docs/usage/application-declaration/
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: true,
|
||||
ignore_watch:['node_modules','public','resources/js','resources/scss']
|
||||
},
|
||||
{
|
||||
name: process.env.APP_NAME + '_react',
|
||||
script: 'node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js "--watch"',
|
||||
// Options reference: https://pm2.keymetrics.io/docs/usage/application-declaration/
|
||||
instances: 1,
|
||||
autorestart: false,
|
||||
watch: false,
|
||||
}]
|
||||
};
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
module.exports = {
|
||||
apps : [{
|
||||
name: process.env.APP_NAME,
|
||||
script: 'server.js',
|
||||
// Options reference: https://pm2.keymetrics.io/docs/usage/application-declaration/
|
||||
instances: 1,
|
||||
autorestart: true,
|
||||
watch: true,
|
||||
ignore_watch:['node_modules','public','resources/js','resources/scss']
|
||||
},
|
||||
{
|
||||
name: process.env.APP_NAME + '_react_hot',
|
||||
script: 'node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js',
|
||||
// Options reference: https://pm2.keymetrics.io/docs/usage/application-declaration/
|
||||
instances: 1,
|
||||
autorestart: false,
|
||||
watch: false,
|
||||
}]
|
||||
};
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: process.env.APP_NAME,
|
||||
script: 'server.js',
|
||||
autorestart: true,
|
||||
instances: 1
|
||||
}
|
||||
]
|
||||
};
|
||||
20161
app/webapp/package-lock.json
generated
20161
app/webapp/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,80 +0,0 @@
|
|||
{
|
||||
"name": "adonis-inertia-react-starter",
|
||||
"version": "4.1.0",
|
||||
"adonis-version": "4.1.0",
|
||||
"description": "Adonis, Inertia, React, Emotion, TailwindCSS, Webpack Mix, PostCSS",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "node server.js",
|
||||
"test": "node ace test",
|
||||
"webpack-server": "/opt/node_modules/webpack/bin/webpack.js --progress --hide-modules --config=/opt/node_modules/laravel-mix/setup/webpack.config.js",
|
||||
"watch": "npm run webpack-server -- --watch"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": "react-app"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not op_mini all"
|
||||
],
|
||||
"development": [
|
||||
"last 1 chrome version",
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"adonisjs",
|
||||
"adonis-app",
|
||||
"inertajs",
|
||||
"react"
|
||||
],
|
||||
"author": "",
|
||||
"license": "UNLICENSED",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@adonisjs/ace": "^5.0.8",
|
||||
"@adonisjs/bodyparser": "^2.0.9",
|
||||
"@adonisjs/cors": "^1.0.7",
|
||||
"@adonisjs/fold": "^4.0.9",
|
||||
"@adonisjs/framework": "^5.0.9",
|
||||
"@adonisjs/ignitor": "^2.0.8",
|
||||
"@adonisjs/lucid": "^6.1.3",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@inertiajs/inertia": "^0.1.7",
|
||||
"@inertiajs/inertia-react": "^0.1.4",
|
||||
"@tailwindcss/ui": "^0.1.3",
|
||||
"@testing-library/jest-dom": "^4.2.4",
|
||||
"@testing-library/react": "^9.3.2",
|
||||
"@testing-library/user-event": "^7.1.2",
|
||||
"inertia-adonis": "^0.1.2",
|
||||
"node-cookie": "^2.1.2",
|
||||
"pg": "^7.18.2",
|
||||
"react": "^16.13.0",
|
||||
"react-dom": "^16.13.0",
|
||||
"react-scripts": "3.4.0",
|
||||
"recharts": "^1.8.5",
|
||||
"tailwindcss": "^1.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||
"@babel/plugin-transform-react-jsx": "^7.9.1",
|
||||
"@babel/preset-react": "^7.9.1",
|
||||
"@emotion/core": "^10.0.28",
|
||||
"@emotion/styled": "^10.0.27",
|
||||
"autoprefixer": "^9.7.4",
|
||||
"babel-plugin-macros": "^2.8.0",
|
||||
"laravel-mix": "^5.0.4",
|
||||
"laravel-mix-purgecss": "^5.0.0-rc.1",
|
||||
"laravel-mix-tailwind": "^0.1.0",
|
||||
"postcss-cli": "^7.1.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"sass": "^1.26.3",
|
||||
"twin.macro": "^1.0.0-alpha.7"
|
||||
},
|
||||
"autoload": {
|
||||
"App": "./app"
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><svg width="36px" height="33px" viewBox="0 0 36 33" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g transform="translate(0 .5)" fill="none" fill-rule="evenodd"><path d="M20 2.236L5.618 31h28.764L20 2.236z" stroke="#FFFFFF" stroke-width="2"/><path fill="#FFFFFF" d="M12 2l12 24H0"/></g></svg>
|
||||
|
Before Width: | Height: | Size: 363 B |
Binary file not shown.
|
Before Width: | Height: | Size: 111 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -1 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><svg width="186px" height="31px" viewBox="0 0 186 31" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M20.25 6.106V.1H.72v6.006h5.712v17.388H.72V29.5h19.53v-6.006h-5.712V6.106h5.712zm18.774 7.35v-5.46h-6.846V1.528h-7.182v3.108c0 2.226-1.218 3.36-3.444 3.36h-.084v5.46h3.528v8.904c0 4.578 3.528 7.686 8.82 7.686 1.932 0 3.276-.126 5.208-1.05v-5.964c-2.016.882-2.982.966-3.822.966-1.806 0-3.024-1.008-3.024-2.898v-7.644h6.846zm37.17-5.46l-3.612 13.692L68.76 7.996H63.3l-3.822 13.692-3.654-13.692h-7.308L55.068 29.5h7.266l3.696-12.516L69.684 29.5h7.308l6.552-21.504h-7.35zM95.43 7.45c6.846 0 11.424 4.746 11.424 11.256 0 6.552-4.578 11.34-11.424 11.34-6.888 0-11.466-4.788-11.466-11.34 0-6.51 4.578-11.256 11.466-11.256zm0 5.628c-2.898 0-4.62 2.352-4.62 5.628 0 3.318 1.722 5.712 4.62 5.712 2.856 0 4.578-2.394 4.578-5.712 0-3.276-1.722-5.628-4.578-5.628zm22.092.714V7.996h-7.182V29.5h7.182v-7.518c0-5.376 1.89-7.728 8.946-6.972V7.534c-4.788 0-7.686 1.806-8.946 6.258zM145.158 29.5h8.4l-7.812-11.886 7.14-9.618h-8.316l-4.284 6.552h-3.612V.1h-7.182v29.4h7.182v-8.442h3.612l4.872 8.442zm22.092-14.196h6.384c-.462-5.46-4.326-7.854-9.87-7.854-6.09 0-9.534 2.436-9.534 6.804 0 4.998 4.494 5.586 8.19 6.426 3.822.882 4.704 1.134 4.704 2.478 0 1.512-1.428 1.932-2.982 1.932-2.394 0-3.822-.966-4.074-3.486h-6.384c.336 5.88 4.536 8.442 10.542 8.442 6.132 0 9.66-2.688 9.66-7.14 0-4.998-4.41-5.628-8.736-6.594-3.234-.672-4.326-.882-4.326-2.31 0-1.134 1.176-1.848 2.856-1.848 2.268 0 3.276.882 3.57 3.15zm11.424 4.536h6.258L185.94.1h-8.316l1.05 19.74zm-.63 9.66h7.518v-6.51h-7.518v6.51z" fill="#FFFFFF" fill-rule="evenodd"/></svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
|
@ -1,16 +0,0 @@
|
|||
import React from 'react'
|
||||
|
||||
const FrameHeading = (props) => {
|
||||
return (
|
||||
<header className="bg-white shadow-sm">
|
||||
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-lg leading-6 font-semibold text-gray-900">
|
||||
{props.heading}
|
||||
</h1>
|
||||
{ props.gametype ? props.gametype : ''}
|
||||
</div>
|
||||
</header>
|
||||
);
|
||||
};
|
||||
|
||||
export default FrameHeading;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './FrameHeading';
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
import React from 'react'
|
||||
|
||||
const returnTotalSumGames = (player) => {
|
||||
let sum = Number(player.ctf) +
|
||||
Number(player.dm) +
|
||||
Number(player.lak) +
|
||||
Number(player.spawnctf);
|
||||
return sum
|
||||
};
|
||||
|
||||
const GameTypesPlayedBoxes = (props) => {
|
||||
return (
|
||||
<>
|
||||
<h3 className="text-md leading-6 font-medium text-gray-900">
|
||||
Games Played {returnTotalSumGames(props)}
|
||||
</h3>
|
||||
<div className="mt-5 grid grid-cols-1 gap-5 sm:grid-cols-4">
|
||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<dl>
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500 truncate">
|
||||
Capture the Flag
|
||||
</dt>
|
||||
<dd className="mt-1 text-3xl leading-9 font-semibold text-gray-900">
|
||||
{props.ctf}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<dl>
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500 truncate">
|
||||
LAK Rabbit
|
||||
</dt>
|
||||
<dd className="mt-1 text-3xl leading-9 font-semibold text-gray-900">
|
||||
{props.lak}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<dl>
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500 truncate">
|
||||
Spawn CTF
|
||||
</dt>
|
||||
<dd className="mt-1 text-3xl leading-9 font-semibold text-gray-900">
|
||||
{props.spawnctf}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-white overflow-hidden shadow rounded-lg">
|
||||
<div className="px-4 py-5 sm:p-6">
|
||||
<dl>
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500 truncate">
|
||||
Deathmatch
|
||||
</dt>
|
||||
<dd className="mt-1 text-3xl leading-9 font-semibold text-gray-900">
|
||||
{props.dm}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GameTypesPlayedBoxes;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './GameTypesPlayedBoxes';
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
import React from 'react'
|
||||
|
||||
const returnTotalSumGames = (player) => {
|
||||
let sum = Number(player.ctf) +
|
||||
Number(player.dm) +
|
||||
Number(player.lak) +
|
||||
Number(player.spawnctf);
|
||||
return sum
|
||||
};
|
||||
|
||||
const GameTypesPlayedCols = (props) => {
|
||||
return (
|
||||
<>
|
||||
<dl className="grid grid-cols-1 col-gap-4 row-gap-8 sm:grid-cols-4">
|
||||
<div className="sm:col-span-1">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
CTF
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{props.ctf} </span>
|
||||
</dd>
|
||||
</div><div className="sm:col-span-1">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
LAK Rabbit
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{props.lak}</span>
|
||||
</dd>
|
||||
</div><div className="sm:col-span-1">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
Spawn CTF
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{props.spawnctf}</span>
|
||||
</dd>
|
||||
</div><div className="sm:col-span-1">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
Deathmatch
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{props.dm}</span>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div className="mt-5">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
Total
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{returnTotalSumGames(props)}</span>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default GameTypesPlayedCols;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './GameTypesPlayedCols';
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
import React from 'react'
|
||||
import { InertiaLink } from '@inertiajs/inertia-react'
|
||||
|
||||
|
||||
const navItems = () =>
|
||||
<div className="ml-10 flex items-baseline">
|
||||
{/* <InertiaLink href="/" className="px-3 py-2 rounded-md text-sm font-medium text-white bg-gray-900 focus:outline-none focus:text-white focus:bg-gray-700">Home</InertiaLink> */}
|
||||
<InertiaLink href="/games" className="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Games</InertiaLink>
|
||||
<InertiaLink href="/players" className="ml-4 px-3 py-2 rounded-md text-sm font-medium text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:text-white focus:bg-gray-700">Players</InertiaLink>
|
||||
</div>;
|
||||
|
||||
const TopNav = () => {
|
||||
return (
|
||||
<nav className="bg-gray-800">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between h-16">
|
||||
<div className="flex items-center">
|
||||
<div className="flex-shrink-0">
|
||||
<img className="h-8 w-8" src="https://d33wubrfki0l68.cloudfront.net/1699fc97aa9b1cb851a6c0039162a9241724e1fb/7289f/images/logo.png" alt="Tribes 2 Stats" />
|
||||
</div>
|
||||
<div className="md:block">
|
||||
{ navItems() }
|
||||
</div>
|
||||
</div>
|
||||
<div className="md:block">
|
||||
<div className="ml-4 flex items-center md:ml-6">
|
||||
<span className="inline-flex rounded-md shadow-sm">
|
||||
<a href="https://www.playt2.com/discord" className="inline-flex items-center px-2.5 py-1.5 border border-gray-300 text-xs leading-4 font-medium rounded text-gray-700 bg-white hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:shadow-outline-blue active:text-gray-800 active:bg-gray-50 transition ease-in-out duration-150">
|
||||
Join Discord
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default TopNav;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from './TopNav';
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
import React, { PureComponent } from 'react';
|
||||
import { InertiaLink } from '@inertiajs/inertia-react';
|
||||
import Layout from '@/Shared/Layout';
|
||||
|
||||
import { PieChart, Pie, Sector } from 'recharts';
|
||||
|
||||
const renderActiveShape = (props) => {
|
||||
const RADIAN = Math.PI / 180;
|
||||
const { cx, cy, midAngle, innerRadius, outerRadius, startAngle, endAngle, fill, payload, percent, value } = props;
|
||||
const sin = Math.sin(-RADIAN * midAngle);
|
||||
const cos = Math.cos(-RADIAN * midAngle);
|
||||
const sx = cx + (outerRadius + 10) * cos;
|
||||
const sy = cy + (outerRadius + 10) * sin;
|
||||
const mx = cx + (outerRadius + 30) * cos;
|
||||
const my = cy + (outerRadius + 30) * sin;
|
||||
const ex = mx + (cos >= 0 ? 1 : -1) * 22;
|
||||
const ey = my;
|
||||
const textAnchor = cos >= 0 ? 'start' : 'end';
|
||||
|
||||
return (
|
||||
<g>
|
||||
<text x={cx} y={cy} dy={8} textAnchor="middle" fill="#5850ec">
|
||||
{payload.name}
|
||||
</text>
|
||||
<Sector
|
||||
cx={cx}
|
||||
cy={cy}
|
||||
innerRadius={innerRadius}
|
||||
outerRadius={outerRadius}
|
||||
startAngle={startAngle}
|
||||
endAngle={endAngle}
|
||||
fill="#8884d8"
|
||||
/>
|
||||
<Sector
|
||||
cx={cx}
|
||||
cy={cy}
|
||||
startAngle={startAngle}
|
||||
endAngle={endAngle}
|
||||
innerRadius={outerRadius + 6}
|
||||
outerRadius={outerRadius + 10}
|
||||
fill="#6761d6"
|
||||
/>
|
||||
<path d={`M${sx},${sy}L${mx},${my}L${ex},${ey}`} stroke={fill} fill="none" />
|
||||
<circle cx={ex} cy={ey} r={2} fill={fill} stroke="none" />
|
||||
<text x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} textAnchor={textAnchor} fill="#333">{`${value}`}</text>
|
||||
<text x={ex + (cos >= 0 ? 1 : -1) * 12} y={ey} dy={18} textAnchor={textAnchor} fill="#999">
|
||||
{`(${(percent * 100).toFixed(2)}%)`}
|
||||
</text>
|
||||
</g>
|
||||
);
|
||||
};
|
||||
|
||||
export class TwoLevelPieChart extends PureComponent {
|
||||
state = {
|
||||
activeIndex: this.props.data.oScore >= this.props.data.dScore ? 0 : 1,
|
||||
data: [ { name: 'Offense', value: this.props.data.oScore }, { name: 'Defense', value: this.props.data.dScore } ]
|
||||
};
|
||||
|
||||
onPieEnter = (data, index) => {
|
||||
this.setState({
|
||||
activeIndex: index
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<PieChart width={400} height={400}>
|
||||
<Pie
|
||||
activeIndex={this.state.activeIndex}
|
||||
activeShape={renderActiveShape}
|
||||
data={this.state.data}
|
||||
cx={200}
|
||||
cy={200}
|
||||
innerRadius={60}
|
||||
outerRadius={80}
|
||||
fill="#ccc"
|
||||
dataKey="value"
|
||||
onMouseEnter={this.onPieEnter}
|
||||
className="text-xs"
|
||||
/>
|
||||
</PieChart>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const PlayerRow = (player, index) => {
|
||||
// dont show scoreless players
|
||||
// if (Number(player.stats.scoreTG) <= 0) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
return (
|
||||
<div className="flex flex-col rounded-lg shadow-lg overflow-hidden" key={index}>
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-lg">
|
||||
<div className="px-4 py-5 border-b border-gray-200 sm:px-6">
|
||||
<h3 className="text-lg leading-6 font-medium">
|
||||
<InertiaLink
|
||||
href={`/player/${player.player_guid}`}
|
||||
className="text-indigo-600 hover:text-indigo-500 transition duration-150 ease-in-out"
|
||||
>
|
||||
{player.player_name}
|
||||
</InertiaLink>
|
||||
</h3>
|
||||
</div>
|
||||
<div>
|
||||
<dl>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Total Score</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.scoreTG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 flex items-center justify-center">
|
||||
{player.gametype == 'CTFGame' || player.gametype == 'SCtFGame' ? (
|
||||
<TwoLevelPieChart
|
||||
data={{
|
||||
oScore: Number(player.stats.offenseScoreTG[0]),
|
||||
dScore: Number(player.stats.defenseScoreTG[0])
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Kills / Assists</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.killsTG} / {player.stats.assistTG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">MAs</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.totalMATG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Flag Grabs / Caps</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.flagGrabsTG} / {player.stats.flagCapsTG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">
|
||||
Flag Defends / Capper Kills / Returns
|
||||
</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.flagDefendsTG} / {player.stats.carrierKillsTG} /{' '}
|
||||
{player.stats.flagReturnsTG}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Game(props) {
|
||||
return (
|
||||
<Layout title={props.pageTitle.name} gametype={props.pageTitle.gametype}>
|
||||
<div className="mt-2 grid gap-5 max-w-lg mx-auto lg:grid-cols-3 lg:max-w-none">
|
||||
{props.gameInfo.map((game, index) => PlayerRow(game, index))}
|
||||
</div>
|
||||
{/*
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-md">
|
||||
<div className="py-10 px-10"><code> {JSON.stringify(props.gameInfo)}</code></div>
|
||||
</div> */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
import React from 'react'
|
||||
import { InertiaLink } from '@inertiajs/inertia-react'
|
||||
import Layout from '@/Shared/Layout'
|
||||
|
||||
|
||||
|
||||
const GameRow = (game, index) => {
|
||||
|
||||
return <li key={index}>
|
||||
<InertiaLink href={`/game/${game.game_id}`} className="block hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out">
|
||||
<div className="flex items-center px-4 py-4 sm:px-6">
|
||||
<div className="min-w-0 flex-1 flex items-center">
|
||||
<div className="min-w-0 flex-1 md:grid md:grid-cols-2 md:gap-4">
|
||||
<div>
|
||||
<div className="text-sm leading-5 font-medium text-indigo-600 truncate">{game.map}</div>
|
||||
<div className="mt-2 flex items-center text-sm leading-5 text-gray-500">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">Played: {game.datestamp.split(/[T]/)[0]}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden md:block">
|
||||
<div>
|
||||
<div className="text-sm leading-5 text-gray-900">
|
||||
|
||||
</div>
|
||||
<div className="mt-2 flex items-center">
|
||||
<span className="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium leading-5 bg-indigo-100 text-indigo-800">{game.gametype}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<svg className="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clipRule="evenodd"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</InertiaLink>
|
||||
</li>;
|
||||
}
|
||||
|
||||
|
||||
export default function Games(props) {
|
||||
return (
|
||||
<Layout title={props.pageTitle}>
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-md">
|
||||
<ul>
|
||||
{ props.games.map((game, index) => GameRow(game, index)) }
|
||||
</ul>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
import React from 'react'
|
||||
import Layout from '@/Shared/Layout'
|
||||
|
||||
|
||||
export default function Index(props) {
|
||||
return (
|
||||
<Layout title={props.pageTitle}>
|
||||
<div className="border-4 border-dashed border-gray-300 rounded-lg h-96">
|
||||
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
import React from 'react'
|
||||
import { InertiaLink } from '@inertiajs/inertia-react'
|
||||
import Layout from '@/Shared/Layout'
|
||||
|
||||
const returnTotalSumGames = (player) => {
|
||||
let sum = Number(player.total_games_ctfgame) +
|
||||
Number(player.total_games_dmgame) +
|
||||
Number(player.total_games_lakrabbitgame) +
|
||||
Number(player.total_games_sctfgame);
|
||||
return sum
|
||||
};
|
||||
|
||||
|
||||
const PlayerRow = (player, index) => {
|
||||
|
||||
let totalGames = returnTotalSumGames(player);
|
||||
|
||||
// only display players that have games associated
|
||||
if (totalGames === 0){return}
|
||||
|
||||
return <li key={index}>
|
||||
<InertiaLink href={`/player/${player.player_guid}`} className="block hover:bg-gray-50 focus:outline-none focus:bg-gray-50 transition duration-150 ease-in-out">
|
||||
<div className="flex items-center px-4 py-4 sm:px-6">
|
||||
<div className="min-w-0 flex-1 flex items-center">
|
||||
<div className="min-w-0 flex-1 md:grid md:grid-cols-2 md:gap-4">
|
||||
<div>
|
||||
<div className="text-sm leading-5 font-medium text-indigo-600 truncate">{player.player_name}</div>
|
||||
<div className="mt-2 flex items-center text-sm leading-5 text-gray-500">
|
||||
<span className="truncate">Last Active: {player.updated_at.split(/[T]/)[0]}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden md:block">
|
||||
<div>
|
||||
<div className="text-sm leading-5 text-gray-900">
|
||||
Total Games Played
|
||||
</div>
|
||||
<div className="mt-2 flex items-center">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">{ totalGames }</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<svg className="h-5 w-5 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clipRule="evenodd"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
</InertiaLink>
|
||||
</li>;
|
||||
}
|
||||
|
||||
|
||||
export default function Players(props) {
|
||||
return (
|
||||
<Layout title={props.pageTitle}>
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-md">
|
||||
<ul>
|
||||
{ props.players.map((player, index) => PlayerRow(player, index)) }
|
||||
</ul>
|
||||
</div>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
import React from 'react';
|
||||
import { InertiaLink } from '@inertiajs/inertia-react';
|
||||
import Layout from '@/Shared/Layout';
|
||||
import GameTypesPlayedCols from '@/Components/GameTypesPlayedCols';
|
||||
|
||||
import { Radar, RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis } from 'recharts';
|
||||
|
||||
const returnWeaponTotals = (statTotals) => {
|
||||
let totals = [
|
||||
{ weapon: 'Chaingun', val: statTotals['cgKillsTG'] },
|
||||
{ weapon: 'Disc', val: statTotals['discKillsTG'] },
|
||||
{ weapon: 'Grenade Launcher', val: statTotals['grenadeKillsTG'] },
|
||||
{ weapon: 'Shocklance', val: statTotals['shockKillsTG'] },
|
||||
{ weapon: 'Laser Rifle', val: statTotals['laserKillsTG'] },
|
||||
{ weapon: 'Blaster', val: statTotals['blasterKillsTG'] },
|
||||
{ weapon: 'Plasma Rifle', val: statTotals['plasmaKillsTG'] },
|
||||
{ weapon: 'Mortar Launcher', val: statTotals['mortarKillsTG'] },
|
||||
{ weapon: 'Missile Launcher', val: statTotals['missileKillsTG'] },
|
||||
{ weapon: 'Hand Grenade', val: statTotals['hGrenadeKillsTG'] },
|
||||
{ weapon: 'Mine', val: statTotals['mineKillsTG'] },
|
||||
{ weapon: 'Satchel', val: statTotals['satchelKillsTG'] }
|
||||
];
|
||||
|
||||
// dont return if the val is 0
|
||||
return totals.filter(function(el) {
|
||||
return el.val > 0;
|
||||
});
|
||||
};
|
||||
|
||||
const GameCard = (player, index) => {
|
||||
// only display card if player has score
|
||||
// if (Number(player.stats.score) <= 0){return}
|
||||
|
||||
return (
|
||||
<div key={index} className="bg-white shadow overflow-hidden sm:rounded-lg mb-5">
|
||||
<div className="px-4 py-5 border-b border-gray-200 sm:px-6">
|
||||
<div className="-ml-4 -mt-4 flex justify-between items-center flex-wrap sm:flex-no-wrap">
|
||||
<div className="ml-4 mt-4">
|
||||
<h3 className="text-lg leading-6 font-medium text-gray-900">
|
||||
<InertiaLink
|
||||
href={`/game/${player.game_id}`}
|
||||
className="text-indigo-600 hover:text-indigo-500 transition duration-150 ease-in-out"
|
||||
>
|
||||
{player.stats.map}
|
||||
</InertiaLink>
|
||||
</h3>
|
||||
|
||||
<p className="mt-1 max-w-2xl text-sm leading-5 text-gray-500">
|
||||
<span className="inline-flex items-center px-2 py-0.5 rounded text-xs font-medium leading-4 bg-gray-100 text-gray-800">
|
||||
{player.stats.dateStamp}
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div className="ml-4 mt-4 flex-shrink-0">
|
||||
<span className="inline-flex items-center px-3 py-0.5 rounded-full text-xs font-medium leading-5 bg-indigo-100 text-indigo-800">
|
||||
{player.gametype}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Total Score</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">{player.stats.scoreTG}</dd>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Kills / Assists</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.killsTG} / {player.stats.assistTG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">MAs</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">{player.stats.totalMATG}</dd>
|
||||
</div>
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Flag Grabs / Caps</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.flagGrabsTG} / {player.stats.flagCapsTG}
|
||||
</dd>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Flag Defends / Carrier Kills / Returns</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
{player.stats.flagDefendsTG} / {player.stats.carrierKillsTG} / {player.stats.flagReturnsTG}
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Player(props) {
|
||||
return (
|
||||
<Layout title={props.pageTitle}>
|
||||
<div className="md:grid md:grid-cols-4 md:gap-6">
|
||||
<div className="md:col-span-1">
|
||||
<div className="px-4 sm:px-0">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-900">Aggregate</h3>
|
||||
<p className="mt-1 text-sm leading-5 text-gray-500">Stat Totals</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-5 md:mt-0 md:col-span-3">
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-lg">
|
||||
<div className="bg-white px-4 py-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
|
||||
<div className="text-sm leading-5 font-medium text-gray-500">Games Played</div>
|
||||
<div className="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
|
||||
<GameTypesPlayedCols
|
||||
ctf={props.playerData.player.total_games_ctfgame}
|
||||
dm={props.playerData.player.total_games_dmgame}
|
||||
lak={props.playerData.player.total_games_lakrabbitgame}
|
||||
spawnctf={props.playerData.player.total_games_sctfgame}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="bg-gray-50 px-4 py-5">
|
||||
<dt className="text-sm leading-5 font-medium text-gray-500">Weapon Usage</dt>
|
||||
<dd className="mt-1 text-sm leading-5 text-gray-900 flex items-center justify-center">
|
||||
<RadarChart
|
||||
cx={300}
|
||||
cy={250}
|
||||
outerRadius={150}
|
||||
width={600}
|
||||
height={500}
|
||||
data={
|
||||
returnWeaponTotals(props.playerData.totals).length ? (
|
||||
returnWeaponTotals(props.playerData.totals)
|
||||
) : (
|
||||
[ { weapon: 'No Data', val: 1 } ]
|
||||
)
|
||||
}
|
||||
className="text-xs"
|
||||
>
|
||||
<PolarGrid />
|
||||
<PolarAngleAxis dataKey="weapon" />
|
||||
<PolarRadiusAxis />
|
||||
<Radar
|
||||
name={props.playerData.player.player_name}
|
||||
dataKey="val"
|
||||
stroke="#8884d8"
|
||||
fill="#8884d8"
|
||||
fillOpacity={0.6}
|
||||
/>
|
||||
</RadarChart>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="md:grid md:grid-cols-4 md:gap-6 mt-10">
|
||||
<div className="md:col-span-1">
|
||||
<div className="px-4 sm:px-0">
|
||||
<h3 className="text-lg font-medium leading-6 text-gray-900">Game History</h3>
|
||||
<p className="mt-1 text-sm leading-5 text-gray-500">
|
||||
Stats for past {props.playerData.stats.length} games
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-5 md:mt-0 md:col-span-3">
|
||||
{props.playerData.stats.map((player, index) => GameCard(player, index))}
|
||||
</div>
|
||||
</div>
|
||||
{/*
|
||||
|
||||
<div className="bg-white shadow overflow-hidden sm:rounded-md">
|
||||
<div className="py-10 px-10"><code> {JSON.stringify(props.playerData.stats)}</code></div>
|
||||
</div> */}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
import React, { useEffect } from 'react'
|
||||
|
||||
import TopNav from '../Components/TopNav';
|
||||
import FrameHeading from '../Components/FrameHeading'
|
||||
|
||||
export default function Layout({ title, gametype, children }) {
|
||||
useEffect(() => {
|
||||
document.title = title + ' - Tribes 2 Stats';
|
||||
}, [title])
|
||||
|
||||
return (
|
||||
<>
|
||||
<TopNav />
|
||||
<FrameHeading heading={title} gametype={gametype} />
|
||||
<main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
<div className="px-4 py-4 sm:px-0">
|
||||
{ children }
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import { InertiaApp } from '@inertiajs/inertia-react'
|
||||
import React from 'react'
|
||||
import { render } from 'react-dom'
|
||||
|
||||
const app = document.getElementById('app')
|
||||
|
||||
render(
|
||||
<InertiaApp
|
||||
initialPage={JSON.parse(app.dataset.page)}
|
||||
resolveComponent={name => import(`@/Pages/${name}`).then(module => module.default)}
|
||||
/>,
|
||||
app
|
||||
)
|
||||
|
||||
// This is required to enable HMR
|
||||
if (module.hot) {
|
||||
module.hot.accept();
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
@import "tailwindcss/base";
|
||||
|
||||
@import "tailwindcss/components";
|
||||
|
||||
@import "tailwindcss/utilities";
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<title>Tribes 2 Stats</title>
|
||||
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
|
||||
@if(node_env().env === "production")
|
||||
{{ style(versioncss('main')) }}
|
||||
@else
|
||||
{{ style('dist/css/main') }}
|
||||
@endif
|
||||
</head>
|
||||
<body class="antialiased font-sans bg-gray-200">
|
||||
|
||||
<div id="popup" class="relative bg-indigo-600">
|
||||
<div class="max-w-screen-xl mx-auto py-3 px-3 sm:px-6 lg:px-8">
|
||||
<div class="pr-16 sm:text-center sm:px-16">
|
||||
<p class="font-medium text-white">
|
||||
Hey! This is a preview. Things aren't quite finished yet. Stay tuned!
|
||||
</p>
|
||||
</div>
|
||||
<div class="absolute inset-y-0 right-0 pt-1 pr-1 flex items-start sm:pt-1 sm:pr-2 sm:items-start">
|
||||
<button type="button" class="flex p-2 rounded-md hover:bg-indigo-500 focus:outline-none focus:bg-indigo-500 transition ease-in-out duration-150" onclick="closePopUp()">
|
||||
<svg class="h-6 w-6 text-white" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{{ startTag }}}
|
||||
|
||||
{{-- {{ edgeVar }} --}}
|
||||
@if(node_env().env === "production" || node_env().hmr === "false")
|
||||
{{ script(versionjs('app')) }}
|
||||
@else
|
||||
{{ script('http://localhost:8081/dist/js/app.js') }}
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
function closePopUp(){
|
||||
document.getElementById("popup").remove();
|
||||
};
|
||||
|
||||
if(top != self){
|
||||
setInterval(() => {
|
||||
parent.postMessage(document.getElementById('app').clientHeight, '*');
|
||||
}, 1000);
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Http server
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This file bootstrap Adonisjs to start the HTTP server. You are free to
|
||||
| customize the process of booting the http server.
|
||||
|
|
||||
| """ Loading ace commands """
|
||||
| At times you may want to load ace commands when starting the HTTP server.
|
||||
| Same can be done by chaining `loadCommands()` method after
|
||||
|
|
||||
| """ Preloading files """
|
||||
| Also you can preload files by calling `preLoad('path/to/file')` method.
|
||||
| Make sure to pass relative path from the project root.
|
||||
*/
|
||||
|
||||
const { Ignitor } = require('@adonisjs/ignitor')
|
||||
|
||||
new Ignitor(require('@adonisjs/fold'))
|
||||
.appRoot(__dirname)
|
||||
.fireHttpServer()
|
||||
.catch(console.error)
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Providers are building blocks for your Adonis app. Anytime you install
|
||||
| a new Adonis specific package, chances are you will register the
|
||||
| provider here.
|
||||
|
|
||||
*/
|
||||
const providers = [
|
||||
'@adonisjs/framework/providers/AppProvider',
|
||||
'@adonisjs/framework/providers/ViewProvider',
|
||||
'@adonisjs/lucid/providers/LucidProvider',
|
||||
'@adonisjs/cors/providers/CorsProvider',
|
||||
'inertia-adonis/providers/InertiaProvider'
|
||||
]
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Ace Providers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Ace providers are required only when running ace commands. For example
|
||||
| Providers for migrations, tests etc.
|
||||
|
|
||||
*/
|
||||
const aceProviders = [
|
||||
]
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Aliases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Aliases are short unique names for IoC container bindings. You are free
|
||||
| to create your own aliases.
|
||||
|
|
||||
| For example:
|
||||
| { Route: 'Adonis/Src/Route' }
|
||||
|
|
||||
*/
|
||||
const aliases = {}
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Commands
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you store ace commands for your package
|
||||
|
|
||||
*/
|
||||
const commands = []
|
||||
|
||||
module.exports = { providers, aceProviders, aliases, commands }
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
const { hooks } = require('@adonisjs/ignitor')
|
||||
const { version } = require('../package.json')
|
||||
const Helpers = use('Helpers')
|
||||
|
||||
const mixManifest = require(Helpers.publicPath('mix-manifest.json'))
|
||||
|
||||
hooks.after.providersBooted(async () => {
|
||||
const View = use('View')
|
||||
|
||||
View.global('node_env', () => {
|
||||
return { "env": process.env.NODE_ENV, "hmr": process.env.WEBPACK_HMR }
|
||||
})
|
||||
|
||||
View.global('versionjs', (filename) => {
|
||||
filename = `/dist/js/${filename}.js`
|
||||
if (!mixManifest.hasOwnProperty(filename)) {
|
||||
throw new Error('Could not find asset for versioning' + filename)
|
||||
}
|
||||
|
||||
return mixManifest[filename]
|
||||
})
|
||||
|
||||
View.global('versioncss', (filename) => {
|
||||
filename = `/dist/css/${filename}.css`
|
||||
if (!mixManifest.hasOwnProperty(filename)) {
|
||||
throw new Error('Could not find asset for versioning' + filename)
|
||||
}
|
||||
|
||||
return mixManifest[filename]
|
||||
})
|
||||
|
||||
const Inertia = use('Adonis/Addons/Inertia')
|
||||
|
||||
// these vars get pushed to the inertia frontend
|
||||
Inertia.setVersion(version)
|
||||
Inertia.share('app.name', process.env.APP_NAME)
|
||||
})
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/** @type {import('@adonisjs/framework/src/Server')} */
|
||||
const Server = use('Server')
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Global middleware are executed on each http request only when the routes
|
||||
| match.
|
||||
|
|
||||
*/
|
||||
const globalMiddleware = [
|
||||
'Adonis/Middleware/Inertia'
|
||||
]
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Named Middleware
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Named middleware is key/value object to conditionally add middleware on
|
||||
| specific routes or group of routes.
|
||||
|
|
||||
| // define
|
||||
| {
|
||||
| auth: 'Adonis/Middleware/Auth'
|
||||
| }
|
||||
|
|
||||
| // use
|
||||
| Route.get().middleware('auth')
|
||||
|
|
||||
*/
|
||||
const namedMiddleware = {}
|
||||
|
||||
Server
|
||||
.registerGlobal(globalMiddleware)
|
||||
.registerNamed(namedMiddleware)
|
||||
.use([
|
||||
'Adonis/Middleware/Static',
|
||||
'Adonis/Middleware/Cors'
|
||||
])
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
'use strict'
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Http routes are entry points to your web application. You can create
|
||||
| routes for different URLs and bind Controller actions to them.
|
||||
|
|
||||
| A complete guide on routing is available here.
|
||||
| http://adonisjs.com/docs/4.0/routing
|
||||
|
|
||||
*/
|
||||
|
||||
/** @type {typeof import('@adonisjs/framework/src/Route/Manager')} */
|
||||
const Route = use('Route')
|
||||
|
||||
// [ Routes ]
|
||||
//Route.get('/', 'IndexController.index').as('home')
|
||||
//temp set games as home
|
||||
Route.get('/', 'GameController.index').as('home')
|
||||
|
||||
// [ player ]
|
||||
Route.get('/players', 'PlayerController.index')
|
||||
Route.get('/player/:player_guid', 'PlayerController.player')
|
||||
|
||||
// [ game ]
|
||||
Route.get('/games', 'GameController.index')
|
||||
Route.get('/game/:game_id', 'GameController.game')
|
||||
|
||||
|
||||
|
||||
// Container Healthcheck route
|
||||
Route.get('/healthz', () => {
|
||||
return { status: "healthy" };
|
||||
})
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['Inter var', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
},
|
||||
},
|
||||
variants: {},
|
||||
plugins: [
|
||||
require('@tailwindcss/ui'),
|
||||
]
|
||||
}
|
||||
|
|
@ -1,134 +0,0 @@
|
|||
const mix = require('laravel-mix');
|
||||
|
||||
//require('laravel-mix-tailwind');
|
||||
require('laravel-mix-purgecss');
|
||||
const tailwindcss = require('tailwindcss');
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Mix Asset Management
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
||||
| for your Laravel application. By default, we are compiling the Sass
|
||||
| file for the application as well as bundling up all the JS files.
|
||||
|
|
||||
*/
|
||||
|
||||
// transpiling, babelling, minifying and creating the public/js/main.js out of our assets
|
||||
mix.setPublicPath('public')
|
||||
.react('resources/js/app.js', 'public/dist/js')
|
||||
// .sass('resources/scss/main.scss', 'public/dist/css')
|
||||
.postCss('resources/scss/main.css', 'public/dist/css')
|
||||
// .tailwind('./tailwind.config.js');
|
||||
|
||||
mix.webpackConfig({
|
||||
output: {
|
||||
chunkFilename: './dist/js/[name].[contenthash].js'
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(css)/,
|
||||
use: [
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
ident: 'postcss',
|
||||
plugins: [
|
||||
tailwindcss('./tailwind.config.js'),
|
||||
require('autoprefixer'),
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(
|
||||
__dirname,
|
||||
"resources/js"
|
||||
),
|
||||
"@sass": path.resolve(
|
||||
__dirname,
|
||||
"resources/scss"
|
||||
)
|
||||
}
|
||||
},
|
||||
devServer: {
|
||||
proxy: {
|
||||
host: '0.0.0.0', // host machine ip
|
||||
port: 8080,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
mix.options({
|
||||
hmrOptions: {
|
||||
host: '0.0.0.0', // site's host name
|
||||
port: 8081
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if (mix.inProduction()) {
|
||||
mix.purgeCss({
|
||||
content: [
|
||||
'./resources/**/*.edge',
|
||||
'./resources/**/*.js',
|
||||
'./resources/**/*.jsx',
|
||||
'./resources/**/*.ts',
|
||||
'./resources/**/*.tsx'
|
||||
],
|
||||
// default in mix
|
||||
//defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [],
|
||||
// default tailwind
|
||||
defaultExtractor: content => content.match(/[\w-/.:]+(?<!:)/g) || [],
|
||||
whitelistPatterns: [/-active$/, /-enter$/, /-leave-to$/]
|
||||
});
|
||||
|
||||
mix.version();
|
||||
}else{
|
||||
// use SourceMaps on dev
|
||||
mix.sourceMaps();
|
||||
}
|
||||
|
||||
// Full mix API
|
||||
// mix.js(src, output);
|
||||
// mix.react(src, output); <-- Identical to mix.js(), but registers React Babel compilation.
|
||||
// mix.preact(src, output); <-- Identical to mix.js(), but registers Preact compilation.
|
||||
// mix.coffee(src, output); <-- Identical to mix.js(), but registers CoffeeScript compilation.
|
||||
// mix.ts(src, output); <-- TypeScript support. Requires tsconfig.json to exist in the same folder as webpack.mix.js
|
||||
// mix.extract(vendorLibs);
|
||||
// mix.sass(src, output);
|
||||
// mix.standaloneSass('src', output); <-- Faster, but isolated from Webpack.
|
||||
// mix.fastSass('src', output); <-- Alias for mix.standaloneSass().
|
||||
// mix.less(src, output);
|
||||
// mix.stylus(src, output);
|
||||
// mix.postCss(src, output, [require('postcss-some-plugin')()]);
|
||||
// mix.browserSync('my-site.test');
|
||||
// mix.combine(files, destination);
|
||||
// mix.babel(files, destination); <-- Identical to mix.combine(), but also includes Babel compilation.
|
||||
// mix.copy(from, to);
|
||||
// mix.copyDirectory(fromDir, toDir);
|
||||
// mix.minify(file);
|
||||
// mix.sourceMaps(); // Enable sourcemaps
|
||||
// mix.version(); // Enable versioning.
|
||||
// mix.disableNotifications();
|
||||
// mix.setPublicPath('path/to/public');
|
||||
// mix.setResourceRoot('prefix/for/resource/locators');
|
||||
// mix.autoload({}); <-- Will be passed to Webpack's ProvidePlugin.
|
||||
// mix.webpackConfig({}); <-- Override webpack.config.js, without editing the file directly.
|
||||
// mix.babelConfig({}); <-- Merge extra Babel configuration (plugins, etc.) with Mix's default.
|
||||
// mix.then(function () {}) <-- Will be triggered each time Webpack finishes building.
|
||||
// mix.extend(name, handler) <-- Extend Mix's API with your own components.
|
||||
// mix.options({
|
||||
// extractVueStyles: false, // Extract .vue component styling to file, rather than inline.
|
||||
// globalVueStyles: file, // Variables file to be imported in every component.
|
||||
// processCssUrls: true, // Process/optimize relative stylesheet url()'s. Set to false, if you don't want them touched.
|
||||
// purifyCss: false, // Remove unused CSS selectors.
|
||||
// uglify: {}, // Uglify-specific options. https://webpack.github.io/docs/list-of-plugins.html#uglifyjsplugin
|
||||
// postCss: [] // Post-CSS options: https://github.com/postcss/postcss/blob/master/docs/plugins.md
|
||||
// });
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
.git
|
||||
node_modules
|
||||
public/dist
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
# [ Stage 1 ] - install node modules
|
||||
FROM node:12.2-alpine as builder
|
||||
RUN apk update
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
COPY ./app/webapp/package.json /build/package.json
|
||||
COPY ./app/webapp/package-lock.json /build/package-lock.json
|
||||
|
||||
RUN npm install
|
||||
RUN npm i --global @adonisjs/cli
|
||||
|
||||
RUN npx adonis key:generate --echo
|
||||
|
||||
# ============================
|
||||
# ============================
|
||||
|
||||
# [ Stage 2 ]
|
||||
FROM node:12.2-alpine
|
||||
LABEL maintainer="Anthony Mineo <anthonymineo@gmail.com>"
|
||||
|
||||
RUN apk update && apk add --no-cache bash curl
|
||||
|
||||
# Default envs as prod
|
||||
ENV ENV_SILENT=true \
|
||||
HOST=0.0.0.0 \
|
||||
PORT=8080 \
|
||||
HASH_DRIVER=bcrypt \
|
||||
NODE_ENV=production \
|
||||
WEBPACK_HMR=false \
|
||||
CACHE_VIEWS=true \
|
||||
APP_NAME=AdonisJs
|
||||
ENV APP_URL=http://${HOST}:${PORT}
|
||||
|
||||
#ENV APP_KEY=you-need-to-generate-this
|
||||
# secrets path _FILE prefix or ENV K=V
|
||||
|
||||
|
||||
# Setup pm2 as our node process manager
|
||||
# https://pm2.keymetrics.io/docs/usage/docker-pm2-nodejs/
|
||||
RUN npm install pm2 -g
|
||||
|
||||
# Set node modules outside our app to keep it clean
|
||||
COPY --from=builder /build/node_modules/ /opt/node_modules/
|
||||
ENV PATH /opt/node_modules/.bin:$PATH
|
||||
|
||||
|
||||
# Start script and config
|
||||
COPY ./build/webapp/entrypoint.sh /entrypoint.sh
|
||||
|
||||
# Our App
|
||||
WORKDIR /app
|
||||
COPY ./app/webapp /app
|
||||
|
||||
RUN ln -nsf /opt/node_modules /app
|
||||
|
||||
|
||||
# Bake prod assets into image
|
||||
RUN rm -rf /app/public/dist && npm run webpack-server
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
|
||||
HEALTHCHECK --interval=20s --timeout=30s --start-period=5s --retries=5 \
|
||||
CMD curl -f http://localhost:8080/healthz || exit 1
|
||||
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Node ENV: $NODE_ENV"
|
||||
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
local val="$def"
|
||||
if [ "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ "${!fileVar:-}" ]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
export "$var"="$val"
|
||||
unset "$fileVar"
|
||||
}
|
||||
|
||||
file_env 'APP_KEY'
|
||||
|
||||
|
||||
# Exit if APP_KEY is missing, this key is important!
|
||||
if [ -z "$APP_KEY" ]
|
||||
then
|
||||
echo >&2 "[ERROR] No ENV for APP_KEY or APP_KEY_FILE found!"
|
||||
echo >&2 "Run the ./generate-adonis-app-key.sh script or provide one at runtime"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
if [[ "$NODE_ENV" == "development" ]]; then
|
||||
echo "Prepping container for dev environment"
|
||||
echo "Setting a symlink for ./node_modules -> /opt/node_modules"
|
||||
ln -nsf /opt/node_modules /app
|
||||
|
||||
echo "Cleaning dist assets..."
|
||||
rm -rf /app/public/dist
|
||||
npm run webpack-server
|
||||
fi
|
||||
|
||||
# Generate a dist assets if they don't exist -- (If they were deleted on the volume mount)
|
||||
[ ! -d "/app/public/dist" ] && npm run webpack-server
|
||||
|
||||
|
||||
if [[ "$NODE_ENV" == "production" ]]; then
|
||||
pm2-runtime start /app/ecosystem._PROD_.config.js
|
||||
elif [[ "$WEBPACK_HMR" == "true" ]]; then
|
||||
pm2-runtime start /app/ecosystem._DEV_HOT_.config.js
|
||||
else
|
||||
pm2-runtime start /app/ecosystem._DEV_.config.js
|
||||
fi
|
||||
|
|
@ -21,19 +21,6 @@ services:
|
|||
volumes:
|
||||
- ./app/t2-stat-parser:/app
|
||||
|
||||
# web:
|
||||
# environment:
|
||||
# DB_USER: "dev"
|
||||
# DB_PASSWORD: "dev"
|
||||
# CACHE_VIEWS: "false"
|
||||
# NODE_ENV: "development" # auto-reloads app on save, dev builds
|
||||
# WEBPACK_HMR: "true" # default is false -- this is useful for when you're focused on Frontend Dev
|
||||
# ports:
|
||||
# - "8080:8080" # adonis http port
|
||||
# - "8081:8081" # webpack-dev-server port
|
||||
# volumes:
|
||||
# - ./app/webapp:/app
|
||||
|
||||
api:
|
||||
environment:
|
||||
NODE_ENV: "development" # auto-reloads app on save
|
||||
|
|
|
|||
|
|
@ -57,35 +57,6 @@ services:
|
|||
- internal
|
||||
- external
|
||||
|
||||
# web:
|
||||
# image: "amineo/t2-stats-web:v0.1.0-rc6"
|
||||
# build:
|
||||
# context: .
|
||||
# dockerfile: ./build/webapp/Dockerfile
|
||||
# environment:
|
||||
# NODE_ENV: "production" # set as default in image
|
||||
# CACHE_VIEWS: "true" # set as default in image
|
||||
# APP_NAME: "Web" # set as default in image
|
||||
# # APP_KEY: "You-need-to-generate-this (npx adonis key:generate --echo)"
|
||||
# APP_KEY_FILE: /run/secrets/adonis.appkey
|
||||
# DB_HOST: "db"
|
||||
# DB_PORT: 5432
|
||||
# DB_USER: ""
|
||||
# DB_PASSWORD: ""
|
||||
# DB_DATABASE: t2_stats
|
||||
# secrets:
|
||||
# - adonis.appkey
|
||||
# ports:
|
||||
# - "8080:8080"
|
||||
# networks:
|
||||
# - internal
|
||||
# - external
|
||||
# deploy:
|
||||
# # labels:
|
||||
# # - traefik.enable=false
|
||||
# mode: replicated
|
||||
# replicas: 1
|
||||
|
||||
volumes:
|
||||
psqldata:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +0,0 @@
|
|||
#!/bin/bash
|
||||
echo "Checking to see if @adonisjs/cli has been installed..."
|
||||
|
||||
package='@adonisjs/cli'
|
||||
if [ `npm list -g | grep -c $package` -eq 0 ]; then
|
||||
while true; do
|
||||
echo "-----------------------------------------------"
|
||||
echo " Adonis CLI not installed"
|
||||
echo "-----------------------------------------------"
|
||||
read -p "Would you like to install this now? [Y/N] " yn
|
||||
case $yn in
|
||||
[Yy]* ) npm i --global @adonisjs/cli; break;;
|
||||
[Nn]* ) break;;
|
||||
* ) echo "Please answer yes or no.";;
|
||||
esac
|
||||
done
|
||||
else
|
||||
echo "Looks good!"
|
||||
fi
|
||||
|
||||
|
||||
echo "Generating key..."
|
||||
APPKEY=$(npx adonis key:generate --echo)
|
||||
|
||||
echo -n "${APPKEY/APP_KEY=}" > ./docker-secrets/adonis.appkey.v1
|
||||
|
||||
echo "Done! Don't share it with anyone!"
|
||||
echo "The key is located here: ./docker-secrets/adonis.appkey.v1"
|
||||
Loading…
Reference in a new issue