Skip to content

Commit

Permalink
Merge pull request #385 from AlexeyShobanov/completed-exercises-list
Browse files Browse the repository at this point in the history
add view completed exercises list
  • Loading branch information
fey committed Jul 7, 2020
2 parents 2fac1ba + 99d153d commit feaccfc
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 54 deletions.
10 changes: 9 additions & 1 deletion app/Http/Controllers/MyController.php
Expand Up @@ -4,7 +4,9 @@

use App\Chapter;
use App\User;
use App\Exercise;
use Auth;
use Illuminate\Pagination\LengthAwarePaginator;

class MyController extends Controller
{
Expand All @@ -19,12 +21,18 @@ public function __invoke()
$chapters = Chapter::with('children', 'exercises')->get();
$mainChapters = $chapters->where('parent_id', null);
$completedExercises = $user->completedExercises->keyBy('exercise_id');
$savedSolutionsExercises = $user->solutions()
->with('exercise')
->distinct('exercise_id')
->orderBy('exercise_id')
->paginate(10);

return view('my.index', compact(
'user',
'chapters',
'mainChapters',
'completedExercises'
'completedExercises',
'savedSolutionsExercises'
));
}
}
24 changes: 21 additions & 3 deletions app/Http/Controllers/SolutionController.php
Expand Up @@ -18,14 +18,15 @@ public function __construct()
public function store(Request $request, User $user)
{
$validatedData = $request->validate([
'exercise_id' => 'required|integer|min:1',
'content' => 'required|string|min:1'
]);

$solution = new Solution($validatedData);
$solution->user()->associate($user);
$exercise = Exercise::findOrFail($request->get('exercise_id'));

$solution = new Solution($validatedData);
$solution->user()->associate($user)->exercise()->associate($exercise);


if ($solution->save()) {
activity()
->performedOn($solution)
Expand All @@ -42,6 +43,23 @@ public function store(Request $request, User $user)
return back();
}

public function show(User $user, Solution $solution)
{

$currentExercise = $solution->exercise;

$solutionsListForCurrentExercise = $solution->exercise
->solutions()
->where('user_id', $user->id)
->get();

return view('solution.show', compact(
'currentExercise',
'solutionsListForCurrentExercise',
'user'
));
}

public function destroy(User $user, Solution $solution)
{
if ($solution->delete()) {
Expand Down
7 changes: 6 additions & 1 deletion app/Policies/SolutionPolicy.php
Expand Up @@ -10,12 +10,17 @@
class SolutionPolicy
{
use HandlesAuthorization;

public function create(User $user)
{
return Auth::check();
}

public function view(User $user, Solution $solution)
{
return $user->id == $solution->user_id;
}

public function delete(User $user, Solution $solution)
{
return $user->id == $solution->user_id;
Expand Down
1 change: 0 additions & 1 deletion app/Solution.php
Expand Up @@ -7,7 +7,6 @@
class Solution extends Model
{
protected $fillable = [
'exercise_id',
'content'
];

Expand Down
15 changes: 15 additions & 0 deletions resources/js/app.js
Expand Up @@ -14,3 +14,18 @@ hljs.registerLanguage('scheme', scheme);
$('#flash-overlay-modal').modal();
hljs.initHighlightingOnLoad();

// LINK TO TABS from https://github.com/twbs/bootstrap/issues/25220#issuecomment-535915733
$(document).ready(function () {
var url = window.location.href;
if (url.indexOf("#") > 0) {
var activeTab = url.substring(url.indexOf("#") + 1);
$('.nav[role="tablist"] a[href="#' + activeTab + '"]').tab('show');
}

$('a[role="tab"]').on("click", function () {
var newUrl;
const hash = $(this).attr("href");
newUrl = url.split("#")[0] + hash;
history.replaceState(null, null, newUrl);
});
});
10 changes: 10 additions & 0 deletions resources/lang/en/progresses.php
@@ -0,0 +1,10 @@
<?php

return [
'сhapters' => 'Chapters',
'my_solutions' => 'My Solutions',
'exercise' => 'Exercise',
'see_details' => 'See details',
'solutions' => 'Solutions',
'exercises' => 'Exercises'
];
5 changes: 4 additions & 1 deletion resources/lang/en/solution.php
Expand Up @@ -6,5 +6,8 @@
'title_add_solution' => 'Solution',
'title_output_solution' => 'My solution',
'add_solution' => 'Add solution',
'show_solution' => 'My solutions'
'show_solution' => 'My solutions',
'exercise' => 'Exercise',
'code_review' => 'Code Review',
'sub_title' => 'Compare your versions'
];
10 changes: 10 additions & 0 deletions resources/lang/ru/progresses.php
@@ -0,0 +1,10 @@
<?php

return [
'сhapters' => 'Главы',
'my_solutions' => 'Мои Решения',
'exercise' => 'Упражнение',
'see_details' => 'Подробнее',
'solutions' => 'Решения',
'exercises' => 'Упражнения'
];
5 changes: 4 additions & 1 deletion resources/lang/ru/solution.php
Expand Up @@ -6,5 +6,8 @@
'title_add_solution' => 'Решение',
'title_output_solution' => 'Мое решение',
'add_solution' => 'Добавить решение',
'show_solution' => 'Мои решения'
'show_solution' => 'Мои решения',
'exercise' => 'Упражнение',
'code_review' => 'Код Ревью',
'sub_title' => 'Сравни свои решения'
];
2 changes: 2 additions & 0 deletions resources/sass/_variables.scss
@@ -1,5 +1,7 @@
// Body
$body-bg: #f8fafc;
//
$nav-tabs-link-active-bg: #fff;

// Typography
$font-family-sans-serif: 'Nunito', sans-serif;
Expand Down
8 changes: 4 additions & 4 deletions resources/views/layouts/app.blade.php
Expand Up @@ -25,20 +25,20 @@
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>

<body class="d-flex flex-column">
<body class="d-flex flex-column min-vh-100">
@if (config('app.env') == 'production')
@include('layouts.deps._gtm_body')
@endif
<div class="d-flex flex-column min-vh-100">
<div class="flex-grow-1">
@include('layouts._nav')
<main class="my-5">
<main class="my-4">
<div class="container mb-3">
@include('flash::message')
@yield('content')
</div>
</main>
@include('layouts._footer')
</div>
@include('layouts._footer')

</body>

Expand Down
55 changes: 15 additions & 40 deletions resources/views/my/index.blade.php
@@ -1,49 +1,24 @@
@extends('layouts.app')

@section('content')
<div class="row">
<div class="col">
<h3>{{ __('layout.nav.my_progress') }}</h3>
</div>
<div class="col text-right">
<h5><a href="{{ route('users.show', $user) }}">{{ $user->name }}</a></h5>
<div class="d-flex flex-wrap justify-content-between">
<div class="h3">{{ __('layout.nav.my_progress') }}</h3></div>
<div class="h5 align-self-center">
<a href="{{ route('users.show', $user) }}">{{ $user->name }}</a>
</div>
</div>
<div class="row mt-2">
<div class="col-12 col-md-4 mb-2">
<div class="nav nav-pills flex-column sticky-top x-z-index-0" role="tablist">
@foreach($mainChapters as $mainChapter)
<a class="nav-item nav-link {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}-tab"
href="#subChapters{{ $mainChapter->id }}"
data-toggle="tab"
role="tab"
aria-controls="subChapters{{ $mainChapter->id }}"
aria-selected="{{ $mainChapter->path === '1' ? 'true' : 'false' }}">
{{ $mainChapter->path }} {{ getChapterName($mainChapter->path) }}
</a>
@endforeach
</div>
<nav>
<div class="nav nav-tabs" id="nav-tab" role="tablist">
<a class="nav-item nav-link active" id="nav-chapters-tab" data-toggle="tab" href="#nav-chapters" role="tab" aria-controls="nav-home" aria-selected="true">{{ __('progresses.сhapters') }}</a>
<a class="nav-item nav-link" id="nav-solutions-tab" data-toggle="tab" href="#nav-solutions" role="tab" aria-controls="nav-profile" aria-selected="false">{{ __('progresses.my_solutions') }}</a>
</div>
</nav>
<div class="tab-content bg-white" id="nav-tabContent">
<div class="tab-pane fade show active" id="nav-chapters" role="tabpanel" aria-labelledby="nav-chapters-tab">
@include('my.progresses._my_chapters')
</div>
<div class="col-12 col-md-8">
<div class="card pl-2 pr-3">
{!! Form::open()->route('users.chapters.store', [$user]) !!}
<div class="tab-content">
@foreach($mainChapters as $mainChapter)
<div
class="tab-pane card-body {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}"
role="tabpanel"
aria-labelledby="subChapters{{ $mainChapter->id }}-tab">
@include('partials.chapter_form_element', ['chapter' => $mainChapter])
</div>
@endforeach
<div class="form-group text-right">
{!! Form::submit(__('layout.common.save')) !!}
</div>
</div>
{!! Form::close() !!}
</div>
<div class="tab-pane fade show" id="nav-solutions" role="tabpanel" aria-labelledby="nav-solutions-tab">
@include('my.progresses._my_solutions')
</div>
</div>
@endsection
35 changes: 35 additions & 0 deletions resources/views/my/progresses/_my_chapters.blade.php
@@ -0,0 +1,35 @@
<div class="row no-gutters border border-top-0">
<div class="col-12 col-md-4 border-right x-z-index-0">
<div class="nav nav-pills flex-column sticky-top m-2 pt-2" role="tablist">
@foreach($mainChapters as $mainChapter)
<a class="nav-item nav-link {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}-tab"
href="#subChapters{{ $mainChapter->id }}"
data-toggle="tab"
role="tab"
aria-controls="subChapters{{ $mainChapter->id }}"
aria-selected="{{ $mainChapter->path === '1' ? 'true' : 'false' }}">
{{ $mainChapter->path }} {{ getChapterName($mainChapter->path) }}
</a>
@endforeach
</div>
</div>
<div class="col-12 col-md-8">
{!! Form::open()->route('users.chapters.store', [$user]) !!}
<div class="tab-content m-2 m-lg-4">
@foreach($mainChapters as $mainChapter)
<div
class="tab-pane {{ $mainChapter->path === '1' ? 'active' : '' }}"
id="subChapters{{ $mainChapter->id }}"
role="tabpanel"
aria-labelledby="subChapters{{ $mainChapter->id }}-tab">
@include('partials.chapter_form_element', ['chapter' => $mainChapter])
</div>
@endforeach
<div class="text-right mt-2 mt-lg-4">
{!! Form::submit(__('layout.common.save')) !!}
</div>
</div>
{!! Form::close() !!}
</div>
</div>
23 changes: 23 additions & 0 deletions resources/views/my/progresses/_my_solutions.blade.php
@@ -0,0 +1,23 @@

<div class="table-responsive border border-top-0 p-2 p-lg-4">
<table class="table">
<thead>
<tr>
<th class="border-top h5">{{ __('progresses.exercises') }}</th>
<th class="border-top h5">{{ __('progresses.solutions') }}</th>
</tr>
@foreach ($savedSolutionsExercises as $solution)
<tr>
<td>
{{ __('progresses.exercise') }} {{ $solution->exercise->path }} {{ getExerciseTitle($solution->exercise) }} (Chapter {{ $solution->exercise->chapter->path }})
</td>
<td>
<a href="{{ route('users.solutions.show', [$user, $solution]) }}">
{{ __('progresses.see_details') }}
</td>
</tr>
@endforeach
</thead>
</table>
</div>
{{ $savedSolutionsExercises->fragment('nav-solutions')->links() }}
80 changes: 80 additions & 0 deletions resources/views/solution/show.blade.php
@@ -0,0 +1,80 @@
@extends('layouts.app')

@section('content')

<div class="d-flex flex-wrap justify-content-between mb-2 mb-lg-4">
<div class="h5">
<a href="{{ route('exercises.show', $currentExercise) }}">
{{ __('solution.exercise') }} {{ $currentExercise->path }}: {{ getExerciseTitle($currentExercise) }}
</div>
<div class="h5">
<a href="{{ route('users.show', $user) }}">{{ $user->name }}</a>
</div>
</div>

<h2 class="text-center">{{ __('solution.code_review') }}</h2>
<div class="text-center h5">{{ __('solution.sub_title') }}</div>
<hr>
<div class="row no-gutters">
<div class="col-12 col-md p-2 p-lg-4">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-{{ $currentSolution->id }}-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}" role="tab" aria-controls="pills-{{ $currentSolution->id }}" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@else
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-{{ $currentSolution->id }}-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}" role="tab" aria-controls="pills-{{ $currentSolution->id }}" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@endif
@endforeach
</ul>
<div class="tab-content" id="pills-tabContent">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<div class="tab-pane fade show active" id="pills-{{ $currentSolution->id }}" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@else
<div class="tab-pane fade show" id="pills-{{ $currentSolution->id }}" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@endif
@endforeach
</div>
</div>

@if (count($solutionsListForCurrentExercise) > 1)
<div class="d-none d-md-block border-left"></div>
<div class="col p-2 p-lg-4">
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<li class="nav-item" role="presentation">
<a class="nav-link active" id="pills-{{ $currentSolution->id }}double-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}double" role="tab" aria-controls="pills-{{ $currentSolution->id }}double" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@else
<li class="nav-item" role="presentation">
<a class="nav-link" id="pills-{{ $currentSolution->id }}double-tab" data-toggle="pill" href="#pills-{{ $currentSolution->id }}double" role="tab" aria-controls="pills-{{ $currentSolution->id }}double" aria-selected="true">v.{{ $loop->iteration }}</a>
</li>
@endif
@endforeach
</ul>
<div class="tab-content" id="pills-tabContent">
@foreach ($solutionsListForCurrentExercise as $currentSolution)
@if ($loop->first)
<div class="tab-pane fade show active" id="pills-{{ $currentSolution->id }}double" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}double-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@else
<div class="tab-pane fade show" id="pills-{{ $currentSolution->id }}double" role="tabpanel" aria-labelledby="pills-{{ $currentSolution->id }}double-tab">
<pre><code>{{ $currentSolution->content }}</code></pre>
</div>
@endif
@endforeach
</div>
</div>
@endif
</div>
@endsection

0 comments on commit feaccfc

Please sign in to comment.