diff --git a/web/app/Grid/SoapService.php b/web/app/Grid/SoapService.php new file mode 100644 index 0000000..5a678a6 --- /dev/null +++ b/web/app/Grid/SoapService.php @@ -0,0 +1,237 @@ +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); + } +} diff --git a/web/app/Helpers/GridHelper.php b/web/app/Helpers/GridHelper.php index fd7940f..ca88131 100644 --- a/web/app/Helpers/GridHelper.php +++ b/web/app/Helpers/GridHelper.php @@ -13,23 +13,31 @@ use App\Models\DynamicWebConfiguration; class GridHelper { - public static function isIpWhitelisted() { + public static function isIpWhitelisted() + { $ip = request()->ip(); $whitelistedIps = explode(';', DynamicWebConfiguration::where('name', 'WhitelistedIPs')->first()->value); return in_array($ip, $whitelistedIps); } - public static function isAccessKeyValid() { + public static function isAccessKeyValid() + { $accessKey = DynamicWebConfiguration::where('name', 'ComputeServiceAccessKey')->first()->value; return (request()->header('AccessKey') == $accessKey); } - public static function hasAllAccess() { + public static function hasAllAccess() + { if(app()->runningInConsole()) return true; if(GridHelper::isIpWhitelisted() && GridHelper::isAccessKeyValid()) return true; return false; } + + public static function createScript($scripts = [], $arguments = []) + { + + } } diff --git a/web/app/Helpers/ValidationHelper.php b/web/app/Helpers/ValidationHelper.php index c4c29a2..7803d92 100644 --- a/web/app/Helpers/ValidationHelper.php +++ b/web/app/Helpers/ValidationHelper.php @@ -11,6 +11,10 @@ use Illuminate\Validation\Validator; class ValidationHelper { + public static function generateValidatorError($validator) { + return response(self::generateErrorJSON($validator), 400); + } + public static function generateErrorJSON(Validator $validator) { $errorModel = [ 'errors' => [] diff --git a/web/app/Http/Controllers/Api/CommentsController.php b/web/app/Http/Controllers/Api/CommentsController.php new file mode 100644 index 0000000..a5f5c80 --- /dev/null +++ b/web/app/Http/Controllers/Api/CommentsController.php @@ -0,0 +1,99 @@ +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]); + } +} diff --git a/web/app/Http/Controllers/Api/FeedController.php b/web/app/Http/Controllers/Api/FeedController.php index 42fd9f5..47f0ea1 100644 --- a/web/app/Http/Controllers/Api/FeedController.php +++ b/web/app/Http/Controllers/Api/FeedController.php @@ -16,7 +16,7 @@ class FeedController extends Controller { // TODO: XlXi: Group shouts. $postsQuery = Shout::getPosts() - ->orderByDesc('created_at') + ->orderByDesc('id') ->cursorPaginate(15); /* */ @@ -38,10 +38,12 @@ class FeedController extends Controller if($post['poster_type'] == 'user') { $user = User::where('id', $post['poster_id'])->first(); + // TODO: XlXi: user profile link $poster = [ 'type' => 'User', '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']; if(Carbon::now()->greaterThan($postDate->copy()->addDays(2))) - $postDate = $postDate->isoFormat('LLLL'); + $postDate = $postDate->isoFormat('lll'); else $postDate = $postDate->calendar(); diff --git a/web/app/Http/Controllers/Api/ShopController.php b/web/app/Http/Controllers/Api/ShopController.php index b161c97..f9a9ede 100644 --- a/web/app/Http/Controllers/Api/ShopController.php +++ b/web/app/Http/Controllers/Api/ShopController.php @@ -23,10 +23,6 @@ class ShopController extends Controller '32' // Packages ]; - protected static function generateValidatorError($validator) { - return response(ValidationHelper::generateErrorJSON($validator), 400); - } - protected static function getAssets($assetTypeIds, $gearGenre=null) { // TODO: XlXi: Group owned assets @@ -49,7 +45,7 @@ class ShopController extends Controller ]); if($validator->fails()) { - return ShopController::generateValidatorError($validator); + return ValidationHelper::generateValidatorError($validator); } $valid = $validator->valid(); @@ -57,13 +53,13 @@ class ShopController extends Controller foreach(explode(',', $valid['assetTypeId']) as $assetTypeId) { if(!in_array($assetTypeId, $this->validAssetTypeIds)) { $validator->errors()->add('assetTypeId', 'Invalid assetTypeId supplied.'); - return ShopController::generateValidatorError($validator); + return ValidationHelper::generateValidatorError($validator); } } if($valid['assetTypeId'] != '19' && isset($valid['gearGenreId'])) { $validator->errors()->add('gearGenreId', 'gearGenreId can only be used with assetTypeId 19.'); - return ShopController::generateValidatorError($validator); + return ValidationHelper::generateValidatorError($validator); } /* */ diff --git a/web/app/Models/Comment.php b/web/app/Models/Comment.php new file mode 100644 index 0000000..01132e2 --- /dev/null +++ b/web/app/Models/Comment.php @@ -0,0 +1,28 @@ + + */ + protected $casts = [ + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + ]; + + public function user() + { + return $this->belongsTo(User::class, 'author_id'); + } +} diff --git a/web/database/migrations/2022_08_03_145311_create_comments_table.php b/web/database/migrations/2022_08_03_145311_create_comments_table.php new file mode 100644 index 0000000..624e021 --- /dev/null +++ b/web/database/migrations/2022_08_03_145311_create_comments_table.php @@ -0,0 +1,35 @@ +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'); + } +}; diff --git a/web/resources/js/app.js b/web/resources/js/app.js index 184155e..5b9c57b 100644 --- a/web/resources/js/app.js +++ b/web/resources/js/app.js @@ -1,15 +1,7 @@ -/** - * 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. - */ +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ 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'); \ No newline at end of file diff --git a/web/resources/js/bootstrap.js b/web/resources/js/bootstrap.js index d7b36b7..7b935ae 100644 --- a/web/resources/js/bootstrap.js +++ b/web/resources/js/bootstrap.js @@ -1,18 +1,6 @@ -window._ = require('lodash'); +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ -/** - * 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 -// }); \ No newline at end of file +window._ = require('lodash'); \ No newline at end of file diff --git a/web/resources/js/components/Comments.js b/web/resources/js/components/Comments.js index 6824b46..136b65e 100644 --- a/web/resources/js/components/Comments.js +++ b/web/resources/js/components/Comments.js @@ -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'; +const commentsId = 'gt-comments'; // XlXi: Keep this in sync with the Item page. + +axios.defaults.withCredentials = true; + class Comments extends Component { constructor(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() { return ( <>

Comments

- { /* TODO: XlXi: Hide comment input when logged out*/ } -
-
- - + { + this.state.canComment != false + ? +
+ { + this.state.error != '' + ? +
{ this.state.error }
+ : + null + } +
+ + +
-
-
- -
+ : + null + } + { + this.state.loaded + ? + ( + this.state.comments.length > 0 + ? + <> +
+ { + this.state.comments.map(({ commentId, poster, time, content }, index) => + <> +
this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }> +
+ + { + +
+
+
+ { poster.name }{ poster.icon ? <>  : null } + { this.state.mouseHover == index ? Report : null } +

{ time }

+
+ +

{ content }

+
+
+
+ { this.state.comments.length != (index+1) ?
: null } + + ) + } +
+ { + this.state.loadingCursor ? +
+ +
+ : + null + } + + : +
+

No comments were found. { this.state.canComment ? 'You could be the first!' : null }

+
+ ) + : +
+ +
+ } ); } diff --git a/web/resources/js/components/Feed.js b/web/resources/js/components/Feed.js index 934d548..5ed1ce4 100644 --- a/web/resources/js/components/Feed.js +++ b/web/resources/js/components/Feed.js @@ -1,10 +1,10 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import { Component, createRef } from 'react'; - import axios from 'axios'; - import Twemoji from 'react-twemoji'; import { buildGenericApiUrl } from '../util/HTTP.js'; @@ -124,7 +124,7 @@ class Feed extends Component { <>
this.setState({ mouseHover: index }) } onMouseLeave={ () => this.setState({ mouseHover: -1 }) }>
- + { poster.type == 'User' ? { : { @@ -133,8 +133,8 @@ class Feed extends Component {
- { poster.name }{ poster.icon ? <>  : null } - { this.state.mouseHover == index ? Report : null } + { poster.name }{ poster.icon ? <>  : null } + { this.state.mouseHover == index ? Report : null }

{ time }

diff --git a/web/resources/js/components/Loader.js b/web/resources/js/components/Loader.js index f967bf1..bf5b6a9 100644 --- a/web/resources/js/components/Loader.js +++ b/web/resources/js/components/Loader.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ const Loader = () => { return ( diff --git a/web/resources/js/components/Main.js b/web/resources/js/components/Main.js index 74769ee..d6338dc 100644 --- a/web/resources/js/components/Main.js +++ b/web/resources/js/components/Main.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import $ from 'jquery'; import * as Bootstrap from 'bootstrap'; diff --git a/web/resources/js/components/PurchaseButton.js b/web/resources/js/components/PurchaseButton.js index 0da81a5..46e35d4 100644 --- a/web/resources/js/components/PurchaseButton.js +++ b/web/resources/js/components/PurchaseButton.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import { createRef, Component } from 'react'; import ReactDOM from 'react-dom'; diff --git a/web/resources/js/components/SearchBar.js b/web/resources/js/components/SearchBar.js index 2014be1..914d371 100644 --- a/web/resources/js/components/SearchBar.js +++ b/web/resources/js/components/SearchBar.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import { useState, useRef, useEffect } from 'react'; diff --git a/web/resources/js/components/Shop.js b/web/resources/js/components/Shop.js index 0e52038..bbdf1e5 100644 --- a/web/resources/js/components/Shop.js +++ b/web/resources/js/components/Shop.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import { Component, createRef } from 'react'; @@ -239,7 +241,7 @@ class Shop extends Component { navigateCategory(categoryId, data) { 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; Object.keys(data).filter(key => { if (key == 'label') diff --git a/web/resources/js/pages/Dashboard.js b/web/resources/js/pages/Dashboard.js index 0c93932..e1787eb 100644 --- a/web/resources/js/pages/Dashboard.js +++ b/web/resources/js/pages/Dashboard.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import $ from 'jquery'; diff --git a/web/resources/js/pages/Item.js b/web/resources/js/pages/Item.js index 2d89811..e1e3983 100644 --- a/web/resources/js/pages/Item.js +++ b/web/resources/js/pages/Item.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import $ from 'jquery'; @@ -10,7 +12,7 @@ import Comments from '../components/Comments'; import PurchaseButton from '../components/PurchaseButton'; 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() { if (document.getElementById(commentsId)) { diff --git a/web/resources/js/pages/Maintenance.js b/web/resources/js/pages/Maintenance.js index 049bcc7..620613b 100644 --- a/web/resources/js/pages/Maintenance.js +++ b/web/resources/js/pages/Maintenance.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import axios from 'axios'; diff --git a/web/resources/js/pages/Shop.js b/web/resources/js/pages/Shop.js index 4b16968..5a77189 100644 --- a/web/resources/js/pages/Shop.js +++ b/web/resources/js/pages/Shop.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ import $ from 'jquery'; diff --git a/web/resources/js/util/HTTP.js b/web/resources/js/util/HTTP.js index 7c9e89d..b1c0eb7 100644 --- a/web/resources/js/util/HTTP.js +++ b/web/resources/js/util/HTTP.js @@ -1,5 +1,7 @@ -// © XlXi 2022 -// Graphictoria 5 +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ const urlObject = new URL(document.location.href); diff --git a/web/resources/views/web/shop/asset.blade.php b/web/resources/views/web/shop/asset.blade.php index fa080dc..9880ff2 100644 --- a/web/resources/views/web/shop/asset.blade.php +++ b/web/resources/views/web/shop/asset.blade.php @@ -7,47 +7,6 @@ @endsection @section('content') -{{-- XlXi: MOVE THESE TO JS --}} -@if(false) - - -@endif -
@if(!$asset->approved)
This asset is pending approval. It will not appear in-game and cannot be voted on or purchased at this time.
@@ -119,7 +78,10 @@
-
+
@endsection \ No newline at end of file diff --git a/web/routes/api.php b/web/routes/api.php index 9c503aa..bdf40c5 100644 --- a/web/routes/api.php +++ b/web/routes/api.php @@ -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::get('/list-json', 'ShopController@listJson')->name('list'); }); diff --git a/web/webpack.mix.js b/web/webpack.mix.js index b4765fc..71d6dc5 100644 --- a/web/webpack.mix.js +++ b/web/webpack.mix.js @@ -1,17 +1,11 @@ +/* + Graphictoria 5 (https://gtoria.net) + Copyright © XlXi 2022 +*/ + const mix = require('laravel-mix'); 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') .js('resources/js/pages/Maintenance.js', 'public/js') .js('resources/js/pages/Dashboard.js', 'public/js')