Sign up and registration have been implemented. The old views have also been re-implemented.
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
Grid helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
|
||||
class GridHelper
|
||||
{
|
||||
public static function isIpWhitelisted() {
|
||||
$ip = request()->ip();
|
||||
$whitelistedIps = explode(';', DynamicWebConfiguration::where('name', 'WhitelistedIPs')->first()->value);
|
||||
|
||||
return in_array($ip, $whitelistedIps);
|
||||
}
|
||||
|
||||
public static function isAccessKeyValid() {
|
||||
$accessKey = DynamicWebConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value;
|
||||
|
||||
return (request()->header('AccessKey') == $accessKey);
|
||||
}
|
||||
|
||||
public static function hasAllAccess() {
|
||||
if(app()->runningInConsole()) return true;
|
||||
if(GridHelper::isIpWhitelisted() && GridHelper::isAccessKeyValid()) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
Graphictoria 2022
|
||||
Maintenance helper
|
||||
*/
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Foundation\Http\MaintenanceModeBypassCookie;
|
||||
|
||||
class MaintenanceHelper
|
||||
{
|
||||
public static function isDown()
|
||||
{
|
||||
if(GridHelper::hasAllAccess())
|
||||
return true;
|
||||
|
||||
if(!file_exists(storage_path('framework/down')))
|
||||
return false;
|
||||
|
||||
$data = json_decode(file_get_contents(storage_path('framework/down')), true);
|
||||
|
||||
return (app()->isDownForMaintenance() && !MaintenanceHelper::hasValidBypassCookie($data));
|
||||
}
|
||||
|
||||
protected static function hasValidBypassCookie(array $data)
|
||||
{
|
||||
$request = request();
|
||||
|
||||
return isset($data['secret']) &&
|
||||
$request->cookie('gt_constraint') &&
|
||||
MaintenanceModeBypassCookie::isValid(
|
||||
$request->cookie('gt_constraint'),
|
||||
$data['secret']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -41,7 +41,7 @@ class RegisteredUserController extends Controller
|
|||
], [
|
||||
'username.min' => 'Username can only be 3 to 20 characters long.',
|
||||
'username.max' => 'Username can only be 3 to 20 characters long.',
|
||||
'username.regex' => 'Username must be alphanumeric and cannot begin or end with a special character. (a-z, 0-9, dot, hyphen, space, underscores are allowed)'
|
||||
'username.regex' => 'Username must be alphanumeric and cannot begin or end with a special character. (a-z, 0-9, dots, hyphens, spaces, and underscores are allowed)'
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,18 @@ class LoginRequest extends FormRequest
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get custom messages for validator errors.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'username.exists' => 'That user doesn\'t seem to exist.'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
|
|
@ -29,7 +41,7 @@ class LoginRequest extends FormRequest
|
|||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => ['required', 'string', 'email'],
|
||||
'username' => ['required', 'string', 'exists:users,username'],
|
||||
'password' => ['required', 'string'],
|
||||
];
|
||||
}
|
||||
|
|
@ -45,11 +57,11 @@ class LoginRequest extends FormRequest
|
|||
{
|
||||
$this->ensureIsNotRateLimited();
|
||||
|
||||
if (! Auth::attempt($this->only('email', 'password'), $this->boolean('remember'))) {
|
||||
if (! Auth::attempt($this->only('username', 'password'), $this->boolean('remember'))) {
|
||||
RateLimiter::hit($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => trans('auth.failed'),
|
||||
'username' => trans('auth.failed'),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -74,7 +86,7 @@ class LoginRequest extends FormRequest
|
|||
$seconds = RateLimiter::availableIn($this->throttleKey());
|
||||
|
||||
throw ValidationException::withMessages([
|
||||
'email' => trans('auth.throttle', [
|
||||
'username' => trans('auth.throttle', [
|
||||
'seconds' => $seconds,
|
||||
'minutes' => ceil($seconds / 60),
|
||||
]),
|
||||
|
|
@ -88,6 +100,6 @@ class LoginRequest extends FormRequest
|
|||
*/
|
||||
public function throttleKey()
|
||||
{
|
||||
return Str::lower($this->input('email')).'|'.$this->ip();
|
||||
return Str::lower($this->input('username')).'|'.$this->ip();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Blade;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
class MaintenanceServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
Blade::directive('live', function() {
|
||||
return '<?php if(!\App\Helpers\MaintenanceHelper::isDown()): ?>';
|
||||
});
|
||||
|
||||
Blade::directive('endlive', function() {
|
||||
return '<?php endif; ?>';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class AppLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('layouts.app');
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components;
|
||||
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class GuestLayout extends Component
|
||||
{
|
||||
/**
|
||||
* Get the view / contents that represents the component.
|
||||
*
|
||||
* @return \Illuminate\View\View
|
||||
*/
|
||||
public function render()
|
||||
{
|
||||
return view('layouts.guest');
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.0.2",
|
||||
"elhebert/laravel-sri": "^3.1",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"laravel/framework": "^9.2",
|
||||
"laravel/sanctum": "^2.14.1",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "35cf349942c6b5a88b3132acd0b27885",
|
||||
"content-hash": "01ebc87de69ddff55214f2b48dae78c1",
|
||||
"packages": [
|
||||
{
|
||||
"name": "brick/math",
|
||||
|
|
@ -437,6 +437,66 @@
|
|||
],
|
||||
"time": "2021-10-11T09:18:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "elhebert/laravel-sri",
|
||||
"version": "3.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Elhebert/laravel-sri.git",
|
||||
"reference": "53cea931d95e88bf9281367b81a03d1799a66700"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Elhebert/laravel-sri/zipball/53cea931d95e88bf9281367b81a03d1799a66700",
|
||||
"reference": "53cea931d95e88bf9281367b81a03d1799a66700",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "^8.71 | ^9.0",
|
||||
"php": "^7.3 | ^7.4 | ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"orchestra/testbench": "^6.23 | ^7.0",
|
||||
"phpunit/phpunit": "^9.5.10"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Elhebert\\SubresourceIntegrity\\SriServiceProvider"
|
||||
],
|
||||
"aliases": {
|
||||
"Sri": "Elhebert\\SubresourceIntegrity\\SriFacade"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Elhebert\\SubresourceIntegrity\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dieter Stinglhamber"
|
||||
}
|
||||
],
|
||||
"description": "Subresource Integrity hash generator for laravel",
|
||||
"keywords": [
|
||||
"laravel-sri",
|
||||
"sri",
|
||||
"subresource integrity"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/Elhebert/laravel-sri/issues",
|
||||
"source": "https://github.com/Elhebert/laravel-sri/tree/3.1.0"
|
||||
},
|
||||
"time": "2022-02-09T08:21:17+00:00"
|
||||
},
|
||||
{
|
||||
"name": "fruitcake/php-cors",
|
||||
"version": "v1.2.0",
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ return [
|
|||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
App\Providers\MaintenanceServiceProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ return new class extends Migration
|
|||
{
|
||||
Schema::create('dynamic_web_configurations', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('name');
|
||||
$table->string('value');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,9 @@ class DatabaseSeeder extends Seeder
|
|||
*/
|
||||
public function run()
|
||||
{
|
||||
// \App\Models\User::factory(10)->create();
|
||||
$this->call([
|
||||
//FFlagSeeder::class,
|
||||
WebConfigurationSeeder::class
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
use App\Models\DynamicWebConfiguration;
|
||||
|
||||
class WebConfigurationSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
DynamicWebConfiguration::create([
|
||||
'name' => 'MaintenancePassword',
|
||||
'value' => json_encode(
|
||||
[
|
||||
'combination' => [0,7,8,9,10,11],
|
||||
'password' => '@bs0lut3lyM@55!v3P@55w0rd'
|
||||
])
|
||||
]); // please please please please please please please change the default password
|
||||
|
||||
DynamicWebConfiguration::create([
|
||||
'name' => 'ComputeServiceAccessKey',
|
||||
'value' => '92a6ac6b-7167-49b1-9ccd-079820ac892b'
|
||||
]); // change this as well
|
||||
|
||||
DynamicWebConfiguration::create([
|
||||
'name' => 'WhitelistedIPs',
|
||||
'value' => '127.0.0.1'
|
||||
]);
|
||||
|
||||
DynamicWebConfiguration::create([
|
||||
'name' => 'VersionCompatibilityVersions',
|
||||
'value' => '0.1.0pcplayer' // version1;version2;version3
|
||||
]);
|
||||
|
||||
DynamicWebConfiguration::create([
|
||||
'name' => 'VersionCompatibilityHashes',
|
||||
'value' => 'debughash' // hash1;hash2;hash3
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -10,14 +10,26 @@
|
|||
"production": "mix --production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/preset-react": "^7.16.7",
|
||||
"@react-three/drei": "^9.6.0",
|
||||
"@react-three/fiber": "^8.0.12",
|
||||
"@tailwindcss/forms": "^0.4.0",
|
||||
"alpinejs": "^3.4.2",
|
||||
"autoprefixer": "^10.4.2",
|
||||
"axios": "^0.25",
|
||||
"laravel-mix": "^6.0.6",
|
||||
"bootstrap": "^5.1.3",
|
||||
"jquery": "^3.6.0",
|
||||
"laravel-mix": "^6.0.43",
|
||||
"lodash": "^4.17.19",
|
||||
"postcss": "^8.4.6",
|
||||
"postcss-import": "^14.0.2",
|
||||
"react": "^18.1.0",
|
||||
"resolve-url-loader": "^5.0.0",
|
||||
"sass": "^1.51.0",
|
||||
"sass-loader": "^12.1.0",
|
||||
"tailwindcss": "^3.0.18"
|
||||
},
|
||||
"dependencies": {
|
||||
"laravel-mix-banner": "^0.1.4"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 0 B After Width: | Height: | Size: 4.2 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 245 240"><style>.st0{fill:#7289DA;}</style><path class="st0" d="M104.4 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1.1-6.1-4.5-11.1-10.2-11.1zM140.9 103.9c-5.7 0-10.2 5-10.2 11.1s4.6 11.1 10.2 11.1c5.7 0 10.2-5 10.2-11.1s-4.5-11.1-10.2-11.1z"/><path class="st0" d="M189.5 20h-134C44.2 20 35 29.2 35 40.6v135.2c0 11.4 9.2 20.6 20.5 20.6h113.4l-5.3-18.5 12.8 11.9 12.1 11.2 21.5 19V40.6c0-11.4-9.2-20.6-20.5-20.6zm-38.6 130.6s-3.6-4.3-6.6-8.1c13.1-3.7 18.1-11.9 18.1-11.9-4.1 2.7-8 4.6-11.5 5.9-5 2.1-9.8 3.5-14.5 4.3-9.6 1.8-18.4 1.3-25.9-.1-5.7-1.1-10.6-2.7-14.7-4.3-2.3-.9-4.8-2-7.3-3.4-.3-.2-.6-.3-.9-.5-.2-.1-.3-.2-.4-.3-1.8-1-2.8-1.7-2.8-1.7s4.8 8 17.5 11.8c-3 3.8-6.7 8.3-6.7 8.3-22.1-.7-30.5-15.2-30.5-15.2 0-32.2 14.4-58.3 14.4-58.3 14.4-10.8 28.1-10.5 28.1-10.5l1 1.2c-18 5.2-26.3 13.1-26.3 13.1s2.2-1.2 5.9-2.9c10.7-4.7 19.2-6 22.7-6.3.6-.1 1.1-.2 1.7-.2 6.1-.8 13-1 20.2-.2 9.5 1.1 19.7 3.9 30.1 9.6 0 0-7.9-7.5-24.9-12.7l1.4-1.6s13.7-.3 28.1 10.5c0 0 14.4 26.1 14.4 58.3 0 0-8.5 14.5-30.6 15.2z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 248 204" style="enable-background:new 0 0 248 204;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#1D9BF0;}
|
||||
</style>
|
||||
<g id="Logo_1_">
|
||||
<path id="white_background" class="st0" d="M221.95,51.29c0.15,2.17,0.15,4.34,0.15,6.53c0,66.73-50.8,143.69-143.69,143.69v-0.04
|
||||
C50.97,201.51,24.1,193.65,1,178.83c3.99,0.48,8,0.72,12.02,0.73c22.74,0.02,44.83-7.61,62.72-21.66
|
||||
c-21.61-0.41-40.56-14.5-47.18-35.07c7.57,1.46,15.37,1.16,22.8-0.87C27.8,117.2,10.85,96.5,10.85,72.46c0-0.22,0-0.43,0-0.64
|
||||
c7.02,3.91,14.88,6.08,22.92,6.32C11.58,63.31,4.74,33.79,18.14,10.71c25.64,31.55,63.47,50.73,104.08,52.76
|
||||
c-4.07-17.54,1.49-35.92,14.61-48.25c20.34-19.12,52.33-18.14,71.45,2.19c11.31-2.23,22.15-6.38,32.07-12.26
|
||||
c-3.77,11.69-11.66,21.62-22.2,27.93c10.01-1.18,19.79-3.86,29-7.95C240.37,35.29,231.83,44.14,221.95,51.29z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg width="159" height="110" xmlns="http://www.w3.org/2000/svg"><path d="m154 17.5c-1.82-6.73-7.07-12-13.8-13.8-9.04-3.49-96.6-5.2-122 0.1-6.73 1.82-12 7.07-13.8 13.8-4.08 17.9-4.39 56.6 0.1 74.9 1.82 6.73 7.07 12 13.8 13.8 17.9 4.12 103 4.7 122 0 6.73-1.82 12-7.07 13.8-13.8 4.35-19.5 4.66-55.8-0.1-75z" fill="#f00"/><path d="m105 55-40.8-23.4v46.8z" fill="#fff"/></svg>
|
||||
|
After Width: | Height: | Size: 373 B |
|
After Width: | Height: | Size: 2.5 MiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
|
@ -0,0 +1,11 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="102.4" height="102.4" viewBox="0 0 1024 1024">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #e59800;
|
||||
fill-rule: evenodd;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<path id="Polygon_1" data-name="Polygon 1" class="cls-1" d="M718.719-.012L1020.99,562.653,579.262,1024,3.994,746.459,90.183,113.587ZM637.405,554.647c-1.474-51.324-42.032-83.369-102.451-104.469-41.717-14.529-68.9-18.909-69.359-34.867-0.341-11.861,14.321-22,35.191-22.618,18.26-.537,47.9,6.576,59.806,24.572l57.1-53.048c-12.388-26.4-43.108-46.43-83.659-53.439l-1.35-47.011-79.209,2.33,1.393,48.521c-52.507,14.71-91.52,52.981-90.146,100.855,1.5,52.4,43.837,80.079,92.761,97.632,37.9,13.993,77.486,28.584,78,46.483,0.409,14.233-20.493,21.97-42.074,22.605-32.016.942-62.031-11.125-78.534-32.006l-59.849,56.582c16.806,31.448,59.675,53.065,109.907,58.278l1.319,45.933,79.209-2.33-1.419-49.384C598.437,644.069,638.892,606.4,637.405,554.647ZM559.964,929.165L83.555,696.984,157.472,172.64,679.564,80.758,928.319,548.316Zm-10.7-92.114L167.181,650.975,226.463,230.75l418.723-73.637,199.5,374.714Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
22717
web/public/js/app.js
|
|
@ -0,0 +1,46 @@
|
|||
/*!
|
||||
* Bootstrap v5.1.3 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Graphictoria 5 (https://gtoria.net)
|
||||
* Copyright © XlXi 2022
|
||||
*
|
||||
* BUILD TIMESTAMP: Sat, 30 Apr 2022 02:02:46 GMT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Sizzle CSS Selector Engine v2.3.6
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://js.foundation/
|
||||
*
|
||||
* Date: 2021-02-16
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.6.0
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2021-03-02T17:08Z
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Lodash <https://lodash.com/>
|
||||
* Copyright OpenJS Foundation and other contributors <https://openjsf.org/>
|
||||
* Released under MIT license <https://lodash.com/license>
|
||||
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
|
||||
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
|
||||
*/
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*!
|
||||
* Graphictoria 5 (https://gtoria.net)
|
||||
* Copyright © XlXi 2022
|
||||
*
|
||||
* BUILD TIMESTAMP: Sat, 30 Apr 2022 02:02:46 GMT
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Sizzle CSS Selector Engine v2.3.6
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://js.foundation/
|
||||
*
|
||||
* Date: 2021-02-16
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.6.0
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2021-03-02T17:08Z
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2010-2022 Three.js Authors
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-dom.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-jsx-runtime.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-reconciler-constants.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react-reconciler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* react.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @license React
|
||||
* scheduler.production.min.js
|
||||
*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"/js/app.js": "/js/app.js",
|
||||
"/css/app.css": "/css/app.css"
|
||||
"/js/app.js": "/js/app.js?id=80aa85302f9cae9ff3974445e60a1a1e",
|
||||
"/js/pages/maintenance.js": "/js/pages/maintenance.js?id=46d62629eccfa8469acbd4536fbcee61",
|
||||
"/css/graphictoria.css": "/css/graphictoria.css?id=7ba4cc490c62318ad457620aa38f5645"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
@import 'tailwindcss/base';
|
||||
@import 'tailwindcss/components';
|
||||
@import 'tailwindcss/utilities';
|
||||
|
|
@ -1,7 +1,15 @@
|
|||
/**
|
||||
* First we will load all of this project's JavaScript dependencies which
|
||||
* includes React and other helpers. It's a great starting point while
|
||||
* building robust, powerful web applications using React + Laravel.
|
||||
*/
|
||||
|
||||
require('./bootstrap');
|
||||
|
||||
import Alpine from 'alpinejs';
|
||||
/**
|
||||
* Next, we will create a fresh React component instance and attach it to
|
||||
* the page. Then, you may begin adding components to this application
|
||||
* or customize the JavaScript scaffolding to fit your unique needs.
|
||||
*/
|
||||
|
||||
window.Alpine = Alpine;
|
||||
|
||||
Alpine.start();
|
||||
require('./components/Main');
|
||||
|
|
@ -1,15 +1,5 @@
|
|||
window._ = require('lodash');
|
||||
|
||||
/**
|
||||
* We'll load the axios HTTP library which allows us to easily issue requests
|
||||
* to our Laravel back-end. This library automatically handles sending the
|
||||
* CSRF token as a header based on the value of the "XSRF" token cookie.
|
||||
*/
|
||||
|
||||
window.axios = require('axios');
|
||||
|
||||
window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
||||
|
||||
/**
|
||||
* Echo exposes an expressive API for subscribing to channels and listening
|
||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
||||
|
|
@ -25,4 +15,4 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
|
|||
// key: process.env.MIX_PUSHER_APP_KEY,
|
||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
||||
// forceTLS: true
|
||||
// });
|
||||
// });
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import $ from 'jquery';
|
||||
import * as Bootstrap from 'bootstrap';
|
||||
|
||||
$(document).ready(function() {
|
||||
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
|
||||
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new Bootstrap.Tooltip(tooltipTriggerEl)
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
const Config = {
|
||||
BaseUrl: 'http://gtoria.local',
|
||||
Protocol: 'http://'
|
||||
};
|
||||
|
||||
export default Config;
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
// © XlXi 2021
|
||||
// Graphictoria 5
|
||||
|
||||
import axios from 'axios';
|
||||
|
||||
import $ from 'jquery';
|
||||
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import React, { useRef, Suspense } from 'react';
|
||||
|
||||
import { buildGenericApiUrl } from '../util/HTTP.js';
|
||||
|
||||
import { Canvas, useFrame } from '@react-three/fiber';
|
||||
import { Instances, Instance, PerspectiveCamera, useGLTF } from '@react-three/drei';
|
||||
|
||||
axios.defaults.withCredentials = true;
|
||||
|
||||
const randomVector = (r) => [r / 2 - Math.random() * r, r / 2 - Math.random() * r, r / 2 - Math.random() * r];
|
||||
const randomEuler = () => [Math.random() * Math.PI, Math.random() * Math.PI, Math.random() * Math.PI];
|
||||
const randomData = Array.from({ length: 2000 }, (r = 200) => ({ random: Math.random(), position: randomVector(r), rotation: randomEuler() }));
|
||||
|
||||
function Scene() {
|
||||
const { nodes, materials } = useGLTF('/models/graphictoriapart.glb');
|
||||
|
||||
return (
|
||||
<>
|
||||
<ambientLight />
|
||||
<pointLight position={[10, 10, 10]} />
|
||||
<Instances range={2000} material={materials.Material} geometry={nodes.Cube.geometry} >
|
||||
{
|
||||
randomData.map((props, i) => (
|
||||
<Box key={i} {...props} />
|
||||
))
|
||||
}
|
||||
</Instances>
|
||||
<Camera makeDefault />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Box({ random, ...props }){
|
||||
const ref = useRef()
|
||||
useFrame((state) => {
|
||||
const t = state.clock.getElapsedTime() + random * 10000
|
||||
ref.current.rotation.set(Math.cos(t / 4) / 2, Math.sin(t / 4) / 2, Math.cos(t / 1.5) / 2)
|
||||
ref.current.position.y = Math.sin(t / 1.5) / 2
|
||||
});
|
||||
return (
|
||||
<group {...props}>
|
||||
<Instance ref={ref} />
|
||||
</group>
|
||||
)
|
||||
}
|
||||
|
||||
function Camera({ ...props }){
|
||||
const ref = useRef()
|
||||
useFrame((state) => {
|
||||
const t = state.clock.getElapsedTime() / 30
|
||||
ref.current.position.x = 10 * Math.cos(t);
|
||||
ref.current.position.y = 4 * Math.sin(t);
|
||||
ref.current.position.z = 10 * Math.sin(t);
|
||||
ref.current.lookAt(0, 0, 0);
|
||||
});
|
||||
return (
|
||||
<PerspectiveCamera ref={ref} {...props} />
|
||||
)
|
||||
}
|
||||
|
||||
let ButtonHistory = []
|
||||
|
||||
function attemptBypass() {
|
||||
axios.post(buildGenericApiUrl('apis', 'v1/maintenance/bypass'), {
|
||||
'password': $('#gt_mt_buttons > input').val(),
|
||||
'buttons': ButtonHistory.slice(-40)
|
||||
})
|
||||
.then((response) => {
|
||||
window.location.reload();
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
ReactDOM.render(
|
||||
(<Canvas>
|
||||
<Suspense fallback={null}>
|
||||
<Scene />
|
||||
</Suspense>
|
||||
</Canvas>),
|
||||
document.getElementsByClassName('gtoria-maintenance-background')[0]
|
||||
);
|
||||
|
||||
$('#gt_mt_buttons').on('click', 'button', function() {
|
||||
let ButtonId = parseInt(this.getAttribute('name').substr(8)); //gt_mtbtnX
|
||||
|
||||
ButtonHistory.push(ButtonId);
|
||||
attemptBypass();
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// © XlXi 2021
|
||||
// Graphictoria 5
|
||||
|
||||
const urlObject = new URL(document.location.href);
|
||||
|
||||
export function getCurrentDomain() {
|
||||
return urlObject.hostname.split('.').slice(-2).join('.');
|
||||
};
|
||||
|
||||
export function getProtocol() {
|
||||
return urlObject.protocol;
|
||||
};
|
||||
|
||||
export function buildGenericApiUrl(subdomain, path) {
|
||||
return `${getProtocol()}//${subdomain}.${getCurrentDomain()}/${path}`;
|
||||
};
|
||||
|
|
@ -0,0 +1,108 @@
|
|||
// © XlXi 2021
|
||||
// Graphictoria 5
|
||||
|
||||
@function tint-color($color, $percent){
|
||||
@return mix(white, $color, $percent);
|
||||
}
|
||||
|
||||
@function shade-color($color, $percent){
|
||||
@return mix(black, $color, $percent);
|
||||
}
|
||||
|
||||
// Lumen 5.0.1
|
||||
// Bootswatch
|
||||
|
||||
$theme: "graphictoria" !default;
|
||||
|
||||
//
|
||||
// Color system
|
||||
//
|
||||
|
||||
$white: #fff !default;
|
||||
$gray-100: #f6f6f6 !default;
|
||||
$gray-200: #f0f0f0 !default;
|
||||
$gray-300: #dee2e6 !default;
|
||||
$gray-400: #ced4da !default;
|
||||
$gray-500: #adb5bd !default;
|
||||
$gray-600: #999 !default;
|
||||
$gray-700: #555 !default;
|
||||
$gray-800: #333 !default;
|
||||
$gray-900: #222 !default;
|
||||
$black: #000 !default;
|
||||
|
||||
$gtblue: #348aff !default;
|
||||
$blue: #158cba !default;
|
||||
$indigo: #6610f2 !default;
|
||||
$purple: #6f42c1 !default;
|
||||
$pink: #e83e8c !default;
|
||||
$red: #ff4136 !default;
|
||||
$orange: #fd7e14 !default;
|
||||
$yellow: #ff851b !default;
|
||||
$green: #28b62c !default;
|
||||
$teal: #20c997 !default;
|
||||
$cyan: #75caeb !default;
|
||||
|
||||
$graphictoria: $gtblue !default;
|
||||
$primary: $blue !default;
|
||||
$secondary: $gray-200 !default;
|
||||
$success: $green !default;
|
||||
$info: $cyan !default;
|
||||
$warning: $yellow !default;
|
||||
$danger: $red !default;
|
||||
$light: $gray-100 !default;
|
||||
$dark: $gray-800 !default;
|
||||
|
||||
$min-contrast-ratio: 1.75 !default;
|
||||
|
||||
// Fonts
|
||||
|
||||
$fa-font-path: "../webfonts";
|
||||
|
||||
// stylelint-disable-next-line value-keyword-case
|
||||
$font-family-sans-serif: "Source Sans Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !default;
|
||||
|
||||
// Tables
|
||||
|
||||
$table-bg-scale: 0 !default;
|
||||
|
||||
// Buttons
|
||||
|
||||
$btn-font-weight: 700 !default;
|
||||
|
||||
// Dropdowns
|
||||
|
||||
$dropdown-link-color: rgba(0, 0, 0, .5) !default;
|
||||
|
||||
// Navs
|
||||
|
||||
$nav-tabs-border-color: $gray-200 !default;
|
||||
$nav-tabs-link-hover-border-color: $nav-tabs-border-color !default;
|
||||
$nav-tabs-link-active-color: $gray-900 !default;
|
||||
$nav-tabs-link-active-border-color: $nav-tabs-border-color !default;
|
||||
|
||||
// Pagination
|
||||
|
||||
$pagination-color: $gray-700 !default;
|
||||
$pagination-bg: $gray-200 !default;
|
||||
$pagination-hover-color: $pagination-color !default;
|
||||
$pagination-hover-bg: $pagination-bg !default;
|
||||
$pagination-active-border-color: darken($primary, 5%) !default;
|
||||
$pagination-disabled-color: $gray-600 !default;
|
||||
$pagination-disabled-bg: $pagination-bg !default;
|
||||
|
||||
// Breadcrumbs
|
||||
|
||||
$breadcrumb-padding-y: .375rem !default;
|
||||
$breadcrumb-padding-x: .75rem !default;
|
||||
$breadcrumb-bg: $pagination-bg !default;
|
||||
$breadcrumb-border-radius: .25rem !default;
|
||||
|
||||
// Modals
|
||||
|
||||
$modal-content-border-color: rgba($black, .1) !default;
|
||||
|
||||
// Close
|
||||
|
||||
$btn-close-color: $black !default;
|
||||
$btn-close-opacity: .4 !default;
|
||||
$btn-close-hover-opacity: 1 !default;
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
// animating icons
|
||||
// --------------------------
|
||||
|
||||
.#{$fa-css-prefix}-beat {
|
||||
animation-name: #{$fa-css-prefix}-beat;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-bounce {
|
||||
animation-name: #{$fa-css-prefix}-bounce;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(0.280, 0.840, 0.420, 1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-fade {
|
||||
animation-name: #{$fa-css-prefix}-fade;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-beat-fade {
|
||||
animation-name: #{$fa-css-prefix}-beat-fade;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, cubic-bezier(.4,0,.6,1));
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip {
|
||||
animation-name: #{$fa-css-prefix}-flip;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, ease-in-out);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-shake {
|
||||
animation-name: #{$fa-css-prefix}-shake;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-spin {
|
||||
animation-name: #{$fa-css-prefix}-spin;
|
||||
animation-delay: var(--#{$fa-css-prefix}-animation-delay, 0);
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 2s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, linear);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-spin-reverse {
|
||||
--#{$fa-css-prefix}-animation-direction: reverse;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pulse,
|
||||
.#{$fa-css-prefix}-spin-pulse {
|
||||
animation-name: #{$fa-css-prefix}-spin;
|
||||
animation-direction: var(--#{$fa-css-prefix}-animation-direction, normal);
|
||||
animation-duration: var(--#{$fa-css-prefix}-animation-duration, 1s);
|
||||
animation-iteration-count: var(--#{$fa-css-prefix}-animation-iteration-count, infinite);
|
||||
animation-timing-function: var(--#{$fa-css-prefix}-animation-timing, steps(8));
|
||||
}
|
||||
|
||||
// if agent or operating system prefers reduced motion, disable animations
|
||||
// see: https://www.smashingmagazine.com/2020/09/design-reduced-motion-sensitivities/
|
||||
// see: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.#{$fa-css-prefix}-beat,
|
||||
.#{$fa-css-prefix}-bounce,
|
||||
.#{$fa-css-prefix}-fade,
|
||||
.#{$fa-css-prefix}-beat-fade,
|
||||
.#{$fa-css-prefix}-flip,
|
||||
.#{$fa-css-prefix}-pulse,
|
||||
.#{$fa-css-prefix}-shake,
|
||||
.#{$fa-css-prefix}-spin,
|
||||
.#{$fa-css-prefix}-spin-pulse {
|
||||
animation-delay: -1ms;
|
||||
animation-duration: 1ms;
|
||||
animation-iteration-count: 1;
|
||||
transition-delay: 0s;
|
||||
transition-duration: 0s;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-beat {
|
||||
0%, 90% { transform: scale(1); }
|
||||
45% { transform: scale(var(--#{$fa-css-prefix}-beat-scale, 1.25)); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-bounce {
|
||||
0% { transform: scale(1,1) translateY(0); }
|
||||
10% { transform: scale(var(--#{$fa-css-prefix}-bounce-start-scale-x, 1.1),var(--#{$fa-css-prefix}-bounce-start-scale-y, 0.9)) translateY(0); }
|
||||
30% { transform: scale(var(--#{$fa-css-prefix}-bounce-jump-scale-x, 0.9),var(--#{$fa-css-prefix}-bounce-jump-scale-y, 1.1)) translateY(var(--#{$fa-css-prefix}-bounce-height, -0.5em)); }
|
||||
50% { transform: scale(var(--#{$fa-css-prefix}-bounce-land-scale-x, 1.05),var(--#{$fa-css-prefix}-bounce-land-scale-y, 0.95)) translateY(0); }
|
||||
57% { transform: scale(1,1) translateY(var(--#{$fa-css-prefix}-bounce-rebound, -0.125em)); }
|
||||
64% { transform: scale(1,1) translateY(0); }
|
||||
100% { transform: scale(1,1) translateY(0); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-fade {
|
||||
50% { opacity: var(--#{$fa-css-prefix}-fade-opacity, 0.4); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-beat-fade {
|
||||
0%, 100% {
|
||||
opacity: var(--#{$fa-css-prefix}-beat-fade-opacity, 0.4);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
opacity: 1;
|
||||
transform: scale(var(--#{$fa-css-prefix}-beat-fade-scale, 1.125));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-flip {
|
||||
50% {
|
||||
transform: rotate3d(var(--#{$fa-css-prefix}-flip-x, 0), var(--#{$fa-css-prefix}-flip-y, 1), var(--#{$fa-css-prefix}-flip-z, 0), var(--#{$fa-css-prefix}-flip-angle, -180deg));
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-shake {
|
||||
0% { transform: rotate(-15deg); }
|
||||
4% { transform: rotate(15deg); }
|
||||
8%, 24% { transform: rotate(-18deg); }
|
||||
12%, 28% { transform: rotate(18deg); }
|
||||
16% { transform: rotate(-22deg); }
|
||||
20% { transform: rotate(22deg); }
|
||||
32% { transform: rotate(-12deg); }
|
||||
36% { transform: rotate(12deg); }
|
||||
40%, 100% { transform: rotate(0deg); }
|
||||
}
|
||||
|
||||
@keyframes #{$fa-css-prefix}-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// bordered + pulled icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-border {
|
||||
border-color: var(--#{$fa-css-prefix}-border-color, #{$fa-border-color});
|
||||
border-radius: var(--#{$fa-css-prefix}-border-radius, #{$fa-border-radius});
|
||||
border-style: var(--#{$fa-css-prefix}-border-style, #{$fa-border-style});
|
||||
border-width: var(--#{$fa-css-prefix}-border-width, #{$fa-border-width});
|
||||
padding: var(--#{$fa-css-prefix}-border-padding, #{$fa-border-padding});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-left {
|
||||
float: left;
|
||||
margin-right: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-pull-right {
|
||||
float: right;
|
||||
margin-left: var(--#{$fa-css-prefix}-pull-margin, #{$fa-pull-margin});
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// base icon class definition
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix} {
|
||||
font-family: var(--#{$fa-css-prefix}-style-family, '#{$fa-style-family}');
|
||||
font-weight: var(--#{$fa-css-prefix}-style, #{$fa-style});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix},
|
||||
.fas,
|
||||
.fa-solid,
|
||||
.far,
|
||||
.fa-regular,
|
||||
.fal,
|
||||
.fa-light,
|
||||
.fat,
|
||||
.fa-thin,
|
||||
.fad,
|
||||
.fa-duotone,
|
||||
.fab,
|
||||
.fa-brands {
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
display: var(--#{$fa-css-prefix}-display, #{$fa-display});
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
line-height: 1;
|
||||
text-rendering: auto;
|
||||
}
|
||||
|
||||
%fa-icon {
|
||||
@include fa-icon;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
// fixed-width icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-fw {
|
||||
text-align: center;
|
||||
width: $fa-fw-width;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// functions
|
||||
// --------------------------
|
||||
|
||||
// Originally obtained from the Bootstrap https://github.com/twbs/bootstrap
|
||||
//
|
||||
// Licensed under: The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) 2011-2021 Twitter, Inc.
|
||||
// Copyright (c) 2011-2021 The Bootstrap Authors
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
@function fa-divide($dividend, $divisor, $precision: 10) {
|
||||
$sign: if($dividend > 0 and $divisor > 0, 1, -1);
|
||||
$dividend: abs($dividend);
|
||||
$divisor: abs($divisor);
|
||||
$quotient: 0;
|
||||
$remainder: $dividend;
|
||||
@if $dividend == 0 {
|
||||
@return 0;
|
||||
}
|
||||
@if $divisor == 0 {
|
||||
@error "Cannot divide by 0";
|
||||
}
|
||||
@if $divisor == 1 {
|
||||
@return $dividend;
|
||||
}
|
||||
@while $remainder >= $divisor {
|
||||
$quotient: $quotient + 1;
|
||||
$remainder: $remainder - $divisor;
|
||||
}
|
||||
@if $remainder > 0 and $precision > 0 {
|
||||
$remainder: fa-divide($remainder * 10, $divisor, $precision - 1) * .1;
|
||||
}
|
||||
@return ($quotient + $remainder) * $sign;
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// specific icon class definition
|
||||
// -------------------------
|
||||
|
||||
/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
|
||||
readers do not read off random characters that represent icons */
|
||||
|
||||
@each $name, $icon in $fa-icons {
|
||||
.#{$fa-css-prefix}-#{$name}::before { content: fa-content($icon); }
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// icons in a list
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-ul {
|
||||
list-style-type: none;
|
||||
margin-left: var(--#{$fa-css-prefix}-li-margin, #{$fa-li-margin});
|
||||
padding-left: 0;
|
||||
|
||||
> li { position: relative; }
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-li {
|
||||
left: calc(var(--#{$fa-css-prefix}-li-width, #{$fa-li-width}) * -1);
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: var(--#{$fa-css-prefix}-li-width, #{$fa-li-width});
|
||||
line-height: inherit;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// mixins
|
||||
// --------------------------
|
||||
|
||||
// base rendering for an icon
|
||||
@mixin fa-icon {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
display: inline-block;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
font-weight: normal;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
// sets relative font-sizing and alignment (in _sizing)
|
||||
@mixin fa-size ($font-size) {
|
||||
font-size: fa-divide($font-size, $fa-size-scale-base) * 1em; // converts step in sizing scale into an em-based value that's relative to the scale's base
|
||||
line-height: fa-divide(1, $font-size) * 1em; // sets the line-height of the icon back to that of it's parent
|
||||
vertical-align: (fa-divide(6, $font-size) - fa-divide(3, 8)) * 1em; // vertically centers the icon taking into account the surrounding text's descender
|
||||
}
|
||||
|
||||
// only display content to screen readers
|
||||
// see: https://www.a11yproject.com/posts/2013-01-11-how-to-hide-content/
|
||||
// see: https://hugogiraudel.com/2016/10/13/css-hide-and-seek/
|
||||
@mixin fa-sr-only() {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
// use in conjunction with .sr-only to only display content when it's focused
|
||||
@mixin fa-sr-only-focusable() {
|
||||
&:not(:focus) {
|
||||
@include fa-sr-only();
|
||||
}
|
||||
}
|
||||
|
||||
// convenience mixins for declaring pseudo-elements by CSS variable,
|
||||
// including all style-specific font properties, and both the ::before
|
||||
// and ::after elements in the duotone case.
|
||||
@mixin fa-icon-solid($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-solid;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
|
||||
@mixin fa-icon-regular($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-regular;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
|
||||
@mixin fa-icon-brands($fa-var) {
|
||||
@extend %fa-icon;
|
||||
@extend .fa-brands;
|
||||
|
||||
&::before {
|
||||
content: unquote("\"#{ $fa-var }\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// rotating + flipping icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-rotate-90 {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-180 {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-270 {
|
||||
transform: rotate(270deg);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-horizontal {
|
||||
transform: scale(-1, 1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-vertical {
|
||||
transform: scale(1, -1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-flip-both,
|
||||
.#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical {
|
||||
transform: scale(-1, -1);
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-rotate-by {
|
||||
transform: rotate(var(--#{$fa-css-prefix}-rotate-angle, none));
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
// screen-reader utilities
|
||||
// -------------------------
|
||||
|
||||
// only display content to screen readers
|
||||
.sr-only,
|
||||
.fa-sr-only {
|
||||
@include fa-sr-only;
|
||||
}
|
||||
|
||||
// use in conjunction with .sr-only to only display content when it's focused
|
||||
.sr-only-focusable,
|
||||
.fa-sr-only-focusable {
|
||||
@include fa-sr-only-focusable;
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// sizing icons
|
||||
// -------------------------
|
||||
|
||||
// literal magnification scale
|
||||
@for $i from 1 through 10 {
|
||||
.#{$fa-css-prefix}-#{$i}x {
|
||||
font-size: $i * 1em;
|
||||
}
|
||||
}
|
||||
|
||||
// step-based scale (with alignment)
|
||||
@each $size, $value in $fa-sizes {
|
||||
.#{$fa-css-prefix}-#{$size} {
|
||||
@include fa-size($value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
// stacking icons
|
||||
// -------------------------
|
||||
|
||||
.#{$fa-css-prefix}-stack {
|
||||
display: inline-block;
|
||||
height: 2em;
|
||||
line-height: 2em;
|
||||
position: relative;
|
||||
vertical-align: $fa-stack-vertical-align;
|
||||
width: $fa-stack-width;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-1x,
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
left: 0;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
z-index: var(--#{$fa-css-prefix}-stack-z-index, #{$fa-stack-z-index});
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-1x {
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-stack-2x {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
.#{$fa-css-prefix}-inverse {
|
||||
color: var(--#{$fa-css-prefix}-inverse, #{$fa-inverse});
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{ $fa-css-prefix }-font-brands: normal 400 1em/1 "Font Awesome 6 Brands";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Brands';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.fab,
|
||||
.fa-brands {
|
||||
font-family: 'Font Awesome 6 Brands';
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@each $name, $icon in $fa-brand-icons {
|
||||
.#{$fa-css-prefix}-#{$name}:before { content: fa-content($icon); }
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
// Font Awesome core compile (Web Fonts-based)
|
||||
// -------------------------
|
||||
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
@import 'mixins';
|
||||
@import 'core';
|
||||
@import 'sizing';
|
||||
@import 'fixed-width';
|
||||
@import 'list';
|
||||
@import 'bordered-pulled';
|
||||
@import 'animated';
|
||||
@import 'rotated-flipped';
|
||||
@import 'stacked';
|
||||
@import 'icons';
|
||||
@import 'screen-reader';
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{ $fa-css-prefix }-font-regular: normal 400 1em/1 "#{ $fa-style-family }";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.far,
|
||||
.fa-regular {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-weight: 400;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
|
||||
:root, :host {
|
||||
--#{ $fa-css-prefix }-font-solid: normal 900 1em/1 "#{ $fa-style-family }";
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: $fa-font-display;
|
||||
src: url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'),
|
||||
url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.fas,
|
||||
.fa-solid {
|
||||
font-family: 'Font Awesome 6 Free';
|
||||
font-weight: 900;
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
/*!
|
||||
* Font Awesome Free 6.0.0 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
* Copyright 2022 Fonticons, Inc.
|
||||
*/
|
||||
// V4 shims compile (Web Fonts-based)
|
||||
// -------------------------
|
||||
|
||||
@import 'functions';
|
||||
@import 'variables';
|
||||
@import 'shims';
|
||||
|
|
@ -1,56 +1,52 @@
|
|||
<x-guest-layout>
|
||||
<x-auth-card>
|
||||
<x-slot name="logo">
|
||||
<a href="/">
|
||||
<x-application-logo class="w-20 h-20 fill-current text-gray-500" />
|
||||
</a>
|
||||
</x-slot>
|
||||
@php
|
||||
$fields = [
|
||||
'username' => 'Username',
|
||||
'password' => 'Password'
|
||||
];
|
||||
@endphp
|
||||
|
||||
<!-- Session Status -->
|
||||
<x-auth-session-status class="mb-4" :status="session('status')" />
|
||||
@extends('layouts.app')
|
||||
|
||||
<!-- Validation Errors -->
|
||||
<x-auth-validation-errors class="mb-4" :errors="$errors" />
|
||||
@section('title', 'Login')
|
||||
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
|
||||
<!-- Email Address -->
|
||||
<div>
|
||||
<x-label for="email" :value="__('Email')" />
|
||||
|
||||
<x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus />
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="mt-4">
|
||||
<x-label for="password" :value="__('Password')" />
|
||||
|
||||
<x-input id="password" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password"
|
||||
required autocomplete="current-password" />
|
||||
</div>
|
||||
|
||||
<!-- Remember Me -->
|
||||
<div class="block mt-4">
|
||||
<label for="remember_me" class="inline-flex items-center">
|
||||
<input id="remember_me" type="checkbox" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" name="remember">
|
||||
<span class="ml-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
@if (Route::has('password.request'))
|
||||
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot your password?') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
<x-button class="ml-3">
|
||||
{{ __('Log in') }}
|
||||
</x-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-auth-card>
|
||||
</x-guest-layout>
|
||||
@section('content')
|
||||
<div class="container graphictoria-center-vh">
|
||||
<x-card>
|
||||
<x-slot name="title">
|
||||
<i class="fas fa-user-circle"></i> SIGN IN
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<div class="p-2 row">
|
||||
<div class="col-md-8 mb-2 d-flex flex-column justify-content-center">
|
||||
@if ($errors->any())
|
||||
<div class="px-3 mb-10">
|
||||
<div class="alert alert-danger graphictoria-alert graphictoria-error-popup">{{ $errors->first() }}</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('login') }}">
|
||||
@csrf
|
||||
@foreach($fields as $field => $label)
|
||||
<input type="{{ $field }}" @class(['form-control', 'mb-2', 'is-invalid'=>($errors->first($field) != null)]) placeholder="{{ $label }}" name="{{ $field }}" :value="old($field)" />
|
||||
@endforeach
|
||||
<div class="mb-2">
|
||||
<input class="form-check-input" type="checkbox" value="" id="remember" name="remember">
|
||||
<label class="form-check-label" for="remember">
|
||||
Remember Me
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-primary px-5" type="submit">Sign In</button>
|
||||
</form>
|
||||
|
||||
<a href="/passwordreset" class="text-decoration-none fw-normal center" target="_blank">Forgot your password?</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<h5>New to Graphictoria?</h5>
|
||||
<p>Creating an account takes less than a minute, and you can join a community of 10k+ users for <b>completely free</b>.<br/><a href="/register" class="btn btn-sm btn-success mt-2" target="_blank">Sign Up</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</x-slot>
|
||||
<x-slot name="footer"></x-slot>
|
||||
</x-card>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,59 +1,48 @@
|
|||
<x-guest-layout>
|
||||
<x-auth-card>
|
||||
<x-slot name="logo">
|
||||
<a href="/">
|
||||
<x-application-logo class="w-20 h-20 fill-current text-gray-500" />
|
||||
</a>
|
||||
</x-slot>
|
||||
@php
|
||||
$fields = [
|
||||
'username' => 'Username',
|
||||
'email' => 'Email',
|
||||
'password' => 'Password',
|
||||
'password_confirmation' => 'Confirm Password'
|
||||
];
|
||||
@endphp
|
||||
|
||||
<!-- Validation Errors -->
|
||||
<x-auth-validation-errors class="mb-4" :errors="$errors" />
|
||||
@extends('layouts.app')
|
||||
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
@section('title', 'Register')
|
||||
|
||||
<!-- Username -->
|
||||
<div>
|
||||
<x-label for="username" :value="__('Username')" />
|
||||
|
||||
<x-input id="username" class="block mt-1 w-full" type="text" name="username" :value="old('username')" required autofocus />
|
||||
</div>
|
||||
|
||||
<!-- Email Address -->
|
||||
<div class="mt-4">
|
||||
<x-label for="email" :value="__('Email')" />
|
||||
|
||||
<x-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required />
|
||||
</div>
|
||||
|
||||
<!-- Password -->
|
||||
<div class="mt-4">
|
||||
<x-label for="password" :value="__('Password')" />
|
||||
|
||||
<x-input id="password" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password"
|
||||
required autocomplete="new-password" />
|
||||
</div>
|
||||
|
||||
<!-- Confirm Password -->
|
||||
<div class="mt-4">
|
||||
<x-label for="password_confirmation" :value="__('Confirm Password')" />
|
||||
|
||||
<x-input id="password_confirmation" class="block mt-1 w-full"
|
||||
type="password"
|
||||
name="password_confirmation" required />
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-end mt-4">
|
||||
<a class="underline text-sm text-gray-600 hover:text-gray-900" href="{{ route('login') }}">
|
||||
{{ __('Already registered?') }}
|
||||
</a>
|
||||
|
||||
<x-button class="ml-4">
|
||||
{{ __('Register') }}
|
||||
</x-button>
|
||||
</div>
|
||||
</form>
|
||||
</x-auth-card>
|
||||
</x-guest-layout>
|
||||
@section('content')
|
||||
<div class="container graphictoria-center-vh">
|
||||
<x-card>
|
||||
<x-slot name="title">
|
||||
<i class="fas fa-user-circle"></i> REGISTER
|
||||
</x-slot>
|
||||
<x-slot name="body">
|
||||
<div class="p-sm-2 d-flex flex-column justify-content-center">
|
||||
<div class="px-3 mb-10">
|
||||
<div class="alert alert-warning graphictoria-alert graphictoria-error-popup">
|
||||
<p class="mb-0">Make sure your password is unique!</p>
|
||||
</div>
|
||||
</div>
|
||||
@if ($errors->any())
|
||||
<div class="px-3 mb-10">
|
||||
<div class="alert alert-danger graphictoria-alert graphictoria-error-popup">{{ $errors->first() }}</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<form method="POST" action="{{ route('register') }}">
|
||||
@csrf
|
||||
@foreach($fields as $field => $label)
|
||||
<input type="{{ $field == 'password_confirmation' ? 'password' : $field }}" @class(['form-control', 'mb-2', 'is-invalid'=>($errors->first($field) != null)]) placeholder="{{ $label }}" name="{{ $field }}" :value="old($field)" />
|
||||
@endforeach
|
||||
<button class="btn btn-success px-5 mt-3" type="submit">Sign Up</button>
|
||||
</form>
|
||||
<a href="{{ route('login') }}" class="text-decoration-none fw-normal center" target="_blank">Already have an account?</a>
|
||||
|
||||
<p class="text-muted mt-3">By creating an account, you agree to our <a href="/legal/terms-of-service" class="text-decoration-none fw-normal" target="_blank">Terms of Service</a> and our <a href="/legal/privacy-policy" class="text-decoration-none fw-normal" target="_blank">Privacy Policy</a>.</p>
|
||||
</div>
|
||||
</x-slot>
|
||||
<x-slot name="footer"></x-slot>
|
||||
</x-card>
|
||||
</div>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -1,3 +0,0 @@
|
|||
<svg viewBox="0 0 316 316" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}>
|
||||
<path d="M305.8 81.125C305.77 80.995 305.69 80.885 305.65 80.755C305.56 80.525 305.49 80.285 305.37 80.075C305.29 79.935 305.17 79.815 305.07 79.685C304.94 79.515 304.83 79.325 304.68 79.175C304.55 79.045 304.39 78.955 304.25 78.845C304.09 78.715 303.95 78.575 303.77 78.475L251.32 48.275C249.97 47.495 248.31 47.495 246.96 48.275L194.51 78.475C194.33 78.575 194.19 78.725 194.03 78.845C193.89 78.955 193.73 79.045 193.6 79.175C193.45 79.325 193.34 79.515 193.21 79.685C193.11 79.815 192.99 79.935 192.91 80.075C192.79 80.285 192.71 80.525 192.63 80.755C192.58 80.875 192.51 80.995 192.48 81.125C192.38 81.495 192.33 81.875 192.33 82.265V139.625L148.62 164.795V52.575C148.62 52.185 148.57 51.805 148.47 51.435C148.44 51.305 148.36 51.195 148.32 51.065C148.23 50.835 148.16 50.595 148.04 50.385C147.96 50.245 147.84 50.125 147.74 49.995C147.61 49.825 147.5 49.635 147.35 49.485C147.22 49.355 147.06 49.265 146.92 49.155C146.76 49.025 146.62 48.885 146.44 48.785L93.99 18.585C92.64 17.805 90.98 17.805 89.63 18.585L37.18 48.785C37 48.885 36.86 49.035 36.7 49.155C36.56 49.265 36.4 49.355 36.27 49.485C36.12 49.635 36.01 49.825 35.88 49.995C35.78 50.125 35.66 50.245 35.58 50.385C35.46 50.595 35.38 50.835 35.3 51.065C35.25 51.185 35.18 51.305 35.15 51.435C35.05 51.805 35 52.185 35 52.575V232.235C35 233.795 35.84 235.245 37.19 236.025L142.1 296.425C142.33 296.555 142.58 296.635 142.82 296.725C142.93 296.765 143.04 296.835 143.16 296.865C143.53 296.965 143.9 297.015 144.28 297.015C144.66 297.015 145.03 296.965 145.4 296.865C145.5 296.835 145.59 296.775 145.69 296.745C145.95 296.655 146.21 296.565 146.45 296.435L251.36 236.035C252.72 235.255 253.55 233.815 253.55 232.245V174.885L303.81 145.945C305.17 145.165 306 143.725 306 142.155V82.265C305.95 81.875 305.89 81.495 305.8 81.125ZM144.2 227.205L100.57 202.515L146.39 176.135L196.66 147.195L240.33 172.335L208.29 190.625L144.2 227.205ZM244.75 114.995V164.795L226.39 154.225L201.03 139.625V89.825L219.39 100.395L244.75 114.995ZM249.12 57.105L292.81 82.265L249.12 107.425L205.43 82.265L249.12 57.105ZM114.49 184.425L96.13 194.995V85.305L121.49 70.705L139.85 60.135V169.815L114.49 184.425ZM91.76 27.425L135.45 52.585L91.76 77.745L48.07 52.585L91.76 27.425ZM43.67 60.135L62.03 70.705L87.39 85.305V202.545V202.555V202.565C87.39 202.735 87.44 202.895 87.46 203.055C87.49 203.265 87.49 203.485 87.55 203.695V203.705C87.6 203.875 87.69 204.035 87.76 204.195C87.84 204.375 87.89 204.575 87.99 204.745C87.99 204.745 87.99 204.755 88 204.755C88.09 204.905 88.22 205.035 88.33 205.175C88.45 205.335 88.55 205.495 88.69 205.635L88.7 205.645C88.82 205.765 88.98 205.855 89.12 205.965C89.28 206.085 89.42 206.225 89.59 206.325C89.6 206.325 89.6 206.325 89.61 206.335C89.62 206.335 89.62 206.345 89.63 206.345L139.87 234.775V285.065L43.67 229.705V60.135ZM244.75 229.705L148.58 285.075V234.775L219.8 194.115L244.75 179.875V229.705ZM297.2 139.625L253.49 164.795V114.995L278.85 100.395L297.21 89.825V139.625H297.2Z"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 3.0 KiB |
|
|
@ -1,9 +0,0 @@
|
|||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100">
|
||||
<div>
|
||||
{{ $logo }}
|
||||
</div>
|
||||
|
||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg">
|
||||
{{ $slot }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
@props(['status'])
|
||||
|
||||
@if ($status)
|
||||
<div {{ $attributes->merge(['class' => 'font-medium text-sm text-green-600']) }}>
|
||||
{{ $status }}
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
@props(['errors'])
|
||||
|
||||
@if ($errors->any())
|
||||
<div {{ $attributes }}>
|
||||
<div class="font-medium text-red-600">
|
||||
{{ __('Whoops! Something went wrong.') }}
|
||||
</div>
|
||||
|
||||
<ul class="mt-3 list-disc list-inside text-sm text-red-600">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
@endif
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<button {{ $attributes->merge(['type' => 'submit', 'class' => 'inline-flex items-center px-4 py-2 bg-gray-800 border border-transparent rounded-md font-semibold text-xs text-white uppercase tracking-widest hover:bg-gray-700 active:bg-gray-900 focus:outline-none focus:border-gray-900 focus:ring ring-gray-300 disabled:opacity-25 transition ease-in-out duration-150']) }}>
|
||||
{{ $slot }}
|
||||
</button>
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
<div class="card graphictoria-small-card shadow-sm">
|
||||
<div class="card-body text-center">
|
||||
<h5 class="card-title fw-bold">{{ isset($title) ? $title : $attributes['title'] }}</h5>
|
||||
<hr class="mx-5"/>
|
||||
<p class="card-text">{{ $body }}</p>
|
||||
{{ $footer }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1 +0,0 @@
|
|||
<a {{ $attributes->merge(['class' => 'block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 focus:outline-none focus:bg-gray-100 transition duration-150 ease-in-out']) }}>{{ $slot }}</a>
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
@props(['align' => 'right', 'width' => '48', 'contentClasses' => 'py-1 bg-white'])
|
||||
|
||||
@php
|
||||
switch ($align) {
|
||||
case 'left':
|
||||
$alignmentClasses = 'origin-top-left left-0';
|
||||
break;
|
||||
case 'top':
|
||||
$alignmentClasses = 'origin-top';
|
||||
break;
|
||||
case 'right':
|
||||
default:
|
||||
$alignmentClasses = 'origin-top-right right-0';
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($width) {
|
||||
case '48':
|
||||
$width = 'w-48';
|
||||
break;
|
||||
}
|
||||
@endphp
|
||||
|
||||
<div class="relative" x-data="{ open: false }" @click.outside="open = false" @close.stop="open = false">
|
||||
<div @click="open = ! open">
|
||||
{{ $trigger }}
|
||||
</div>
|
||||
|
||||
<div x-show="open"
|
||||
x-transition:enter="transition ease-out duration-200"
|
||||
x-transition:enter-start="transform opacity-0 scale-95"
|
||||
x-transition:enter-end="transform opacity-100 scale-100"
|
||||
x-transition:leave="transition ease-in duration-75"
|
||||
x-transition:leave-start="transform opacity-100 scale-100"
|
||||
x-transition:leave-end="transform opacity-0 scale-95"
|
||||
class="absolute z-50 mt-2 {{ $width }} rounded-md shadow-lg {{ $alignmentClasses }}"
|
||||
style="display: none;"
|
||||
@click="open = false">
|
||||
<div class="rounded-md ring-1 ring-black ring-opacity-5 {{ $contentClasses }}">
|
||||
{{ $content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
@props(['disabled' => false])
|
||||
|
||||
<input {{ $disabled ? 'disabled' : '' }} {!! $attributes->merge(['class' => 'rounded-md shadow-sm border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50']) !!}>
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
@props(['value'])
|
||||
|
||||
<label {{ $attributes->merge(['class' => 'block font-medium text-sm text-gray-700']) }}>
|
||||
{{ $value ?? $slot }}
|
||||
</label>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
@props(['active'])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'inline-flex items-center px-1 pt-1 border-b-2 border-indigo-400 text-sm font-medium leading-5 text-gray-900 focus:outline-none focus:border-indigo-700 transition duration-150 ease-in-out'
|
||||
: 'inline-flex items-center px-1 pt-1 border-b-2 border-transparent text-sm font-medium leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300 transition duration-150 ease-in-out';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
@props(['active'])
|
||||
|
||||
@php
|
||||
$classes = ($active ?? false)
|
||||
? 'block pl-3 pr-4 py-2 border-l-4 border-indigo-400 text-base font-medium text-indigo-700 bg-indigo-50 focus:outline-none focus:text-indigo-800 focus:bg-indigo-100 focus:border-indigo-700 transition duration-150 ease-in-out'
|
||||
: 'block pl-3 pr-4 py-2 border-l-4 border-transparent text-base font-medium text-gray-600 hover:text-gray-800 hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:text-gray-800 focus:bg-gray-50 focus:border-gray-300 transition duration-150 ease-in-out';
|
||||
@endphp
|
||||
|
||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
||||
{{ $slot }}
|
||||
</a>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<div class="col-lg-4 mb-4 d-flex flex-column align-items-center">
|
||||
<svg class="rounded-circle" width="140" height="140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="{{ $title }}"><image width="100%" height="100%" href="{{ asset('images/social/' . $title . '.png') }}"></image></svg>
|
||||
<h2 class="mt-3">{{ $title }}</h2>
|
||||
<p class="mb-3">{{ $description }}</p>
|
||||
<a class="btn btn-primary mt-auto" href="{{ $link }}" rel="noreferrer" target="_blank" role="button">View »</a>
|
||||
</div>
|
||||
|
|
@ -1,17 +1,5 @@
|
|||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Dashboard') }}
|
||||
</h2>
|
||||
</x-slot>
|
||||
@extends('layouts.app')
|
||||
|
||||
<div class="py-12">
|
||||
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
|
||||
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||
<div class="p-6 bg-white border-b border-gray-200">
|
||||
You're logged in!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
@section('content')
|
||||
<p>You're logged in!</p>
|
||||
@endsection
|
||||
|
|
@ -1,36 +1,44 @@
|
|||
@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 lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<html class="gtoria-{{ View::hasSection('theme') ? View::getSection('theme') : 'light' }}" lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>{{ config('app.name', 'Laravel') }}</title>
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap">
|
||||
|
||||
<!-- Styles -->
|
||||
<link rel="stylesheet" href="{{ asset('css/app.css') }}">
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src="{{ asset('js/app.js') }}" defer></script>
|
||||
</head>
|
||||
<body class="font-sans antialiased">
|
||||
<div class="min-h-screen bg-gray-100">
|
||||
@include('layouts.navigation')
|
||||
|
||||
<!-- Page Heading -->
|
||||
<header class="bg-white shadow">
|
||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
{{ $header }}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Page Content -->
|
||||
<main>
|
||||
{{ $slot }}
|
||||
</main>
|
||||
</div>
|
||||
<title>Graphictoria{{ 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{{ View::hasSection('title') ? ' | ' . View::getSection('title') : '' }}"/>
|
||||
<meta property="og:site_name" content="Graphictoria"/>
|
||||
<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">
|
||||
@if(!isset($noNav))
|
||||
@include('layouts.nav')
|
||||
@endif
|
||||
|
||||
@yield('content')
|
||||
|
||||
@if(!isset($noFooter))
|
||||
@include('layouts.footer')
|
||||
@endif
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
@php
|
||||
// TODO: load from website configuration?
|
||||
$routes = [
|
||||
[
|
||||
"label" => "About Us",
|
||||
"location" => "/legal/about-us"
|
||||
],
|
||||
[
|
||||
"label" => "Terms of Use",
|
||||
"location" => "/legal/terms-of-use"
|
||||
],
|
||||
[
|
||||
"label" => "Privacy Policy",
|
||||
"location" => "/legal/privacy-policy"
|
||||
],
|
||||
[
|
||||
"label" => "DMCA",
|
||||
"location" => "/legal/dmca"
|
||||
],
|
||||
[
|
||||
"label" => "Support",
|
||||
"location" => "/support"
|
||||
],
|
||||
[
|
||||
"label" => "Blog",
|
||||
"location" => 'https://blog.gtoria.net'
|
||||
],
|
||||
]
|
||||
@endphp
|
||||
|
||||
<div class="footer mt-auto pt-3 text-center shadow-lg">
|
||||
<div class="container">
|
||||
<h4 class="fw-bold mb-0">Graphictoria</h4>
|
||||
@live
|
||||
<p class="text-muted fw-bold mb-0 mt-1">
|
||||
@foreach($routes as $index => $route)
|
||||
@php
|
||||
// HACK
|
||||
$route = (object)$route;
|
||||
@endphp
|
||||
<a class="text-decoration-none fw-normal" href="{{ url($route->location) }}"{{ $route->label == 'Blog' ? ' target="_blank"' : '' }}>{{ $route->label }}</a>
|
||||
@if($index != array_key_last($routes))
|
||||
{{ ' | ' }}
|
||||
@endif
|
||||
@endforeach
|
||||
</p>
|
||||
@endlive
|
||||
<hr class="mx-auto my-2 w-25"/>
|
||||
<p class="text-muted fw-light m-0">Copyright © {{ \Carbon\Carbon::now()->format('Y') }} Graphictoria. All rights reserved.</p>
|
||||
<p class="text-muted fw-light m-0">Graphictoria is not affiliated with, endorsed by, or sponsored by Roblox Corporation. The usage of this website signifies your acceptance of the <a class="text-decoration-none fw-normal" href="{{ url('/legal/terms-of-use') }}">Terms of Use</a> and our <a class="text-decoration-none fw-normal" href="{{ url('/legal/privacy-policy') }}">Privacy Policy</a>.</p>
|
||||
<div class="my-1">
|
||||
<a class="mx-1" href="https://www.youtube.com/graphictoria?sub_confirmation=1" rel="noreferrer" target="_blank"><img src="{{ asset('/images/YouTube.svg') }}" alt="YouTube" height="22" width="28"></img></a>
|
||||
<a class="mx-1" href="https://twitter.com/intent/user?screen_name=gtoriadotnet" rel="noreferrer" target="_blank"><img src="{{ asset('/images/Twitter.svg') }}" alt="Twitter" height="28" width="28"></img></a>
|
||||
<a class="mx-1" href="https://discord.gg/q666a2sF6d" rel="noreferrer" target="_blank"><img src="{{ asset('/images/Discord.svg') }}" alt="Discord" height="28" width="28"></img></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||