Feature #33682 » 0001-Support-vertical-list-layout-calendar-33682.patch
| app/controllers/my_controller.rb | ||
|---|---|---|
| 33 | 33 |
helper :custom_fields |
| 34 | 34 |
helper :queries |
| 35 | 35 |
helper :activities |
| 36 |
helper :calendars |
|
| 37 | 36 | |
| 38 | 37 |
def index |
| 39 | 38 |
page |
| app/helpers/calendars_helper.rb | ||
|---|---|---|
| 1 |
# frozen_string_literal: true |
|
| 2 | ||
| 3 |
# Redmine - project management software |
|
| 4 |
# Copyright (C) 2006-2023 Jean-Philippe Lang |
|
| 5 |
# |
|
| 6 |
# This program is free software; you can redistribute it and/or |
|
| 7 |
# modify it under the terms of the GNU General Public License |
|
| 8 |
# as published by the Free Software Foundation; either version 2 |
|
| 9 |
# of the License, or (at your option) any later version. |
|
| 10 |
# |
|
| 11 |
# This program is distributed in the hope that it will be useful, |
|
| 12 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 13 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 14 |
# GNU General Public License for more details. |
|
| 15 |
# |
|
| 16 |
# You should have received a copy of the GNU General Public License |
|
| 17 |
# along with this program; if not, write to the Free Software |
|
| 18 |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
| 19 | ||
| 20 |
module CalendarsHelper |
|
| 21 |
include Redmine::Utils::DateCalculation |
|
| 22 | ||
| 23 |
def calendar_day_css_classes(calendar, day) |
|
| 24 |
css = day.month==calendar.month ? +'even' : +'odd' |
|
| 25 |
css << " today" if User.current.today == day |
|
| 26 |
css << " nwday" if non_working_week_days.include?(day.cwday) |
|
| 27 |
css |
|
| 28 |
end |
|
| 29 |
end |
|
| app/views/common/_calendar.html.erb | ||
|---|---|---|
| 1 | 1 |
<%= form_tag({}, :data => {:cm_url => issues_context_menu_path}) do -%>
|
| 2 | 2 |
<%= hidden_field_tag 'back_url', url_for(:params => request.query_parameters), :id => nil %> |
| 3 |
<table class="cal"> |
|
| 4 |
<thead> |
|
| 5 |
<tr> |
|
| 6 |
<th scope="col" title="<%= l(:label_week) %>" class="week-number"></th> |
|
| 7 |
<% 7.times do |i| %> |
|
| 8 |
<th scope="col"><%= day_name((calendar.first_wday + i) % 7) %></th> |
|
| 9 |
<% end %> |
|
| 10 |
</tr> |
|
| 11 |
</thead> |
|
| 12 |
<tbody> |
|
| 13 |
<tr> |
|
| 14 |
<% day = calendar.startdt %> |
|
| 15 |
<% while day <= calendar.enddt %> |
|
| 16 |
<% if day.cwday == calendar.first_wday %> |
|
| 17 |
<td class='week-number' title='<%= l(:label_week) %>'> |
|
| 18 |
<%= (day + (11 - day.cwday) % 7).cweek %> |
|
| 19 |
</td> |
|
| 3 |
<ul class="cal"> |
|
| 4 |
<li scope="col" title="<%= l(:label_week) %>" class="calhead week-number"></li> |
|
| 5 |
<% 7.times do |i| %> |
|
| 6 |
<li scope="col" class="calhead"><%= day_name((calendar.first_wday + i) % 7) %></li> |
|
| 20 | 7 |
<% end %> |
| 21 |
<td class="<%= calendar_day_css_classes(calendar, day) %>"> |
|
| 22 |
<p class="day-num"><%= day.day %></p> |
|
| 23 |
<% calendar.events_on(day).each do |i| %> |
|
| 24 |
<% if i.is_a? Issue %> |
|
| 25 |
<div class="<%= i.css_classes %> <%= 'starting' if day == i.start_date %> <%= 'ending' if day == i.due_date %> tooltip hascontextmenu"> |
|
| 26 |
<%= "#{i.project} -" unless @project && @project == i.project %>
|
|
| 27 |
<%= link_to_issue i, :truncate => 30 %> |
|
| 28 |
<span class="tip"><%= render_issue_tooltip i %></span> |
|
| 29 |
<%= check_box_tag 'ids[]', i.id, false, :style => 'display:none;', :id => nil %> |
|
| 30 |
</div> |
|
| 31 |
<% else %> |
|
| 32 |
<span class="icon icon-package"> |
|
| 33 |
<%= "#{i.project} -" unless @project && @project == i.project %>
|
|
| 34 |
<%= link_to_version i %> |
|
| 35 |
</span> |
|
| 8 |
<% calendar.format_month.each_slice(7) do |week| %> |
|
| 9 |
<li class='week-number' title='<%= l(:label_week) %>'> |
|
| 10 |
<%= calendar.week_number week.first %><span class="label-week"><%= l(:label_week) %></span> |
|
| 11 |
</li> |
|
| 12 |
<% week.each do |day| %> |
|
| 13 |
<li class="<%= calendar.day_css_classes day %> calbody"> |
|
| 14 |
<p class="day-num"><%= day.day %> |
|
| 15 |
<span class="day-letter"> (<%= calendar.day_letter(day.cwday) %>)</span> |
|
| 16 |
</p> |
|
| 17 |
<% calendar.events_on(day).each do |i| %> |
|
| 18 |
<% if i.is_a? Issue %> |
|
| 19 |
<%= tag.div class: [ i.css_classes, 'tooltip hascontextmenu', starting: day == i.start_date, ending: day == i.due_date] do %> |
|
| 20 |
<%= "#{i.project} -" unless @project && @project == i.project %>
|
|
| 21 |
<%= link_to_issue i, :truncate => 30 %> |
|
| 22 |
<span class="tip"><%= render_issue_tooltip i %></span> |
|
| 23 |
<%= check_box_tag 'ids[]', i.id, false, :style => 'display:none;', :id => nil %> |
|
| 24 |
<% end %> |
|
| 25 |
<% else %> |
|
| 26 |
<span class="icon icon-package"> |
|
| 27 |
<%= "#{i.project} -" unless @project && @project == i.project %>
|
|
| 28 |
<%= link_to_version i %> |
|
| 29 |
</span> |
|
| 30 |
<% end %> |
|
| 31 |
<% end %> |
|
| 32 |
</li> |
|
| 33 |
<% end %> |
|
| 36 | 34 |
<% end %> |
| 37 |
<% end %> |
|
| 38 |
</td> |
|
| 39 |
<% if day.cwday==calendar.last_wday and day!=calendar.enddt %> |
|
| 40 |
</tr><tr> |
|
| 41 |
<% end %> |
|
| 42 |
<% day = day + 1 %> |
|
| 43 |
<% end %> |
|
| 44 |
</tr> |
|
| 45 |
</tbody> |
|
| 46 |
</table> |
|
| 35 |
</ul> |
|
| 47 | 36 |
<% end %> |
| 48 | 37 |
<%= context_menu %> |
| lib/redmine/helpers/calendar.rb | ||
|---|---|---|
| 23 | 23 |
# Simple class to compute the start and end dates of a calendar |
| 24 | 24 |
class Calendar |
| 25 | 25 |
include Redmine::I18n |
| 26 |
include Redmine::Utils::DateCalculation |
|
| 27 | ||
| 26 | 28 |
attr_reader :startdt, :enddt |
| 27 | 29 | |
| 28 | 30 |
def initialize(date, lang = current_language, period = :month) |
| ... | ... | |
| 47 | 49 |
end |
| 48 | 50 |
end |
| 49 | 51 | |
| 52 |
def format_month |
|
| 53 |
(@startdt..@enddt).to_a |
|
| 54 |
end |
|
| 55 | ||
| 56 |
def week_number(day) |
|
| 57 |
(day + (11 - day.cwday) % 7).cweek |
|
| 58 |
end |
|
| 59 | ||
| 60 |
def day_css_classes(day) |
|
| 61 |
css = day.month==month ? +'even' : +'odd' |
|
| 62 |
css << " today" if User.current.today == day |
|
| 63 |
css << " nwday" if non_working_week_days.include?(day.cwday) |
|
| 64 |
css |
|
| 65 |
end |
|
| 66 | ||
| 50 | 67 |
# Sets calendar events |
| 51 | 68 |
def events=(events) |
| 52 | 69 |
@events = events |
| ... | ... | |
| 82 | 99 |
def last_wday |
| 83 | 100 |
@last_dow ||= (first_wday + 5)%7 + 1 |
| 84 | 101 |
end |
| 102 | ||
| 103 |
def day_letter(day) |
|
| 104 |
::I18n.t('date.abbr_day_names')[day % 7]
|
|
| 105 |
end |
|
| 85 | 106 |
end |
| 86 | 107 |
end |
| 87 | 108 |
end |
| public/stylesheets/application.css | ||
|---|---|---|
| 1100 | 1100 |
} |
| 1101 | 1101 | |
| 1102 | 1102 |
/***** Calendar *****/ |
| 1103 |
table.cal {width: 100%; margin: 0 0 6px 0; border: 1px solid #c0c0c0; border-spacing: 0; border-radius: 3px;}
|
|
| 1104 |
table.cal thead th {width: 14%; background-color:#EEEEEE; padding: 4px; }
|
|
| 1105 |
table.cal thead th.week-number {width: auto;}
|
|
| 1106 |
table.cal tbody tr {height: 100px;}
|
|
| 1107 |
table.cal td .icon {padding-top: 2px; padding-bottom: 3px;}
|
|
| 1108 |
table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em; border-bottom: 0; border-right: 0;}
|
|
| 1109 |
table.cal td.week-number { background-color:#EEEEEE; padding: 4px; border:none; font-size: 1em;}
|
|
| 1110 |
table.cal td p.day-num {font-size: 1.1em; text-align:right;}
|
|
| 1111 |
table.cal td.odd p.day-num {color: #bbb;}
|
|
| 1112 |
table.cal td.today {background:#ffffdd;}
|
|
| 1113 |
table.cal td.today p.day-num {font-weight: bold;}
|
|
| 1114 |
table.cal td.nwday:not(.odd) {background-color:#f1f1f1;}
|
|
| 1115 |
table.cal .starting a.issue, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1116 |
table.cal .ending a.issue, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1117 |
table.cal .starting.ending a.issue, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1103 |
ul.cal {
|
|
| 1104 |
list-style: none; |
|
| 1105 |
width: 100%; |
|
| 1106 |
padding: 0; |
|
| 1107 |
display: grid; |
|
| 1108 |
grid-template-columns: 2rem repeat(7, 1fr); |
|
| 1109 |
margin: 0; |
|
| 1110 |
border: 1px solid #c0c0c0; |
|
| 1111 |
border-spacing: 0; |
|
| 1112 |
border-radius: 3px; |
|
| 1113 |
} |
|
| 1114 | ||
| 1115 |
.cal .calhead {
|
|
| 1116 |
background-color:#eee; |
|
| 1117 |
text-align: center; |
|
| 1118 |
font-weight: bold; |
|
| 1119 |
padding: 4px |
|
| 1120 |
} |
|
| 1121 | ||
| 1122 |
.cal .week-number {
|
|
| 1123 |
background-color:#eee; |
|
| 1124 |
border:none; |
|
| 1125 |
font-size: 1em; |
|
| 1126 |
padding: 4px; |
|
| 1127 |
text-align: center; |
|
| 1128 |
} |
|
| 1129 | ||
| 1130 |
.cal .week-number .label-week {
|
|
| 1131 |
display: none; |
|
| 1132 |
} |
|
| 1133 | ||
| 1134 |
.cal .calbody {
|
|
| 1135 |
border: 1px solid #d7d7d7; |
|
| 1136 |
vertical-align: top; |
|
| 1137 |
font-size: 0.9em; |
|
| 1138 |
border-bottom: 0; |
|
| 1139 |
border-right: 0; |
|
| 1140 |
line-height: 1.2; |
|
| 1141 |
min-height: calc(1.2em * 6); |
|
| 1142 |
padding: 2px; |
|
| 1143 |
} |
|
| 1144 | ||
| 1145 |
.cal .calbody p.day-num {font-size: 1.1em; text-align:right;}
|
|
| 1146 |
.cal .calbody .day-letter {display:none}
|
|
| 1147 |
.cal .calbody.odd p.day-num {color: #bbb;}
|
|
| 1148 |
.cal .calbody.today {background:#ffd;}
|
|
| 1149 |
.cal .calbody.today p.day-num {font-weight: bold;}
|
|
| 1150 | ||
| 1151 |
.cal .calbody .icon {padding-top: 2px; padding-bottom: 3px;}
|
|
| 1152 |
.cal .calbody.nwday:not(.odd) {background-color:#f1f1f1;}
|
|
| 1153 |
.cal .starting a.issue, p.cal.legend .starting {background: url(../images/bullet_go.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1154 |
.cal .ending a.issue, p.cal.legend .ending {background: url(../images/bullet_end.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1155 |
.cal .starting.ending a.issue, p.cal.legend .starting.ending {background: url(../images/bullet_diamond.png) no-repeat -1px -2px; padding-left:16px;}
|
|
| 1156 | ||
| 1118 | 1157 |
p.cal.legend span {display:block;}
|
| 1119 | 1158 |
.controller-calendars p.buttons {margin-top: unset;}
|
| 1120 | 1159 | |
| public/stylesheets/responsive.css | ||
|---|---|---|
| 819 | 819 |
margin-left: 0; |
| 820 | 820 |
width: 100%; |
| 821 | 821 |
} |
| 822 | ||
| 823 |
/* Calendar */ |
|
| 824 |
ul.cal {
|
|
| 825 |
display: block |
|
| 826 |
} |
|
| 827 |
.cal .calhead {
|
|
| 828 |
display: none |
|
| 829 |
} |
|
| 830 | ||
| 831 |
.cal .calbody {
|
|
| 832 |
min-height: calc(1.2em * 3); |
|
| 833 |
} |
|
| 834 | ||
| 835 |
.cal .calbody .day-letter {
|
|
| 836 |
display: inline; |
|
| 837 |
} |
|
| 838 | ||
| 839 |
.cal .week-number {
|
|
| 840 |
border: 1px solid #c0c0c0; |
|
| 841 |
text-align: left; |
|
| 842 |
font-weight: bold; |
|
| 843 |
background-color: #def; |
|
| 844 |
} |
|
| 845 | ||
| 846 |
.cal .week-number .label-week {
|
|
| 847 |
display: inline; |
|
| 848 |
} |
|
| 849 | ||
| 850 |
.cal .calbody p.day-num {
|
|
| 851 |
font-size: 1.1em; |
|
| 852 |
text-align: left; |
|
| 853 |
} |
|
| 822 | 854 |
} |
| 823 | 855 | |
| 824 | 856 |
@media all and (max-width: 599px) {
|