diff --git a/README.md b/README.md index 81f2f62ba99fae61f50a9b32afcf99aec1884485..4979c493e7d7c9f0251f39a291877ea69272d16f 100644 --- a/README.md +++ b/README.md @@ -1,78 +1,90 @@ -<p align="center"><img src="https://res.cloudinary.com/dtfbvvkyp/image/upload/v1566331377/laravel-logolockup-cmyk-red.svg" width="400"></p> - -<p align="center"> -<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a> -<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/d/total.svg" alt="Total Downloads"></a> -<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/v/stable.svg" alt="Latest Stable Version"></a> -<a href="https://packagist.org/packages/laravel/framework"><img src="https://poser.pugx.org/laravel/framework/license.svg" alt="License"></a> -</p> - -## About Laravel - -Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: - -- [Simple, fast routing engine](https://laravel.com/docs/routing). -- [Powerful dependency injection container](https://laravel.com/docs/container). -- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. -- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). -- Database agnostic [schema migrations](https://laravel.com/docs/migrations). -- [Robust background job processing](https://laravel.com/docs/queues). -- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). - -Laravel is accessible, powerful, and provides tools required for large, robust applications. - -## Learning Laravel - -Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. - -If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. - -## Laravel Sponsors - -We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell). - -- **[Vehikl](https://vehikl.com/)** -- **[Tighten Co.](https://tighten.co)** -- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** -- **[64 Robots](https://64robots.com)** -- **[Cubet Techno Labs](https://cubettech.com)** -- **[Cyber-Duck](https://cyber-duck.co.uk)** -- **[British Software Development](https://www.britishsoftware.co)** -- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)** -- **[DevSquad](https://devsquad.com)** -- [UserInsights](https://userinsights.com) -- [Fragrantica](https://www.fragrantica.com) -- [SOFTonSOFA](https://softonsofa.com/) -- [User10](https://user10.com) -- [Soumettre.fr](https://soumettre.fr/) -- [CodeBrisk](https://codebrisk.com) -- [1Forge](https://1forge.com) -- [TECPRESSO](https://tecpresso.co.jp/) -- [Runtime Converter](http://runtimeconverter.com/) -- [WebL'Agence](https://weblagence.com/) -- [Invoice Ninja](https://www.invoiceninja.com) -- [iMi digital](https://www.imi-digital.de/) -- [Earthlink](https://www.earthlink.ro/) -- [Steadfast Collective](https://steadfastcollective.com/) -- [We Are The Robots Inc.](https://watr.mx/) -- [Understand.io](https://www.understand.io/) -- [Abdel Elrafa](https://abdelelrafa.com) -- [Hyper Host](https://hyper.host) -- [Appoly](https://www.appoly.co.uk) -- [OP.GG](https://op.gg) - -## Contributing - -Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). - -## Code of Conduct - -In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). - -## Security Vulnerabilities - -If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. - -## License - -The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). +# Datalearn + +Datalearn is simple LMS with spreadsheet and autograder tools. It uses Google Spreadsheet with Sheets and Drive API. This application is developed for my final project. + +## Tech Stack +- Framework used is **Laravel 6.18.3** with **PHP 7** +- Database used is **MySQL** + +## Requirements +- PHP 7.4 or newer +- MySQL 10.4.11-MariaDB or newer +- Composer 1.9.3 or newer + +## Installation +1. Make a copy `.env.example` and change its name to `.env` +2. Customize `.env` file with your configuration +3. Create a new database with the same name as defined in `.env` file +4. Run these commands in terminal +``` +composer install +composer update +php artisan storage:link +php artisan key:generate +php artisan config:cache +php artisan migrate +``` +5. The application uses Google Spreadsheet. Configure the Google Service Account to use it +6. This application uses TinyMCE. Configure it +7. There are problems with the libraries. Fix it +8. Congratulation, the application has been successfully installed. Run the application with this command +``` +php artisan serve +``` + +## Configure Google Service Account +1. Open [Google API Console](https://console.developers.google.com) +2. Go to **Credentials tab** and open **CREATE CREDENTIALS --> Service Account** +3. Fill the forms in first step. Second step and third step are optional +4. After done, there is a service account that newly created under **Service Accounts** list. Open it +5. Click the button **ADD KEY** and choose **JSON** +6. Download the file and change its name to `credentials.json` +7. Move this file to project directory in `app/Http/Controllers` +8. Finish + +## Configure TinyMCE +1. Open [TinyMCE](https://www.tiny.cloud) +2. Complete the registration +3. After that, you got API Key in Dashboard +4. Copy the API Key and paste to `app.blade.php` file in project direcotry `resources/views/layouts` on `line 16` +```php +<script src="https://cdn.tiny.cloud/1/<API KEY>/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> +``` +5. Finish + +## Solve Libraries Problem +There are problems with the libraries. Do this step to solve the problems +### Problem 1 +#### Error +``` +ErrorException +implode(): Passing glue string after array is deprecated. Swap the parameters +``` +#### Solution +Open `Resouce.php` file in project directory `vendor/google/apiclient/src/Google/Service`. In `line 291`, change +```php +$requestUrl .= '?' . implode($queryVars, '&'); +``` +to +```php +$requestUrl .= '?' . implode('&', $queryVars); +``` + +### Problem 2 +#### Error +``` +ErrorException +count(): Parameter must be an array or an object that implements Countable +``` +#### Solution +Open `CurlFactory.php` file in project directory `vendor/guzzlehttp/guzzle/src/Handler`. In `line 67`, change +```php +if (count($this->handles) >= $this->maxHandles) { +``` +to +```php +if (count( (array) $this->handles) >= $this->maxHandles) { +``` + +## Author +Kurniandha Sukma Yunastrian \ No newline at end of file diff --git a/app/Http/Controllers/AutograderController.php b/app/Http/Controllers/AutograderController.php index 67993bd06f9bb10ca323b789792372abbc909099..6d7adb5a3a5f76fe7360981b4857e5a3c63041c2 100644 --- a/app/Http/Controllers/AutograderController.php +++ b/app/Http/Controllers/AutograderController.php @@ -42,10 +42,10 @@ class AutograderController extends Controller $answers_value = AutograderController::getStudentAnswer($request->id_spreadsheet, $cells, 1); $results_formula = AutograderController::gradeFormula($keys_formula, $answers_formula); - $results_value = AutograderController::gradeFormula($keys_value, $answers_value); + $results_value = AutograderController::gradeValue($keys_value, $answers_value); $results = []; for ($i=0; $i<count($results_formula); $i++) { - $results[] = ($results_formula[$i] + $results_value[$i])/2; + $results[] = $results_formula[$i]*0.8 + $results_value[$i]*0.2; } echo ' @@ -72,7 +72,7 @@ class AutograderController extends Controller echo '<td>' . $answers_formula[$i] . '</td>'; echo '<td>' . $keys_value[$i] . '</td>'; echo '<td>' . $answers_value[$i] . '</td>'; - echo '<td>' . $results[$i]*100 . '/100</td>'; + echo '<td>' . number_format($results[$i]*100, 2, '.', ''). '</td>'; echo '</tr>'; } echo ' @@ -82,7 +82,7 @@ class AutograderController extends Controller <td></td> <td></td> <th class="table-primary">Skor Akhir</th> - <th class="table-primary">' . $score/count($results) . '</th> + <th class="table-primary">' . number_format($score/count($results), 2, '.', '') . '</th> </tr> </tbody> </table> @@ -133,6 +133,15 @@ class AutograderController extends Controller $key_temp = preg_split("/[)\s,(-]+/", $keys[$i]); $answer_temp = preg_split("/[)\s,(-]+/", $answers[$i]); + $flag = 0; + $range_func = array("COUNTBLANK", "MDETERM", "MINVERSE", "SUMPRODUCT", "TRANSPOSE", "COLUMNS", "ROWS"); + foreach($range_func as $func) { + if (in_array('=' . $func, $answer_temp)) { + $flag = 1; + break; + } + } + $key = []; for($j=0; $j<count($key_temp); $j++) { if (!empty($key_temp[$j])) { @@ -143,7 +152,49 @@ class AutograderController extends Controller $answer = []; for($j=0; $j<count($answer_temp); $j++) { if (!empty($answer_temp[$j])) { - $answer[] = $answer_temp[$j]; + $array = str_split($answer_temp[$j]); + if (in_array(':', $array)) { + if ($flag == 0) { + $idx = strpos($answer_temp[$j], ":"); + + $row_start_temp = ''; + $column_start = 0; + for ($k=0; $k<$idx; $k++) { + if ($k == 0) { + $column_start = ord($array[$k]); + } else { + $row_start_temp .= $array[$k]; + } + } + $row_start = intval($row_start_temp); + + $row_end_temp = ''; + $column_end = 0; + for ($k=$idx+1; $k<count($array); $k++) { + if ($k == $idx+1) { + $column_end = ord($array[$k]); + } else { + $row_end_temp .= $array[$k]; + } + } + $row_end = intval($row_end_temp); + + $new_arr = []; + for ($k=$column_start; $k<=$column_end; $k++) { + for ($l=$row_start; $l<=$row_end; $l++) { + $new_arr[] = chr($k) . strval($l); + } + } + + foreach($new_arr as $n) { + $answer[] = $n; + } + } else { + $answer[] = $answer_temp[$j]; + } + } else { + $answer[] = $answer_temp[$j]; + } } } @@ -159,48 +210,52 @@ class AutograderController extends Controller * @return score */ public function cosine($key, $answer) { - $token = []; - $vector1 = []; - $vector2 = []; - foreach($key as $k) { - if (!in_array($k, $token)) { - $token[] = $k; - $vector1[] = 0; - $vector2[] = 0; + if (count($answer) == 0) { + return 0; + } else { + $token = []; + $vector1 = []; + $vector2 = []; + foreach($key as $k) { + if (!in_array($k, $token)) { + $token[] = $k; + $vector1[] = 0; + $vector2[] = 0; + } } - } - foreach($answer as $k) { - if (!in_array($k, $token)) { - $token[] = $k; - $vector1[] = 0; - $vector2[] = 0; + foreach($answer as $k) { + if (!in_array($k, $token)) { + $token[] = $k; + $vector1[] = 0; + $vector2[] = 0; + } } - } - foreach($key as $k) { - $vector1[array_search($k, $token)] += 1; - } - foreach($answer as $k) { - $vector2[array_search($k, $token)] += 1; - } + foreach($key as $k) { + $vector1[array_search($k, $token)] += 1; + } + foreach($answer as $k) { + $vector2[array_search($k, $token)] += 1; + } - $dot_product = 0; - for($i=0; $i<count($token); $i++) { - $dot_product += ($vector1[$i])*($vector2[$i]); - } + $dot_product = 0; + for($i=0; $i<count($token); $i++) { + $dot_product += ($vector1[$i])*($vector2[$i]); + } - $length1 = 0; - $length2 = 0; + $length1 = 0; + $length2 = 0; - for($i=0; $i<count($token); $i++) { - $length1 += pow($vector1[$i], 2); - $length2 += pow($vector2[$i], 2); - } + for($i=0; $i<count($token); $i++) { + $length1 += pow($vector1[$i], 2); + $length2 += pow($vector2[$i], 2); + } - $similarity = $dot_product/sqrt($length1*$length2); - - return $similarity; + $similarity = $dot_product/sqrt($length1*$length2); + + return $similarity; + } } /** diff --git a/app/Http/Controllers/CourseController.php b/app/Http/Controllers/CourseController.php index 6d8109cd61b6c416af84c51caca9ab254b08f7fa..d2ae817976400ea7f720de39b84fcb4343d22c5b 100644 --- a/app/Http/Controllers/CourseController.php +++ b/app/Http/Controllers/CourseController.php @@ -138,4 +138,49 @@ class CourseController extends Controller return redirect()->route('course', ['id_course' => $id_course, 'msg' => 4]); } + + /** + * Show grade + * + * @return grade + */ + public function grade($id_course) { + if (Auth::user()->role == 0) { + return redirect()->route('course', ['id_course' => $id_course, 'msg' => 6]); + } + + $enrolled_id = DB::table('user_course')->where('id_course', $id_course)->pluck('id_user'); + + $topics = DB::table('topics')->where('id_course', $id_course)->get(); + $name = []; + $ids = []; + $grades = []; + foreach($enrolled_id as $id) { + $user = DB::table('users')->where('id', $id)->first(); + + if ($user->role == 0) { + $name[] = $user->name; + $ids[] = $user->id; + + $usergrade = []; + foreach($topics as $topic) { + $grade = DB::table('grades')->where([ + ['id_course', '=' ,$id_course], + ['id_user', '=', $user->id], + ['id_topic', '=', $topic->id] + ])->first(); + + if (empty($grade)) { + $usergrade[] = '-'; + } else { + $usergrade[] = $grade->grade; + } + } + + $grades[] = $usergrade; + } + } + + return view('grade', ['topics' => $topics, 'names' => $name, 'grades' => $grades, 'id_course' => $id_course]); + } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index ad747df869ccc82454cd798f351bce00403f14de..c50e4d2b20fa6cc2b058faf5938523677b5974b3 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -42,7 +42,12 @@ class HomeController extends Controller $enrolled[] = DB::table('courses')->where('id', $id)->first(); } - return view('home', ['profile' => $profile, 'role' => $role, 'courses' => $courses, 'enrolled' => $enrolled]); + $image = 'student.png'; + if (Auth::user()->role == 1) { + $image = 'lecturer.png'; + } + + return view('home', ['image' => $image, 'profile' => $profile, 'role' => $role, 'courses' => $courses, 'enrolled' => $enrolled]); } /** diff --git a/app/Http/Controllers/LearnController.php b/app/Http/Controllers/LearnController.php index 1f5193d54094d11f54c2f2fc15ec80417d2a17c1..021bfba1fe41d93bb61c0f21a17bd48c91a79870 100644 --- a/app/Http/Controllers/LearnController.php +++ b/app/Http/Controllers/LearnController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\DB; +use Illuminate\Support\Facades\Auth; use Google_Client; class LearnController extends Controller @@ -25,6 +26,10 @@ class LearnController extends Controller */ public function index($id_course, $id_topic) { + if (Auth::user()->role == 1) { + return redirect()->route('course', ['id_course' => $id_course, 'msg' => 6]); + } + $topic = DB::table('topics')->where('id', $id_topic)->first(); $cells = DB::table('spreadsheets')->where('id', $id_topic)->get(); $ranges = []; @@ -127,7 +132,24 @@ class LearnController extends Controller */ public function edit($id_course, $id_topic) { + if (Auth::user()->role == 0) { + return redirect()->route('course', ['id_course' => $id_course, 'msg' => 6]); + } + + $enrolled = DB::table('user_course')->where('id_user', Auth::id())->get(); + + $flag = 0; $topic = DB::table('topics')->where('id', $id_topic)->first(); + foreach($enrolled as $enroll) { + if ($enroll->id_course == $id_course and $topic->id_course == $enroll->id_course) { + $flag = 1; + } + } + + if ($flag == 0) { + return redirect()->route('course', ['id_course' => $id_course, 'msg' => 6]); + } + $cells = DB::table('spreadsheets')->where('id', $id_topic)->get(); return view('edit', ['cells' => $cells, 'id_course' => $id_course, 'id_spreadsheet' => $topic->id_spreadsheet, 'topic' => $topic]); diff --git a/app/Http/Controllers/credentials.json b/app/Http/Controllers/credentials.json deleted file mode 100644 index f5377c7a8d2b71c2b14fd64803c5c691c1ea8031..0000000000000000000000000000000000000000 --- a/app/Http/Controllers/credentials.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "type": "service_account", - "project_id": "datalearn", - "private_key_id": "049b061b5b9de5f1f32142109307deb932917eea", - "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCUa1lxNZ82CwFu\n48ndNtYB9MRwGLVy7OeE2S8m/WiMpXjGL23qdq8s9G1VBfBbf+ibMeVvQcUjXJHw\nUmoggvRgW6UJ5GjxNcprPMhghas84JCU8MB+qfvH3hXxEU/ZrXJ1e9WqWKLV2WmB\ni2TNPJOVSCTOEaxyuDQyS/8PNy25xRktf7O2aXeuhO/F1+6KGkfpXAf39NMdBQ2W\nbK61WIjWaHqWicBSDXgkxGGHyw28U3TDW5qXOjfzxxz+/aROv+qHb5uopeLJIBQI\n6SWDjRlRNh19N5dZm6/KVS81Cmx7HoZpOAjc0O3+kiBLOyPnYIvJOEVDNUeaFkrs\nU4zqJxizAgMBAAECggEADRM18nS8XWjzy96SYoQZr1tuUMfEeGbpcHknn8I0Syuq\nq57zCnRBM28nEJXw2ka26bEoGriLEvXtP2QrSEjxGWoJbIksO4+3EOJubp5n+vl3\nkz9wXdhAv5dPjIivZahTjIkHxjV/xuIb2tc6XqBHCiAsaeEBtauHoaSzSBZe114k\n3XCu3ubB6/meQeNMxRI+Al26CUfMENejkB1dIU2eaVJXa0cTog1wkdOan4A4jV/U\ncu6uF+8TZEu0Y7PoL7VQR0STKXmEX8Fj2PH7qKbLLu9kSwawyBaoIzLjcDVyHX5R\nRTTldQoFomwNlSQGudG7CHP/nDDPgOWSXnoGituowQKBgQDLM8jQG4KkrnlXv2LQ\nc8PUBJEVDU+jaKdb5wnDsU74JNRBhpXAZvsz8bJIcXzuIB2Cs2bMD0Fh6iFCFkZw\nnzce8fsHzuYdZPpC9WJvZYFv2cmeri/Uu0R5q/sn3io09kS3JYlwiAdRGmKtXRsJ\ns9sT8ZmsL2oTBVLK+ME+L4qD8wKBgQC6+55xlGZsAk4My7QpqnTpPHGKYiwqa/5B\nW/wxPmaPWAtVQfJ+/hFrJA3BPnC07DTM8AwsTmkXgx1M3khPqNEX0t+eYRcx8mcP\nKQn0aOqoZGX9RYJIF+F6MAraQ039WM0u3InfszvZOBdqio3OhNJWxzv7WYXTd1ck\nV39fj7QIQQKBgC4aOKRmqXRdlXBAHtY2faabxqLlGz1y4A2s1H1OvCD2kiWvuEgn\n1TSK0K04+mQ4axmdRGRlzaq+aP9KeH7S0Lm3owG5gmIG5/TLIaMuf3h2DBVxZa65\nMib8ywXXlPHhMePvo0ghxK808lBtAFZqNPlIZlo3g7R/D7K3T3ihZqbbAoGAbnRZ\nAotBfahW5uQmhz50VZspDzAzGtQ0m/N0pLpR53eBKloMn8wCCiKAJZl3BslJ344m\nAr5HAmanllLwsG3vJn2hL3P3OcAR9Tiu8rxPci3suZKoBWJmBcH/hzOfDHu6qWYJ\n5CWCwyyJWJyEbGy1vCFxY2dc0LB8v7EYQyEmnoECgYBIsScq8OWX+OUaYjj47ySL\nIQyyOxStwv0nr6LKoeW1hUjFKi3BQi6LaG343vZkSWEIRKIENXnpn+3pa79+dUfJ\n7OLv3OozOhyPqiT+yUjakhilnwnQ4c0cZNz0nlXzJf49ugxn+tXlHaDs7EzoF2ag\n7GGhIVGKIIejOAH/1Oe9Rg==\n-----END PRIVATE KEY-----\n", - "client_email": "aljabar@datalearn.iam.gserviceaccount.com", - "client_id": "112946705019770577593", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/aljabar%40datalearn.iam.gserviceaccount.com" -} diff --git a/public/img/course1.png b/public/img/course.png similarity index 100% rename from public/img/course1.png rename to public/img/course.png diff --git a/public/img/course2.png b/public/img/course2.png deleted file mode 100644 index 5835f1b9e122b187fbd4b757753464059c69e091..0000000000000000000000000000000000000000 Binary files a/public/img/course2.png and /dev/null differ diff --git a/public/img/lecturer.png b/public/img/lecturer.png new file mode 100644 index 0000000000000000000000000000000000000000..d6bc7ddf41334b5efac85d2f8acb1691ab3a07b1 Binary files /dev/null and b/public/img/lecturer.png differ diff --git a/public/img/profile.jpg b/public/img/profile.jpg deleted file mode 100644 index c9d2de1809454045034632e4c766d4b11c3c0ee2..0000000000000000000000000000000000000000 Binary files a/public/img/profile.jpg and /dev/null differ diff --git a/public/img/student.png b/public/img/student.png new file mode 100644 index 0000000000000000000000000000000000000000..93885b8b734e43e8a7ba7f37d8f88245fffe6ae5 Binary files /dev/null and b/public/img/student.png differ diff --git a/public/js/learn.js b/public/js/learn.js index 3fb867d8821e8eb8b61a6308dd9c9781c720eea6..6d54322b9b2adf821986d368f6d59d0797914923 100644 --- a/public/js/learn.js +++ b/public/js/learn.js @@ -1,10 +1,14 @@ function submit(id_spreadsheet, url) { document.getElementById("submit").disabled = true; + document.getElementById("submit").style.display = "none"; document.getElementById("back").disabled = true; + document.getElementById("loading").style.display = "block"; var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("result-detail").innerHTML = this.responseText; + document.getElementById("submit").style.display = "block"; + document.getElementById("loading").style.display = "none"; var x = document.getElementById("result"); if (x.style.display === "none") { x.style.display = "block"; diff --git a/resources/views/course.blade.php b/resources/views/course.blade.php index d1e60c6a7e486ccebde3557a3071700262db0476..e2a6382577df828ec12bca3cf7b4e28df7e44f50 100644 --- a/resources/views/course.blade.php +++ b/resources/views/course.blade.php @@ -38,6 +38,13 @@ <span aria-hidden="true">×</span> </button> </div> + @elseif( request()->get('msg') == 6 ) + <div class="alert alert-warning alert-dismissible fade show" role="alert"> + Akses Tidak Diperbolehkan + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> + <span aria-hidden="true">×</span> + </button> + </div> @else <div class="alert alert-danger alert-dismissible fade show" role="alert"> Pembuatan Materi Gagal @@ -50,7 +57,7 @@ <div class="row justify-content"> <div class="col-md-8"> <div class="card"> - <div class="card-header"><b>Kelas {{ $course->name }}</b></div> + <div class="card-header bg-primary text-white"><b>Kelas {{ $course->name }}</b></div> @if( count($topics) == 0 ) <div class="card-body">Tidak ada Materi</div> @endif @@ -219,7 +226,7 @@ <div class="col-md-4"> @if(Auth::user()->role == 0) <div class="card"> - <div class="card-header"><b>Progress</b></div> + <div class="card-header bg-primary text-white"><b>Progress</b></div> <div class="card-body"> <table class="table table-hover"> <thead> @@ -242,12 +249,16 @@ <br/> @endif <div class="card"> - <div class="card-header"><b>Peserta Kelas</b></div> + <div class="card-header bg-primary text-white"><b>Peserta Kelas</b></div> <div class="card-body"> {{ $teacher }} (Pengajar) <br/> @foreach($students as $student) {{ $student }} <br/> @endforeach + @if(Auth::user()->role == 1) + <br/> + <a href="<?php echo $course->id; ?>/grade" class="btn btn-primary" role="button">Lihat Nilai</a> + @endif </div> </div> </div> diff --git a/resources/views/grade.blade.php b/resources/views/grade.blade.php new file mode 100644 index 0000000000000000000000000000000000000000..3617cc57cd2fe61a0f94f41a28e53be228a3c622 --- /dev/null +++ b/resources/views/grade.blade.php @@ -0,0 +1,37 @@ +@extends('layouts.app') + +@section('content') +<div class="container"> + <div class="row justify-content"> + <div class="col-md-12"> + <div class="card"> + <div class="card-header"><b>Hasil Penilaian</b></div> + <div class="card-body"> + <table class="table table-hover"> + <thead> + <tr> + <th scope="col">Nama</th> + @foreach($topics as $topic) + <th scope="col">Materi {{ $topic->name }}</th> + @endforeach + </tr> + </thead> + <tbody> + @foreach($names as $index => $name) + <tr> + <td>{{ $name }}</td> + @foreach($grades[$index] as $grade) + <td>{{ $grade }}</td> + @endforeach + </tr> + @endforeach + </tbody> + </table> + </div> + </div> + <br/> + <a href="/course/<?php echo $id_course; ?>" class="btn btn-primary" id="back" role="button">Kembali ke Kelas</a> + </div> + </div> +</div> +@endsection \ No newline at end of file diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 05cce0a1a1937756bab01cc50df620660f5c8d17..c7347c306420317ae263887213fd783e4b263522 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -43,14 +43,14 @@ <div class="row justify-content"> <div class="col-md-8"> <div class="card"> - <div class="card-header"><b>Kelasku</b></div> + <div class="card-header bg-primary text-white"><b>Kelasku</b></div> <div class="card-columns card-body"> @if( count($enrolled) == 0 ) Tidak ada kelas yang diikuti @endif @foreach($enrolled as $enroll) <div class="card course" style="width: 14rem"> - <img src="img/course1.png" class="card-img-top" alt="No Picture"> + <img src="img/course.png" class="card-img-top" alt="No Picture"> <div class="card-header">{{ $enroll->name }}</div> <a href="/course/<?php echo $enroll->id; ?>" class="stretched-link"></a> </div> @@ -95,9 +95,9 @@ </div> <div class="col-md-4"> <div class="card"> - <div class="card-header"><b>Profil</b></div> + <div class="card-header bg-primary text-white"><b>Profil</b></div> <div class="card-body profile"> - <img src="img/profile.jpg" style="width:120px;height:120px;" alt="No Picture"> <br/> <br/> + <img src="img/{{ $image }}" style="width:120px;height:120px;" alt="No Picture"> <br/> <a id="profile-name">{{ $profile->name }}</a> <br/> <a id="email">{{ $profile->email }}</a> <br/> <a id="role">{{ $role }}</a> <br/><br/> @@ -138,7 +138,7 @@ <div class="py-4 row justify-content-center"> <div class="col-md-12"> <div class="card"> - <div class="card-header"><b>Kelas Tersedia</b></div> + <div class="card-header bg-primary text-white"><b>Kelas Tersedia</b></div> <div class="accordion" id="accordionCourses"> @foreach($courses as $index => $course) <div class="card"> @@ -149,11 +149,15 @@ <div id="collapse<?php echo $course->id; ?>" class="collapse" aria-labelledby="heading<?php echo $course->id; ?>" data-parent="#accordionCourses"> <div class="card-body"> {{ $course->description }} <br/><br/> - <form action="course/enroll" method="post"> - {{ csrf_field() }} - <input style="display: none;" type="number" class="form-control" name="enroll_id" id="enroll_id" required="required" value="<?php echo $course->id ?>"> - <button type="submit" class="btn btn-primary">Daftar Kelas</button> - </form> + @if( in_array($course, $enrolled) ) + <a style="color:green;">Anda sudah mengikuti kelas ini</a> + @else + <form action="course/enroll" method="post"> + {{ csrf_field() }} + <input style="display: none;" type="number" class="form-control" name="enroll_id" id="enroll_id" required="required" value="<?php echo $course->id ?>"> + <button type="submit" class="btn btn-primary">Daftar Kelas</button> + </form> + @endif </div> </div> </div> diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index fed7123e6123768b0f242c0648121c6b9af83ff9..e18428a2bbe941216aea4b22be721e28e75aeae5 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -13,7 +13,7 @@ <script src="{{ asset('js/app.js') }}" defer></script> <script src="{{ asset('js/text.js') }}" defer></script> <script src="{{ asset('js/learn.js') }}" defer></script> - <script src="https://cdn.tiny.cloud/1/yaezxtmh9h1roazzxnkx70is63n62nbov3xskxim3rpnbcoj/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> + <script src="https://cdn.tiny.cloud/1/<API KEY>/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script> <script>tinymce.init({selector:'mytextarea'});</script> <!-- Fonts --> @@ -26,7 +26,7 @@ </head> <body onLoad="iFrameOn();"> <div id="app"> - <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> + <nav class="navbar navbar-expand-md navbar-dark bg-primary shadow-sm"> <div class="container"> <a class="navbar-brand" href="{{ url('/') }}"> {{ config('app.name', 'Laravel') }} diff --git a/resources/views/learn.blade.php b/resources/views/learn.blade.php index 40b0435bda34ef03ee8e995f3eb654eda22ec48f..3b28eae030fc781f7af799d95d4e1cfd3e1f91df 100644 --- a/resources/views/learn.blade.php +++ b/resources/views/learn.blade.php @@ -5,7 +5,7 @@ <div class="row justify-content-center"> <div class="col-lg-4"> <div class="card"> - <div class="card-header">{{ $topic_name }}</div> + <div class="card-header bg-primary text-white"><b>{{ $topic_name }}</b></div> <div class="card-body"> <?php echo $content;?> </div> @@ -19,10 +19,11 @@ </iframe> <a href="/course/<?php echo $id_course; ?>" class="btn btn-primary" id="back" role="button">Kembali ke Kelas</a> <button id="submit" style="float: right;" type="text" onclick="submit('<?php echo $id_spreadsheet; ?>', '<?php echo Request::url(); ?>/submit')" class="btn btn-success"><b>Submit</b></button> + <button id="loading" style="float: right; display: none;" type="button" class="btn btn-success" disabled><span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span><b> menilai...</b></button> </div> - <div id="result" class="col-lg-10" style="margin-top: 1rem; display:none"> + <div id="result" class="col-lg-12" style="margin-top: 1rem; display:none"> <div class="card"> - <div class="card-header">Hasil</div> + <div class="card-header bg-primary text-white">Hasil</div> <div id="result-detail" class="card-body"></div> </div> </div> diff --git a/routes/web.php b/routes/web.php index 3d26056a7b5704c45f7718ec0ee467d2a4a70e71..96da8347b5007fe1e3778d912b77c8316ad8ba9b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -22,6 +22,7 @@ Route::post('/course/new', 'CourseController@new')->name('course/new'); Route::post('/course/enroll', 'CourseController@enroll')->name('course/enroll'); Route::post('/course/{id_course}/delete', 'CourseController@delete')->name('course/delete'); Route::post('/course/{id_course}/edit', 'CourseController@edit')->name('course/edit'); +Route::get('/course/{id_course}/grade', 'CourseController@grade')->name('course/grade'); Route::post('/course/{id_course}/learn/new', 'LearnController@new')->name('learn/new'); Route::get('/course/{id_course}/learn/{id_topic}', 'LearnController@index')->name('learn'); Route::get('/course/{id_course}/learn/{id_topic}/edit', 'LearnController@edit')->name('edit');