A ton of frontend.
- Added basic blog layout and routes. - Basic games frontend. - Basic frontend for admin site configuration. - User profiles. - User last online dates. - Fixed performance issues with CPU and memory usage counters. They are now queued events that update their respective rows in the database every minute. - Renamed "graphictoria-item-page" css class to "graphictoria-smaller-page". - Added screenshots that some images were based on.
This commit is contained in:
parent
ac65f02703
commit
ed3cef5057
|
|
@ -1,10 +1,16 @@
|
|||
# Allow read in the public directories.
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public/">
|
||||
Require local
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public_api/">
|
||||
Require local
|
||||
Require all granted
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
# Disallow access to admin JS
|
||||
<Directory "C:/graphictoria/COMMIT_HASH/web/public/js/adm/">
|
||||
Require all denied
|
||||
AllowOverride All
|
||||
</Directory>
|
||||
|
||||
|
|
@ -14,15 +20,14 @@
|
|||
ServerName gtoria.net
|
||||
|
||||
ServerAlias www.gtoria.net
|
||||
ServerAlias wiki.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/localhost.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/localhost.key"
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/graphictoria/logs/gt-test-error.log"
|
||||
ErrorLog "C:/graphictoria/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-test-access.log" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-access.log" gtoria
|
||||
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTP_HOST} !^www\. [NC]
|
||||
|
|
@ -31,7 +36,28 @@
|
|||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
|
||||
|
||||
DocumentRoot "D:/wamp320/graphictoria/sitetest3/web/public"
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public"
|
||||
</VirtualHost>
|
||||
|
||||
# Blog/Wiki
|
||||
<VirtualHost *:80 *:443>
|
||||
ServerName gtoria.net
|
||||
|
||||
ServerAlias blog.gtoria.net
|
||||
ServerAlias wiki.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/xampp/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/xampp/logs/gt-access.log" gtoria
|
||||
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
|
||||
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public"
|
||||
</VirtualHost>
|
||||
|
||||
# Api endpoints.
|
||||
|
|
@ -49,12 +75,12 @@
|
|||
ServerAlias test.public.ecs.gtoria.net
|
||||
|
||||
SSLEngine on
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/localhost.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/localhost.key"
|
||||
SSLCertificateFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.crt"
|
||||
SSLCertificateKeyFile "C:/graphictoria/COMMIT_HASH/etc/cert/cloudflare.key"
|
||||
|
||||
ErrorLog "C:/graphictoria/logs/gt-test-error.log"
|
||||
ErrorLog "C:/graphictoria/logs/gt-error.log"
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Host}i\" \"%{Referer}i\" \"%{User-agent}i\"" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-test-access.log" gtoria
|
||||
CustomLog "C:/graphictoria/logs/gt-access.log" gtoria
|
||||
|
||||
DocumentRoot "D:/wamp320/graphictoria/sitetest3/web/public_api"
|
||||
DocumentRoot "C:/graphictoria/COMMIT_HASH/web/public_api"
|
||||
</VirtualHost>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 9.9 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 7.7 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 445 KiB |
|
|
@ -5,6 +5,8 @@ namespace App\Console;
|
|||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
use App\Jobs\UpdateUsageCounters;
|
||||
|
||||
class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
|
|
@ -15,7 +17,7 @@ class Kernel extends ConsoleKernel
|
|||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
$schedule->job(new UpdateUsageCounters)->everyMinute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@
|
|||
|
||||
namespace App\Helpers;
|
||||
|
||||
use App\Models\UsageCounter;
|
||||
|
||||
class QAaMBHelper
|
||||
{
|
||||
public static function wmiWBemLocatorQuery($query)
|
||||
|
|
@ -78,31 +80,29 @@ class QAaMBHelper
|
|||
|
||||
public static function getSystemCpuInfo($output_key = '')
|
||||
{
|
||||
return cache()->remember('QAaMB-Cpu-Info', 5, function(){
|
||||
$result = 0;
|
||||
$result = 0;
|
||||
|
||||
try {
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||
// LINUX
|
||||
|
||||
return sys_getloadavg();
|
||||
} else {
|
||||
// WINDOWS
|
||||
|
||||
$wmi_found = false;
|
||||
if ( $wmi_query = self::wmiWBemLocatorQuery(
|
||||
"SELECT LoadPercentage FROM Win32_Processor" ) ) {
|
||||
foreach($wmi_query as $r) {
|
||||
$result = $r->LoadPercentage / 100;
|
||||
$wmi_found = true;
|
||||
}
|
||||
try {
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
|
||||
// LINUX
|
||||
|
||||
return sys_getloadavg();
|
||||
} else {
|
||||
// WINDOWS
|
||||
|
||||
$wmi_found = false;
|
||||
if ( $wmi_query = self::wmiWBemLocatorQuery(
|
||||
"SELECT LoadPercentage FROM Win32_Processor" ) ) {
|
||||
foreach($wmi_query as $r) {
|
||||
$result = $r->LoadPercentage / 100;
|
||||
$wmi_found = true;
|
||||
}
|
||||
}
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
return empty($output_key) || !isset($result[$output_key]) ? $result : $result[$output_key];
|
||||
});
|
||||
} catch(Exception $e) {
|
||||
echo $e->getMessage();
|
||||
}
|
||||
return empty($output_key) || !isset($result[$output_key]) ? $result : $result[$output_key];
|
||||
}
|
||||
|
||||
public static function memoryString($memory)
|
||||
|
|
@ -113,7 +113,7 @@ class QAaMBHelper
|
|||
|
||||
public static function getMemoryUsage()
|
||||
{
|
||||
$memoryInfo = self::getSystemMemoryInfo();
|
||||
$memoryInfo = json_decode(UsageCounter::where('name', 'Memory')->first()->value, true);
|
||||
|
||||
// XlXi: the -2 is required so it fits inside of the bar thing
|
||||
// XlXi: change this if theres ever a separate graph
|
||||
|
|
@ -128,18 +128,27 @@ class QAaMBHelper
|
|||
|
||||
public static function getMemoryPercentage()
|
||||
{
|
||||
$memoryInfo = self::getSystemMemoryInfo();
|
||||
$memoryInfo = json_decode(UsageCounter::where('name', 'Memory')->first()->value, true);
|
||||
|
||||
return ($memoryInfo['MemTotal'] - $memoryInfo['MemFree']) / $memoryInfo['MemTotal'];
|
||||
}
|
||||
|
||||
public static function getCpuUsage()
|
||||
{
|
||||
$cpuInfo = UsageCounter::where('name', 'CPU')->first();
|
||||
|
||||
// XlXi: the -2 is required so it fits inside of the bar thing
|
||||
// XlXi: change this if theres ever a separate graph
|
||||
return sprintf(
|
||||
'%s%% CPU Usage',
|
||||
round(self::getSystemCpuInfo() * (100-2))
|
||||
round(floatval($cpuInfo->value) * (100-2))
|
||||
);
|
||||
}
|
||||
|
||||
public static function getCpuPercentage()
|
||||
{
|
||||
$cpuInfo = UsageCounter::where('name', 'CPU')->first();
|
||||
|
||||
return $cpuInfo->value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
|
||||
class AdminController extends Controller
|
||||
{
|
||||
// Moderator+
|
||||
|
|
@ -30,4 +32,11 @@ class AdminController extends Controller
|
|||
'arbiter' => $arbiterType
|
||||
]);
|
||||
}
|
||||
|
||||
function configuration(Request $request)
|
||||
{
|
||||
return view('web.admin.configuration')->with([
|
||||
'values' => DynamicWebConfiguration::get()
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Web;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class GamesController extends Controller
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return view('web.games.index');
|
||||
}
|
||||
}
|
||||
|
|
@ -39,9 +39,10 @@ class Kernel extends HttpKernel
|
|||
\App\Http\Middleware\VerifyCsrfToken::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
|
||||
// Yeah no, the double session protector was stupid.
|
||||
// XlXi: Yeah no, the double session protector was stupid.
|
||||
//\App\Http\Middleware\DoubleSessionProtector::class, // Prevents DDoS attacks.
|
||||
\App\Http\Middleware\DailyReward::class
|
||||
\App\Http\Middleware\DailyReward::class,
|
||||
\App\Http\Middleware\LastSeenMiddleware::class
|
||||
],
|
||||
|
||||
'api' => [
|
||||
|
|
@ -71,5 +72,6 @@ class Kernel extends HttpKernel
|
|||
|
||||
'roleset' => \App\Http\Middleware\Roleset::class,
|
||||
'banned' => \App\Http\Middleware\CheckBan::class,
|
||||
'lastseen' => \App\Http\Middleware\LastSeenMiddleware::class,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class LastSeenMiddleware
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
if(Auth::check()) {
|
||||
$user = Auth::user();
|
||||
$user->last_seen = Carbon::now();
|
||||
$user->timestamps = false;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldBeUnique;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
use App\Helpers\QAaMBHelper;
|
||||
use App\Models\UsageCounter;
|
||||
|
||||
class UpdateUsageCounters implements ShouldQueue
|
||||
{
|
||||
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$memoryInfo = QAaMBHelper::getSystemMemoryInfo();
|
||||
$cpuInfo = QAaMBHelper::getSystemCpuInfo();
|
||||
|
||||
UsageCounter::where('name', 'CPU')->update([ 'value' => $cpuInfo ]);
|
||||
UsageCounter::where('name', 'Memory')->update([ 'value' => $memoryInfo ]);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,10 +2,66 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class DynamicWebConfiguration extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that should be cast.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
protected $casts = [
|
||||
'created_at' => 'datetime',
|
||||
'updated_at' => 'datetime',
|
||||
'masked' => 'boolean'
|
||||
];
|
||||
|
||||
public function getTruncatedValue($value = null)
|
||||
{
|
||||
if($value == null)
|
||||
$value = $this->value;
|
||||
|
||||
if(strlen($value) < 50)
|
||||
return $value;
|
||||
|
||||
return (substr($value, 0, 50) . '...');
|
||||
}
|
||||
|
||||
public function getJumbledValue()
|
||||
{
|
||||
$letters = 'abcdefghijklmnopqrstuvwxyz0123456789 `~!@#$%^&*()-_=+[{]}\\|;:\'",<.>/?';
|
||||
$result = '';
|
||||
|
||||
for($i=0; strlen($this->value) > $i; $i++)
|
||||
$result .= $letters[rand(0, strlen($letters)-1)];
|
||||
|
||||
return $this->getTruncatedValue($result);
|
||||
}
|
||||
|
||||
public function getCreated()
|
||||
{
|
||||
$date = $this['created_at'];
|
||||
if(Carbon::now()->greaterThan($date->copy()->addDays(2)))
|
||||
$date = $date->isoFormat('lll');
|
||||
else
|
||||
$date = $date->calendar();
|
||||
|
||||
return $date;
|
||||
}
|
||||
|
||||
public function getUpdated()
|
||||
{
|
||||
$date = $this['updated_at'];
|
||||
if(Carbon::now()->greaterThan($date->copy()->addDays(2)))
|
||||
$date = $date->isoFormat('lll');
|
||||
else
|
||||
$date = $date->calendar();
|
||||
|
||||
return $date;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UsageCounter extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
|
@ -47,6 +48,7 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'next_reward' => 'datetime',
|
||||
'last_seen' => 'datetime',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
@ -73,12 +75,39 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return route('user.profile', ['user' => $this->id]);
|
||||
}
|
||||
|
||||
public function getLastSeen()
|
||||
{
|
||||
if($this->last_seen >= Carbon::now()->subMinutes(2))
|
||||
return 'Now';
|
||||
|
||||
if(Carbon::now() >= $this->last_seen->copy()->addDays(2))
|
||||
return $this->last_seen->isoFormat('ll');
|
||||
else
|
||||
return $this->last_seen->calendar();
|
||||
}
|
||||
|
||||
public function getJoinDate()
|
||||
{
|
||||
return $this->created_at->isoFormat('ll');
|
||||
}
|
||||
|
||||
// XlXi: Returns a class name like text-success or
|
||||
// gt-status-studio to show next to the
|
||||
// user's name.
|
||||
public function getOnlineClass()
|
||||
{
|
||||
if($this->last_seen >= Carbon::now()->subMinutes(2))
|
||||
return 'text-success';
|
||||
|
||||
return 'text-muted';
|
||||
}
|
||||
|
||||
public function _hasRolesetInternal($roleName)
|
||||
{
|
||||
$roleset = Roleset::where('Name', $roleName)->first();
|
||||
if(
|
||||
UserRoleset::where('Roleset_id', $roleset->id)
|
||||
->where('User_id', Auth::user()->id)
|
||||
->where('User_id', $this->id)
|
||||
->exists()
|
||||
)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -47,6 +47,14 @@ class RouteServiceProvider extends ServiceProvider
|
|||
->namespace('App\Http\Controllers\Web')
|
||||
->group(base_path('routes/web.php'));
|
||||
|
||||
//
|
||||
// Domain: www.gtoria.net
|
||||
//
|
||||
Route::domain('blog.' . DomainHelper::TopLevelDomain())
|
||||
->middleware('web')
|
||||
->namespace('App\Http\Controllers\Blog')
|
||||
->group(base_path('routes/blog.php'));
|
||||
|
||||
//
|
||||
// Domain: api.gtoria.net
|
||||
//
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ return new class extends Migration
|
|||
$table->string('thumbnail2DHash')->nullable();
|
||||
$table->string('thumbnail3DHash')->nullable();
|
||||
|
||||
$table->dateTime('last_seen')->useCurrent();
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ return new class extends Migration
|
|||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('value');
|
||||
$table->boolean('masked')->default(false);
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('usage_counters', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('value');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('usage_counters');
|
||||
}
|
||||
};
|
||||
|
|
@ -15,9 +15,10 @@ class DatabaseSeeder extends Seeder
|
|||
public function run()
|
||||
{
|
||||
$this->call([
|
||||
//FFlagSeeder::class,
|
||||
WebConfigurationSeeder::class,
|
||||
UsageCounterSeeder::class,
|
||||
RolesetSeeder::class
|
||||
//FFlagSeeder::class
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
use App\Models\UsageCounter;
|
||||
|
||||
class UsageCounterSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
UsageCounter::create([
|
||||
'name' => 'CPU',
|
||||
'value' => '1'
|
||||
]);
|
||||
|
||||
UsageCounter::create([
|
||||
'name' => 'Memory',
|
||||
'value' => '{"MemTotal":32768,"MemFree":1}'
|
||||
]);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
|
|
@ -5,12 +5,16 @@
|
|||
|
||||
import $ from 'jquery';
|
||||
import * as Bootstrap from 'bootstrap';
|
||||
import axios from 'axios';
|
||||
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import { buildGenericApiUrl } from '../util/HTTP.js';
|
||||
import SearchBar from './SearchBar';
|
||||
|
||||
axios.defaults.withCredentials = true;
|
||||
|
||||
const searchBarId = 'graphictoria-nav-searchbar';
|
||||
|
||||
$(document).ready(function() {
|
||||
|
|
@ -24,4 +28,8 @@ $(document).ready(function() {
|
|||
}
|
||||
|
||||
window.Bootstrap = Bootstrap;
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(function(){
|
||||
axios.get(buildGenericApiUrl('api', 'ping'))
|
||||
}, 120000)
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Graphictoria 5 (https://gtoria.net)
|
||||
Copyright © XlXi 2022
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
const configId = 'gt-config-values';
|
||||
|
||||
$(document).ready(function() {
|
||||
if (document.getElementById(configId)) {
|
||||
let configItems = document.getElementById(configId).children;
|
||||
let items = [];
|
||||
|
||||
for(let i = 0; i < configItems.length; i++) {
|
||||
let item = configItems[i];
|
||||
items.push({
|
||||
id: item.getAttribute('data-id'),
|
||||
name: item.getAttribute('data-name'),
|
||||
isMasked: (item.getAttribute('data-is-masked') === '1'),
|
||||
value: item.getAttribute('data-value'),
|
||||
created: item.getAttribute('data-created'),
|
||||
updated: item.getAttribute('data-updated')
|
||||
});
|
||||
}
|
||||
|
||||
console.log(items);
|
||||
}
|
||||
});
|
||||
|
|
@ -73,7 +73,7 @@ img.twemoji {
|
|||
height: 420px;
|
||||
}
|
||||
|
||||
.graphictoria-item-page {
|
||||
.graphictoria-smaller-page {
|
||||
max-width: 1096px;
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
||||
|
|
@ -368,6 +368,16 @@ html {
|
|||
background-position: center;
|
||||
}
|
||||
|
||||
.graphictoria-blog {
|
||||
/* XlXi: I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS I LOVE CSS */
|
||||
background-image: url("/Images/Backgrounds/Blog.png")!important;
|
||||
background-size: cover!important;
|
||||
background-repeat: no-repeat!important;
|
||||
background-position: center!important;
|
||||
height: 330px;
|
||||
background: #141414;
|
||||
}
|
||||
|
||||
// Home Page
|
||||
|
||||
.graphictoria-homepage-header {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
@php
|
||||
$slogan = (View::hasSection('description') ? View::getSection('description') . ' ' : '') . 'Graphictoria is an online social platform for those looking to relive the classic Roblox experience. So what are you waiting for? Join 8k+ other users in reliving the good ol\' days! Graphictoria is not affiliated with or sponsored by Roblox Corporation, all Roblox related indica and slogans belong to Roblox Corporation.';
|
||||
@endphp
|
||||
<!DOCTYPE html>
|
||||
<html class="gtoria-dark" lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<title>Graphictoria Blog{{ View::hasSection('title') ? ' | ' . View::getSection('title') : '' }}</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta name="theme-color" content="#348AFF"/>
|
||||
<meta name="author" content="Graphictoria"/>
|
||||
<meta name="description" content="{{ $slogan }}"/>
|
||||
<meta name="keywords" content="graphictoria, xdiscuss, nostalgia, roblox, gtoria, private server, classic, old roblox, classic roblox, forum, game engine, mmo, classic mmo, old internet"/>
|
||||
<meta property="og:title" content="Graphictoria Blog{{ View::hasSection('title') ? ' | ' . View::getSection('title') : '' }}"/>
|
||||
<meta property="og:site_name" content="Graphictoria Blog"/>
|
||||
<meta property="og:description" content="{{ $slogan }}"/>
|
||||
<meta property="og:type" content="website"/>
|
||||
<meta property="og:image" content="{{ asset('images/banner.png') }}">
|
||||
<meta name="twitter:image" content="{{ asset('images/banner.png') }}">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
@once
|
||||
<link href="{{ asset('favicon.ico') }}" rel="icon" integrity="{{ Sri::hash('favicon.ico') }}" crossorigin="anonymous" />
|
||||
<link href="{{ asset('images/logo.png') }}" rel="apple-touch-icon" integrity="{{ Sri::hash('images/logo.png') }}" crossorigin="anonymous" />
|
||||
<link href="{{ mix('css/Graphictoria.css') }}" rel="stylesheet" integrity="{{ Sri::hash('css/graphictoria.css') }}" crossorigin="anonymous" />
|
||||
<script src="{{ mix('js/app.js') }}" integrity="{{ Sri::hash('js/app.js') }}" crossorigin="anonymous"></script>
|
||||
@endonce
|
||||
@yield('extra-headers')
|
||||
@yield('page-specific')
|
||||
</head>
|
||||
<body>
|
||||
<div id="gtoria-root">
|
||||
@include('layouts.blog.nav')
|
||||
|
||||
@yield('content')
|
||||
|
||||
@include('layouts.footer')
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<div class="container graphictoria-smaller-page fixed-top">
|
||||
<div class="navbar navbar-expand-lg graphictoria-navbar rounded m-2">
|
||||
<div class="container-fluid px-4">
|
||||
<a class="navbar-brand" href="/">
|
||||
<img src="{{ asset('/images/logo.png') }}" alt="Graphictoria" width="43" height="43" draggable="false"/>
|
||||
Blog
|
||||
</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#graphictoria-nav" aria-controls="graphictoria-nav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse justify-content-md-center" id="graphictoria-nav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="{{ url('/') }}">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url('/') }}">About</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://gtoria.net">Main Site</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="graphictoria-blog shadow-sm"></div>
|
||||
|
|
@ -25,7 +25,14 @@
|
|||
"label" => "Blog",
|
||||
"location" => 'https://blog.gtoria.net'
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
if(str_starts_with(request()->getHost(), 'blog.')) {
|
||||
foreach($routes as $key => $route) {
|
||||
if($route['label'] == 'Blog')
|
||||
array_splice($routes, $key, $key);
|
||||
}
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div class="footer mt-auto pt-3 text-center shadow-lg">
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@
|
|||
<a href="{{ route('admin.dashboard') }}" class="nav-link py-0"><i class="fa-solid fa-gavel"></i></a>
|
||||
</li>
|
||||
@admin
|
||||
<li class="nav-item" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true" title="<strong>Only accurate at page load</strong><br/>{{ \App\Helpers\QAaMBHelper::getMemoryUsage() }}">
|
||||
<li class="nav-item" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true" title="<strong>Updates every minute</strong><br/>{{ \App\Helpers\QAaMBHelper::getMemoryUsage() }}">
|
||||
<span class="px-md-2 d-flex" style="height:24px;">
|
||||
<div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative graphictoria-admin-memorybar">
|
||||
@php
|
||||
|
|
@ -98,12 +98,12 @@
|
|||
<i class="my-auto fa-solid fa-gear"></i>
|
||||
</span>
|
||||
</li>
|
||||
<li class="nav-item" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true" title="<strong>Only accurate at page load</strong><br/>{{ \App\Helpers\QAaMBHelper::getCpuUsage() }}">
|
||||
<li class="nav-item" data-bs-toggle="tooltip" data-bs-placement="bottom" data-bs-html="true" title="<strong>Updates every minute</strong><br/>{{ \App\Helpers\QAaMBHelper::getCpuUsage() }}">
|
||||
<span class="px-md-2 d-flex" style="height:24px;">
|
||||
<div class="my-auto rounded-1 bg-secondary border border-light right-0 me-1 position-relative graphictoria-admin-memorybar">
|
||||
@php
|
||||
$admin_cpubar_color = 'bg-primary';
|
||||
$admin_cpubar_usage = \App\Helpers\QAaMBHelper::getSystemCpuInfo() * 100;
|
||||
$admin_cpubar_usage = \App\Helpers\QAaMBHelper::getCpuPercentage() * 100;
|
||||
|
||||
if($admin_cpubar_usage <= 25)
|
||||
$admin_cpubar_color = 'bg-success'; // Green
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
@extends('layouts.admin')
|
||||
|
||||
@section('title', 'Site Configuration')
|
||||
|
||||
@section('page-specific')
|
||||
<style>
|
||||
.gt-small-row {
|
||||
width: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.gt-masked-text {
|
||||
filter: blur(3px);
|
||||
}
|
||||
|
||||
.gt-masked-text-shown {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Secure Page JS -->
|
||||
<script src="data:text/javascript;base64,{{ base64_encode(File::get(public_path('js/adm/SiteConfiguration.js'))) }}"></script>
|
||||
@endsection
|
||||
|
||||
@push('content')
|
||||
<div class="container-md">
|
||||
<h4>Site Configuration</h4>
|
||||
<div class="card p-2">
|
||||
<table class="table table-sm table-bordered table-striped mb-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Actions</th>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<th>Created</th>
|
||||
<th>Modified</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="gt-config-values">
|
||||
@foreach($values as $conf)
|
||||
@php
|
||||
$confValue = ($conf->masked ? $conf->getJumbledValue() : $conf->getTruncatedValue())
|
||||
@endphp
|
||||
<tr
|
||||
data-id="{{ $conf->id }}"
|
||||
data-name="{{ $conf->name }}"
|
||||
data-is-masked="{{ $conf->masked }}"
|
||||
data-value="{{ $confValue }}"
|
||||
data-created="{{ $conf->getCreated() }}"
|
||||
data-updated="{{ $conf->getUpdated() }}"
|
||||
>
|
||||
<th class="gt-small-row">{{ $conf->id }}</th>
|
||||
<td class="gt-small-row"><button class="btn btn-sm btn-primary" disabled>Edit</button></td>
|
||||
<td>{{ $conf->name }}</td>
|
||||
<td @class(['d-flex' => $conf->masked])>
|
||||
@if($conf->masked)
|
||||
<span class="gt-masked-text">{{ $confValue }}</span>
|
||||
<button class="ms-auto btn btn-sm btn-danger" disabled>Unmask</button>
|
||||
@else
|
||||
{{ $confValue }}
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ $conf->getCreated() }}</td>
|
||||
<td>{{ $conf->getUpdated() }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@endpush
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Games')
|
||||
|
||||
@section('content')
|
||||
<div id="gt-games-main" class="container-lg my-2 d-flex flex-column">
|
||||
<h4 class="my-auto">Games</h4>
|
||||
<x-loader />
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
@if(!$asset->approved)
|
||||
<div class="alert alert-danger text-center"><strong>This asset is pending approval.</strong> It will not appear in-game and cannot be voted on or purchased at this time.</div>
|
||||
@endif
|
||||
<div id="gt-item" class="graphictoria-item-page"
|
||||
<div id="gt-item" class="graphictoria-smaller-page"
|
||||
@auth
|
||||
data-asset-id="{{ $asset->id }}"
|
||||
data-asset-name="{{ $asset->name }}"
|
||||
|
|
|
|||
|
|
@ -5,6 +5,125 @@
|
|||
@section('page-specific')
|
||||
@endsection
|
||||
|
||||
@section('quick-admin')
|
||||
<li class="nav-item">
|
||||
{{-- TODO: XlXi: Make this use route() --}}
|
||||
<a href="{{ url('/admin') }}" class="nav-link py-0">User Admin</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
{{-- TODO: XlXi: Make this use route() --}}
|
||||
<a href="{{ url('/admin') }}" class="nav-link py-0">Moderate User</a>
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<h1>this is {{ $user->username }}'s profile</h1>
|
||||
<style>
|
||||
.graphictoria-user-profile-buttons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.graphictoria-user-profile-buttons > .btn:not(:last-child) {
|
||||
/* me-1 */
|
||||
margin-right: 0.25rem!important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="container-lg my-2">
|
||||
<div class="graphictoria-smaller-page">
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="card p-2 text-center">
|
||||
<h5 class="mb-0"><span class="{{ $user->getOnlineClass() }}">●</span> {{ $user->username }}</h5>
|
||||
@if(false)
|
||||
{{-- TODO: XlXi: this lol --}}
|
||||
<p class="text-success">[ Playing: Among Us ]</p>
|
||||
@endif
|
||||
<img src="{{ asset('/images/testing/avatar.png') }}" width="300px" height="300px" class="img-fluid mx-auto gt-charimg" />
|
||||
<p class="text-muted pb-2">TODO: user description</p>
|
||||
@auth
|
||||
<div class="graphictoria-user-profile-buttons">
|
||||
<button class="btn btn-secondary">Add Friend</button>
|
||||
<button class="btn btn-secondary">Send Message</button>
|
||||
<button class="btn btn-secondary">Block</button>
|
||||
</div>
|
||||
@endauth
|
||||
<hr class="mb-1" />
|
||||
<div class="row text-center">
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Joined</p>
|
||||
<p>{{ $user->getJoinDate() }}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Last Seen</p>
|
||||
<p>{{ $user->getLastSeen() }}</p>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<p class="fw-bold">Visits</p>
|
||||
<p>0</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mt-1 mb-1" />
|
||||
@auth
|
||||
<a href="https://www.gtoria.local/todo123" class="ms-auto text-decoration-none link-danger">Report <i class="fa-solid fa-circle-exclamation"></i></a>
|
||||
@endauth
|
||||
</div>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Official Badges
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Badges
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<x-MiniCard class="mt-3 mt-md-0 d-flex">
|
||||
<x-slot name="title">
|
||||
Games
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Favorites
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Friends
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
</div>
|
||||
</div>
|
||||
<x-MiniCard class="mt-3 d-flex">
|
||||
<x-slot name="title">
|
||||
Groups
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<p class="text-muted">todo</p>
|
||||
</x-slot>
|
||||
</x-MiniCard>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
Route::get('/', 'ApiController@index')->name('index');
|
||||
|
||||
Route::get('/ping', function() {
|
||||
return response('');
|
||||
})->middleware('lastseen');
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::group(['as' => 'feed.', 'prefix' => 'feed'], function() {
|
||||
Route::group(['as' => 'v1.', 'prefix' => 'v1'], function() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
Route::get('/', function(){
|
||||
return view('layouts.blog');
|
||||
});
|
||||
|
|
@ -17,6 +17,11 @@ Route::group(['as' => 'shop.', 'prefix' => 'shop'], function() {
|
|||
Route::get('/{asset}/{assetName:slug?}', 'ShopController@showAsset')->name('asset');
|
||||
});
|
||||
|
||||
Route::group(['as' => 'games.', 'prefix' => 'games'], function() {
|
||||
Route::get('/', 'GamesController@index')->name('index');
|
||||
//Route::get('/{asset}/{assetName:slug?}', 'GamesController@showGame')->name('game');
|
||||
});
|
||||
|
||||
Route::middleware('auth')->group(function () {
|
||||
Route::group(['as' => 'user.', 'prefix' => 'my'], function() {
|
||||
Route::get('/settings', 'SettingsController@index')->name('index');
|
||||
|
|
@ -34,6 +39,8 @@ Route::group(['as' => 'admin.', 'prefix' => 'admin'], function() {
|
|||
|
||||
Route::middleware('roleset:owner')->group(function () {
|
||||
Route::get('/arbiter-management/{arbiterType?}/{jobId?}', 'AdminController@arbiterManagement')->name('arbitermanagement');
|
||||
|
||||
Route::get('/configuration', 'AdminController@configuration')->name('configuration');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@
|
|||
<category name="Service">
|
||||
<link name="Arbiter Management" route="admin.arbitermanagement" />
|
||||
<link name="Arbiter Diag" route="admin.diag" />
|
||||
<link name="Configuration Editor" route="admin.dashboard" />
|
||||
<link name="Configuration Editor" route="admin.configuration" />
|
||||
<link name="Banner Editor" route="admin.dashboard" />
|
||||
</category>
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ mix.js('resources/js/app.js', 'public/js')
|
|||
.js('resources/js/pages/Dashboard.js', 'public/js')
|
||||
.js('resources/js/pages/Shop.js', 'public/js')
|
||||
.js('resources/js/pages/Item.js', 'public/js')
|
||||
.js('resources/js/pages/SiteConfiguration.js', 'public/js/adm')
|
||||
.react()
|
||||
.sass('resources/sass/Graphictoria.scss', 'public/css')
|
||||
.banner({
|
||||
|
|
|
|||
Loading…
Reference in New Issue