├── LICENSE ├── app ├── Commands │ └── PublishCommand.php ├── Controllers │ ├── Admin │ │ ├── CategoriesController.php │ │ ├── FAQsController.php │ │ └── OrderController.php │ └── Website │ │ └── FAQController.php ├── FAQServiceProvider.php └── Models │ ├── FAQ.php │ └── FaqCategory.php ├── composer.json ├── database ├── migrations │ ├── 2017_07_08_094112_create_faq_categories_table.php │ └── 2017_07_08_102625_create_faqs_table.php └── seeds │ └── FAQTableSeeder.php ├── readme.md └── resources └── views ├── admin ├── categories │ ├── create_edit.blade.php │ └── index.blade.php ├── create_edit.blade.php ├── index.blade.php ├── order.blade.php └── show.blade.php └── website └── faq.blade.php /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ben-Piet O'Callaghan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /app/Commands/PublishCommand.php: -------------------------------------------------------------------------------- 1 | filesystem = $filesystem; 44 | 45 | $this->basePath = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR; 46 | } 47 | 48 | /** 49 | * Execute the command 50 | */ 51 | public function handle() 52 | { 53 | $filesToPublish = $this->option('files'); 54 | 55 | switch ($filesToPublish) { 56 | case 'database': 57 | $this->copyDatabase(); 58 | break; 59 | case 'all': 60 | $this->copyModels(); 61 | $this->copyViews(); 62 | $this->copyControllers(); 63 | break; 64 | } 65 | 66 | $this->info("All files have been copied to your application."); 67 | } 68 | 69 | /** 70 | * Replace the default directory seperator with the 71 | * computer's directory seperator (windows, mac, linux) 72 | * @param $path 73 | * @return mixed 74 | */ 75 | private function formatFilePath($path) 76 | { 77 | return str_replace('\\', DIRECTORY_SEPARATOR, $path); 78 | } 79 | 80 | /** 81 | * Copy the models files 82 | */ 83 | private function copyModels() 84 | { 85 | $source = $this->basePath . "app\Models"; 86 | $destination = app_path('Models'); 87 | 88 | // copy files 89 | $search = "namespace Bpocallaghan\FAQ\Models;"; 90 | $replace = "namespace App\Models;"; 91 | $this->copyFilesFromSource($source, $destination, $search, $replace); 92 | } 93 | 94 | /** 95 | * Copy the view files 96 | */ 97 | private function copyViews() 98 | { 99 | // ADMIN 100 | $source = $this->basePath . "resources\\views\admin"; 101 | $destination = resource_path('views\admin\faq'); 102 | $this->copyFilesFromSource($source, $destination); 103 | 104 | $source = $this->basePath . "resources\\views\admin\\categories"; 105 | $destination = resource_path('views\admin\faq\\categories'); 106 | $this->copyFilesFromSource($source, $destination); 107 | 108 | // WEBSITE 109 | $source = $this->basePath . "resources\\views\website"; 110 | $destination = resource_path('views\website\faq'); 111 | $this->copyFilesFromSource($source, $destination); 112 | } 113 | 114 | /** 115 | * Copy the controllers to the correct destinations 116 | */ 117 | private function copyControllers() 118 | { 119 | // ADMIN 120 | $source = $this->basePath . "app\Controllers\Admin"; 121 | $destination = app_path('Http\Controllers\Admin\FAQ'); 122 | 123 | // copy files 124 | $search = ["faq::", "Bpocallaghan\FAQ\Models", "namespace Bpocallaghan\FAQ\Controllers\Admin;"]; 125 | $replace = ["faq.", "App\Models", "namespace App\Http\Controllers\Admin\FAQ;"]; 126 | $this->copyFilesFromSource($source, $destination, $search, $replace); 127 | 128 | // WEBSITE 129 | $source = $this->basePath . "app\Controllers\Website"; 130 | $destination = app_path('Http\Controllers\Website'); 131 | 132 | // replace files 133 | $search = ["faq::", "Bpocallaghan\FAQ\Models", "namespace Bpocallaghan\FAQ\Controllers\Website;"]; 134 | $replace = ["faq.", "App\Models", "namespace App\Http\Controllers\Website;"]; 135 | $this->copyFilesFromSource($source, $destination, $search, $replace); 136 | } 137 | 138 | /** 139 | * Copy the database files 140 | */ 141 | private function copyDatabase() 142 | { 143 | // SEEDS 144 | $source = $this->basePath . "database\seeds"; 145 | $destination = database_path('seeds'); 146 | 147 | $search = "namespace Bpocallaghan\FAQ\Seeds;"; 148 | $this->copyFilesFromSource($source, $destination, $search); 149 | 150 | // MIGRATIONS 151 | $source = $this->basePath . "database\migrations"; 152 | $destination = database_path('migrations'); 153 | 154 | $search = "namespace Bpocallaghan\FAQ\Migrations;"; 155 | $this->copyFilesFromSource($source, $destination, $search); 156 | } 157 | 158 | /** 159 | * Copy files from the source to destination 160 | * @param $source 161 | * @param $destination 162 | * @param boolean $search 163 | * @param string $replace 164 | */ 165 | private function copyFilesFromSource($source, $destination, $search = false, $replace = "") 166 | { 167 | $source = $this->formatFilePath($source . DIRECTORY_SEPARATOR); 168 | $destination = $this->formatFilePath($destination . DIRECTORY_SEPARATOR); 169 | $files = collect($this->filesystem->files($source)); 170 | 171 | // can we override the existing files or not 172 | $override = $this->overrideExistingFiles($files, $destination); 173 | 174 | $files->map(function (SplFileInfo $file) use ( 175 | $source, 176 | $destination, 177 | $override, 178 | $search, 179 | $replace 180 | ) { 181 | 182 | $fileSource = $source . $file->getFilename(); 183 | $fileDestination = $destination . $file->getFilename(); 184 | 185 | // if not exist or if we can override the files 186 | if ($this->filesystem->exists($fileDestination) == false || $override == true) { 187 | 188 | // make all the directories 189 | $this->makeDirectory($fileDestination); 190 | 191 | // replace file namespace 192 | $stub = $this->filesystem->get($fileSource); 193 | 194 | if (is_string($search)) { 195 | $stub = str_replace($search, $replace, $stub); 196 | } 197 | else if (is_array($search)) { 198 | foreach ($search as $k => $value) { 199 | $stub = str_replace($value, $replace[$k], $stub); 200 | } 201 | } 202 | 203 | $this->filesystem->put($fileDestination, $stub); 204 | 205 | // copy files 206 | //$this->filesystem->copy($fileSource, $fileDestination); 207 | $this->info("Copied: {$fileDestination}"); // {$file->getFilename()} 208 | } 209 | //dump($file->getFilename()); 210 | }); 211 | } 212 | 213 | /** 214 | * See if any files exist 215 | * Ask to override or not 216 | * @param Collection $files 217 | * @param $destination 218 | * @return bool 219 | */ 220 | private function overrideExistingFiles(Collection $files, $destination) 221 | { 222 | $answer = true; 223 | $filesFound = []; 224 | // map over to see if same filename already exist in destination 225 | $files->map(function (SplFileInfo $file) use ($destination, &$filesFound) { 226 | if ($this->filesystem->exists($destination . $file->getFilename())) { 227 | $filesFound [] = $file->getFilename(); 228 | } 229 | }); 230 | 231 | // if files found 232 | if (count($filesFound) >= 1) { 233 | dump($filesFound); 234 | 235 | $this->info("Destination: " . $destination); 236 | $answer = $this->confirm("Above is a list of the files already exist. Override all files?"); 237 | } 238 | 239 | return $answer; 240 | } 241 | 242 | /** 243 | * Build the directory for the class if necessary. 244 | * 245 | * @param string $path 246 | * @return string 247 | */ 248 | protected function makeDirectory($path) 249 | { 250 | if (!$this->filesystem->isDirectory(dirname($path))) { 251 | $this->filesystem->makeDirectory(dirname($path), 0777, true, true); 252 | } 253 | 254 | return $path; 255 | } 256 | 257 | /** 258 | * Get the console command options. 259 | * 260 | * @return array 261 | */ 262 | protected function getOptions() 263 | { 264 | return [ 265 | [ 266 | 'files', 267 | null, 268 | InputOption::VALUE_OPTIONAL, 269 | 'Which files must be published (database, all)', 270 | 'database' 271 | ], 272 | ]; 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /app/Controllers/Admin/CategoriesController.php: -------------------------------------------------------------------------------- 1 | view('faq::categories.index')->with('items', FaqCategory::all()); 23 | } 24 | 25 | /** 26 | * Show the form for creating a new faq_category. 27 | * 28 | * @return Response 29 | */ 30 | public function create() 31 | { 32 | return $this->view('faq::categories.create_edit'); 33 | } 34 | 35 | /** 36 | * Store a newly created faq_category in storage. 37 | * 38 | * @param Request $request 39 | * @return Response 40 | */ 41 | public function store(Request $request) 42 | { 43 | $this->validate($request, FaqCategory::$rules, FaqCategory::$messages); 44 | 45 | $this->createEntry(FaqCategory::class, $request->only('name')); 46 | 47 | return redirect_to_resource(); 48 | } 49 | 50 | /** 51 | * Display the specified faq_category. 52 | * 53 | * @param FaqCategory $category 54 | * @return Response 55 | */ 56 | public function show(FaqCategory $category) 57 | { 58 | return $this->view('faq::.categories.show')->with('item', $category); 59 | } 60 | 61 | /** 62 | * Show the form for editing the specified faq_category. 63 | * 64 | * @param FaqCategory $category 65 | * @return Response 66 | */ 67 | public function edit(FaqCategory $category) 68 | { 69 | return $this->view('faq::categories.create_edit')->with('item', $category); 70 | } 71 | 72 | /** 73 | * Update the specified faq_category in storage. 74 | * 75 | * @param FaqCategory $category 76 | * @param Request $request 77 | * @return Response 78 | */ 79 | public function update(FaqCategory $category, Request $request) 80 | { 81 | $this->validate($request, FaqCategory::$rules, FaqCategory::$messages); 82 | 83 | $this->updateEntry($category, $request->only('name')); 84 | 85 | return redirect_to_resource(); 86 | } 87 | 88 | /** 89 | * Remove the specified faq_category from storage. 90 | * 91 | * @param FaqCategory $category 92 | * @param Request $request 93 | * @return Response 94 | */ 95 | public function destroy(FaqCategory $category, Request $request) 96 | { 97 | $this->deleteEntry($category, $request); 98 | 99 | return redirect_to_resource(); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /app/Controllers/Admin/FAQsController.php: -------------------------------------------------------------------------------- 1 | get(); 23 | 24 | return $this->view('faq::index')->with('items', $items); 25 | } 26 | 27 | /** 28 | * Show the form for creating a new faq. 29 | * 30 | * @return Response 31 | */ 32 | public function create() 33 | { 34 | $categories = FaqCategory::getAllList(); 35 | 36 | return $this->view('faq::create_edit', compact('categories')); 37 | } 38 | 39 | /** 40 | * Store a newly created faq in storage. 41 | * 42 | * @param Request $request 43 | * @return Response 44 | */ 45 | public function store(Request $request) 46 | { 47 | $this->validate($request, FAQ::$rules, FAQ::$messages); 48 | 49 | $this->createEntry(FAQ::class, $request->only('question', 'answer', 'category_id')); 50 | 51 | return redirect_to_resource(); 52 | } 53 | 54 | /** 55 | * Display the specified faq. 56 | * 57 | * @param FAQ $faq 58 | * @return Response 59 | */ 60 | public function show(FAQ $faq) 61 | { 62 | return $this->view('faq::show')->with('item', $faq); 63 | } 64 | 65 | /** 66 | * Show the form for editing the specified faq. 67 | * 68 | * @param FAQ $faq 69 | * @return Response 70 | */ 71 | public function edit(FAQ $faq) 72 | { 73 | $categories = FaqCategory::getAllList(); 74 | 75 | return $this->view('faq::create_edit', compact('categories'))->with('item', $faq); 76 | } 77 | 78 | /** 79 | * Update the specified faq in storage. 80 | * 81 | * @param FAQ $faq 82 | * @param Request $request 83 | * @return Response 84 | */ 85 | public function update(FAQ $faq, Request $request) 86 | { 87 | $this->validate($request, FAQ::$rules, FAQ::$messages); 88 | 89 | $this->updateEntry($faq, $request->only('question', 'answer', 'category_id')); 90 | 91 | return redirect_to_resource(); 92 | } 93 | 94 | /** 95 | * Remove the specified faq from storage. 96 | * 97 | * @param FAQ $faq 98 | * @param Request $request 99 | * @return Response 100 | */ 101 | public function destroy(FAQ $faq, Request $request) 102 | { 103 | $this->deleteEntry($faq, $request); 104 | 105 | return redirect_to_resource(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /app/Controllers/Admin/OrderController.php: -------------------------------------------------------------------------------- 1 | getOrderHtml(); 21 | 22 | return $this->view('faq::order')->with('itemsHtml', $html); 23 | } 24 | 25 | /** 26 | * Update the order 27 | * @param Request $request 28 | * @return array 29 | */ 30 | public function updateOrder(Request $request) 31 | { 32 | $navigation = json_decode($request->get('list'), true); 33 | 34 | foreach ($navigation as $key => $nav) { 35 | $row = $this->updateListOrder($nav['id'], ($key + 1)); 36 | } 37 | 38 | return ['result' => 'success']; 39 | } 40 | 41 | /** 42 | * Generate the nestable html 43 | * 44 | * @param null $parent 45 | * 46 | * @return string 47 | */ 48 | private function getOrderHtml($parent = null) 49 | { 50 | $html = '
    '; 51 | 52 | $items = FaqCategory::with('faqs')->orderBy('name')->get(); 53 | foreach ($items as $key => $item) { 54 | 55 | foreach ($item->faqs as $k => $faq) { 56 | $html .= '
  1. '; 57 | $html .= '
    '; 58 | $html .= '' . $item->name . ' - ' . $faq->question . ' ' . ' ' . $faq->answer_summary . '
    '; 59 | $html .= '
  2. '; 60 | } 61 | 62 | $html .= '
    '; 63 | } 64 | 65 | $html .= '
'; 66 | 67 | return (count($items) >= 1 ? $html : ''); 68 | } 69 | 70 | /** 71 | * Update Navigation Item, with new list order and parent id (list and parent can change) 72 | * 73 | * @param $id 74 | * @param $listOrder 75 | * @param int $parentId 76 | * 77 | * @return mixed 78 | */ 79 | private function updateListOrder($id, $listOrder, $parentId = 0) 80 | { 81 | $row = FAQ::find($id); 82 | $row->list_order = $listOrder; 83 | $row->save(); 84 | 85 | return $row; 86 | } 87 | } -------------------------------------------------------------------------------- /app/Controllers/Website/FAQController.php: -------------------------------------------------------------------------------- 1 | orderBy('name')->get(); 17 | 18 | return $this->view('faq::faq', compact('items', 'categories')); 19 | } 20 | 21 | /** 22 | * Increments the total views 23 | * @param FAQ $faq 24 | * @param string $type 25 | * @return \Illuminate\Http\JsonResponse 26 | */ 27 | public function incrementClick(FAQ $faq, $type = 'total_read') 28 | { 29 | if ($type == 'total_read' || $type == 'helpful_yes' || $type == 'helpful_no') { 30 | $faq->increment($type); 31 | } 32 | 33 | return json_response(''); 34 | } 35 | } -------------------------------------------------------------------------------- /app/FAQServiceProvider.php: -------------------------------------------------------------------------------- 1 | loadViewsFrom(__DIR__ . '/../resources/views', 'faq'); 18 | 19 | $this->registerCommand(PublishCommand::class, 'publish'); 20 | } 21 | 22 | /** 23 | * Register a singleton command 24 | * 25 | * @param $class 26 | * @param $command 27 | */ 28 | private function registerCommand($class, $command) 29 | { 30 | $path = 'bpocallaghan.faq.commands.'; 31 | $this->app->singleton($path . $command, function ($app) use ($class) { 32 | return $app[$class]; 33 | }); 34 | 35 | $this->commands($path . $command); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/Models/FAQ.php: -------------------------------------------------------------------------------- 1 | 'required|min:3:max:255', 23 | 'answer' => 'required|min:5:max:1500', 24 | 'category_id' => 'required|exists:faq_categories,id', 25 | ]; 26 | 27 | protected function getSlugOptions() 28 | { 29 | return SlugOptions::create()->generateSlugFrom('question'); 30 | } 31 | 32 | /** 33 | * Get the summary text 34 | * 35 | * @return mixed 36 | */ 37 | public function getAnswerSummaryAttribute() 38 | { 39 | return substr(strip_tags($this->attributes['answer']), 0, 80) . '...'; 40 | } 41 | 42 | /** 43 | * Get the category 44 | */ 45 | public function category() 46 | { 47 | return $this->belongsTo(FaqCategory::class, 'category_id', 'id'); 48 | } 49 | } -------------------------------------------------------------------------------- /app/Models/FaqCategory.php: -------------------------------------------------------------------------------- 1 | 'required|min:3:max:255', 22 | ]; 23 | 24 | /** 25 | * Get the faqs 26 | */ 27 | public function faqs() 28 | { 29 | return $this->hasMany(FAQ::class, 'category_id')->orderBy('list_order'); 30 | } 31 | 32 | /** 33 | * Get all the rows as an array (ready for dropdowns) 34 | * 35 | * @return array 36 | */ 37 | public static function getAllList() 38 | { 39 | return self::orderBy('name')->get()->pluck('name', 'id')->toArray(); 40 | } 41 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bpocallaghan/faq", 3 | "description": "Add Frequently Asked Questions to your laravel admin project - https://github.com/bpocallaghan/laravel-admin-starter", 4 | "keywords": [ 5 | "laravel", 6 | "admin", 7 | "cms", 8 | "faq", 9 | "frequently asked questions" 10 | ], 11 | "license": "MIT", 12 | "authors": [ 13 | { 14 | "name": "Ben-Piet O'Callaghan", 15 | "email": "bpocallaghan@gmail.com" 16 | } 17 | ], 18 | "require": { 19 | "php": ">=7.0.0" 20 | }, 21 | "autoload": { 22 | "psr-4": { 23 | "Bpocallaghan\\FAQ\\": "app/" 24 | } 25 | }, 26 | "extra": { 27 | "laravel": { 28 | "providers": [ 29 | "Bpocallaghan\\FAQ\\FAQServiceProvider" 30 | ] 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /database/migrations/2017_07_08_094112_create_faq_categories_table.php: -------------------------------------------------------------------------------- 1 | increments('id')->unique()->index(); 19 | $table->string('name')->index(); 20 | $table->string('slug'); 21 | $table->timestamps(); 22 | $table->softDeletes(); 23 | $table->integer('created_by')->unsigned(); 24 | $table->integer('updated_by')->unsigned()->nullable(); 25 | $table->integer('deleted_by')->unsigned()->nullable(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::drop('faq_categories'); 37 | } 38 | } -------------------------------------------------------------------------------- /database/migrations/2017_07_08_102625_create_faqs_table.php: -------------------------------------------------------------------------------- 1 | increments('id')->unique()->index(); 19 | $table->string('question')->index(); 20 | $table->string('slug')->index(); 21 | $table->text('answer'); 22 | $table->unsignedBigInteger('total_read')->default(0); 23 | $table->unsignedBigInteger('helpful_yes')->default(0); 24 | $table->unsignedBigInteger('helpful_no')->default(0); 25 | $table->unsignedBigInteger('category_id')->index(); 26 | $table->unsignedBigInteger('list_order')->nullable(); 27 | $table->timestamps(); 28 | $table->softDeletes(); 29 | $table->integer('created_by')->unsigned(); 30 | $table->integer('updated_by')->unsigned()->nullable(); 31 | $table->integer('deleted_by')->unsigned()->nullable(); 32 | }); 33 | } 34 | 35 | /** 36 | * Reverse the migrations. 37 | * 38 | * @return void 39 | */ 40 | public function down() 41 | { 42 | Schema::drop('faqs'); 43 | } 44 | } -------------------------------------------------------------------------------- /database/seeds/FAQTableSeeder.php: -------------------------------------------------------------------------------- 1 | $faker->sentence(2) 19 | ]); 20 | 21 | for ($a = 0; $a < $faker->numberBetween(3, 8); $a++) { 22 | $item->faqs()->create([ 23 | 'question' => $faker->sentence(8), 24 | 'answer' => $faker->paragraph(3), 25 | ]); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Frequently Asked Questions 2 | This will add faq questions and answers to your laravel project. 3 | The questions have a 'total views', 'total helpful' and 'total not helpful' counters. 4 | 5 | ## Installation 6 | Update your project's `composer.json` file. 7 | 8 | ```bash 9 | composer require bpocallaghan/faq 10 | ``` 11 | 12 | ## Usage 13 | 14 | Register the routes in the `routes/vendor.php` file. 15 | - Website 16 | ```bash 17 | Route::group(['prefix' => 'faq', 'namespace' => 'FAQ\Controllers\Website'], function () { 18 | Route::get('', 'FAQController@index'); 19 | Route::post('/question/{faq}/{type?}', 'FAQController@incrementClick'); 20 | }); 21 | ``` 22 | - Admin 23 | ```bash 24 | Route::group(['namespace' => 'FAQ\Controllers\Admin'], function () { 25 | Route::resource('/faqs/categories', 'CategoriesController'); 26 | Route::get('faqs/order', 'OrderController@index'); 27 | Route::post('faqs/order', 'OrderController@updateOrder'); 28 | Route::resource('/faqs', 'FAQsController'); 29 | }); 30 | ``` 31 | 32 | ## Commands 33 | ```bash 34 | php artisan faq:publish 35 | ``` 36 | This will copy the `database/seeds` and `database/migrations` to your application. 37 | Remember to add `$this->call(FAQTableSeeder::class);` in the `DatabaseSeeder.php` 38 | 39 | ```bash 40 | php artisan faq:publish --files=all 41 | ``` 42 | This will copy the `model, views and controller` to their respective directories. 43 | Please note when you execute the above command. You need to update your `routes`. 44 | - Website 45 | ```bash 46 | Route::get('/faq', 'FAQController@index'); 47 | Route::post('/faq/question/{faq}/{type?}', 'FAQController@incrementClick'); 48 | ``` 49 | - Admin 50 | ```bash 51 | Route::group(['namespace' => 'FAQ'], function () { 52 | Route::resource('/faqs/categories', 'CategoriesController'); 53 | Route::get('faqs/order', 'OrderController@index'); 54 | Route::post('faqs/order', 'OrderController@updateOrder'); 55 | Route::resource('/faqs', 'FaqsController'); 56 | }); 57 | ``` 58 | 59 | ## Demo 60 | Package is being used at [Laravel Admin Starter](https://github.com/bpocallaghan/laravel-admin-starter) project. 61 | 62 | ### TODO 63 | - add the navigation seeder information (to create the navigation/urls) -------------------------------------------------------------------------------- /resources/views/admin/categories/create_edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | {{ isset($item)? 'Edit the ' . $item->title . ' entry': 'Create a new Faq Category' }} 11 |

12 |
13 |
14 | 15 | @include('titan::admin.partials.info') 16 | 17 |
id}" : '')}}" accept-charset="UTF-8"> 18 | 19 | 20 | 21 |
22 |
23 |
24 |
25 | 26 | 27 | {!! form_error_message('name', $errors) !!} 28 |
29 |
30 |
31 |
32 | 33 | @include('titan::admin.partials.form_footer') 34 |
35 |
36 |
37 |
38 |
39 | @endsection -------------------------------------------------------------------------------- /resources/views/admin/categories/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | List All Faq Categories 11 |

12 |
13 | 14 |
15 | 16 | @include('titan::admin.partials.info') 17 | 18 | @include('titan::admin.partials.toolbar') 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | @foreach ($items as $item) 31 | 32 | 33 | 34 | 35 | 36 | 37 | @endforeach 38 | 39 |
NameSlugCreatedAction
{{ $item->name }}{{ $item->slug }}{{ format_date($item->created_at) }}{!! action_row($selectedNavigation->url, $item->id, $item->name, ['edit', 'delete']) !!}
40 |
41 |
42 |
43 |
44 | @endsection -------------------------------------------------------------------------------- /resources/views/admin/create_edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | {{ isset($item)? 'Edit the ' . $item->question . ' entry': 'Create a new FAQ' }} 11 |

12 |
13 | 14 |
15 | 16 | @include('titan::admin.partials.info') 17 | 18 |
id}" : '')}}" accept-charset="UTF-8" enctype="multipart/form-data"> 19 | 20 | 21 | 22 |
23 |
24 |
25 |
26 | 27 | 28 | {!! form_error_message('question', $errors) !!} 29 |
30 |
31 |
32 |
33 | 34 | {!! form_select('category_id', ([0 => 'Please select a Category'] + $categories), ($errors && $errors->any()? old('category_id') : (isset($item)? $item->category_id : '')), ['class' => 'select2 form-control']) !!} 35 | {!! form_error_message('category_id', $errors) !!} 36 |
37 |
38 |
39 | 40 |
41 | 42 | 43 | {!! form_error_message('answer', $errors) !!} 44 |
45 |
46 | 47 | @include('titan::admin.partials.form_footer') 48 |
49 |
50 |
51 |
52 |
53 | @endsection 54 | 55 | @section('scripts') 56 | @parent 57 | 69 | @endsection 70 | -------------------------------------------------------------------------------- /resources/views/admin/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | List All Faqs 11 |

12 |
13 | 14 |
15 | 16 | @include('titan::admin.partials.info') 17 | 18 | @include('titan::admin.partials.toolbar', ['order' => true]) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | @foreach ($items as $item) 33 | 34 | 35 | 36 | 37 | 42 | 43 | 44 | 45 | @endforeach 46 | 47 |
QuestionAnswerCategoryTotalsUpdatedAction
{{ $item->question }}{!! $item->answer_summary !!}{!! $item->category->name !!} 38 | {{ $item->total_read }} 39 | {{ $item->helpful_yes }} 40 | {{ $item->helpful_no }} 41 | {{ format_date($item->updated_at) }}{!! action_row($selectedNavigation->url, $item->id, $item->title, ['show', 'edit', 'delete']) !!}
48 |
49 |
50 |
51 |
52 | @endsection -------------------------------------------------------------------------------- /resources/views/admin/order.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | Update {{ ucfirst($resource) }} List Order 11 |

12 |
13 | 14 |
15 | 16 | @include('titan::admin.partials.info') 17 | 18 |
19 | 20 | Back 21 | 22 | 23 | 27 | 28 | 32 |
33 | 34 |
35 |
36 |
37 | {!! $itemsHtml !!} 38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | 46 | @include('titan::admin.partials.nestable') 47 | @endsection 48 | 49 | @section('scripts') 50 | @parent 51 | 57 | @endsection -------------------------------------------------------------------------------- /resources/views/admin/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('titan::layouts.admin') 2 | 3 | @section('content') 4 |
5 |
6 |
7 |
8 |

9 | 10 | FAQ - {{ $item->question }} 11 |

12 |
13 | 14 |
15 | 16 | @include('titan::admin.partials.info') 17 | 18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 | 26 | 27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 | 35 |
36 |
37 |
38 | 39 |
40 | 41 |
42 | {!! $item->answer !!} 43 |
44 |
45 |
46 | 47 | @include('titan::admin.partials.form_footer', ['submit' => false]) 48 |
49 |
50 |
51 |
52 |
53 | @endsection -------------------------------------------------------------------------------- /resources/views/website/faq.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layouts.website') 2 | 3 | @section('content') 4 |
5 | @include('website.partials.page_header') 6 | 7 |
8 |
9 | @include('website.partials.breadcrumb') 10 | 11 |
12 |
13 | @foreach($items as $category) 14 |

{!! $category->name !!}

15 |
16 | @foreach($category->faqs as $faq) 17 | 18 |
19 |
20 |

21 | {!! $faq->question !!} 22 |

23 |
24 |
25 |
26 | {!! $faq->answer !!} 27 |
28 | 39 |
40 |
41 | 42 | @endforeach 43 |
44 | @endforeach 45 |
46 |
47 |
48 | 49 | @include('website.partials.page_side') 50 |
51 |
52 | @endsection 53 | 54 | @section('scripts') 55 | @parent 56 | 83 | @endsection --------------------------------------------------------------------------------