From e7afaa7c32381004d2bdd8bd34135283f1a74c72 Mon Sep 17 00:00:00 2001 From: Jonathan Juursema Date: Wed, 16 May 2018 00:10:55 +0200 Subject: [PATCH] Dropdown for users, products, events, committees replaced with search fields. (Fixes #655) * Initial ajax search functionality. (Refs #655) * Further search field functionalit. (Refs #655) * Further search field functionalit. (Refs #655) * Finalized search fields! (Fixes #655) --- app/Console/Commands/FeeCron.php | 2 +- app/Http/Controllers/AliasController.php | 2 +- app/Http/Controllers/ApiController.php | 23 --- app/Http/Controllers/EventController.php | 2 +- app/Http/Controllers/OrderLineController.php | 28 ++- app/Http/Controllers/SearchController.php | 40 ++++ app/Models/Committee.php | 2 +- app/Models/Event.php | 17 ++ app/Models/Product.php | 4 +- app/Models/User.php | 12 +- bower.json | 3 +- composer.lock | 119 ++++++++++- package.json | 6 +- resources/views/achievement/manage.blade.php | 56 +---- resources/views/aliases/add.blade.php | 7 +- .../views/authorization/overview.blade.php | 10 +- resources/views/committee/edit.blade.php | 22 -- .../views/committee/form-members.blade.php | 10 +- resources/views/event/display.blade.php | 69 +------ resources/views/event/edit.blade.php | 17 +- .../omnomcom/orders/adminhistory.blade.php | 43 +++- .../omnomcom/tipcie/orderhistory.blade.php | 87 -------- resources/views/tempadmin/edit.blade.php | 52 +---- resources/views/tickets/edit.blade.php | 20 +- .../website/layouts/assets/globalcss.scss | 4 + .../layouts/assets/javascripts.blade.php | 192 +++++++++++++++++- .../welcomemessages/addmessage.blade.php | 41 +--- routes/api.php | 8 +- routes/web.php | 1 + 29 files changed, 497 insertions(+), 402 deletions(-) create mode 100644 resources/views/website/layouts/assets/globalcss.scss diff --git a/app/Console/Commands/FeeCron.php b/app/Console/Commands/FeeCron.php index ecf09710b..b9194f395 100755 --- a/app/Console/Commands/FeeCron.php +++ b/app/Console/Commands/FeeCron.php @@ -113,7 +113,7 @@ public function handle() $charged->count++; $product = Product::findOrFail($fee); - $product->buyForUser($member->user, 1, $product->price); + $product->buyForUser($member->user, 1); Mail::to($member->user)->queue((new FeeEmail($member->user, $email_fee, $product->price, $email_remmitance_reason))->onQueue('high')); diff --git a/app/Http/Controllers/AliasController.php b/app/Http/Controllers/AliasController.php index ec052a6ff..5c0ca62c6 100755 --- a/app/Http/Controllers/AliasController.php +++ b/app/Http/Controllers/AliasController.php @@ -103,7 +103,7 @@ public function store(Request $request) return Redirect::route('alias::index'); - } elseif ($request->input('user') != 'off') { + } elseif ($request->input('user') != '') { $user = User::findOrFail($request->input('user')); diff --git a/app/Http/Controllers/ApiController.php b/app/Http/Controllers/ApiController.php index a27d57def..79d30529d 100755 --- a/app/Http/Controllers/ApiController.php +++ b/app/Http/Controllers/ApiController.php @@ -19,29 +19,6 @@ class ApiController extends Controller { - public function members(Request $request) - { - - if (!Auth::check() || !Auth::user()->member) { - abort(403); - } - - $users = User::all(); - $data = array(); - - foreach ($users as $user) { - if (!$user->member) continue; - if ($request->has('term') && strpos(strtolower($user->name), strtolower($request->term)) === false) continue; - - $member = new \stdClass(); - $member->name = $user->name; - $member->id = $user->id; - $data[] = $member; - } - - return $data; - - } public function train(Request $request) { diff --git a/app/Http/Controllers/EventController.php b/app/Http/Controllers/EventController.php index 02abbdb45..f4c016e19 100755 --- a/app/Http/Controllers/EventController.php +++ b/app/Http/Controllers/EventController.php @@ -317,7 +317,7 @@ public function finclose(Request $request, $id) $product->save(); foreach ($activity->users as $user) { - $product->buyForUser($user, 1, $product->price); + $product->buyForUser($user, 1); } $activity->closed = true; diff --git a/app/Http/Controllers/OrderLineController.php b/app/Http/Controllers/OrderLineController.php index 7816020c4..4dff84174 100755 --- a/app/Http/Controllers/OrderLineController.php +++ b/app/Http/Controllers/OrderLineController.php @@ -114,6 +114,7 @@ public function adminindex(Request $request) */ public function bulkStore(Request $request) { + for ($i = 0; $i < count($request->input('user')); $i++) { $user = User::findOrFail($request->input('user')[$i]); @@ -121,7 +122,7 @@ public function bulkStore(Request $request) $price = ($request->input('price')[$i] != "" ? floatval(str_replace(",", ".", $request->input('price')[$i])) : $product->price); $units = $request->input('units')[$i]; - $product->buyForUser($user, $units, $price * $units); + $product->buyForUser($user, $units); } @@ -129,6 +130,31 @@ public function bulkStore(Request $request) return Redirect::back(); } + /** + * Store (a) simple orderline(s). + * + * @param Request $request + * @return \Illuminate\Http\RedirectResponse + */ + public function store(Request $request) + { + + for ($u = 0; $u < count($request->input('user')); $u++) { + for ($p = 0; $p < count($request->input('product')); $p++) { + + $user = User::findOrFail($request->input('user')[$u]); + $product = Product::findOrFail($request->input('product')[$p]); + + $product->buyForUser($user, 1); + + } + } + + $request->session()->flash('flash_message', 'Your manual orders have been added.'); + return Redirect::back(); + + } + /** * Remove the specified resource from storage. * diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 70d216edf..f6390b4fe 100755 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -4,6 +4,7 @@ use Illuminate\Http\Request; +use Proto\Models\Product; use Proto\Models\User; use Proto\Models\Event; use Proto\Models\Page; @@ -254,4 +255,43 @@ public function openSearch() return Response::make(View::make('website.opensearch'))->header('Content-Type', 'text/xml'); } + public function getUserSearch(Request $request) + { + $search_attributes = ['id', 'name', 'calling_name', 'email', 'phone', 'edu_username']; + return $this->getGenericSearch(User::class, $request->get('q'), $search_attributes); + } + + public function getEventSearch(Request $request) + { + $search_attributes = ['id', 'title', 'description']; + return $this->getGenericSearch(Event::class, $request->get('q'), $search_attributes); + } + + public function getCommitteeSearch(Request $request) + { + $search_attributes = ['id', 'name', 'slug', 'description']; + return $this->getGenericSearch(Committee::class, $request->get('q'), $search_attributes); + } + + public function getProductSearch(Request $request) + { + $search_attributes = ['id', 'name', 'nicename']; + return $this->getGenericSearch(Product::class, $request->get('q'), $search_attributes); + } + + private function getGenericSearch($model, $query, $attributes) + { + $terms = explode(' ', $query); + $results = collect([]); + foreach ($terms as $term) { + $query = $model::query(); + $t = sprintf('%%%s%%', $term); + foreach ($attributes as $attr) { + $query = $query->orWhere($attr, 'LIKE', $t); + } + $results = $results->merge($query->get()); + } + return $results->unique(); + } + } diff --git a/app/Models/Committee.php b/app/Models/Committee.php index c73c2c9c6..e6556b344 100755 --- a/app/Models/Committee.php +++ b/app/Models/Committee.php @@ -20,7 +20,7 @@ class Committee extends Model * @var string */ protected $table = 'committees'; - protected $hidden = ['id', 'image_id']; + protected $hidden = ['image_id']; public function getPublicId() { diff --git a/app/Models/Event.php b/app/Models/Event.php index 301a5b28a..bec979d62 100755 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -20,6 +20,8 @@ class Event extends Model */ protected $table = 'events'; + protected $appends = ['is_future', 'formatted_date']; + public function getPublicId() { return Hashids::connection('event')->encode($this->id); @@ -165,4 +167,19 @@ public function shouldShowDietInfo() return $this->involves_food && $this->end > strtotime('-1 week'); } + public function getIsFutureAttribute() + { + return date('U') < $this->start; + } + + public function getFormattedDateAttribute() + { + return (object)[ + 'simple' => date('M d, Y', $this->start), + 'year' => date('Y', $this->start), + 'month' => date('M Y', $this->start), + 'time' => date('H:i', $this->start) + ]; + } + } diff --git a/app/Models/Product.php b/app/Models/Product.php index 7fee1dc7b..1642d611d 100755 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -44,12 +44,14 @@ public function ticket() return $this->hasOne('Proto\Models\Ticket', 'product_id'); } - public function buyForUser(User $user, $amount, $total, $withCash = false) + public function buyForUser(User $user, $amount, $total = null, $withCash = false) { $this->stock -= $amount; $this->save(); + $total = ($total ? $total : $this->price * $amount); + $orderline = OrderLine::create([ 'user_id' => ($withCash ? null : $user->id), 'cashier_id' => ($withCash || $total == 0 ? $user->id : null), diff --git a/app/Models/User.php b/app/Models/User.php index a013695a1..4b9710ecc 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -42,12 +42,14 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon protected $guarded = ['password', 'remember_token']; + protected $appends = ['is_member', 'photo_preview']; + /** * The attributes excluded from the model's JSON form. * * @var array */ - protected $hidden = ['id', 'password', 'remember_token', 'personal_key', 'deleted_at', 'created_at', 'image_id', 'tfa_totp_key', 'updated_at']; + protected $hidden = ['password', 'remember_token', 'personal_key', 'deleted_at', 'created_at', 'image_id', 'tfa_totp_key', 'updated_at', 'diet']; public function getPublicId() { @@ -440,4 +442,12 @@ public function helperReminderSubscriptions() return $this->belongsTo('Proto\Models\HelperReminder'); } + public function getIsMemberAttribute() { + return $this->member !== null; + } + + public function getPhotoPreviewAttribute() { + return $this->generatePhotoPath(); + } + } diff --git a/bower.json b/bower.json index 5ce7f6409..810449508 100755 --- a/bower.json +++ b/bower.json @@ -27,7 +27,8 @@ "Croppie": "croppie#^2.3.0", "jquery-dateFormat": "^1.0.2", "angular": "^1.6.4", - "TheaterJS": "theaterjs#^3.1.0" + "TheaterJS": "theaterjs#^3.1.0", + "select2": "~4.0" }, "devDependencies": { "font-awesome": "^4.6.3", diff --git a/composer.lock b/composer.lock index 54484e347..0dccac693 100755 --- a/composer.lock +++ b/composer.lock @@ -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": "9791a4c02ce67f1110a241785d3869b4", + "content-hash": "f42d16b1c959e52ef39a7c862159e724", "packages": [ { "name": "aacotroneo/laravel-saml2", @@ -2359,6 +2359,71 @@ ], "time": "2017-09-24T14:21:39+00:00" }, + { + "name": "laravel/scout", + "version": "v4.0.3", + "source": { + "type": "git", + "url": "https://github.com/laravel/scout.git", + "reference": "297d9c5ef94c3f70e9c76b87a02d4b527698956e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/scout/zipball/297d9c5ef94c3f70e9c76b87a02d4b527698956e", + "reference": "297d9c5ef94c3f70e9c76b87a02d4b527698956e", + "shasum": "" + }, + "require": { + "illuminate/bus": "~5.4", + "illuminate/contracts": "~5.4", + "illuminate/database": "~5.4", + "illuminate/pagination": "~5.4", + "illuminate/queue": "~5.4", + "illuminate/support": "~5.4", + "php": ">=7.0" + }, + "require-dev": { + "algolia/algoliasearch-client-php": "^1.10", + "mockery/mockery": "~1.0", + "phpunit/phpunit": "~6.0" + }, + "suggest": { + "algolia/algoliasearch-client-php": "Required to use the Algolia engine (^1.10)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Scout\\ScoutServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Scout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Scout provides a driver based solution to searching your Eloquent models.", + "keywords": [ + "algolia", + "laravel", + "search" + ], + "time": "2018-03-16T18:00:44+00:00" + }, { "name": "laravelcollective/html", "version": "v5.5.4", @@ -5585,6 +5650,58 @@ "description": "Laravel 5 Service Provider for the SimplePie library", "time": "2018-02-08T04:35:37+00:00" }, + { + "name": "yab/laravel-scout-mysql-driver", + "version": "v2.0.3", + "source": { + "type": "git", + "url": "https://github.com/YABhq/laravel-scout-mysql-driver.git", + "reference": "3f9cf88098265d36e158c595b25e3aa4a99e106d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/YABhq/laravel-scout-mysql-driver/zipball/3f9cf88098265d36e158c595b25e3aa4a99e106d", + "reference": "3f9cf88098265d36e158c595b25e3aa4a99e106d", + "shasum": "" + }, + "require": { + "laravel/framework": "5.3.*|5.4.*|5.5.*|5.6.*", + "laravel/scout": "^2.0|^3.0|^4.0", + "php": ">=5.6.4" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "Yab\\MySQLScout\\Providers\\MySQLScoutServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Yab\\MySQLScout\\": "src/" + }, + "files": [ + "src/helpers.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Lantz", + "email": "matt@yabhq.com" + }, + { + "name": "Damian Crisafulli", + "email": "damian.crisafulli@troyweb.com" + } + ], + "description": "MySQL driver for Laravel Scout.", + "time": "2018-02-17T11:47:40+00:00" + }, { "name": "zendframework/zend-diactoros", "version": "1.7.1", diff --git a/package.json b/package.json index 7eed0c7ab..6bb1d230c 100755 --- a/package.json +++ b/package.json @@ -64,7 +64,8 @@ "./resources/assets/bower/chocolat/dist/js/jquery.chocolat.min.js", "./resources/assets/bower/Croppie/croppie.min.js", "./resources/assets/bower/ng-img-crop/compile/minified/ng-img-crop.js", - "./resources/assets/bower/jquery-dateFormat/dist/jquery-dateFormat.min.js" + "./resources/assets/bower/jquery-dateFormat/dist/jquery-dateFormat.min.js", + "./resources/assets/bower/select2/dist/js/select2.full.min.js" ], "dest": "application.js", "destmin": "application.min.js", @@ -92,7 +93,8 @@ "./resources/assets/bower/on-screen-keyboard/onScreenKeyboard.css", "./resources/assets/bower/chocolat/dist/css/chocolat.css", "./resources/assets/bower/Croppie/croppie.css", - "./resources/assets/bower/ng-img-crop/compile/minifiedo/ng-img-crop.css" + "./resources/assets/bower/ng-img-crop/compile/minifiedo/ng-img-crop.css", + "./resources/assets/bower/select2/dist/css/select2.min.css" ], "dest": "./resources/assets/sass/components.scss", "watch": [ diff --git a/resources/views/achievement/manage.blade.php b/resources/views/achievement/manage.blade.php index 3abc5d74c..f48c2dc0d 100755 --- a/resources/views/achievement/manage.blade.php +++ b/resources/views/achievement/manage.blade.php @@ -227,15 +227,8 @@
-
- - -
-
- +
+
@@ -311,49 +304,4 @@ class="btn btn-danger">
-@endsection - -@section('javascript') - - @parent - - - - - - - - - - - - @endsection \ No newline at end of file diff --git a/resources/views/aliases/add.blade.php b/resources/views/aliases/add.blade.php index 161e9d1d2..c06ebc60e 100755 --- a/resources/views/aliases/add.blade.php +++ b/resources/views/aliases/add.blade.php @@ -25,12 +25,7 @@ - @endsection diff --git a/resources/views/authorization/overview.blade.php b/resources/views/authorization/overview.blade.php index 6c1310830..9b02afede 100755 --- a/resources/views/authorization/overview.blade.php +++ b/resources/views/authorization/overview.blade.php @@ -77,14 +77,10 @@ @endforeach - + +
+ {!! csrf_field() !!} diff --git a/resources/views/committee/edit.blade.php b/resources/views/committee/edit.blade.php index 97046bec1..eb1df435e 100755 --- a/resources/views/committee/edit.blade.php +++ b/resources/views/committee/edit.blade.php @@ -51,28 +51,6 @@ }) - - - - - - - -@endsection - @section('stylesheet') @parent diff --git a/resources/views/event/edit.blade.php b/resources/views/event/edit.blade.php index 5967521cd..d885b91ef 100755 --- a/resources/views/event/edit.blade.php +++ b/resources/views/event/edit.blade.php @@ -52,14 +52,8 @@
- + {!! $event && $event->committee ? sprintf('
%s', $event->committee->name) : '' !!} +
@@ -394,12 +388,7 @@ class="btn btn-default pull-right">Cancel
- +
diff --git a/resources/views/omnomcom/orders/adminhistory.blade.php b/resources/views/omnomcom/orders/adminhistory.blade.php index 259c8c878..0800f947f 100755 --- a/resources/views/omnomcom/orders/adminhistory.blade.php +++ b/resources/views/omnomcom/orders/adminhistory.blade.php @@ -10,6 +10,42 @@
+
+ + {!! csrf_field() !!} + +
+ +
+ + Add simple orderline + +
+ +
+
+ + +
+
+ + +
+
+ + + +
+ +
+ + +
@@ -49,9 +85,6 @@ -
@@ -118,7 +151,7 @@ style="margin-left: 10px;" href="{{ ($orderline->isPayed() ? '#' : route('omnomcom::orders::delete', ['id' => $orderline->id])) }}" role="button" - onclick="javascript:return confirm('You are about to delete an onrderline for {{ $orderline->user->name }}. Are you sure? ');" + onclick="javascript:return confirm('You are about to delete an orderline for {{ $orderline->user->name }}. Are you sure? ');" {{ ($orderline->isPayed() ? 'disabled' : '') }}> @@ -182,7 +215,7 @@
- @foreach(Proto\Models\User::orderBy('name', 'asc')->has('member')->get() as $user) - - @endforeach - - -
- -
- - - -
- -
- -
- - x -
- -
- -
- -
- - -
- -
- -
- - - -
- -
- -
- - -
- - - - - - - @endsection @section('javascript') diff --git a/resources/views/tempadmin/edit.blade.php b/resources/views/tempadmin/edit.blade.php index cdfbaf99d..c72791ea2 100755 --- a/resources/views/tempadmin/edit.blade.php +++ b/resources/views/tempadmin/edit.blade.php @@ -25,17 +25,8 @@
@if($new) -
- - - - - +
+
@else
@@ -64,43 +55,4 @@ -@endsection - -@section('javascript') - - @parent - - - - - @endsection \ No newline at end of file diff --git a/resources/views/tickets/edit.blade.php b/resources/views/tickets/edit.blade.php index e21ecd1f8..cfb2cfdb9 100755 --- a/resources/views/tickets/edit.blade.php +++ b/resources/views/tickets/edit.blade.php @@ -18,28 +18,12 @@
- +
- +
diff --git a/resources/views/website/layouts/assets/globalcss.scss b/resources/views/website/layouts/assets/globalcss.scss new file mode 100644 index 000000000..a683a9455 --- /dev/null +++ b/resources/views/website/layouts/assets/globalcss.scss @@ -0,0 +1,4 @@ +.select2-selection { + border-color: #ccc !important; + border-radius: 0 !important; +} \ No newline at end of file diff --git a/resources/views/website/layouts/assets/javascripts.blade.php b/resources/views/website/layouts/assets/javascripts.blade.php index 2a11374f3..fef19bb52 100755 --- a/resources/views/website/layouts/assets/javascripts.blade.php +++ b/resources/views/website/layouts/assets/javascripts.blade.php @@ -87,4 +87,194 @@ function initSlack(countRoute, inviteRoute) { s.parentNode.insertBefore(g, s); })(); - \ No newline at end of file + + +@if(Auth::user() && Auth::user()->can('admin')) + +@endif \ No newline at end of file diff --git a/resources/views/welcomemessages/addmessage.blade.php b/resources/views/welcomemessages/addmessage.blade.php index 4f2b1472d..ccabda9f1 100755 --- a/resources/views/welcomemessages/addmessage.blade.php +++ b/resources/views/welcomemessages/addmessage.blade.php @@ -4,17 +4,12 @@
-
- - -
-
- -
+
- +
@@ -26,32 +21,4 @@
- - -@section('javascript') - - @parent - - - - - -@endsection \ No newline at end of file + \ No newline at end of file diff --git a/routes/api.php b/routes/api.php index e68273e27..2fabf09cc 100755 --- a/routes/api.php +++ b/routes/api.php @@ -24,7 +24,6 @@ Route::get('timetable/boardroom', ['as' => 'timetable::boardroom', 'uses' => 'SmartXpScreenController@boardroomTimetable']); Route::get('timetable/protopeners', ['as' => 'timetable::protopeners', 'uses' => 'SmartXpScreenController@protopenersTimetable']); Route::get('timetable/smartxp', ['as' => 'timetable::smartxp', 'uses' => 'SmartXpScreenController@smartxpTimetable']); - Route::get('members', ['as' => 'members', 'uses' => 'ApiController@members']); Route::get('narrowcasting', ['as' => 'narrowcasting', 'uses' => 'NarrowcastingController@indexApi']); Route::get('token', ['as' => 'token', 'uses' => 'ApiController@getToken']); @@ -52,6 +51,13 @@ Route::get('dmx_values', ['as', 'dmx_values', 'uses' => 'DmxController@valueApi']); + Route::group(['prefix' => 'search', 'as' => 'search::', 'middleware' => ['auth', 'permission:board']], function () { + Route::get('user', ['as' => 'user', 'uses' => 'SearchController@getUserSearch']); + Route::get('committee', ['as' => 'committee', 'uses' => 'SearchController@getCommitteeSearch']); + Route::get('event', ['as' => 'event', 'uses' => 'SearchController@getEventSearch']); + Route::get('product', ['as' => 'product', 'uses' => 'SearchController@getProductSearch']); + }); + }); Route::group(['prefix' => 'user', 'middleware' => ['auth:api']], function () { diff --git a/routes/web.php b/routes/web.php index 1ff7e956c..271638000 100755 --- a/routes/web.php +++ b/routes/web.php @@ -499,6 +499,7 @@ Route::get('history/{user_id?}/{date?}', ['as' => 'list', 'uses' => 'OrderLineController@index']); Route::post('add/bulk', ['as' => 'addbulk', 'middleware' => ['permission:omnomcom'], 'uses' => 'OrderLineController@bulkStore']); + Route::post('add/single', ['as' => 'add', 'middleware' => ['permission:omnomcom'], 'uses' => 'OrderLineController@store']); Route::get('delete/{id}', ['as' => 'delete', 'middleware' => ['permission:omnomcom'], 'uses' => 'OrderLineController@destroy']); });