mirror of
https://github.com/rickbarrette/redmine_qbo_calendar.git
synced 2026-10-03 20:40:43 -04:00
Refactor appointment model and views to use a single date field; update tooltip and calendar display for improved functionality
This commit is contained in:
1 parent
88a40b356c
commit
86533981bc
8 files changed
+66
-76
No files matched your search
@@ -41,8 +41,7 @@ class CustomerAppointmentsController < ApplicationController
|
||||
def new
|
||||
@appointment = CustomerAppointment.new
|
||||
@appointment.project = @project
|
||||
@appointment.start_date = (params[:start_date].to_date + 9.hours) if params[:start_date].present?
|
||||
@appointment.end_date = @appointment.start_date + 1.hour if @appointment.start_date.present?
|
||||
@appointment.date = (params[:start_date].to_date + 9.hours) if params[:start_date].present?
|
||||
end
|
||||
|
||||
def create
|
||||
@@ -89,8 +88,7 @@ class CustomerAppointmentsController < ApplicationController
|
||||
:description,
|
||||
:status,
|
||||
:user_id,
|
||||
:start_date,
|
||||
:end_date,
|
||||
:date,
|
||||
:estimated_hours,
|
||||
:estimate_id,
|
||||
:duration
|
||||
|
||||
@@ -17,8 +17,7 @@ class CustomerAppointment < ActiveRecord::Base
|
||||
belongs_to :estimate, optional: true
|
||||
|
||||
validates :subject, presence: true
|
||||
validates :start_date, presence: true
|
||||
validate :date_order
|
||||
validates :date, presence: true
|
||||
|
||||
STATUSES = %w[
|
||||
Scheduled
|
||||
@@ -29,9 +28,15 @@ class CustomerAppointment < ActiveRecord::Base
|
||||
Cancelled
|
||||
]
|
||||
|
||||
# Cast datetime to Date for Redmine Calendar compatibility
|
||||
def start_date
|
||||
date&.to_date
|
||||
end
|
||||
|
||||
def due_date
|
||||
return end_date&.to_date if end_date.present?
|
||||
return start_date&.to_date
|
||||
return nil unless date
|
||||
# Accounts for multi-day duration spanning across dates
|
||||
start_date + ([duration.to_i, 1].max - 1).days
|
||||
end
|
||||
|
||||
def self.visible(user)
|
||||
@@ -40,15 +45,6 @@ class CustomerAppointment < ActiveRecord::Base
|
||||
|
||||
private
|
||||
|
||||
def date_order
|
||||
return if end_date.blank?
|
||||
return if start_date.blank?
|
||||
|
||||
if end_date < start_date
|
||||
errors.add( :end_date, "cannot be before start date")
|
||||
end
|
||||
end
|
||||
|
||||
def log(msg)
|
||||
Rails.logger.info "[Event] #{msg}"
|
||||
end
|
||||
|
||||
@@ -24,10 +24,9 @@
|
||||
<%= f.collection_select :user_id, User.active.sorted, :id, :name, { include_blank: true }, { label: false } %>
|
||||
</p>
|
||||
|
||||
<p><%= f.datetime_local_field :start_date %></p>
|
||||
<p><%= f.date_field :end_date, size: 10 %></p>
|
||||
<p><%= f.datetime_local_field :date %></p>
|
||||
|
||||
<p><%= f.number_field :estimated_hours, step: 0.1, size: 6 %></p>
|
||||
<p><%= f.number_field :estimated_hours, step: 1, size: 6 %></p>
|
||||
<p><%= f.number_field :duration, step: 1, size: 6, label: :label_duration %></p>
|
||||
|
||||
<p><%= f.select :status, CustomerAppointment::STATUSES, label: :field_status %></p>
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
|
||||
<tr>
|
||||
<th><%= l(:label_end_date) %></th>
|
||||
<td><%= format_date(appointment.end_date || appointment.start_date) %></td>
|
||||
<td><%= format_date(appointment.due_date ) %></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
||||
@@ -15,57 +15,12 @@
|
||||
|
||||
<span class="appointment-dates">
|
||||
(<%= format_date(@appointment.start_date) %>
|
||||
<% if @appointment.end_date && @appointment.start_date != @appointment.end_date %>
|
||||
- <%= format_date(@appointment.end_date) %>
|
||||
<% if @appointment.duration > 1 %>
|
||||
- <%= format_date(@appointment.due_date) %>
|
||||
<% end %>)
|
||||
</span>
|
||||
</h2>
|
||||
|
||||
<style>
|
||||
.calendar-badge {
|
||||
display: inline-block;
|
||||
width: 38px;
|
||||
border: 1px solid #b8c0c8;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
margin-right: 8px;
|
||||
line-height: 1;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.calendar-badge .month {
|
||||
background-color: #c22b2b; /* Redmine primary red tone */
|
||||
color: #ffffff;
|
||||
font-size: 9px;
|
||||
font-weight: bold;
|
||||
padding: 3px 0 2px 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.calendar-badge .day {
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 4px 0 3px 0;
|
||||
}
|
||||
|
||||
.appointment-title {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.appointment-dates {
|
||||
font-size: 70%;
|
||||
color: #666;
|
||||
margin-left: 8px;
|
||||
font-weight: normal;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="issue details">
|
||||
<div class="attributes">
|
||||
<div class="splitcontent">
|
||||
|
||||
File renamed without changes.
@@ -23,8 +23,8 @@ table.cal td {
|
||||
background: #edf4ff;
|
||||
border: 1px solid #c5d8f3;
|
||||
border-radius: 3px;
|
||||
font-size: 10px;
|
||||
line-height: 1.2;
|
||||
font-size: 0.9em; /* Matches Redmine calendar default text size */
|
||||
line-height: 1.3;
|
||||
overflow: visible !important; /* Allows tooltip popover to extend outside */
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
@@ -100,7 +100,7 @@ table.cal td {
|
||||
.appointment-hours {
|
||||
flex-shrink: 0;
|
||||
color: #444;
|
||||
font-size: 9px;
|
||||
font-size: 0.85em; /* Slightly smaller than main text to keep layout balanced */
|
||||
font-weight: bold;
|
||||
margin-left: auto;
|
||||
}
|
||||
@@ -108,11 +108,11 @@ table.cal td {
|
||||
/* Option B: Multi-line wrapping for details */
|
||||
.appointment-detail {
|
||||
color: #555;
|
||||
font-size: 9px;
|
||||
font-size: 0.9em; /* Matches calendar item body text */
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
margin-top: 1px;
|
||||
margin-top: 2px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
@@ -203,4 +203,47 @@ table.cal td {
|
||||
.appointment-block .tip .buttons {
|
||||
margin: 0;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.calendar-badge {
|
||||
display: inline-block;
|
||||
width: 38px;
|
||||
border: 1px solid #b8c0c8;
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
margin-right: 8px;
|
||||
line-height: 1;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.calendar-badge .month {
|
||||
background-color: #c22b2b; /* Redmine primary red tone */
|
||||
color: #ffffff;
|
||||
font-size: 9px;
|
||||
font-weight: bold;
|
||||
padding: 3px 0 2px 0;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
.calendar-badge .day {
|
||||
color: #333333;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
padding: 4px 0 3px 0;
|
||||
}
|
||||
|
||||
.appointment-title {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.appointment-dates {
|
||||
font-size: 70%;
|
||||
color: #666;
|
||||
margin-left: 8px;
|
||||
font-weight: normal;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@@ -15,8 +15,7 @@ class CreateCustomerAppointments < ActiveRecord::Migration[7.0]
|
||||
t.text :subject, null: false
|
||||
t.text :description, null: false
|
||||
|
||||
t.datetime :start_date, null: false
|
||||
t.datetime :end_date
|
||||
t.datetime :date, null: false
|
||||
t.integer :duration, default: 1
|
||||
t.integer :estimated_hours, default: 1
|
||||
|
||||
@@ -31,7 +30,7 @@ class CreateCustomerAppointments < ActiveRecord::Migration[7.0]
|
||||
|
||||
end
|
||||
|
||||
add_index :customer_appointments, :start_date
|
||||
add_index :customer_appointments, :date
|
||||
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user