diff options
Diffstat (limited to 'app')
| -rw-r--r-- | app/assets/stylesheets/components/_referential_overview.sass | 171 | ||||
| -rw-r--r-- | app/helpers/referentials_helper.rb | 5 | ||||
| -rw-r--r-- | app/services/referential_overview.rb | 218 | ||||
| -rw-r--r-- | app/views/referentials/_overview.html.slim | 31 | ||||
| -rw-r--r-- | app/views/referentials/show.html.slim | 2 |
5 files changed, 427 insertions, 0 deletions
diff --git a/app/assets/stylesheets/components/_referential_overview.sass b/app/assets/stylesheets/components/_referential_overview.sass new file mode 100644 index 000000000..0af5a99f7 --- /dev/null +++ b/app/assets/stylesheets/components/_referential_overview.sass @@ -0,0 +1,171 @@ +.referential-overview + display: flex + margin-top: 50px + $left-size: 100px + .head + height: $left-size + border-top: 1px solid $lightgrey + .line + height: 80px + .left + flex: 0 0 + background: $lightgrey + min-width: $left-size + overflow: hidden + border-right: 1px solid white + .head + position: relative + border-bottom: 1px solid white + border-right: 1px solid $lightgrey + .dates, .lines + position: absolute + font-size: 0.8em + z-index: 2 + .dates + right: 20px + top: 20px + .lines + left: 20px + bottom: 20px + &:after + position: absolute + border-left: ($left-size - 2px)/2 solid transparent + border-bottom: ($left-size - 2px)/2 solid transparent + border-right: ($left-size - 2px)/2 solid white + border-top: ($left-size - 2px)/2 solid white + z-index: 1 + top: 0 + right: 0 + width: 0 + content: "" + .line + padding: 15px 10px 10px + border-bottom: 1px solid white + font-size: 0.8em + &:last-child + border-bottom: 1px solid $grey + .number + border-radius: 100px + display: inline-block + width: 20px + height: 20px + text-align: center + padding-top: 1px + text-decoration: none + color: black + border: 1px solid $grey + .name + display: inline-block + width: $left-size - 50px() + white-space: nowrap + line-height: 20px + margin-left: 5px + text-overflow: ellipsis + overflow: hidden + vertical-align: bottom + color: black + text-decoration: none + + .company, .mode + font-size: 0.9em + margin-top: 5px + white-space: nowrap + text-overflow: ellipsis + overflow: hidden + + .mode + margin-top: 0 + text-transform: uppercase + color: $grey + font-weight: bold + .right + flex: 1 1 + overflow-x: scroll + overflow-y: hidden + .head + white-space: nowrap + .week + display: inline-block + position: relative + height: 100% + .week-span + left: 5px + top: 10px + right: 30px + white-space: nowrap + overflow: hidden + text-overflow: ellipsis + position: absolute + + .week-number + background-color: lightgrey + color: white + position: absolute + top: 0 + right: 0 + padding: 2px 4px + + &:after + position: absolute + right: 0 + top: 0 + bottom: 0 + background: $grey + width: 1px + content: "" + + .days + position: relative + top: 50% + height: 50% + border-top: 1px solid $grey + border-bottom: 1px solid $grey + + .day + float: left + border-left: 1px solid $grey + box-sizing: border-box + padding-left: 5px + padding-top: 3px + position: relative + height: 100% + .name, .number + position: absolute + left: 10px + right: 10px + top: 50% + transform: translateY(-50%) + margin-top: 10px + .name + font-weight: bold + font-size: 0.8em + margin-top: -10px + &:first-child + border: none + &.weekend + background: $lightgrey + + .line + border-bottom: 1px solid $grey + position: relative + overflow: hidden + + .period + height: 100% + top: 0 + background: rgb(219, 249, 196) + position: absolute + &:before + content: "" + border-right: 1px dashed $grey + top: -100% + bottom: -100% + position: absolute + right: -1px + z-index: 10 + &.empty + background: rgb(244, 67, 67) + background: repeating-linear-gradient(-45deg, #f5e1cf,#f5e1cf 10px,#e49393 10px,#e49393 20px) + &.accepted + background: #f19039 + background: repeating-linear-gradient(-45deg, #f5e1cf,#f5e1cf 10px,#f19039 10px,#f19039 20px) diff --git a/app/helpers/referentials_helper.rb b/app/helpers/referentials_helper.rb index 01e5a5879..8251377aa 100644 --- a/app/helpers/referentials_helper.rb +++ b/app/helpers/referentials_helper.rb @@ -10,4 +10,9 @@ module ReferentialsHelper t('true') end end + + def referential_overview referential + service = ReferentialOverview.new referential, self + render partial: "referentials/overview", locals: {referential: referential, overview: service} + end end diff --git a/app/services/referential_overview.rb b/app/services/referential_overview.rb new file mode 100644 index 000000000..5b0e144db --- /dev/null +++ b/app/services/referential_overview.rb @@ -0,0 +1,218 @@ +class ReferentialOverview + attr_reader :h + + def initialize referential, h + @referential = referential + @page = 1 + @h = h + end + + def lines + @referential.metadatas_lines.includes(:company).page(@page).map{|l| Line.new(l, @referential, period.first, h)} + end + + def period + @period ||= @referential.metadatas_period || [] + end + + def weeks + @weeks = {} + period.map do |d| + @weeks[Week.key(d)] ||= Week.new(d, period.last, h) + end + @weeks.values + end + + class Line + attr_reader :h + attr_reader :referential_line + + delegate :name, :number, :company, :color, :transport_mode, to: :referential_line + + def initialize line, referential, start, h + @referential_line = line + @referential = referential + @start = start + @h = h + end + + def period + @period ||= @referential.metadatas_period || [] + end + + def referential_periods + @referential_periods ||= @referential.metadatas.include_lines([@referential_line.id]).map(&:periodes).flatten.sort{|p1, p2| p1.first <=> p2.first} + end + + def periods + @periods ||= begin + periods = referential_periods.flatten.map{|p| Period.new p, @start, h} + periods = fill_periods periods + periods = merge_periods periods + periods + end + end + + def fill_periods periods + [].tap do |out| + previous = OpenStruct.new(end: period.first - 1.day) + (periods + [OpenStruct.new(start: period.last + 1.day)]).each do |p| + if p.start > previous.end + 1.day + out << Period.new((previous.end+1.day..p.start-1.day), @start, h).tap{|p| p.empty = true} + end + out << p if p.respond_to?(:end) + previous = p + end + end + end + + def merge_periods periods + [].tap do |out| + current = periods.first + periods[1..-1].each do |p| + if p.start <= current.end + current.end = p.end + else + out << current + current = p + end + end + out << current + end + end + + def width + period.count * Day::WIDTH + end + + def html_style + { + width: "#{width}px" + }.map{|k, v| "#{k}: #{v}"}.join("; ") + end + + def html_class + out = [] + out + end + + class Period + attr_accessor :empty + attr_accessor :h + + def initialize period, start, h + @period = period + @start = start + @empty = false + @h = h + end + + def start + @period.first + end + + def end + @period.last + end + + def end= val + @period = (start..val) + end + + def width + @period.count * Day::WIDTH + end + + def left + (@period.first - @start).to_i * Day::WIDTH + end + + def html_style + { + width: "#{width}px", + left: "#{left}px", + }.map{|k, v| "#{k}: #{v}"}.join("; ") + end + + def empty? + @empty + end + + def accepted? + @period.count < 7 + end + + def title + h.l(self.start, format: :short) + " - " + h.l(self.end, format: :short) + end + + def html_class + out = [] + out << "empty" if empty? + out << "accepted" if accepted? + out + end + end + end + + class Week + attr_reader :h + attr_reader :start_date + attr_reader :end_date + + def initialize start_date, boundary, h + @start_date = start_date.to_date + @end_date = [start_date.end_of_week, boundary].min.to_date + @h = h + end + + def self.key date + date.beginning_of_week.to_s + end + + def span + h.l(@start_date, format: "#{@start_date.day}-#{@end_date.day} %b") + end + + def number + h.l(@start_date, format: "%W") + end + + def period + (@start_date..@end_date) + end + + def days + period.map {|d| Day.new d, h } + end + end + + class Day + attr_reader :h + + WIDTH=50 + + def initialize date, h + @date = date + @h = h + end + + def html_style + {width: "#{WIDTH}px"}.map{|k, v| "#{k}: #{v}"}.join("; ") + end + + def html_class + out = [] + out << "weekend" if [0, 6].include?(@date.wday) + out + end + + def short_name + h.l(@date, format: "%a") + end + + def number + @date.day + end + end +end diff --git a/app/views/referentials/_overview.html.slim b/app/views/referentials/_overview.html.slim new file mode 100644 index 000000000..03c72752e --- /dev/null +++ b/app/views/referentials/_overview.html.slim @@ -0,0 +1,31 @@ +.referential-overview + .left + .head + .dates= I18n.t("referentials.overview.head.dates") + .lines= I18n.t("referentials.overview.head.lines") + .lines + - overview.lines.each do |line| + .line + a.number style="background-color: #{line.color.present? ? "##{line.color}" : 'whitesmoke'}" title=line.name + = line.number + - unless line.number == line.name + a.name title=line.name + = line.name + .company= line.company&.name + .mode= line.transport_mode + .right + .head + - overview.weeks.each do |week| + .week + .week-span= week.span + .week-number= week.number + .days + - week.days.each do |day| + .day style=day.html_style class=day.html_class + .name= day.short_name + .number= day.number + .lines + - overview.lines.each do |line| + .line style=line.html_style class=line.html_class + - line.periods.each do |period| + .period style=period.html_style class=period.html_class title=period.title diff --git a/app/views/referentials/show.html.slim b/app/views/referentials/show.html.slim index 6c88f5b81..289e802d7 100644 --- a/app/views/referentials/show.html.slim +++ b/app/views/referentials/show.html.slim @@ -67,6 +67,8 @@ = replacement_msg t('referential_lines.search_no_results') + = referential_overview resource + / Modal(s) = modalbox 'purgeModal' do = simple_form_for [@referential, CleanUp.new] do |f| |
