Commit bbbe8087 authored by Antonio Amaddio's avatar Antonio Amaddio 🚀
Browse files

Initial commit of Webapp that contains basic required features of code challenge..

parents
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1
MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
* text=auto
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
.env
.env.backup
.phpunit.result.cache
docker-compose.override.yml
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
/.idea
/.vscode
php:
preset: laravel
version: 8
disabled:
- no_unused_imports
finder:
not-name:
- index.php
- server.php
js:
finder:
not-name:
- webpack.mix.js
css: true
# Project Description
The following instructions were given to complete the coding challenge.
> "Please implement a dynamic web page that presents an overview of the research projects run at the Max-Planck-Institute for Human Development.
A project should be addable through a simple survey mask. Required fields are project title, responsible researcher, department (ARC, LIP, CHM or HoE), data type (Online Survey, EEG, Behavioral, Simulation, MRI, Video, multiple options possible). An optional field might contain an identifier to a corresponding publication supported by Semantic Scholar (https://www.semanticscholar.org), e.g. DOI or ArXiv ID. A unique project ID is assigned to each project entered.
All projects are displayed on a webpage in a tabular form. There is a filter based on data type and department. If an identifier to a publication is provided, the title of the publication is displayed along with the current number of citations the publications received (as provided by https://www.semanticscholar.org).
Optional: Prepare the project for deployment i.e. through dockerization.
User management as well as editing of projects after submission, is not required. We expect the task to be solved within 6 hours maximum. Please organize your time accordingly and cut requirements as necessary.
The solution can be programmed from scratch, an open-source solution can be adopted, or existing services can be composed.
Please provide us with the source code conveniently or showcase your solution in another suitable manner. Be prepared to present it during the interview in English or in German."
# Installation
- php artisan migrate:refresh --seed
- npm install && npn run dev
<?php
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
}
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\AdminUser\DestroyAdminUser;
use App\Http\Requests\Admin\AdminUser\ImpersonalLoginAdminUser;
use App\Http\Requests\Admin\AdminUser\IndexAdminUser;
use App\Http\Requests\Admin\AdminUser\StoreAdminUser;
use App\Http\Requests\Admin\AdminUser\UpdateAdminUser;
use Brackets\AdminAuth\Models\AdminUser;
use Spatie\Permission\Models\Role;
use Brackets\AdminAuth\Activation\Facades\Activation;
use Brackets\AdminAuth\Services\ActivationService;
use Brackets\AdminListing\Facades\AdminListing;
use Exception;
use Illuminate\Support\Facades\Auth;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Config;
use Illuminate\View\View;
class AdminUsersController extends Controller
{
/**
* Guard used for admin user
*
* @var string
*/
protected $guard = 'admin';
/**
* AdminUsersController constructor.
*
* @return void
*/
public function __construct()
{
$this->guard = config('admin-auth.defaults.guard');
}
/**
* Display a listing of the resource.
*
* @param IndexAdminUser $request
* @return Factory|View
*/
public function index(IndexAdminUser $request)
{
// create and AdminListing instance for a specific model and
$data = AdminListing::create(AdminUser::class)->processRequestAndGet(
// pass the request with params
$request,
// set columns to query
['id', 'first_name', 'last_name', 'email', 'activated', 'forbidden', 'language', 'last_login_at'],
// set columns to searchIn
['id', 'first_name', 'last_name', 'email', 'language']
);
if ($request->ajax()) {
return ['data' => $data, 'activation' => Config::get('admin-auth.activation_enabled')];
}
return view('admin.admin-user.index', ['data' => $data, 'activation' => Config::get('admin-auth.activation_enabled')]);
}
/**
* Show the form for creating a new resource.
*
* @throws AuthorizationException
* @return Factory|View
*/
public function create()
{
$this->authorize('admin.admin-user.create');
return view('admin.admin-user.create', [
'activation' => Config::get('admin-auth.activation_enabled'),
'roles' => Role::where('guard_name', $this->guard)->get(),
]);
}
/**
* Store a newly created resource in storage.
*
* @param StoreAdminUser $request
* @return array|RedirectResponse|Redirector
*/
public function store(StoreAdminUser $request)
{
// Sanitize input
$sanitized = $request->getModifiedData();
// Store the AdminUser
$adminUser = AdminUser::create($sanitized);
// But we do have a roles, so we need to attach the roles to the adminUser
$adminUser->roles()->sync(collect($request->input('roles', []))->map->id->toArray());
if ($request->ajax()) {
return ['redirect' => url('admin/admin-users'), 'message' => trans('brackets/admin-ui::admin.operation.succeeded')];
}
return redirect('admin/admin-users');
}
/**
* Display the specified resource.
*
* @param AdminUser $adminUser
* @throws AuthorizationException
* @return void
*/
public function show(AdminUser $adminUser)
{
$this->authorize('admin.admin-user.show', $adminUser);
// TODO your code goes here
}
/**
* Show the form for editing the specified resource.
*
* @param AdminUser $adminUser
* @throws AuthorizationException
* @return Factory|View
*/
public function edit(AdminUser $adminUser)
{
$this->authorize('admin.admin-user.edit', $adminUser);
$adminUser->load('roles');
return view('admin.admin-user.edit', [
'adminUser' => $adminUser,
'activation' => Config::get('admin-auth.activation_enabled'),
'roles' => Role::where('guard_name', $this->guard)->get(),
]);
}
/**
* Update the specified resource in storage.
*
* @param UpdateAdminUser $request
* @param AdminUser $adminUser
* @return array|RedirectResponse|Redirector
*/
public function update(UpdateAdminUser $request, AdminUser $adminUser)
{
// Sanitize input
$sanitized = $request->getModifiedData();
// Update changed values AdminUser
$adminUser->update($sanitized);
// But we do have a roles, so we need to attach the roles to the adminUser
if ($request->input('roles')) {
$adminUser->roles()->sync(collect($request->input('roles', []))->map->id->toArray());
}
if ($request->ajax()) {
return ['redirect' => url('admin/admin-users'), 'message' => trans('brackets/admin-ui::admin.operation.succeeded')];
}
return redirect('admin/admin-users');
}
/**
* Remove the specified resource from storage.
*
* @param DestroyAdminUser $request
* @param AdminUser $adminUser
* @throws Exception
* @return ResponseFactory|RedirectResponse|Response
*/
public function destroy(DestroyAdminUser $request, AdminUser $adminUser)
{
$adminUser->delete();
if ($request->ajax()) {
return response(['message' => trans('brackets/admin-ui::admin.operation.succeeded')]);
}
return redirect()->back();
}
/**
* Resend activation e-mail
*
* @param Request $request
* @param ActivationService $activationService
* @param AdminUser $adminUser
* @return array|RedirectResponse
*/
public function resendActivationEmail(Request $request, ActivationService $activationService, AdminUser $adminUser)
{
if (Config::get('admin-auth.activation_enabled')) {
$response = $activationService->handle($adminUser);
if ($response == Activation::ACTIVATION_LINK_SENT) {
if ($request->ajax()) {
return ['message' => trans('brackets/admin-ui::admin.operation.succeeded')];
}
return redirect()->back();
} else {
if ($request->ajax()) {
abort(409, trans('brackets/admin-ui::admin.operation.failed'));
}
return redirect()->back();
}
} else {
if ($request->ajax()) {
abort(400, trans('brackets/admin-ui::admin.operation.not_allowed'));
}
return redirect()->back();
}
}
/**
* @param ImpersonalLoginAdminUser $request
* @param AdminUser $adminUser
* @return RedirectResponse
* @throws AuthorizationException
*/
public function impersonalLogin(ImpersonalLoginAdminUser $request, AdminUser $adminUser) {
Auth::login($adminUser);
return redirect()->back();
}
}
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\Admin\DataType\BulkDestroyDataType;
use App\Http\Requests\Admin\DataType\DestroyDataType;
use App\Http\Requests\Admin\DataType\IndexDataType;
use App\Http\Requests\Admin\DataType\StoreDataType;
use App\Http\Requests\Admin\DataType\UpdateDataType;
use App\Models\DataType;
use Brackets\AdminListing\Facades\AdminListing;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Routing\ResponseFactory;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Response;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;
class DataTypeController extends Controller
{
/**
* Display a listing of the resource.
*
* @param IndexDataType $request
* @return array|Factory|View
*/
public function index(IndexDataType $request)
{
// create and AdminListing instance for a specific model and
$data = AdminListing::create(DataType::class)->processRequestAndGet(
// pass the request with params
$request,
// set columns to query
['id', 'name'],
// set columns to searchIn
['id', 'name']
);
if ($request->ajax()) {
if ($request->has('bulk')) {
return [
'bulkItems' => $data->pluck('id')
];
}
return ['data' => $data];
}
return view('admin.data-type.index', ['data' => $data]);
}
/**
* Show the form for creating a new resource.
*
* @throws AuthorizationException
* @return Factory|View
*/
public function create()
{
$this->authorize('admin.data-type.create');
return view('admin.data-type.create');
}
/**
* Store a newly created resource in storage.
*
* @param StoreDataType $request
* @return array|RedirectResponse|Redirector
*/
public function store(StoreDataType $request)
{
// Sanitize input
$sanitized = $request->getSanitized();
// Store the DataType
$dataType = DataType::create($sanitized);
if ($request->ajax()) {
return ['redirect' => url('admin/data-types'), 'message' => trans('brackets/admin-ui::admin.operation.succeeded')];
}
return redirect('admin/data-types');
}
/**
* Display the specified resource.
*
* @param DataType $dataType
* @throws AuthorizationException
* @return void
*/
public function show(DataType $dataType)
{
$this->authorize('admin.data-type.show', $dataType);
// TODO your code goes here
}
/**
* Show the form for editing the specified resource.
*
* @param DataType $dataType
* @throws AuthorizationException
* @return Factory|View
*/
public function edit(DataType $dataType)
{
$this->authorize('admin.data-type.edit', $dataType);
return view('admin.data-type.edit', [
'dataType' => $dataType,
]);
}
/**
* Update the specified resource in storage.
*
* @param UpdateDataType $request
* @param DataType $dataType
* @return array|RedirectResponse|Redirector
*/
public function update(UpdateDataType $request, DataType $dataType)
{
// Sanitize input
$sanitized = $request->getSanitized();
// Update changed values DataType
$dataType->update($sanitized);
if ($request->ajax()) {
return [
'redirect' => url('admin/data-types'),
'message' => trans('brackets/admin-ui::admin.operation.succeeded'),
];
}
return redirect('admin/data-types');
}
/**
* Remove the specified resource from storage.
*