Updated JS copyright headers and added asset comments
This commit is contained in:
parent
8e0a66247d
commit
d8e0aaa50f
|
|
@ -0,0 +1,237 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
Graphictoria 2022
|
||||||
|
This file handles communications between the arbiter and the website.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Grid;
|
||||||
|
|
||||||
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use SoapClient;
|
||||||
|
|
||||||
|
class SoapService
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* SoapClient used by the functions in this class.
|
||||||
|
*
|
||||||
|
* @var SoapClient
|
||||||
|
*/
|
||||||
|
public $Client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs the SoapClient.
|
||||||
|
*
|
||||||
|
* Arbiter address should be formatted like "http://127.0.0.1:64989"
|
||||||
|
*
|
||||||
|
* @param string $arbiterAddr
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function __construct($arbiterAddr) {
|
||||||
|
$this->Client = new SoapClient(
|
||||||
|
Storage::path('grid/RCCService.wsdl'),
|
||||||
|
[
|
||||||
|
'location' => $arbiterAddr,
|
||||||
|
'uri' => 'http://roblox.com/',
|
||||||
|
'exceptions' => false
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls on the soap service.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param array $args
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function CallService($name, $args = []) {
|
||||||
|
$soapResult = $this->Client->{$name}($args);
|
||||||
|
|
||||||
|
if(is_soap_fault($soapResult)) {
|
||||||
|
// TODO: XlXi: log faults
|
||||||
|
}
|
||||||
|
|
||||||
|
return $soapResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Job constructors */
|
||||||
|
|
||||||
|
public static function LuaValue($value)
|
||||||
|
{
|
||||||
|
switch ($value) {
|
||||||
|
case is_bool(json_encode($value)) || $value == 1:
|
||||||
|
return json_encode($value);
|
||||||
|
default:
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function CastType($value)
|
||||||
|
{
|
||||||
|
$luaTypeConversions = [
|
||||||
|
'NULL' => 'LUA_TNIL',
|
||||||
|
'boolean' => 'LUA_TBOOLEAN',
|
||||||
|
'integer' => 'LUA_TNUMBER',
|
||||||
|
'double' => 'LUA_TNUMBER',
|
||||||
|
'string' => 'LUA_TSTRING',
|
||||||
|
'array' => 'LUA_TTABLE',
|
||||||
|
'object' => 'LUA_TNIL'
|
||||||
|
];
|
||||||
|
return $luaTypeConversions[gettype($value)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function ToLuaArguments($luaArguments = [])
|
||||||
|
{
|
||||||
|
$luaValue = ['LuaValue' => []];
|
||||||
|
|
||||||
|
foreach ($luaArguments as $argument) {
|
||||||
|
array_push(
|
||||||
|
$luaValue['LuaValue'],
|
||||||
|
[
|
||||||
|
'type' => SoapService::CastType($argument),
|
||||||
|
'value' => SoapService::LuaValue($argument)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $luaValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function MakeJobJSON($jobID, $expiration, $category, $cores, $scriptName, $script, $scriptArgs = [])
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'job' => [
|
||||||
|
'id' => $jobID,
|
||||||
|
'expirationInSeconds' => $expiration,
|
||||||
|
'category' => $category,
|
||||||
|
'cores' => $cores
|
||||||
|
],
|
||||||
|
'script' => [
|
||||||
|
'name' => $scriptName,
|
||||||
|
'script' => $script,
|
||||||
|
'arguments' => SoapService::ToLuaArguments($scriptArgs)
|
||||||
|
]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Service functions */
|
||||||
|
|
||||||
|
public function HelloWorld()
|
||||||
|
{
|
||||||
|
return $this->CallService('HelloWorld');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetVersion()
|
||||||
|
{
|
||||||
|
return $this->CallService('GetVersion');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetStatus()
|
||||||
|
{
|
||||||
|
return $this->CallService('GetStatus');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Job specific functions */
|
||||||
|
|
||||||
|
public function BatchJobEx($args)
|
||||||
|
{
|
||||||
|
return $this->CallService('BatchJobEx', $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function OpenJobEx($args)
|
||||||
|
{
|
||||||
|
return $this->CallService('OpenJobEx', $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function ExecuteEx($args)
|
||||||
|
{
|
||||||
|
return $this->CallService('ExecuteEx', $args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetAllJobsEx()
|
||||||
|
{
|
||||||
|
return $this->CallService('GetAllJobsEx');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CloseExpiredJobs()
|
||||||
|
{
|
||||||
|
return $this->CallService('CloseExpiredJobs');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CloseAllJobs()
|
||||||
|
{
|
||||||
|
return $this->CallService('CloseAllJobs');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Job management */
|
||||||
|
|
||||||
|
public function DiagEx($jobID, $type)
|
||||||
|
{
|
||||||
|
return $this->CallService(
|
||||||
|
'DiagEx',
|
||||||
|
[
|
||||||
|
'type' => $type,
|
||||||
|
'jobID' => $jobID
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function CloseJob($jobID)
|
||||||
|
{
|
||||||
|
return $this->CallService(
|
||||||
|
'CloseJob',
|
||||||
|
[
|
||||||
|
'jobID' => $jobID
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetExpiration($jobID)
|
||||||
|
{
|
||||||
|
return $this->CallService(
|
||||||
|
'GetExpiration',
|
||||||
|
[
|
||||||
|
'jobID' => $jobID
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function RenewLease($jobID, $expiration)
|
||||||
|
{
|
||||||
|
return $this->CallService(
|
||||||
|
'RenewLease',
|
||||||
|
[
|
||||||
|
'jobID' => $jobID,
|
||||||
|
'expirationInSeconds' => $expiration
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* dep */
|
||||||
|
|
||||||
|
public function BatchJob($args)
|
||||||
|
{
|
||||||
|
return $this->BatchJobEx($args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function OpenJob($args)
|
||||||
|
{
|
||||||
|
return $this->OpenJobEx($args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Execute($args)
|
||||||
|
{
|
||||||
|
return $this->ExecuteEx($args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function GetAllJobs()
|
||||||
|
{
|
||||||
|
return $this->GetAllJobsEx();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function Diag($jobID, $type)
|
||||||
|
{
|
||||||
|
return $this->DiagEx($jobID, $type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,23 +13,31 @@ use App\Models\DynamicWebConfiguration;
|
||||||
|
|
||||||
class GridHelper
|
class GridHelper
|
||||||
{
|
{
|
||||||
public static function isIpWhitelisted() {
|
public static function isIpWhitelisted()
|
||||||
|
{
|
||||||
$ip = request()->ip();
|
$ip = request()->ip();
|
||||||
$whitelistedIps = explode(';', DynamicWebConfiguration::where('name', 'WhitelistedIPs')->first()->value);
|
$whitelistedIps = explode(';', DynamicWebConfiguration::where('name', 'WhitelistedIPs')->first()->value);
|
||||||
|
|
||||||
return in_array($ip, $whitelistedIps);
|
return in_array($ip, $whitelistedIps);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function isAccessKeyValid() {
|
public static function isAccessKeyValid()
|
||||||
|
{
|
||||||
$accessKey = DynamicWebConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value;
|
$accessKey = DynamicWebConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value;
|
||||||
|
|
||||||
return (request()->header('AccessKey') == $accessKey);
|
return (request()->header('AccessKey') == $accessKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function hasAllAccess() {
|
public static function hasAllAccess()
|
||||||
|
{
|
||||||
if(app()->runningInConsole()) return true;
|
if(app()->runningInConsole()) return true;
|
||||||
if(GridHelper::isIpWhitelisted() && GridHelper::isAccessKeyValid()) return true;
|
if(GridHelper::isIpWhitelisted() && GridHelper::isAccessKeyValid()) return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function createScript($scripts = [], $arguments = [])
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,10 @@ use Illuminate\Validation\Validator;
|
||||||
|
|
||||||
class ValidationHelper
|
class ValidationHelper
|
||||||
{
|
{
|
||||||
|
public static function generateValidatorError($validator) {
|
||||||
|
return response(self::generateErrorJSON($validator), 400);
|
||||||
|
}
|
||||||
|
|
||||||
public static function generateErrorJSON(Validator $validator) {
|
public static function generateErrorJSON(Validator $validator) {
|
||||||
$errorModel = [
|
$errorModel = [
|
||||||
'errors' => []
|
'errors' => []
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Api;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
|
use App\Helpers\ValidationHelper;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Asset;
|
||||||
|
use App\Models\Comment;
|
||||||
|
|
||||||
|
class CommentsController extends Controller
|
||||||
|
{
|
||||||
|
protected function listJson(Request $request)
|
||||||
|
{
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'assetId' => [
|
||||||
|
'required',
|
||||||
|
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||||
|
return $query->where('moderated', false);
|
||||||
|
})
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
if($validator->fails())
|
||||||
|
return ValidationHelper::generateValidatorError($validator);
|
||||||
|
|
||||||
|
$valid = $validator->valid();
|
||||||
|
|
||||||
|
$comments = Comment::where('asset_id', $valid['assetId'])
|
||||||
|
->where('deleted', false)
|
||||||
|
->orderByDesc('id')
|
||||||
|
->cursorPaginate(15);
|
||||||
|
|
||||||
|
$prevCursor = $comments->previousCursor();
|
||||||
|
$nextCursor = $comments->nextCursor();
|
||||||
|
|
||||||
|
$result = [
|
||||||
|
'data' => [],
|
||||||
|
'prev_cursor' => ($prevCursor ? $prevCursor->encode() : null),
|
||||||
|
'next_cursor' => ($nextCursor ? $nextCursor->encode() : null)
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach($comments as $comment) {
|
||||||
|
// TODO: XlXi: user profile link
|
||||||
|
// TODO: XlXi: user thumbnail
|
||||||
|
$poster = [
|
||||||
|
'name' => $comment->user->username,
|
||||||
|
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png',
|
||||||
|
'url' => 'https://gtoria.local/todo123'
|
||||||
|
];
|
||||||
|
|
||||||
|
$postDate = $comment['updated_at'];
|
||||||
|
if(Carbon::now()->greaterThan($postDate->copy()->addDays(2)))
|
||||||
|
$postDate = $postDate->isoFormat('lll');
|
||||||
|
else
|
||||||
|
$postDate = $postDate->calendar();
|
||||||
|
|
||||||
|
array_push($result['data'], [
|
||||||
|
'commentId' => $comment->id,
|
||||||
|
'poster' => $poster,
|
||||||
|
'content' => $comment->content,
|
||||||
|
'time' => $postDate
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function share(Request $request)
|
||||||
|
{
|
||||||
|
$validator = Validator::make($request->all(), [
|
||||||
|
'assetId' => [
|
||||||
|
'required',
|
||||||
|
Rule::exists('App\Models\Asset', 'id')->where(function($query) {
|
||||||
|
return $query->where('moderated', false);
|
||||||
|
})
|
||||||
|
],
|
||||||
|
'content' => ['required', 'max:200']
|
||||||
|
]);
|
||||||
|
|
||||||
|
if($validator->fails())
|
||||||
|
return ValidationHelper::generateValidatorError($validator);
|
||||||
|
|
||||||
|
$valid = $validator->valid();
|
||||||
|
|
||||||
|
$comment = new Comment();
|
||||||
|
$comment->asset_id = $valid['assetId'];
|
||||||
|
$comment->author_id = Auth::id();
|
||||||
|
$comment->content = $valid['content'];
|
||||||
|
$comment->save();
|
||||||
|
|
||||||
|
return response(['success' => true]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ class FeedController extends Controller
|
||||||
{
|
{
|
||||||
// TODO: XlXi: Group shouts.
|
// TODO: XlXi: Group shouts.
|
||||||
$postsQuery = Shout::getPosts()
|
$postsQuery = Shout::getPosts()
|
||||||
->orderByDesc('created_at')
|
->orderByDesc('id')
|
||||||
->cursorPaginate(15);
|
->cursorPaginate(15);
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
@ -38,10 +38,12 @@ class FeedController extends Controller
|
||||||
if($post['poster_type'] == 'user') {
|
if($post['poster_type'] == 'user') {
|
||||||
$user = User::where('id', $post['poster_id'])->first();
|
$user = User::where('id', $post['poster_id'])->first();
|
||||||
|
|
||||||
|
// TODO: XlXi: user profile link
|
||||||
$poster = [
|
$poster = [
|
||||||
'type' => 'User',
|
'type' => 'User',
|
||||||
'name' => $user->username,
|
'name' => $user->username,
|
||||||
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png'
|
'thumbnail' => 'https://www.gtoria.local/images/testing/headshot.png',
|
||||||
|
'url' => 'https://gtoria.local/todo123'
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -49,7 +51,7 @@ class FeedController extends Controller
|
||||||
|
|
||||||
$postDate = $post['updated_at'];
|
$postDate = $post['updated_at'];
|
||||||
if(Carbon::now()->greaterThan($postDate->copy()->addDays(2)))
|
if(Carbon::now()->greaterThan($postDate->copy()->addDays(2)))
|
||||||
$postDate = $postDate->isoFormat('LLLL');
|
$postDate = $postDate->isoFormat('lll');
|
||||||
else
|
else
|
||||||
$postDate = $postDate->calendar();
|
$postDate = $postDate->calendar();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,6 @@ class ShopController extends Controller
|
||||||
'32' // Packages
|
'32' // Packages
|
||||||
];
|
];
|
||||||
|
|
||||||
protected static function generateValidatorError($validator) {
|
|
||||||
return response(ValidationHelper::generateErrorJSON($validator), 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static function getAssets($assetTypeIds, $gearGenre=null)
|
protected static function getAssets($assetTypeIds, $gearGenre=null)
|
||||||
{
|
{
|
||||||
// TODO: XlXi: Group owned assets
|
// TODO: XlXi: Group owned assets
|
||||||
|
|
@ -49,7 +45,7 @@ class ShopController extends Controller
|
||||||
]);
|
]);
|
||||||
|
|
||||||
if($validator->fails()) {
|
if($validator->fails()) {
|
||||||
return ShopController::generateValidatorError($validator);
|
return ValidationHelper::generateValidatorError($validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
$valid = $validator->valid();
|
$valid = $validator->valid();
|
||||||
|
|
@ -57,13 +53,13 @@ class ShopController extends Controller
|
||||||
foreach(explode(',', $valid['assetTypeId']) as $assetTypeId) {
|
foreach(explode(',', $valid['assetTypeId']) as $assetTypeId) {
|
||||||
if(!in_array($assetTypeId, $this->validAssetTypeIds)) {
|
if(!in_array($assetTypeId, $this->validAssetTypeIds)) {
|
||||||
$validator->errors()->add('assetTypeId', 'Invalid assetTypeId supplied.');
|
$validator->errors()->add('assetTypeId', 'Invalid assetTypeId supplied.');
|
||||||
return ShopController::generateValidatorError($validator);
|
return ValidationHelper::generateValidatorError($validator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if($valid['assetTypeId'] != '19' && isset($valid['gearGenreId'])) {
|
if($valid['assetTypeId'] != '19' && isset($valid['gearGenreId'])) {
|
||||||
$validator->errors()->add('gearGenreId', 'gearGenreId can only be used with assetTypeId 19.');
|
$validator->errors()->add('gearGenreId', 'gearGenreId can only be used with assetTypeId 19.');
|
||||||
return ShopController::generateValidatorError($validator);
|
return ValidationHelper::generateValidatorError($validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* */
|
/* */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
|
||||||
|
class Comment extends Model
|
||||||
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The attributes that should be cast.
|
||||||
|
*
|
||||||
|
* @var array<string, string>
|
||||||
|
*/
|
||||||
|
protected $casts = [
|
||||||
|
'created_at' => 'datetime',
|
||||||
|
'updated_at' => 'datetime',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function user()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(User::class, 'author_id');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?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('comments', function (Blueprint $table) {
|
||||||
|
$table->id();
|
||||||
|
$table->unsignedBigInteger('author_id');
|
||||||
|
$table->longText('asset_id');
|
||||||
|
$table->longText('content');
|
||||||
|
$table->boolean('deleted')->default(false);
|
||||||
|
$table->timestamps();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('comments');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -1,15 +1,7 @@
|
||||||
/**
|
/*
|
||||||
* First we will load all of this project's JavaScript dependencies which
|
Graphictoria 5 (https://gtoria.net)
|
||||||
* includes React and other helpers. It's a great starting point while
|
Copyright © XlXi 2022
|
||||||
* building robust, powerful web applications using React + Laravel.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
require('./bootstrap');
|
require('./bootstrap');
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
require('./components/Main');
|
require('./components/Main');
|
||||||
|
|
@ -1,18 +1,6 @@
|
||||||
window._ = require('lodash');
|
/*
|
||||||
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
window._ = require('lodash');
|
||||||
* Echo exposes an expressive API for subscribing to channels and listening
|
|
||||||
* for events that are broadcast by Laravel. Echo and event broadcasting
|
|
||||||
* allows your team to easily build robust real-time web applications.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// import Echo from 'laravel-echo';
|
|
||||||
|
|
||||||
// window.Pusher = require('pusher-js');
|
|
||||||
|
|
||||||
// window.Echo = new Echo({
|
|
||||||
// broadcaster: 'pusher',
|
|
||||||
// key: process.env.MIX_PUSHER_APP_KEY,
|
|
||||||
// cluster: process.env.MIX_PUSHER_APP_CLUSTER,
|
|
||||||
// forceTLS: true
|
|
||||||
// });
|
|
||||||
|
|
@ -1,29 +1,185 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import { Component } from 'react';
|
import { Component, createRef } from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
|
import Twemoji from 'react-twemoji';
|
||||||
|
|
||||||
|
import { buildGenericApiUrl } from '../util/HTTP.js';
|
||||||
import Loader from './Loader';
|
import Loader from './Loader';
|
||||||
|
|
||||||
|
const commentsId = 'gt-comments'; // XlXi: Keep this in sync with the Item page.
|
||||||
|
|
||||||
|
axios.defaults.withCredentials = true;
|
||||||
|
|
||||||
class Comments extends Component {
|
class Comments extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
loaded: false,
|
||||||
|
loadingCursor: false,
|
||||||
|
disabled: false,
|
||||||
|
error: '',
|
||||||
|
comments: [],
|
||||||
|
mouseHover: -1
|
||||||
|
};
|
||||||
|
|
||||||
|
this.inputBox = createRef();
|
||||||
|
|
||||||
|
this.loadComments = this.loadComments.bind(this);
|
||||||
|
this.loadMore = this.loadMore.bind(this);
|
||||||
|
this.postComment = this.postComment.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
window.addEventListener('scroll', this.loadMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
window.removeEventListener('scroll', this.loadMore);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
let commentsElement = document.getElementById(commentsId);
|
||||||
|
if (commentsElement) {
|
||||||
|
this.assetId = commentsElement.getAttribute('data-asset-id')
|
||||||
|
this.setState({
|
||||||
|
canComment: (commentsElement.getAttribute('data-can-comment') === '1')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loadComments();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadComments() {
|
||||||
|
axios.get(buildGenericApiUrl('api', `comments/v1/list-json?assetId=${this.assetId}`))
|
||||||
|
.then(res => {
|
||||||
|
const comments = res.data;
|
||||||
|
|
||||||
|
this.nextCursor = comments.next_cursor;
|
||||||
|
this.setState({ comments: comments.data, loaded: true });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// XlXi: https://stackoverflow.com/questions/57778950/how-to-load-more-search-results-when-scrolling-down-the-page-in-react-js
|
||||||
|
loadMore() {
|
||||||
|
// XlXi: Taking the height of the footer into account.
|
||||||
|
if (window.innerHeight + document.documentElement.scrollTop >= document.scrollingElement.scrollHeight-200) {
|
||||||
|
if (!!(this.nextCursor) && !this.state.loadingCursor) {
|
||||||
|
this.setState({ loadingCursor: true });
|
||||||
|
|
||||||
|
axios.get(buildGenericApiUrl('api', `comments/v1/list-json?assetId=${this.assetId}&cursor=${this.nextCursor}`))
|
||||||
|
.then(res => {
|
||||||
|
const comments = res.data;
|
||||||
|
|
||||||
|
this.nextCursor = comments.next_cursor;
|
||||||
|
this.setState({ comments: this.state.comments.concat(comments.data), loadingCursor: false });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
postComment() {
|
||||||
|
this.setState({ disabled: true });
|
||||||
|
|
||||||
|
const postText = this.inputBox.current.value;
|
||||||
|
if (postText == '') {
|
||||||
|
this.setState({ disabled: false, error: 'Your comment cannot be blank.' });
|
||||||
|
this.inputBox.current.focus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
axios.post(buildGenericApiUrl('api', `comments/v1/share`), { assetId: this.assetId, content: postText })
|
||||||
|
.then(res => {
|
||||||
|
this.inputBox.current.value = '';
|
||||||
|
this.setState({ loaded: false, loadingCursor: false, disabled: false });
|
||||||
|
this.loadComments();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
const data = err.response.data;
|
||||||
|
|
||||||
|
this.setState({ disabled: false, error: data.message });
|
||||||
|
this.inputBox.current.focus();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h4 className="pt-3">Comments</h4>
|
<h4 className="pt-3">Comments</h4>
|
||||||
{ /* TODO: XlXi: Hide comment input when logged out*/ }
|
{
|
||||||
<div className="card mb-2">
|
this.state.canComment != false
|
||||||
<div className="input-group p-2">
|
?
|
||||||
<input disabled="disabled" type="text" className="form-control" placeholder="Write a comment!" />
|
<div className="card mb-2">
|
||||||
<button disabled="disabled" type="submit" className="btn btn-secondary">Share</button>
|
{
|
||||||
|
this.state.error != ''
|
||||||
|
?
|
||||||
|
<div className="alert alert-danger graphictoria-alert graphictoria-error-popup m-2 mb-0">{ this.state.error }</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
<div className="input-group p-2">
|
||||||
|
<input disabled={ (!this.state.loaded || this.state.disabled) } type="text" className="form-control" placeholder="Write a comment!" ref={ this.inputBox }/>
|
||||||
|
<button disabled={ (!this.state.loaded || this.state.disabled) } type="submit" className="btn btn-secondary" onClick={ this.postComment }>Post</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
:
|
||||||
<div className="d-flex">
|
null
|
||||||
<Loader />
|
}
|
||||||
</div>
|
{
|
||||||
|
this.state.loaded
|
||||||
|
?
|
||||||
|
(
|
||||||
|
this.state.comments.length > 0
|
||||||
|
?
|
||||||
|
<>
|
||||||
|
<div className="card">
|
||||||
|
{
|
||||||
|
this.state.comments.map(({ commentId, poster, time, content }, index) =>
|
||||||
|
<>
|
||||||
|
<div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
|
||||||
|
<div className="me-2">
|
||||||
|
<a href={ poster.url }>
|
||||||
|
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="flex-fill">
|
||||||
|
<div className="d-flex">
|
||||||
|
<a href={ poster.url } className="text-decoration-none me-auto fw-bold">{ poster.name }{ poster.icon ? <> <i className={ poster.icon }></i></> : null }</a>
|
||||||
|
{ this.state.mouseHover == index ? <a href={ buildGenericApiUrl('www', `report/comment/${commentId}`) } target="_blank" className="text-decoration-none link-danger me-2">Report <i className="fa-solid fa-circle-exclamation"></i></a> : null }
|
||||||
|
<p className="text-muted">{ time }</p>
|
||||||
|
</div>
|
||||||
|
<Twemoji options={{ className: 'twemoji', base: '/images/twemoji/', folder: 'svg', ext: '.svg' }}>
|
||||||
|
<p>{ content }</p>
|
||||||
|
</Twemoji>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{ this.state.comments.length != (index+1) ? <hr className="m-0" /> : null }
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
{
|
||||||
|
this.state.loadingCursor ?
|
||||||
|
<div className="d-flex mt-2">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
null
|
||||||
|
}
|
||||||
|
</>
|
||||||
|
:
|
||||||
|
<div className="text-center mt-3">
|
||||||
|
<p className="text-muted">No comments were found. { this.state.canComment ? 'You could be the first!' : null }</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
:
|
||||||
|
<div className="d-flex">
|
||||||
|
<Loader />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import { Component, createRef } from 'react';
|
import { Component, createRef } from 'react';
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import Twemoji from 'react-twemoji';
|
import Twemoji from 'react-twemoji';
|
||||||
|
|
||||||
import { buildGenericApiUrl } from '../util/HTTP.js';
|
import { buildGenericApiUrl } from '../util/HTTP.js';
|
||||||
|
|
@ -124,7 +124,7 @@ class Feed extends Component {
|
||||||
<>
|
<>
|
||||||
<div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
|
<div className="d-flex p-2" onMouseEnter={ () => this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
|
||||||
<div className="me-2">
|
<div className="me-2">
|
||||||
<a href={ buildGenericApiUrl('www', (poster.type == 'User' ? `users/${poster.name}/profile` : `groups/${poster.id}`)) }>
|
<a href={ poster.url }>
|
||||||
{ poster.type == 'User' ?
|
{ poster.type == 'User' ?
|
||||||
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" /> :
|
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="border graphictora-feed-user-circle" /> :
|
||||||
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="img-fluid" />
|
<img src={ poster.thumbnail } alt={ poster.name } width="50" height="50" className="img-fluid" />
|
||||||
|
|
@ -133,8 +133,8 @@ class Feed extends Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-fill">
|
<div className="flex-fill">
|
||||||
<div className="d-flex">
|
<div className="d-flex">
|
||||||
<a href={ buildGenericApiUrl('www', (poster.type == 'User' ? `users/${poster.name}/profile` : `groups/${poster.id}`)) } className="text-decoration-none fw-bold me-auto">{ poster.name }{ poster.icon ? <> <i className={ poster.icon }></i></> : null }</a>
|
<a href={ poster.url } className="text-decoration-none fw-bold me-auto">{ poster.name }{ poster.icon ? <> <i className={ poster.icon }></i></> : null }</a>
|
||||||
{ this.state.mouseHover == index ? <a href={ buildGenericApiUrl('www', `report/user-wall/${postId}`) } target="_blank" className="text-decoration-none link-danger me-2">Report <i className="fa-solid fa-circle-exclamation"></i></a> : null }
|
{ this.state.mouseHover == index ? <a href={ buildGenericApiUrl('www', `report/wall/${postId}`) } target="_blank" className="text-decoration-none link-danger me-2">Report <i className="fa-solid fa-circle-exclamation"></i></a> : null }
|
||||||
<p className="text-muted">{ time }</p>
|
<p className="text-muted">{ time }</p>
|
||||||
</div>
|
</div>
|
||||||
<Twemoji options={{ className: 'twemoji', base: '/images/twemoji/', folder: 'svg', ext: '.svg' }}>
|
<Twemoji options={{ className: 'twemoji', base: '/images/twemoji/', folder: 'svg', ext: '.svg' }}>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
const Loader = () => {
|
const Loader = () => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import * as Bootstrap from 'bootstrap';
|
import * as Bootstrap from 'bootstrap';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import { createRef, Component } from 'react';
|
import { createRef, Component } from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import { useState, useRef, useEffect } from 'react';
|
import { useState, useRef, useEffect } from 'react';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import { Component, createRef } from 'react';
|
import { Component, createRef } from 'react';
|
||||||
|
|
||||||
|
|
@ -239,7 +241,7 @@ class Shop extends Component {
|
||||||
navigateCategory(categoryId, data) {
|
navigateCategory(categoryId, data) {
|
||||||
this.setState({selectedCategoryId: categoryId, pageLoaded: false});
|
this.setState({selectedCategoryId: categoryId, pageLoaded: false});
|
||||||
|
|
||||||
let url = buildGenericApiUrl('api', 'catalog/v1/list-json');
|
let url = buildGenericApiUrl('api', 'shop/v1/list-json');
|
||||||
let paramIterator = 0;
|
let paramIterator = 0;
|
||||||
Object.keys(data).filter(key => {
|
Object.keys(data).filter(key => {
|
||||||
if (key == 'label')
|
if (key == 'label')
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
|
@ -10,7 +12,7 @@ import Comments from '../components/Comments';
|
||||||
import PurchaseButton from '../components/PurchaseButton';
|
import PurchaseButton from '../components/PurchaseButton';
|
||||||
|
|
||||||
const purchaseId = 'gt-purchase-button';
|
const purchaseId = 'gt-purchase-button';
|
||||||
const commentsId = 'gt-comments';
|
const commentsId = 'gt-comments'; // XlXi: Keep this in sync with the Comments component.
|
||||||
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
if (document.getElementById(commentsId)) {
|
if (document.getElementById(commentsId)) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
// © XlXi 2022
|
/*
|
||||||
// Graphictoria 5
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
const urlObject = new URL(document.location.href);
|
const urlObject = new URL(document.location.href);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,47 +7,6 @@
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
{{-- XlXi: MOVE THESE TO JS --}}
|
|
||||||
@if(false)
|
|
||||||
<div class="modal fade show" id="purchase-modal" aria-hidden="true" tabindex="-1">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content text-center">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Purchase Item</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body d-flex flex-column">
|
|
||||||
<p>Would you like to purchase the {{ $asset->typeString() }} "<strong>{{ $asset->name }}</strong>" from {{ $asset->user->username }} for <strong style="color:#e59800!important;font-weight:bold"><img src="{{ asset('images/symbols/token.svg') }}" height="16" width="16" class="img-fluid" style="margin-top:-1px" />{{ number_format($asset->priceInTokens) }}</strong>?</p>
|
|
||||||
<img src={{ asset('images/testing/hat.png') }} width="240" height="240" alt="{{ $asset->name }}" class="mx-auto my-2 img-fluid" />
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer flex-column">
|
|
||||||
<div class="mx-auto">
|
|
||||||
<button class="btn btn-success" data-bs-dismiss="modal">Purchase</button>
|
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
|
||||||
</div>
|
|
||||||
<p class="text-muted pt-1">You will have <strong style="color:#e59800!important;font-weight:bold"><img src="{{ asset('images/symbols/token.svg') }}" height="16" width="16" class="img-fluid" style="margin-top:-1px" />{{ max(0, number_format(Auth::user()->tokens - $asset->priceInTokens)) }}</strong> after this purchase.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal fade show" id="purchase-modal" aria-hidden="true" tabindex="-1">
|
|
||||||
<div class="modal-dialog modal-dialog-centered">
|
|
||||||
<div class="modal-content text-center">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Insufficient Funds</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<p>You don't have enough tokens to buy this item.</p>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-secondary" data-bs-dismiss="modal">Ok</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
|
|
||||||
<div class="container mx-auto py-5">
|
<div class="container mx-auto py-5">
|
||||||
@if(!$asset->approved)
|
@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>
|
<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>
|
||||||
|
|
@ -119,7 +78,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="gt-comments"></div>
|
<div id="gt-comments"
|
||||||
|
data-can-comment="{{ intval(Auth::check()) }}"
|
||||||
|
data-asset-id="{{ $asset->id }}"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
@ -11,7 +11,14 @@ Route::middleware('auth')->group(function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Route::group(['as' => 'catalog.', 'prefix' => 'catalog'], function() {
|
Route::group(['as' => 'comments.', 'prefix' => 'comments'], function() {
|
||||||
|
Route::group(['as' => 'v1.', 'prefix' => 'v1'], function() {
|
||||||
|
Route::get('/list-json', 'CommentsController@listJson')->name('list');
|
||||||
|
Route::post('/share', 'CommentsController@share')->name('share')->middleware(['auth', 'throttle:3,2']);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Route::group(['as' => 'shop.', 'prefix' => 'shop'], function() {
|
||||||
Route::group(['as' => 'v1.', 'prefix' => 'v1'], function() {
|
Route::group(['as' => 'v1.', 'prefix' => 'v1'], function() {
|
||||||
Route::get('/list-json', 'ShopController@listJson')->name('list');
|
Route::get('/list-json', 'ShopController@listJson')->name('list');
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,11 @@
|
||||||
|
/*
|
||||||
|
Graphictoria 5 (https://gtoria.net)
|
||||||
|
Copyright © XlXi 2022
|
||||||
|
*/
|
||||||
|
|
||||||
const mix = require('laravel-mix');
|
const mix = require('laravel-mix');
|
||||||
require('laravel-mix-banner');
|
require('laravel-mix-banner');
|
||||||
|
|
||||||
/*
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
| Mix Asset Management
|
|
||||||
|--------------------------------------------------------------------------
|
|
||||||
|
|
|
||||||
| Mix provides a clean, fluent API for defining some Webpack build steps
|
|
||||||
| for your Laravel application. By default, we are compiling the Sass
|
|
||||||
| file for the application as well as bundling up all the JS files.
|
|
||||||
|
|
|
||||||
*/
|
|
||||||
|
|
||||||
mix.js('resources/js/app.js', 'public/js')
|
mix.js('resources/js/app.js', 'public/js')
|
||||||
.js('resources/js/pages/Maintenance.js', 'public/js')
|
.js('resources/js/pages/Maintenance.js', 'public/js')
|
||||||
.js('resources/js/pages/Dashboard.js', 'public/js')
|
.js('resources/js/pages/Dashboard.js', 'public/js')
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue