Merge branch 'develop' into trunk
This commit is contained in:
commit
d641208a44
16 changed files with 2470 additions and 378 deletions
45
app/Enums/Planning/ActivityType.php
Normal file
45
app/Enums/Planning/ActivityType.php
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<?php
|
||||
|
||||
namespace App\Enums\Planning;
|
||||
|
||||
use Kwaadpepper\Enum\BaseEnumRoutable;
|
||||
|
||||
/**
|
||||
* This is an enumeration class,
|
||||
* the following methods are its possible values
|
||||
*
|
||||
* @method static self support()
|
||||
* @method static self rnd()
|
||||
* @method static self dev()
|
||||
* @method static self projects()
|
||||
* @method static self management()
|
||||
* @method static self absence()
|
||||
*
|
||||
*/
|
||||
class ActivityType extends BaseEnumRoutable
|
||||
{
|
||||
|
||||
public static function labels()
|
||||
{
|
||||
return [
|
||||
'support' => trans('Support'),
|
||||
'rnd' => trans('R&D'),
|
||||
'dev' => trans('Développement/Facturable'),
|
||||
'projects' => trans('Projets & Réunions'),
|
||||
'management' => trans('Organisation management'),
|
||||
'absence' => trans('Absence'),
|
||||
];
|
||||
}
|
||||
|
||||
public static function colors(): array
|
||||
{
|
||||
return [
|
||||
'support' => '#c6e0b4',
|
||||
'rnd' => '#b4c6e7',
|
||||
'dev' => '#00b0f0',
|
||||
'projects' => '#ffe699',
|
||||
'management' => '#f4b084',
|
||||
'absence' => '#aeaaaa'
|
||||
];
|
||||
}
|
||||
}
|
||||
163
app/Http/Controllers/ScheduleController.php
Normal file
163
app/Http/Controllers/ScheduleController.php
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Enums\Planning\ActivityType;
|
||||
use App\Enums\Role;
|
||||
use App\Http\Requests\StoreScheduleRequest;
|
||||
use App\Models\Schedule;
|
||||
use App\Models\User;
|
||||
use App\Models\WeekPlanning;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Carbon\CarbonImmutable;
|
||||
|
||||
/**
|
||||
* Alternate planner for Dev Team
|
||||
*
|
||||
* @author Olivier Legat <olivier.legat@ldc.fr>
|
||||
*
|
||||
*/
|
||||
class ScheduleController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
{
|
||||
$date = CarbonImmutable::now()->startOfWeek();
|
||||
$nbweeks = 2;
|
||||
if ($request->p) {
|
||||
$date = CarbonImmutable::createFromFormat('d/m/Y', $request->p)->startOfWeek();
|
||||
}
|
||||
|
||||
|
||||
$dbusers = User::where('role', Role::developper())->get();
|
||||
$users = [];
|
||||
foreach ($dbusers as $user) {
|
||||
$users[$user->id] = ['name' => $user->name];
|
||||
}
|
||||
|
||||
$schedules = Schedule::whereDate('date', '>=', $date)
|
||||
->whereDate('date', '<=', $date->addDays($nbweeks * 7 - 1))
|
||||
->orderBy('user_id')
|
||||
->orderBy('slot')
|
||||
->orderBy('date')
|
||||
->get();
|
||||
|
||||
$arSchedules = array();
|
||||
$prevUserId = null;
|
||||
$prevDate = null;
|
||||
$prevSlot = null;
|
||||
foreach ($schedules as $schedule) {
|
||||
$id_lie = array('label'=> null, 'value'=> null);
|
||||
if(!is_null($schedule->model_lie)) {
|
||||
if (isset($schedule->relatedModel->name)) {
|
||||
$id_lie = array('label'=>$schedule->relatedModel->name, 'value'=>$schedule->id_lie);
|
||||
} else {
|
||||
$id_lie = array('label'=>'Ticket '.$schedule->id_lie, 'value'=>$schedule->id_lie);
|
||||
}
|
||||
$model_lie = $schedule->model_lie;
|
||||
} else {
|
||||
$model_lie = array('label'=> null, 'value'=> null);
|
||||
}
|
||||
|
||||
if ($prevUserId != $schedule->user_id) {
|
||||
//nouveau user
|
||||
$arSchedules[$schedule->user_id] = array(
|
||||
$schedule->slot => array(
|
||||
$schedule->date->format('d/m/Y') => array(
|
||||
'id' => $schedule->id,
|
||||
'type' => $schedule->activity,
|
||||
'text' => $schedule->description,
|
||||
'id_lie' => $id_lie, //$schedule->id_lie,
|
||||
'model_lie' => $model_lie,
|
||||
),
|
||||
)
|
||||
);
|
||||
} else {
|
||||
//same user
|
||||
if ($prevSlot != $schedule->slot) {
|
||||
//new slot
|
||||
$arSchedules[$schedule->user_id][$schedule->slot] = array(
|
||||
$schedule->date->format('d/m/Y') => array(
|
||||
'id' => $schedule->id,
|
||||
'type' => $schedule->activity,
|
||||
'text' => $schedule->description,
|
||||
'id_lie' => $id_lie, //$schedule->id_lie,
|
||||
'model_lie' => $model_lie,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
//same slot
|
||||
if ($prevDate != $schedule->date) {
|
||||
//new date
|
||||
$arSchedules[$schedule->user_id][$schedule->slot][$schedule->date->format('d/m/Y')] = array(
|
||||
'id' => $schedule->id,
|
||||
'type' => $schedule->activity,
|
||||
'text' => $schedule->description,
|
||||
'id_lie' => $id_lie, //$schedule->id_lie,
|
||||
'model_lie' => $model_lie,
|
||||
);
|
||||
} else {
|
||||
//same date
|
||||
//should never be here
|
||||
}
|
||||
}
|
||||
}
|
||||
$prevUserId = $schedule->user_id;
|
||||
$prevDate = $schedule->date;
|
||||
$prevSlot = $schedule->slot;
|
||||
}
|
||||
|
||||
$weekCells = array();
|
||||
for ($i=0; $i < $nbweeks; $i++) {
|
||||
$weekCells[] = array(
|
||||
"num" => $date->addDays($i * 7)->weekOfYear,
|
||||
"month" => $date->addDays($i * 7)->shortLocaleMonth,
|
||||
"year" => $date->addDays($i * 7)->format('Y')
|
||||
);
|
||||
}
|
||||
|
||||
return view('schedule.index', compact('users', 'date', 'weekCells', 'arSchedules'));
|
||||
}
|
||||
|
||||
public function setCellContent(StoreScheduleRequest $request)
|
||||
{
|
||||
$date = CarbonImmutable::createFromFormat('d/m/Y', $request->date);
|
||||
$fill = $request->all();
|
||||
$fill['date'] = $date;
|
||||
|
||||
$schedule = Schedule::updateOrCreate(['id' => $request->id],$fill);
|
||||
$schedule->saveOrFail();
|
||||
|
||||
$id_lie = array('label'=> null, 'value'=> null);
|
||||
if(!is_null($schedule->model_lie)) {
|
||||
if (isset($schedule->relatedModel->name)) {
|
||||
$id_lie = array('label'=>$schedule->relatedModel->name, 'value'=>$schedule->id_lie);
|
||||
} else {
|
||||
$id_lie = array('label'=>'Ticket '.$schedule->id_lie, 'value'=>$schedule->id_lie);
|
||||
}
|
||||
$model_lie = $schedule->model_lie;
|
||||
} else {
|
||||
$model_lie = array('label'=> null, 'value'=> null);
|
||||
}
|
||||
|
||||
$arSchd = [
|
||||
'id' => $schedule->id,
|
||||
'user_id' => $schedule->user_id,
|
||||
'date' => $schedule->date->format('d/m/Y'),
|
||||
'activity' => $schedule->activity,
|
||||
'description' => $schedule->description,
|
||||
'id_lie' => $id_lie,
|
||||
'model_lie' => $model_lie,
|
||||
'slot' => $schedule->slot,
|
||||
];
|
||||
|
||||
return \response()->json(['status' => true, 'sched'=>$arSchd]);
|
||||
}
|
||||
|
||||
public function eraseCellContent(Request $request)
|
||||
{
|
||||
$schedule = Schedule::findOrFail($request->id);
|
||||
$schedule->delete();
|
||||
return \response()->json(['status' => true]);
|
||||
}
|
||||
}
|
||||
49
app/Http/Requests/StoreScheduleRequest.php
Normal file
49
app/Http/Requests/StoreScheduleRequest.php
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Enums\Planning\ActivityType;
|
||||
use App\Enums\Planning\CellModel;
|
||||
use App\Enums\Planning\TableRow;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Kwaadpepper\Enum\Rules\EnumIsValidRule;
|
||||
|
||||
class StoreScheduleRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return auth()->check() and $this->ajax();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'user_id' => 'required|exists:users,id',
|
||||
'date' => 'date',
|
||||
'activity' => [
|
||||
'required',
|
||||
new EnumIsValidRule(ActivityType::class)
|
||||
],
|
||||
'slot' => [
|
||||
'required',
|
||||
new EnumIsValidRule(TableRow::class)
|
||||
],
|
||||
'model_lie' => [
|
||||
'nullable',
|
||||
new EnumIsValidRule(CellModel::class)
|
||||
],
|
||||
'id_lie' => 'required_with:model_lie|nullable|numeric',
|
||||
'description' => 'required|string|min:5|max:90'
|
||||
];
|
||||
}
|
||||
}
|
||||
65
app/Models/Schedule.php
Normal file
65
app/Models/Schedule.php
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\Planning\ActivityType;
|
||||
use App\Enums\Planning\CellModel;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Kwaadpepper\Enum\Traits\CastsEnums;
|
||||
|
||||
class Schedule extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use CastsEnums;
|
||||
|
||||
protected $enumCasts = [
|
||||
'activity' => ActivityType::class,
|
||||
'model_lie' => CellModel::class
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that should be cast to native types.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $casts = [
|
||||
'date' => 'date',
|
||||
];
|
||||
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'date',
|
||||
'slot',
|
||||
'activity',
|
||||
'description',
|
||||
'id_lie',
|
||||
'model_lie'
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
//relationship to linked objet
|
||||
public function relatedModel()
|
||||
{
|
||||
switch ($this->model_lie) {
|
||||
case 'sites':
|
||||
return $this->belongsTo(Site::class, 'id_lie');
|
||||
break;
|
||||
case 'projects':
|
||||
return $this->belongsTo(Project::class, 'id_lie');
|
||||
break;
|
||||
case 'tickets':
|
||||
return $this->belongsTo(Ticket::class, 'id_lie');
|
||||
break;
|
||||
default:
|
||||
//no model
|
||||
return new BelongsTo($this->newQuery(), $this, '', '', '');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -34,6 +34,10 @@ class AppServiceProvider extends ServiceProvider
|
|||
URL::forceScheme('https');
|
||||
}
|
||||
|
||||
if (config('app.env') === 'local') {
|
||||
setlocale(LC_TIME, strtoupper(config('app.locale')) . "_" . config('app.locale') . '.utf8');
|
||||
}
|
||||
|
||||
$appInfos = json_decode(File::get(\app_path('../composer.json')));
|
||||
|
||||
View::share('name', $appInfos->name);
|
||||
|
|
|
|||
739
composer.lock
generated
739
composer.lock
generated
File diff suppressed because it is too large
Load diff
|
|
@ -236,6 +236,7 @@ return [
|
|||
'LoadLevel' => App\Enums\LoadLevel::class,
|
||||
'CellModel' => App\Enums\Planning\CellModel::class,
|
||||
'CellType' => App\Enums\Planning\CellType::class,
|
||||
'ActivityType' => App\Enums\Planning\ActivityType::class,
|
||||
'TableRow' => App\Enums\Planning\TableRow::class,
|
||||
'Carbon' => 'Carbon\Carbon'
|
||||
],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Schedule;
|
||||
use App\Models\WeekPlanning;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class CreateSchedulesTable extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::create('schedules', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->foreignId('user_id')->constrained('users');
|
||||
$table->date('date');
|
||||
$table->smallInteger('slot');
|
||||
$table->string('activity')->nullable();
|
||||
$table->text('description');
|
||||
$table->bigInteger('id_lie')->nullable();
|
||||
$table->string('model_lie')->nullable();
|
||||
$table->timestamps();
|
||||
$table->unique(['user_id','date','slot'], 'user_day_slot_unique');
|
||||
});
|
||||
|
||||
//migrate data from week plannings
|
||||
$week_plannings = WeekPlanning::all();
|
||||
|
||||
foreach ($week_plannings as $oneweek) {
|
||||
$user_id = $oneweek->user_id;
|
||||
$plan = $oneweek->planning;
|
||||
foreach ($plan as $time => $data) {
|
||||
$date = Carbon::createFromTimestamp($time);
|
||||
foreach ($data as $dayslot => $cell) {
|
||||
$activite = $this->convertColorToType($cell["type"]);
|
||||
$description = $cell["text"];
|
||||
$id_objetlie = $cell["foreign"];
|
||||
$type_objetlie = $cell["cellModel"]; //c'est une table d'après l'Enum CellModel
|
||||
|
||||
$collected = [
|
||||
'user_id' => $user_id,
|
||||
'date' => $date,
|
||||
'slot' => $dayslot,
|
||||
'activity' => $activite,
|
||||
'description' => $description,
|
||||
'id_lie' => $id_objetlie,
|
||||
'model_lie' => $type_objetlie
|
||||
];
|
||||
//si activite null et description null ne pas enregistrer
|
||||
if (!is_null($activite) && !is_null($description)) {
|
||||
$schedule = new Schedule();
|
||||
$schedule->fill($collected);
|
||||
$schedule->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::dropIfExists('schedules');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* convertir une value de couleur en type
|
||||
*/
|
||||
private function convertColorToType($value) {
|
||||
$converter = array(
|
||||
'#c6e0b4' => 'support',
|
||||
'#b4c6e7' => 'rnd',
|
||||
'#00b0f0' => 'dev',
|
||||
'#ffe699' => 'projects',
|
||||
'#f4b084' => 'management',
|
||||
'#aeaaaa' => 'absence',
|
||||
'abscence' => 'absence'
|
||||
);
|
||||
return $converter[$value] ?? null;
|
||||
}
|
||||
}
|
||||
801
package-lock.json
generated
801
package-lock.json
generated
File diff suppressed because it is too large
Load diff
10
package.json
10
package.json
|
|
@ -1,18 +1,20 @@
|
|||
{
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "mix",
|
||||
"development": "mix",
|
||||
"clear-manifest": "node ./node_modules/del-cli/cli.js public/mix-manifest.json",
|
||||
"development": "npm run clear-manifest && mix",
|
||||
"dev": "npm run development",
|
||||
"watch": "mix watch",
|
||||
"watch-poll": "mix watch -- --watch-options-poll=1000",
|
||||
"hot": "mix watch --hot",
|
||||
"production": "mix --production",
|
||||
"prod": "mix --production"
|
||||
"production": "npm run clear-manifest && mix --production",
|
||||
"prod": "npm run production"
|
||||
},
|
||||
"devDependencies": {
|
||||
"axios": "^0.21.1",
|
||||
"bootstrap": "^5.0.2",
|
||||
"cross-env": "^7.0",
|
||||
"del-cli": "^4.0.1",
|
||||
"fslightbox": "^3.2.3",
|
||||
"laravel-mix": "^6.0.16",
|
||||
"laravel-mix-polyfill": "^3.0.1",
|
||||
|
|
|
|||
3
resources/js/app.js
vendored
3
resources/js/app.js
vendored
|
|
@ -1,5 +1,6 @@
|
|||
require('./bootstrap');
|
||||
window.Vue = require('vue/dist/vue.min.js');
|
||||
//window.Vue = require('vue/dist/vue.min.js');
|
||||
import Vue from 'vue'
|
||||
import moment from 'moment'
|
||||
import vSelect from "vue-select"
|
||||
|
||||
|
|
|
|||
796
resources/js/components/ScheduleComponent.vue
Normal file
796
resources/js/components/ScheduleComponent.vue
Normal file
|
|
@ -0,0 +1,796 @@
|
|||
<template>
|
||||
<div class="plannings">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-1 text-center actions_col">
|
||||
<a class="sticky-top btn btn-primary mt-5" @click="goToPlanning(false)">←</a>
|
||||
</div>
|
||||
|
||||
<div class="col-10">
|
||||
<table class="table table-bordered align-middle text-center schedules_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th rowspan="2" >
|
||||
|
||||
</th>
|
||||
<th :colspan="showWeekends ? 7:5" v-for="item in weeksCells" class="Mon Fri" :key="item.num">
|
||||
S {{item.num}} - {{item.month}} {{item.year}}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th v-for="day in days" :class="'day '+day.eday" :key="day.num">
|
||||
{{day.day}} {{day.num}}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<template v-for="(user,index) in schedules">
|
||||
<tr v-for="(slot,key) in user" :key="index + '' + key">
|
||||
<td rowspan="4" class="resource_ident" v-if="key == 1">
|
||||
{{users[index].name}}
|
||||
</td>
|
||||
<td v-for="day in days" :class="'dynCell day '+user[key][day.key].type.value+ ' ' +day.eday" :key="day.key">
|
||||
<div class="cellsizer">
|
||||
<b v-if="user[key][day.key]['model_lie']['value']">
|
||||
<a target="_blank" class="text-light bg-dark"
|
||||
:href="getCellObjectInfo(user[key][day.key]).url">
|
||||
{{user[key][day.key]['id_lie']['label']}}
|
||||
</a>
|
||||
</b><br/>
|
||||
{{user[key][day.key]['text']}}
|
||||
</div>
|
||||
<button class="btn btn-edit" type="button" data-bs-toggle="modal"
|
||||
data-bs-target="#editModal" @click="setModalData(index,key,day.key,user[key][day.key]['id'])">✎</button>
|
||||
<button :class="'btn btn-paste '+(!clipBoard.set ? 'hide' : '') " type="button"
|
||||
@click="pasteCell(index,key,day.key,user[key][day.key]['id'])">📋</button>
|
||||
<button class="btn btn-copy" type="button"
|
||||
@click="copyCell(index,key,day.key,user[key][day.key]['id'])">
|
||||
<span style="font-size: .875em; margin-right: .125em; position: relative; top: -.25em; left: -.125em">
|
||||
📄<span style="position: absolute; top: .25em; left: .25em">📄</span>
|
||||
</span></button>
|
||||
<button :class="'btn btn-clear '+(!user[key][day.key]['id'] ? 'hide' : '')" @click="eraseCell(index,key,day.key,user[key][day.key]['id'])">⌫</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-1 text-center actions_col">
|
||||
<a class="sticky-top btn btn-primary mt-5" @click="goToPlanning(true)">→</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal -->
|
||||
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="modalLabel" aria-hidden="true" >
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="modalLabel" ref="modalLabel">{{modale.title}}</h5>
|
||||
<button ref="close" type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close" ></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div v-if="error" class="alert alert-danger" role="alert">
|
||||
{{ error }}
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<div class="form-group mb-3">
|
||||
<label for="categorie" class="col-form-label text-md-right ms-5">Categorie</label>
|
||||
<select id="categorie" ref="type" class="form-select" aria-label="Sélectionnez une catégorie">
|
||||
<option value="" >Sélectionnez une catégorie</option>
|
||||
<option v-for="activity in activities" :key="activity.value" :value="activity.value"
|
||||
:selected="modale.activity.value == activity.value"
|
||||
:class="activity.value">{{ activity.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<label for="morph" class="col-form-label text-md-right ms-5">Type d'élément lié</label>
|
||||
<select id="morph" ref="morph" class="form-select" @change="selectChange" aria-label="Sélectionnez un élément à lier">
|
||||
<option value="">Sélectionnez un type d'objet à lier</option>
|
||||
<option v-for="model in models" :key="model.value" :value="model.value"
|
||||
:selected="modale.model_lie.value == model.value"
|
||||
>{{ model.label }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group mb-3" v-if="modale.dDisplay">
|
||||
<label for="select_id_lie" class="col-form-label text-md-right ms-5">Élément lié</label>
|
||||
<v-select
|
||||
id="select_id_lie"
|
||||
ref="select"
|
||||
:loading="loading"
|
||||
v-model="value"
|
||||
:clearable="false"
|
||||
label="label"
|
||||
:options='data'
|
||||
@search="search"
|
||||
:disabled="dReadonly||dDisabled"
|
||||
:filterable="true"
|
||||
:searchable="true"
|
||||
@input="setSelected">
|
||||
<li slot="list-footer" class="pagination">
|
||||
<button
|
||||
@click="$event.preventDefault(); page -= 1"
|
||||
:disabled="!hasPrevPage"
|
||||
class="btn btn-sm btn-primary mt-2 mb-2 ms-2 me-2">Précédent</button>
|
||||
<button
|
||||
@click="$event.preventDefault(); page += 1"
|
||||
:disabled="!hasNextPage"
|
||||
class="btn btn-sm btn-primary mt-2 mb-2">Suivant</button>
|
||||
</li>
|
||||
</v-select>
|
||||
</div>
|
||||
<div class="form-group mb-3">
|
||||
<label for="text" class="col-form-label text-md-right ms-5">Description courte</label>
|
||||
<textarea ref="text" class="form-control" name="text"
|
||||
id="text" rows="2" placeholder="" @keydown="limitLines($event)" v-model="modale.text"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8 text-center">
|
||||
<button class="btn btn-primary me-3" @click="saveCell()">Valider</button>
|
||||
<button class="btn btn-danger" @click="$refs.close.click()">Fermer</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Toastify from 'toastify-js'
|
||||
export default {
|
||||
props: {
|
||||
dbSchedules: {
|
||||
type: String,
|
||||
},
|
||||
dbActivities: {
|
||||
type: String,
|
||||
},
|
||||
dbModels: {
|
||||
type: String,
|
||||
},
|
||||
dbUsers: {
|
||||
type: String,
|
||||
},
|
||||
weeks: {
|
||||
type: String,
|
||||
},
|
||||
browseDate: {
|
||||
type: String,
|
||||
default: function() {
|
||||
return new Date();
|
||||
}
|
||||
},
|
||||
showWeekends: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.Toastify = Toastify
|
||||
this.currentDate = JSON.parse(this.browseDate);
|
||||
this.weeksCells = JSON.parse(this.weeks);
|
||||
this.numweeks = this.weeksCells.length;
|
||||
this.days = this.prepareDays();
|
||||
this.users = JSON.parse(this.dbUsers);
|
||||
this.schedules = this.prepareSched(JSON.parse(this.dbSchedules));
|
||||
this.activities = JSON.parse(this.dbActivities);
|
||||
this.models = JSON.parse(this.dbModels);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentDate: null,
|
||||
weeksCells: [],
|
||||
days: [],
|
||||
users:[],
|
||||
schedules: [],
|
||||
activities: [],
|
||||
models: [],
|
||||
error: '',
|
||||
modale:{
|
||||
id: null,
|
||||
userid: 0,
|
||||
slot: 0,
|
||||
day: '01/01/1900',
|
||||
title: 0,
|
||||
dDisplay: false,
|
||||
text: '',
|
||||
activity: {
|
||||
label: '',
|
||||
value: '',
|
||||
},
|
||||
model_lie: {
|
||||
label: '',
|
||||
value: '',
|
||||
},
|
||||
id_lie: {
|
||||
label: '',
|
||||
value: '',
|
||||
},
|
||||
},
|
||||
//v-select de ses morts
|
||||
dDisabled : false,
|
||||
dReadonly : false,
|
||||
loading: false,
|
||||
value: {
|
||||
label: null,
|
||||
value: null
|
||||
},
|
||||
searchText: '',
|
||||
data: [],
|
||||
page: 1,
|
||||
perPage: 15,
|
||||
hasNextPage: true,
|
||||
hasPrevPage: false,
|
||||
emptyCell: {
|
||||
"type": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"text":"",
|
||||
"id_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"model_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"id":null
|
||||
},
|
||||
clipBoard: {
|
||||
"set": false,
|
||||
"type": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"text":"",
|
||||
"id_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"model_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"id":null
|
||||
},
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
page() {
|
||||
if(this.page < 1) {
|
||||
this.page = 1
|
||||
}
|
||||
if(this.page > 1) {
|
||||
this.hasPrevPage = true
|
||||
} else {
|
||||
this.hasPrevPage = false
|
||||
}
|
||||
this.search()
|
||||
},
|
||||
data() {
|
||||
if(this.data.length == this.perPage) {
|
||||
this.hasNextPage = true
|
||||
} else {
|
||||
this.hasNextPage = false
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
sendToast(message) {
|
||||
Toastify({
|
||||
text: message,
|
||||
duration: 3000,
|
||||
gravity: "top",
|
||||
position: "right",
|
||||
offset: {
|
||||
x: '2rem',
|
||||
y: '3rem'
|
||||
},
|
||||
style: {
|
||||
background: "linear-gradient(to right, #00317d, #0058ca)",
|
||||
}
|
||||
}).showToast();
|
||||
},
|
||||
goToPlanning(forward) {
|
||||
// console.log(forward);
|
||||
let date = this.moment(this.currentDate).startOf('week').subtract(7, 'day');
|
||||
if(forward) {
|
||||
date = this.moment(this.currentDate).add(7, 'day')
|
||||
}
|
||||
let url = new URL(this.route('schedule.index'))
|
||||
location = url.origin+ url.pathname + '?p='+date.format('DD/MM/YYYY')
|
||||
},
|
||||
prepareDays() {
|
||||
let mydays = [];
|
||||
for(let i=0; i < this.numweeks * 7; i++) {
|
||||
let date = this.moment(this.currentDate).add(i, 'day');
|
||||
let obj = {
|
||||
day: date.format('ddd'),
|
||||
num: date.format('DD'),
|
||||
eday: date.locale("en").format('ddd'),
|
||||
key: date.format('DD/MM/YYYY'),
|
||||
}
|
||||
mydays.push(obj);
|
||||
if(!this.showWeekends) {
|
||||
if(date.day() == 5) {
|
||||
i+=2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mydays;
|
||||
},
|
||||
prepareSched(dbscheds) {
|
||||
var templateObj = {
|
||||
"type": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"text":"",
|
||||
"id_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"model_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"id":null}
|
||||
//we need to make missing users
|
||||
Object.keys(this.users).forEach(id => {
|
||||
if(dbscheds[id] === undefined) {
|
||||
dbscheds[id] = {};
|
||||
}
|
||||
});
|
||||
Object.keys(dbscheds).forEach(userid => {
|
||||
//what if we missing a slot for the whole period ?
|
||||
//we need to make missing slots too
|
||||
for(let i=1; i < 5; i++) {
|
||||
if(dbscheds[userid][i] === undefined) {
|
||||
dbscheds[userid][i] = {};
|
||||
}
|
||||
}
|
||||
Object.keys(dbscheds[userid]).forEach(slotkey => {
|
||||
this.days.forEach(day => {
|
||||
if(dbscheds[userid][slotkey][day.key] === undefined) {
|
||||
//console.log('need ' + day.key + ' for slot ' + slotkey + ' for user ' + userid);
|
||||
dbscheds[userid][slotkey][day.key] = templateObj;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
return dbscheds;
|
||||
},
|
||||
getCellObjectInfo(cellData) {
|
||||
for(let model of this.models) {
|
||||
if(cellData['model_lie'].value === model.value && model.value == 'tickets') {
|
||||
return {
|
||||
'url': this.route('ticket.show', { TICKET: cellData['id_lie'].value }),
|
||||
'text': cellData['model_lie'].label
|
||||
}
|
||||
}
|
||||
if(cellData['model_lie'].value === model.value && model.value == 'sites') {
|
||||
return {
|
||||
'url': this.route('sites.show', { SITE: cellData['id_lie'].value}),
|
||||
'text': cellData['model_lie'].label
|
||||
}
|
||||
}
|
||||
if(cellData['model_lie'].value === model.value && model.value == 'projects') {
|
||||
return {
|
||||
'url': this.route('projects.show', { PROJECT: cellData['id_lie'].value}),
|
||||
'text': cellData['model_lie'].label
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
},
|
||||
resetModalFields() {
|
||||
this.$set(this, 'currentType' , null)
|
||||
this.$set(this, 'value' , {
|
||||
label: null,
|
||||
value: null
|
||||
})
|
||||
this.$refs.type.value = ''
|
||||
this.$refs.morph.value = ''
|
||||
},
|
||||
setModalData(userid,slotkey,day,id) {
|
||||
let text = this.schedules[userid][slotkey][day]['text'];
|
||||
let activity = this.schedules[userid][slotkey][day]['type'];
|
||||
let model = this.schedules[userid][slotkey][day]['model_lie'];
|
||||
let enumobject = {
|
||||
label: '',
|
||||
value: '',
|
||||
};
|
||||
let currentModale = {
|
||||
id: this.schedules[userid][slotkey][day]['id'],
|
||||
userid: userid,
|
||||
slot: slotkey,
|
||||
day: day,
|
||||
title: id,
|
||||
dDisplay: false,
|
||||
text: text,
|
||||
activity: activity,
|
||||
model_lie: model ?? enumobject,
|
||||
id_lie: this.schedules[userid][slotkey][day]['id_lie'],
|
||||
}
|
||||
this.modale = currentModale;
|
||||
this.$nextTick(() => {
|
||||
let route = null
|
||||
switch(this.modale.model_lie.value) {
|
||||
case 'tickets':
|
||||
this.dDisplay = true
|
||||
route = this.route('ticket.show', {
|
||||
TICKET: this.modale.id_lie
|
||||
})
|
||||
break
|
||||
case 'projects':
|
||||
this.dDisplay = true
|
||||
route = this.route('projects.show', {
|
||||
PROJECT: this.modale.id_lie
|
||||
})
|
||||
break
|
||||
case 'sites':
|
||||
this.dDisplay = true
|
||||
route = this.route('sites.show', {
|
||||
SITE: this.modale.id_lie
|
||||
})
|
||||
break
|
||||
default: this.dDisplay = false
|
||||
}
|
||||
this.selectChange();
|
||||
this.value = this.schedules[userid][slotkey][day]['id_lie'];
|
||||
})
|
||||
},
|
||||
pasteCell(userid,slotkey,day,id) {
|
||||
//this.eraseCell(userid,slotkey,day,id)
|
||||
const data = {
|
||||
'id': id,
|
||||
'user_id': userid,
|
||||
'date': day,
|
||||
'activity': this.clipBoard.activity.value,
|
||||
'slot': slotkey,
|
||||
'model_lie': this.clipBoard.model_lie.value,
|
||||
'id_lie': this.clipBoard.id_lie.value,
|
||||
'description': this.clipBoard.description,
|
||||
}
|
||||
this.saveCellOnServer(data)
|
||||
this.clearClipBoard()
|
||||
this.sendToast('Cellule collée')
|
||||
},
|
||||
clearClipBoard() {
|
||||
this.clipBoard = {
|
||||
"set": false,
|
||||
"type": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"text":"",
|
||||
"id_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"model_lie": {
|
||||
"label":"",
|
||||
"value":""
|
||||
},
|
||||
"id":null
|
||||
}
|
||||
},
|
||||
copyCell(userid,slotkey,day,id) {
|
||||
this.clipBoard = {
|
||||
'set' : true,
|
||||
'id': id,
|
||||
'user_id': userid,
|
||||
'date': day,
|
||||
'activity': this.schedules[userid][slotkey][day].type,
|
||||
'slot': slotkey,
|
||||
'model_lie': this.schedules[userid][slotkey][day].model_lie,
|
||||
'id_lie': this.schedules[userid][slotkey][day].id_lie,
|
||||
'description': this.schedules[userid][slotkey][day].text,
|
||||
}
|
||||
this.sendToast('Cellule copiée')
|
||||
},
|
||||
setSelected(value) {
|
||||
this.modale.id_lie = value;
|
||||
},
|
||||
search (search = null) {
|
||||
this.$nextTick(() => {
|
||||
this.error = null
|
||||
let route;
|
||||
switch(this.$refs.morph.value) {
|
||||
case 'tickets':
|
||||
route = this.route('ticket.index')
|
||||
break
|
||||
case 'projects':
|
||||
route = this.route('projects.index')
|
||||
break
|
||||
case 'sites':
|
||||
route = this.route('sites.index')
|
||||
break
|
||||
default: return
|
||||
}
|
||||
if(search !== false && search !== null) {
|
||||
this.searchText = search
|
||||
}
|
||||
let init = search === false ? true : false
|
||||
route += '?page='+this.page
|
||||
route += '&s='+this.searchText
|
||||
this.loading = true
|
||||
axios.get(route)
|
||||
.then(response => {
|
||||
this.data = response.data
|
||||
})
|
||||
.catch(error => {
|
||||
if(error.response.status === 429) {
|
||||
location.reload()
|
||||
}
|
||||
this.error = error
|
||||
}).then(() => {
|
||||
this.loading = false
|
||||
})
|
||||
});
|
||||
},
|
||||
saveCell() {
|
||||
this.error = false
|
||||
const data = {
|
||||
'id': this.modale.id,
|
||||
'user_id': this.modale.userid,
|
||||
'date': this.modale.day,
|
||||
'activity': this.$refs.type.value,
|
||||
'slot': this.modale.slot,
|
||||
'model_lie': this.$refs.morph.value,
|
||||
'id_lie': this.value.value,
|
||||
'description': this.$refs.text.value,
|
||||
}
|
||||
this.saveCellOnServer(data)
|
||||
},
|
||||
saveCellOnServer(data) {
|
||||
this.error = false
|
||||
axios.post(this.route('schedule.setCellContent'), data)
|
||||
.then(response => {
|
||||
if(response.data.status) {
|
||||
let sched = response.data.sched;
|
||||
// sched.date = Date.parse(sched.date)
|
||||
// sched.date = this.moment(sched.date).format('DD/MM/YYYY');
|
||||
let cellData = {
|
||||
"type": sched.activity,
|
||||
"text": sched.description,
|
||||
"id_lie": sched.id_lie,
|
||||
"model_lie": sched.model_lie,
|
||||
"id": sched.id
|
||||
};
|
||||
this.$set(this.schedules[sched.user_id][sched.slot], sched.date, cellData);
|
||||
this.$refs.close.click()
|
||||
} else {
|
||||
this.error = 'Réponse inconnue';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.log(error);
|
||||
if(error.response.status === 429) {
|
||||
location.reload()
|
||||
}
|
||||
if(error.response.status === 422) {
|
||||
if(error.response.data.errors) {
|
||||
this.error = ''
|
||||
for(let id in error.response.data.errors) {
|
||||
let field = error.response.data.errors[id]
|
||||
this.error += field.join('\n') + '\n'
|
||||
}
|
||||
return
|
||||
} else if(error.response.data.message) {
|
||||
this.error = error.response.data.message
|
||||
return
|
||||
}
|
||||
}
|
||||
this.error = error
|
||||
})
|
||||
},
|
||||
eraseCell(userid,slotkey,day,id) {
|
||||
const data = {
|
||||
'id': id,
|
||||
}
|
||||
axios.post(this.route('schedule.eraseCellContent'), data)
|
||||
.then(response => {
|
||||
if(response.data.status) {
|
||||
this.$set(this.schedules[userid][slotkey], day, this.emptyCell);
|
||||
} else {
|
||||
console.error('Unknown response')
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if(error.response.status === 429) {
|
||||
location.reload()
|
||||
}
|
||||
console.error(error)
|
||||
})
|
||||
},
|
||||
selectChange() {
|
||||
this.value = {
|
||||
label: null,
|
||||
value: null
|
||||
}
|
||||
switch(this.$refs.morph.value) {
|
||||
case 'tickets':
|
||||
case 'projects':
|
||||
case 'sites':
|
||||
this.modale.dDisplay = true
|
||||
this.search(false)
|
||||
break
|
||||
default: this.modale.dDisplay = false
|
||||
}
|
||||
},
|
||||
limitLines(e) {
|
||||
let keynum, lines = this.$refs.text.value.split('\n').length;
|
||||
// IE
|
||||
if(window.event) {
|
||||
keynum = e.keyCode;
|
||||
// Netscape/Firefox/Opera
|
||||
} else if(e.which) {
|
||||
keynum = e.which;
|
||||
}
|
||||
if(keynum != 8 && this.$refs.text.value.length >= this.textLimit) {
|
||||
e.preventDefault()
|
||||
return false;
|
||||
}
|
||||
if(keynum == 13 && lines == this.$refs.text.rows) {
|
||||
e.preventDefault()
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "vue-select/src/scss/vue-select.scss";
|
||||
|
||||
.actions_col {
|
||||
width: 45px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.plannings {
|
||||
.sticky-top {
|
||||
top: 20rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
.Mon {
|
||||
border-left: 4px solid;
|
||||
}
|
||||
// .Fri {
|
||||
// border-right: 4px solid;
|
||||
// }
|
||||
}
|
||||
|
||||
table.schedules_table {
|
||||
table-layout: fixed;
|
||||
|
||||
.resource_ident {
|
||||
font-weight: bold;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.cellsizer {
|
||||
height: 150px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
|
||||
b {
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dynCell{
|
||||
position: relative;
|
||||
|
||||
&.day {
|
||||
//position: relative;
|
||||
&:hover .btn {
|
||||
opacity: 1;
|
||||
}
|
||||
$buttonBgColor: #4d4d4d;
|
||||
|
||||
// Reset button Style to nice one
|
||||
button {
|
||||
display: inline;
|
||||
border: none;
|
||||
padding: 0.6rem 3rem;
|
||||
margin: 0;
|
||||
text-decoration: none;
|
||||
background: $buttonBgColor;
|
||||
font-size: 1rem;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
transition: background 250ms ease-in-out, transform 150ms ease;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
}
|
||||
|
||||
button:disabled,
|
||||
button[disabled] {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
button:hover,
|
||||
button:focus {
|
||||
background: darken($buttonBgColor, 10%);
|
||||
}
|
||||
|
||||
button:focus {
|
||||
outline: 1px solid #fff;
|
||||
outline-offset: -4px;
|
||||
}
|
||||
|
||||
button:active {
|
||||
transform: scale(0.99);
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
top: 0.1rem;
|
||||
right: 0.1rem;
|
||||
padding: 0;
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
margin: 0;
|
||||
background-color: $buttonBgColor;
|
||||
opacity: 0;
|
||||
transition: 200ms opacity;
|
||||
&.hide {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: darken($buttonBgColor, 10%);
|
||||
}
|
||||
&.btn-clear {
|
||||
color: darken($color: #fff, $amount: 5);
|
||||
}
|
||||
&:nth-last-child(2) {
|
||||
right: inherit;
|
||||
left: 0.1rem;
|
||||
}
|
||||
&:nth-last-child(3) {
|
||||
right: inherit;
|
||||
top: 2.1rem;
|
||||
left: 0.1rem;
|
||||
}
|
||||
&:nth-last-child(1) {
|
||||
top: 2.1rem;
|
||||
right: 0.1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@import "toastify-js/src/toastify.css";
|
||||
@import "vue-select/src/scss/vue-select.scss";
|
||||
.planning {
|
||||
overflow: auto;
|
||||
|
||||
td {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
#text {
|
||||
height: 5.5rem;
|
||||
padding: 1rem 2rem;
|
||||
resize: none;
|
||||
width: 37rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -24,6 +24,7 @@
|
|||
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.16/dist/sweetalert2.min.css" integrity="sha256-qpXwccFYncH5gTqXFe9EXZ8QeDw1Re68bbNVfFZzIzg=" crossorigin="anonymous">
|
||||
@crudPoliciesCSS
|
||||
@stack('customCss')
|
||||
</head>
|
||||
<body>
|
||||
@include('layout.nav')
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<a class="nav-link @if(strpos(request()->route()->getName(), 'users') === 0)active @endif" href="{{ route('users.index') }}">Utilisateurs</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @if(strpos(request()->route()->getName(), 'planning') === 0)active @endif" href="{{ route('planning.index') }}">{{ __('Planning') }}</a>
|
||||
<a class="nav-link @if(strpos(request()->route()->getName(), 'schedule') === 0)active @endif" href="{{ route('schedule.index') }}">{{ __('Planning') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
@endif
|
||||
|
|
|
|||
68
resources/views/schedule/index.blade.php
Normal file
68
resources/views/schedule/index.blade.php
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
@extends('layout.app')
|
||||
|
||||
|
||||
|
||||
@section('content')
|
||||
<div id="planning" class="container container-xxl vueComponent">
|
||||
<div class="row mb-3 sticky-top bg-white">
|
||||
<div class="col-2">
|
||||
<h1><a href="{{ route('schedule.index') }}">{{__('Planning') }}</a></h1>
|
||||
</div>
|
||||
<div class="col pt-2">
|
||||
<h4 class="d-inline me-3">Légende</h4>
|
||||
<div class="d-inline">
|
||||
@foreach(CellType::toArray() as $type)
|
||||
<span style="background-color: {{ $type->value }}; border: 1px solid black;">{{ $type->label }}</span>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<schedule-component
|
||||
browse-date='@json($date)'
|
||||
db-schedules='@json($arSchedules)'
|
||||
db-activities='@json(ActivityType::toArray())'
|
||||
db-models='@json(CellModel::toArray())'
|
||||
db-users='@json($users)'
|
||||
weeks='@json($weekCells)'
|
||||
v-bind:show-weekends='false'></schedule-component>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@push('scriptsConstants')
|
||||
<script>
|
||||
window._routes = {
|
||||
"schedule.index": "{{ route('schedule.index') }}",
|
||||
"ticket.show": "{{ route('ticket.show', 'TICKET') }}",
|
||||
"projects.show": "{{ route('projects.show', 'PROJECT') }}",
|
||||
"sites.show": "{{ route('sites.show', 'SITE') }}",
|
||||
"ticket.index": "{{ route('ticket.index') }}",
|
||||
"projects.index": "{{ route('projects.index') }}",
|
||||
"sites.index": "{{ route('sites.index') }}",
|
||||
"schedule.setCellContent": "{{ route('schedule.setCellContent') }}",
|
||||
"schedule.eraseCellContent": "{{ route('schedule.eraseCellContent') }}"
|
||||
};
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@push('customCss')
|
||||
<style>
|
||||
.support {
|
||||
background-color: {{CellType::support()->value}} !important;
|
||||
}
|
||||
.rnd {
|
||||
background-color: {{CellType::rnd()->value}} !important;
|
||||
}
|
||||
.dev {
|
||||
background-color: {{CellType::dev()->value}} !important;
|
||||
}
|
||||
.projects {
|
||||
background-color: {{CellType::projects()->value}} !important;
|
||||
}
|
||||
.management {
|
||||
background-color: {{CellType::management()->value}} !important;
|
||||
}
|
||||
.absence, .Sat, .Sun {
|
||||
background-color: {{CellType::absence()->value}} !important;
|
||||
}
|
||||
</style>
|
||||
@endpush
|
||||
|
|
@ -5,6 +5,7 @@ use App\Http\Controllers\HomeController;
|
|||
use App\Http\Controllers\LogController;
|
||||
use App\Http\Controllers\PlanningController;
|
||||
use App\Http\Controllers\ProjectController;
|
||||
use App\Http\Controllers\ScheduleController;
|
||||
use App\Http\Controllers\SiteController;
|
||||
use App\Http\Controllers\TicketController;
|
||||
use App\Http\Controllers\UserController;
|
||||
|
|
@ -82,4 +83,12 @@ Route::middleware(['auth'])->group(function () {
|
|||
Route::post('/eraseCellContent', [PlanningController::class, 'eraseCellContent'])
|
||||
->name('eraseCellContent');
|
||||
});
|
||||
|
||||
Route::prefix('/schedule')->name('schedule.')->group(function () {
|
||||
Route::get('/', [ScheduleController::class, 'index'])->name('index');
|
||||
Route::post('/setCellContent', [ScheduleController::class, 'setCellContent'])
|
||||
->name('setCellContent');
|
||||
Route::post('/eraseCellContent', [ScheduleController::class, 'eraseCellContent'])
|
||||
->name('eraseCellContent');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue