Add tags and fix completed
This commit is contained in:
parent
3e80ff4cdd
commit
8ce2538f01
21 changed files with 173 additions and 73 deletions
3
app.rb
3
app.rb
|
|
@ -6,6 +6,7 @@ require './app/models/user'
|
|||
require './app/models/area'
|
||||
require './app/models/project'
|
||||
require './app/models/task'
|
||||
require './app/models/tag'
|
||||
|
||||
require './app/helpers/authentication_helper'
|
||||
|
||||
|
|
@ -91,5 +92,7 @@ get '/' do
|
|||
end
|
||||
|
||||
get '/inbox' do
|
||||
@tasks = current_user.tasks.incomplete.where(project_id: nil).order(:name)
|
||||
|
||||
erb :inbox
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,4 +2,7 @@ class Project < ActiveRecord::Base
|
|||
belongs_to :user
|
||||
belongs_to :area, optional: true
|
||||
has_many :tasks, dependent: :destroy
|
||||
|
||||
scope :with_incomplete_tasks, -> { joins(:tasks).where(tasks: { completed: false }).distinct }
|
||||
scope :with_complete_tasks, -> { joins(:tasks).where(tasks: { completed: true }).distinct }
|
||||
end
|
||||
|
|
|
|||
4
app/models/tag.rb
Normal file
4
app/models/tag.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
class Tag < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
has_and_belongs_to_many :tasks
|
||||
end
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
class Task < ActiveRecord::Base
|
||||
belongs_to :user
|
||||
belongs_to :project, optional: true
|
||||
has_and_belongs_to_many :tags
|
||||
|
||||
default_scope { where(completed: false) }
|
||||
scope :complete, -> { where(completed: true) }
|
||||
scope :incomplete, -> { where(completed: false) }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ class User < ActiveRecord::Base
|
|||
has_many :areas
|
||||
has_many :projects
|
||||
has_many :tasks
|
||||
has_many :tags, dependent: :destroy
|
||||
|
||||
validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP }, uniqueness: true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
class Sinatra::Application
|
||||
get '/projects' do
|
||||
@projects_with_tasks = current_user.projects.includes(:tasks).order(:name)
|
||||
@projects_with_tasks = current_user.projects.with_incomplete_tasks.order(:name)
|
||||
@projects_with_tasks_complete = current_user.projects.with_complete_tasks.order(:name)
|
||||
|
||||
erb :'projects/index'
|
||||
end
|
||||
|
|
@ -14,9 +15,10 @@ class Sinatra::Application
|
|||
|
||||
post '/project/create' do
|
||||
project = current_user.projects.new(
|
||||
name: params[:name],
|
||||
name: params[:name],
|
||||
description: params[:description],
|
||||
area_id: params[:area_id].presence)
|
||||
area_id: params[:area_id].presence
|
||||
)
|
||||
|
||||
if project.save
|
||||
redirect '/'
|
||||
|
|
|
|||
|
|
@ -1,26 +1,45 @@
|
|||
class Sinatra::Application
|
||||
def update_task_tags(task, tags_json)
|
||||
return if tags_json.blank?
|
||||
|
||||
begin
|
||||
tag_names = JSON.parse(tags_json).map { |tag| tag['value'] }.uniq
|
||||
tags = tag_names.map do |name|
|
||||
current_user.tags.find_or_create_by(name: name)
|
||||
end
|
||||
task.tags = tags
|
||||
rescue JSON::ParserError
|
||||
puts "Failed to parse JSON for tags: #{tags_json}"
|
||||
end
|
||||
end
|
||||
|
||||
get '/tasks' do
|
||||
case params[:due_date]
|
||||
when 'today'
|
||||
today = Date.today
|
||||
@tasks = current_user.tasks.where(due_date: today.beginning_of_day..today.end_of_day, project: nil)
|
||||
@projects_with_tasks = current_user.projects
|
||||
.joins(:tasks)
|
||||
.where(tasks: { due_date: today.beginning_of_day..today.end_of_day })
|
||||
@tasks = current_user.tasks.incomplete.where('due_date <= ?', today.end_of_day).where(project: nil)
|
||||
|
||||
@projects_with_tasks = current_user.projects.with_incomplete_tasks
|
||||
.where('tasks.due_date <= ?', today.end_of_day)
|
||||
.distinct.order('projects.name ASC')
|
||||
|
||||
when 'upcoming'
|
||||
one_week_from_today = Date.today + 7.days
|
||||
@tasks = current_user.tasks.where(due_date: Date.today..one_week_from_today, project: nil)
|
||||
@projects_with_tasks = current_user.projects.includes(:tasks).where(tasks: { due_date: Date.today..one_week_from_today }).order('projects.name ASC')
|
||||
@tasks = current_user.tasks.incomplete.where(due_date: Date.today..one_week_from_today, project: nil)
|
||||
@projects_with_tasks = current_user.projects.with_incomplete_tasks.includes(:tasks).where(tasks: { due_date: Date.today..one_week_from_today }).order('projects.name ASC')
|
||||
|
||||
when 'never'
|
||||
@tasks = current_user.tasks.where(due_date: nil, project: nil)
|
||||
@projects_with_tasks = current_user.projects.includes(:tasks).where(tasks: { due_date: nil }).order('projects.name ASC')
|
||||
@tasks = current_user.tasks.incomplete.where(due_date: nil, project: nil)
|
||||
@projects_with_tasks = current_user.projects.with_incomplete_tasks.includes(:tasks).where(tasks: { due_date: nil }).order('projects.name ASC')
|
||||
|
||||
else
|
||||
@tasks = current_user.tasks.where(project: nil)
|
||||
@projects_with_tasks = current_user.projects.includes(:tasks).order('projects.name ASC')
|
||||
if params[:status] == 'completed'
|
||||
@tasks = current_user.tasks.complete.where(project: nil)
|
||||
@projects_with_tasks = current_user.projects.with_complete_tasks.includes(:tasks).order('projects.name ASC')
|
||||
else
|
||||
@tasks = current_user.tasks.incomplete.where(project: nil)
|
||||
@projects_with_tasks = current_user.projects.with_incomplete_tasks.includes(:tasks).order('projects.name ASC')
|
||||
end
|
||||
end
|
||||
|
||||
@tasks ||= []
|
||||
|
|
@ -46,6 +65,7 @@ class Sinatra::Application
|
|||
end
|
||||
|
||||
if task.save
|
||||
update_task_tags(task, params[:tags])
|
||||
redirect request.referrer || '/'
|
||||
else
|
||||
halt 400, 'There was a problem creating the task.'
|
||||
|
|
@ -72,6 +92,7 @@ class Sinatra::Application
|
|||
end
|
||||
|
||||
if task.update(task_attributes)
|
||||
update_task_tags(task, params[:tags])
|
||||
redirect request.referrer || '/'
|
||||
else
|
||||
halt 400, 'There was a problem updating the task.'
|
||||
|
|
@ -80,7 +101,7 @@ class Sinatra::Application
|
|||
|
||||
patch '/task/:id/toggle_completion' do
|
||||
content_type :json
|
||||
task = current_user.tasks.find(params[:id])
|
||||
task = current_user.tasks.find_by(id: params[:id])
|
||||
if task
|
||||
task.completed = !task.completed
|
||||
if task.save
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@
|
|||
<%= partial :'tasks/_form', locals: { task: Task.new } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-3 my-2">
|
||||
<% standalone_tasks = current_user.tasks.where(project_id: nil) %>
|
||||
<% if standalone_tasks.any? %>
|
||||
<% standalone_tasks.each do |task| %>
|
||||
<div class="mx-3 mt-4 mb-2">
|
||||
<% if @tasks %>
|
||||
<% @tasks.each do |task| %>
|
||||
<div id="edit_task_form_<%= task.id %>" class="d-none">
|
||||
<%= partial :'tasks/_form', locals: { task: task } %>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,22 +7,24 @@
|
|||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap" rel="stylesheet">
|
||||
<link href="https://cdn.jsdelivr.net/npm/@yaireo/tagify/dist/tagify.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/css/app.css">
|
||||
</head>
|
||||
<body class="container-fluid bg-light">
|
||||
<body class="container-fluid" style="background: #fcfcfc">
|
||||
<div class="row flex-nowrap">
|
||||
<% if current_user %>
|
||||
<%= partial :'sidebar' %>
|
||||
<%= partial :'projects/_new_project_modal' %>
|
||||
<div class="px-md-4 pt-4 mb-3 main-content col-md-9 col-lg-10" style="background: #fbfbfb">
|
||||
<div class="px-md-4 pt-4 mb-3 main-content col-md-9 col-lg-10">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="px-md-4 pt-4 mb-3 col-md-12" style="background: #fbfbfb">
|
||||
<div class="px-md-4 pt-4 mb-3 col-md-12">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL" crossorigin="anonymous"></script> </body>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@yaireo/tagify@latest/dist/tagify.min.js"></script>
|
||||
<script src="/js/app.js"></script>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
<% if @projects_with_tasks.any? %>
|
||||
<% @projects_with_tasks.each do |project| %>
|
||||
<% if project.tasks.any? %>
|
||||
<h5 class="mt-4 ms-4 mb-2">
|
||||
<h5 class="mt-4 mb-2">
|
||||
<div class="px-2 py-1 mb-1 border border-dark d-inline-block"><%= project.name.upcase %></div>
|
||||
</h5>
|
||||
<% project.tasks.each do |task| %>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<%= @project.description %>
|
||||
</div>
|
||||
<% end %>
|
||||
<div class="bg-light py-2 px-3 mx-3 d-flex align-items-center border" data-bs-toggle="collapse" data-bs-target="#newTaskForm" aria-expanded="false" aria-controls="newTaskForm" style="cursor: pointer;">
|
||||
<div class="bg-light py-2 mb-4 px-3 mx-3 d-flex align-items-center border" data-bs-toggle="collapse" data-bs-target="#newTaskForm" aria-expanded="false" aria-controls="newTaskForm" style="cursor: pointer;">
|
||||
<i class="fs-4 bi bi-plus-circle-fill text-primary me-2"></i> <span class="fs-6">New task</span>
|
||||
</div>
|
||||
<div class="collapse" id="newTaskForm">
|
||||
|
|
|
|||
|
|
@ -24,13 +24,13 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/tasks?due_date=anytime" class="<%= nav_link('/tasks', 'due_date' => 'anytime') %>">
|
||||
<i class="bi bi-sun-fill me-1"></i> Anytime
|
||||
<a href="/tasks?due_date=never" class="<%= nav_link('/tasks', 'due_date' => 'never') %>">
|
||||
<i class="bi bi-moon-stars-fill me-1"></i> Someday
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/tasks?due_date=never" class="<%= nav_link('/tasks', 'due_date' => 'never') %>">
|
||||
<i class="bi bi-moon-stars-fill me-1"></i> Someday
|
||||
<a href="/tasks?status=completed" class="<%= nav_link('/tasks', 'status' => 'completed') %>">
|
||||
<i class="bi bi-check-circle me-1"></i> Completed
|
||||
</a>
|
||||
</li>
|
||||
<li class="border-top my-3"></li>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
<% action_url = task.new_record? ? '/task/create' : "/task/#{task.id}" %>
|
||||
<% method = task.new_record? ? 'post' : 'patch' %>
|
||||
|
||||
<form action="<%= action_url %>" method="post" class="">
|
||||
<% unless task.new_record? %>
|
||||
<input type="hidden" name="_method" value="<%= method %>">
|
||||
|
|
@ -19,13 +18,13 @@
|
|||
<option value="">No Project</option>
|
||||
<% current_user.projects.each do |project| %>
|
||||
<option value="<%= project.id %>" <%= 'selected' if task.project_id == project.id %>><%= project.name %></option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="task_priority" class="form-label">Priority:</label>
|
||||
<select id="task_priority" name="priority" class="form-select">
|
||||
<option value="Low" <%= 'selected' if task.priority == 'Low' %>>Low</option>
|
||||
<% end %>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="task_priority" class="form-label">Priority:</label>
|
||||
<select id="task_priority" name="priority" class="form-select">
|
||||
<option value="Low" <%= 'selected' if task.priority == 'Low' %>>Low</option>
|
||||
<option value="Medium" <%= 'selected' if task.priority == 'Medium' %>>Medium</option>
|
||||
<option value="High" <%= 'selected' if task.priority == 'High' %>>High</option>
|
||||
</select>
|
||||
|
|
@ -33,32 +32,36 @@
|
|||
<div class="col-md-4">
|
||||
<label for="task_due_date" class="form-label">Due Date:</label>
|
||||
<input type="date" id="task_due_date" name="due_date" value="<%= task.due_date.strftime('%Y-%m-%d') if task.due_date %>" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<%= task.new_record? ? 'Create Task' : 'Update Task' %>
|
||||
</button>
|
||||
<% unless task.new_record? %>
|
||||
<button type="button" class="btn btn-outline-danger" onclick="deleteTask('<%= task.id %>')">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<label for="task_tags" class="form-label">Tags:</label>
|
||||
<input name="tags" id="task_tags" class="form-control" value="<%= task.tags&.map(&:name)&.join(',') %>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<%= task.new_record? ? 'Create Task' : 'Update Task' %>
|
||||
</button>
|
||||
<% unless task.new_record? %>
|
||||
<button type="button" class="btn btn-outline-danger" onclick="deleteTask('<%= task.id %>')">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
<% if !task.new_record? %>
|
||||
<form id="delete_task_<%= task.id %>" action="/task/<%= task.id %>" method="post" class="d-none">
|
||||
<input type="hidden" name="_method" value="delete">
|
||||
</form>
|
||||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<% if !task.new_record? %>
|
||||
<form id="delete_task_<%= task.id %>" action="/task/<%= task.id %>" method="post" class="d-none">
|
||||
<input type="hidden" name="_method" value="delete">
|
||||
</form>
|
||||
<% end %>
|
||||
|
||||
<script>
|
||||
function deleteTask(taskId) {
|
||||
if (confirm('Are you sure you want to delete this task?')) {
|
||||
var form = document.getElementById('delete_task_' + taskId);
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
function deleteTask(taskId) {
|
||||
if (confirm('Are you sure you want to delete this task?')) {
|
||||
var form = document.getElementById('delete_task_' + taskId);
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
<h2 class="mb-5"><i class="bi bi-calendar3 ms-3 me-2"></i> Upcoming</h2>
|
||||
<% elsif params[:due_date] == 'never' %>
|
||||
<h2 class="mb-5"><i class="bi bi-moon-stars-fill ms-3 me-2"></i> Someday</h2>
|
||||
<% elsif params[:due_date] == 'anytime' %>
|
||||
<h2 class="mb-5"><i class="bi bi-sun-fill ms-3 me-2"></i> Anytime</h2>
|
||||
<% elsif params[:status] == 'completed' %>
|
||||
<h2 class="mb-5"><i class="bi bi-check-circle ms-3 me-2"></i> Completed</h2>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
<div class="col-md-5">
|
||||
<%= task.name %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<% task.tags.each do |tag| %>
|
||||
<span class="badge bg-primary-subtle text-primary rounded">
|
||||
<%= tag.name %>
|
||||
</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<% if task.due_date %>
|
||||
<% if task.due_date.to_date == Date.today %>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
<%= partial :'tasks/_form', locals: { task: Task.new } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-3 my-2">
|
||||
<div class="mx-3 mt-4 mb-4">
|
||||
<% if @tasks.any? %>
|
||||
<% @tasks.each do |task| %>
|
||||
<div id="edit_task_form_<%= task.id %>" class="d-none">
|
||||
|
|
|
|||
10
db/migrate/20231114203847_add_tags.rb
Normal file
10
db/migrate/20231114203847_add_tags.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
class AddTags < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
create_table :tags do |t|
|
||||
t.string :name
|
||||
t.references :user, null: false, foreign_key: { on_delete: :cascade }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
8
db/migrate/20231114210336_create_tasks_tags.rb
Normal file
8
db/migrate/20231114210336_create_tasks_tags.rb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
class CreateTasksTags < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
create_table :tasks_tags, id: false do |t|
|
||||
t.belongs_to :task, null: false, foreign_key: true
|
||||
t.belongs_to :tag, null: false, foreign_key: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
class RenameTasksTagsToTagsTasks < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
rename_table :tasks_tags, :tags_tasks
|
||||
end
|
||||
end
|
||||
20
db/schema.rb
20
db/schema.rb
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.1].define(version: 2023_11_10_163101) do
|
||||
ActiveRecord::Schema[7.1].define(version: 2023_11_15_092055) do
|
||||
create_table "areas", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "user_id", null: false
|
||||
|
|
@ -30,6 +30,21 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_10_163101) do
|
|||
t.index ["user_id"], name: "index_projects_on_user_id"
|
||||
end
|
||||
|
||||
create_table "tags", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.integer "user_id", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["user_id"], name: "index_tags_on_user_id"
|
||||
end
|
||||
|
||||
create_table "tags_tasks", id: false, force: :cascade do |t|
|
||||
t.integer "task_id", null: false
|
||||
t.integer "tag_id", null: false
|
||||
t.index ["tag_id"], name: "index_tags_tasks_on_tag_id"
|
||||
t.index ["task_id"], name: "index_tags_tasks_on_task_id"
|
||||
end
|
||||
|
||||
create_table "tasks", force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "priority"
|
||||
|
|
@ -56,6 +71,9 @@ ActiveRecord::Schema[7.1].define(version: 2023_11_10_163101) do
|
|||
add_foreign_key "areas", "users"
|
||||
add_foreign_key "projects", "areas", on_delete: :cascade
|
||||
add_foreign_key "projects", "users"
|
||||
add_foreign_key "tags", "users", on_delete: :cascade
|
||||
add_foreign_key "tags_tasks", "tags"
|
||||
add_foreign_key "tags_tasks", "tasks"
|
||||
add_foreign_key "tasks", "projects", on_delete: :cascade
|
||||
add_foreign_key "tasks", "users"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
attachEventListeners();
|
||||
new Tagify(document.getElementById('task_tags'));
|
||||
});
|
||||
|
||||
function attachEventListeners() {
|
||||
|
|
@ -17,10 +18,13 @@ function attachCollapseListeners() {
|
|||
}
|
||||
|
||||
function toggleFolderIcon(collapseElement, isOpening) {
|
||||
const closedFolderIcon = collapseElement.previousElementSibling.querySelector('.bi-folder');
|
||||
const openFolderIcon = collapseElement.previousElementSibling.querySelector('.bi-folder2-open');
|
||||
closedFolderIcon.classList.toggle('d-none', isOpening);
|
||||
openFolderIcon.classList.toggle('d-none', !isOpening);
|
||||
const closedFolderIcon = collapseElement.previousElementSibling?.querySelector('.bi-folder');
|
||||
const openFolderIcon = collapseElement.previousElementSibling?.querySelector('.bi-folder2-open');
|
||||
|
||||
if (closedFolderIcon && openFolderIcon) {
|
||||
closedFolderIcon.classList.toggle('d-none', isOpening);
|
||||
openFolderIcon.classList.toggle('d-none', !isOpening);
|
||||
}
|
||||
}
|
||||
|
||||
function attachTaskClickListeners() {
|
||||
|
|
@ -40,10 +44,15 @@ function openEditTaskModal(taskId) {
|
|||
return;
|
||||
}
|
||||
const formHtml = formContainer.innerHTML;
|
||||
document.getElementById('editTaskFormContainer').innerHTML = formHtml;
|
||||
const editTaskFormContainer = document.getElementById('editTaskFormContainer');
|
||||
editTaskFormContainer.innerHTML = formHtml;
|
||||
|
||||
new Tagify(editTaskFormContainer.querySelector('#task_tags'));
|
||||
|
||||
new bootstrap.Modal(document.getElementById('editTaskModal')).show();
|
||||
}
|
||||
|
||||
|
||||
function attachProjectModalListeners() {
|
||||
document.querySelectorAll('[data-bs-toggle="modal"][data-project-id]').forEach(button => {
|
||||
button.addEventListener('click', () => openProjectModalForEdit(button.getAttribute('data-project-id')));
|
||||
|
|
@ -152,14 +161,17 @@ function updateTaskCompletionStatus(taskId, data) {
|
|||
taskIcon.classList.remove('bi-circle', 'text-warning', 'text-danger');
|
||||
taskIcon.classList.add('bi-check-circle-fill', 'text-success');
|
||||
taskDiv.classList.add('opacity-50');
|
||||
|
||||
} else {
|
||||
taskIcon.classList.remove('bi-check-circle-fill', 'text-success');
|
||||
taskIcon.classList.add('bi-circle');
|
||||
taskDiv.classList.remove('opacity-50');
|
||||
applyPriorityColor(taskIcon, data.priority);
|
||||
}
|
||||
setTimeout(() => taskDiv.remove(), 200);
|
||||
}
|
||||
|
||||
|
||||
function applyPriorityColor(taskIcon, priority) {
|
||||
taskIcon.classList.remove('text-warning', 'text-danger', 'text-secondary');
|
||||
switch (priority) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue