Skip to content

Commit

Permalink
Merge pull request #27 from HE-Arc/9-timeline-edit-logic
Browse files Browse the repository at this point in the history
9 timeline edit logic
  • Loading branch information
katsulon authored Dec 17, 2024
2 parents d92a645 + d5df4b5 commit 3f8b618
Show file tree
Hide file tree
Showing 13 changed files with 342 additions and 48 deletions.
105 changes: 104 additions & 1 deletion timeliner/app/Http/Controllers/TimelineController.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public function store(Request $request)
'nodes.*.milestones.*.description' => 'nullable|string|max:255',
]);

$timeline = Timeline::create(['name' => $validated['name'], 'description' => $validated['description'], 'private'=> $validated['private']]);
$timeline = Timeline::create(['name' => $validated['name'], 'description' => $validated['description'], 'private'=> !$validated['private']]);
Ownership::create(['id' => $timeline->id . Auth::user()->id]);

if (!empty($validated['nodes'])) {
Expand All @@ -106,4 +106,107 @@ public function store(Request $request)
return redirect()->route('timeline.index')
->with('success','Timeline created successfully.');
}

public function edit($id)
{
$timeline = Timeline::findOrFail($id);

if(($timeline != null) && (Auth::check() && Ownership::find($timeline->id . Auth::user()->id)))
{
$nodes = Node::where('timeline','=',$timeline->id)
->with('milestones')
->get();

return view('timeline.edit', ['timeline' => $timeline, 'nodes' => $nodes]);
}

return redirect()->route('timeline.show', $id)
->withErrors(["You don't have access."]);
}

public function update(Request $request, $id)
{
$timeline = Timeline::findOrFail($id);

if (($timeline != null) && (!$timeline->private || (Auth::check() && Ownership::find($timeline->id . Auth::user()->id)))) {

$request->merge([
'private' => $request->has('private'),
]);

$validated = $request->validate([
'name' => 'required|max:50',
'description' => 'required|max:200',
'private' => 'required|boolean',
'nodes' => 'nullable|array',
'nodes.*.name' => 'required|string|max:255',
'nodes.*.milestones' => 'nullable|array',
'nodes.*.milestones.*.date' => 'required|date',
'nodes.*.milestones.*.description' => 'nullable|string|max:255',
]);

// Update timeline details
$timeline->update([
'name' => $validated['name'],
'description' => $validated['description'],
'private' => !$validated['private']
]);

// Handle nodes
if (!empty($validated['nodes'])) {
// First, delete any nodes that were removed from the form
$existingNodeIds = collect($validated['nodes'])->pluck('id')->filter();
Node::where('timeline', $timeline->id)
->whereNotIn('id', $existingNodeIds)
->delete();

// Update existing nodes or create new ones
foreach ($validated['nodes'] as $nodeData) {
if (isset($nodeData['id'])) {
// Update existing node
$node = Node::findOrFail($nodeData['id']);
$node->update([
'name' => $nodeData['name'],
'color' => '#FFFFFF', // Default color (you can adjust this)
]);
} else {
// Create new node
$node = Node::create([
'name' => $nodeData['name'],
'color' => '#FFFFFF', // Default color (you can adjust this)
'timeline' => $timeline->id,
]);
}

// Handle milestones
if (!empty($nodeData['milestones'])) {
foreach ($nodeData['milestones'] as $milestoneData) {
if (isset($milestoneData['id'])) {
// Update existing milestone
$milestone = Milestone::findOrFail($milestoneData['id']);
$milestone->update([
'date' => $milestoneData['date'],
'description' => $milestoneData['description'] ?? null,
]);
} else {
// Create new milestone
Milestone::create([
'date' => $milestoneData['date'],
'description' => $milestoneData['description'] ?? null,
'node' => $node->id
]);
}
}
}
}
}

return redirect()->route('timeline.show', $id)
->with('success', 'Timeline updated successfully.');
}

return redirect()->route('timeline.index')
->withErrors(["You don't have access."]);
}

}
2 changes: 0 additions & 2 deletions timeliner/database/seeders/DatabaseSeeder.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,5 @@ public function run(): void
$this->call(CommentSeeder::class);
$this->call(NodeSeeder::class);
$this->call(MilestoneSeeder::class);

DB::statement('PRAGMA foreign_keys=ON;');
}
}
2 changes: 1 addition & 1 deletion timeliner/resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import './timelinelistener';
import './formfunctions';
import './createformfunctions';

import './bootstrap-toggle.min.js'
import './bootstrap-toggle.min'


import Alpine from 'alpinejs';
Expand Down
20 changes: 11 additions & 9 deletions timeliner/resources/js/createformfunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ Author: Brandt Mael
*/


let ni = 0; // node index
let ni = window.ni || 0; // use global ni if set, else defaults to 0
let mi = 0; // milestone index

window.addMilestone = addMilestone; // makes the function available to the global scope

//add a row to a list of milestone creation form
function addMilestone(milestone_list_id, nodeIndex, nodeMilestoneCount) {
const ms_id = `ms-${nodeIndex}-${nodeMilestoneCount}` // the id of the milestone depend of it's parent node
Expand Down Expand Up @@ -43,10 +45,10 @@ function addMilestone(milestone_list_id, nodeIndex, nodeMilestoneCount) {
// create delete button
let delete_button = document.createElement('button');
let delete_button_id = "ms-delete-button-" + mi;
delete_button.setAttribute("class", "btn btn-primary");
delete_button.setAttribute("class", "btn btn-danger bi bi-trash");
delete_button.setAttribute("type", "button");
delete_button.setAttribute("id", delete_button_id);
delete_button.innerHTML += 'delete';
delete_button.innerHTML += ' delete';

// add listener to delete_button
delete_button.addEventListener('click', function() {
Expand Down Expand Up @@ -78,10 +80,10 @@ if (nodeCreateButton) {
nodeCreateButton.addEventListener('click', function() {

// recover the node table
let node_table = document.getElementById('node-list');
let node_table = document.getElementById('node-list-body');

// declare new row of milestone table
let tr_node_form = document.createElement("div"); // row holding the node form
let tr_node_form = document.createElement("tr"); // row holding the node form
let tr_milestone_table = document.createElement("tr"); // row holding the milestone table

let td_label = document.createElement("td");
Expand Down Expand Up @@ -129,10 +131,10 @@ if (nodeCreateButton) {
// create 'add milestone' button
let add_milestone_button = document.createElement('button');
let milestone_create_button_id = "milestone-create-button-" + ni;
add_milestone_button.setAttribute("class", "btn btn-primary");
add_milestone_button.setAttribute("class", "btn btn-primary bi bi-calendar-plus");
add_milestone_button.setAttribute("type", "button");
add_milestone_button.setAttribute("id", milestone_create_button_id);
add_milestone_button.innerHTML += 'create milestone';
add_milestone_button.innerHTML += ' create milestone';

let current_ni_number = ni;
let nodeMilestoneCount = 0;
Expand All @@ -145,10 +147,10 @@ if (nodeCreateButton) {
// create delete button
let delete_button = document.createElement('button');
let delete_button_id = "node-delete-button-" + ni;
delete_button.setAttribute("class", "btn btn-primary");
delete_button.setAttribute("class", "btn btn-danger bi bi-trash ");
delete_button.setAttribute("type", "button");
delete_button.setAttribute("id", delete_button_id);
delete_button.innerHTML += 'delete';
delete_button.innerHTML += ' delete';

// add listener to delete_button
delete_button.addEventListener('click', function() {
Expand Down
2 changes: 0 additions & 2 deletions timeliner/resources/views/index.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
</h2>
</x-slot>

<x-notification/>

<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
Expand Down
2 changes: 2 additions & 0 deletions timeliner/resources/views/layouts/app.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
</div>
</header>
@endisset

<x-notification/>

<main>
{{ $slot }}
Expand Down
2 changes: 1 addition & 1 deletion timeliner/resources/views/layouts/navigation.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
</x-nav-link>
</div>
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('createtimeline')" :active="request()->routeIs('createtimeline')">
<x-nav-link :href="route('timeline.create')" :active="request()->routeIs('createtimeline')">
{{ __('Create timeline') }}
</x-nav-link>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,29 +44,16 @@
</div>

<div class="form-group col-6">
<button class="btn btn-primary" href={{ route('timeline.create') }} type="submit" class="btn btn-primary mt-3">Add</button>
<button class="btn btn-primary" href={{ route('timeline.create') }} type="submit" class="btn btn-primary mt-3 "><i class="bi bi-plus-lg"></i> Add</button>
</div>
<div class="form-group col-6">
</div>
</div>
</div>
</div>

@if ($errors->any())
<div class="alert alert-danger mt-3 col-12">
<strong>Oops!</strong> There's a problem with your entries.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
</div>
</div>
</form>


</x-app-layout>


57 changes: 57 additions & 0 deletions timeliner/resources/views/timeline/edit.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
{{ __('Edit timeline ') . $timeline->name }}
</h2>
</x-slot>

<form action="{{ route("timeline.update", $timeline->id) }}" method="POST">
@csrf
@method('PUT')
<div class="row">
<div class="col-12 col-lg-6 offset-0 offset-lg-3">
<div class="card">
<div class="card-header">
Edit timeline
</div>
<div class="card-body">
<div class="form-row">
<div class="form-group col-12">
<label for="inputTitle">Name</label>
<input type="text" name="name" value="{{ $timeline->name }}" class="form-control" id="inputTitle">
</div>

<!-- TODO accecpt several people as owners (fields for adding owners) -->

<div class="form-group col-12">
<label for="inputDescription">Description</label>
<input type="text" name="description" value="{{ $timeline->description }}" class="form-control" id="inputDescription">
</div>
<div class="form-group col-12">
<div class="row mt-3">
</div>

</div>
<div id="node-edit-form" class="form-group col-12">
@include('timeline.partials.nodeedit', ['nodes' => $nodes])
</div>

<div class="form-group col-12">
<label for="accesibility">Status (public/private)</label>
<input id="accesibility" name="private" type="checkbox" data-toggle="toggle" data-offstyle="secondary" data-on="Public" data-off="Private" data-width="90"{{ $timeline->private ? '' : 'checked' }}>
</div>

<div class="form-group col-6">
<a href="{{ route('timeline.show', $timeline->id) }}" class="btn btn-secondary mt-3"><i class="bi bi-arrow-90deg-left"></i> Back</a>

<button class="btn btn-success mt-3" type="submit"><i class="bi bi-check2"></i> Confirm</button>
</div>
<div class="form-group col-6"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</x-app-layout>
Loading

0 comments on commit 3f8b618

Please sign in to comment.