Browse Source

Scheduler UI improvements

development
Godwin 7 years ago
parent
commit
f36d9468df
  1. 292
      app/assets/stylesheets/_admin.scss
  2. 69
      app/assets/stylesheets/_application.scss
  3. 8
      app/assets/stylesheets/_settings.scss
  4. 4
      app/controllers/application_controller.rb
  5. 19
      app/helpers/widgets_helper.rb
  6. 44
      app/views/conference_administration/_schedule.html.haml
  7. 4
      config/locales/en.yml
  8. 3
      config/locales/fr.yml

292
app/assets/stylesheets/_admin.scss

@ -41,7 +41,7 @@ table, .table {
white-space: nowrap; white-space: nowrap;
@include after { @include after {
content: ''; content: $down-icon;
position: absolute; position: absolute;
bottom: -1em; bottom: -1em;
left: 50%; left: 50%;
@ -67,18 +67,18 @@ table, .table {
&:hover { &:hover {
@include after { @include after {
content: ''; content: $up-icon;
} }
} }
} }
[data-dir="up"] { [data-dir="up"] {
@include after { @include after {
content: ''; content: $up-icon;
} }
&:hover { &:hover {
@include after { @include after {
content: ''; content: $down-icon;
} }
} }
} }
@ -98,26 +98,6 @@ table, .table {
background-color: transparent; background-color: transparent;
border: 0; border: 0;
} }
&.state {
background-size: 1.333em;
background-repeat: no-repeat;
background-position: center;
width: 1.75em;
&.happy {
@include after {
content: '\1F601';
opacity: 0.5;
}
}
&.unhappy {
@include after {
content: '\1F621';
}
}
}
} }
td, .table-td { td, .table-td {
@ -809,6 +789,103 @@ nav.sub-menu {
} }
} }
.admin-notes {
position: relative;
float: left;
margin-top: -0.2em;
margin-right: 0.25em;
cursor: pointer;
@include after {
content: $note-icon;
width: 2em;
height: 2em;
}
.notes {
@include hover-info;
top: auto;
bottom: 100%;
right: auto;
min-width: 25em;
p {
font-size: 1.125em;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
}
&:hover, &:focus {
.notes {
display: block;
}
}
}
#main article .admin-status.state {
background-size: 1.333em;
background-repeat: no-repeat;
background-position: center;
width: 1.75em;
position: relative;
font-family: inherit;
padding: 0;
position: relative;
width: 2em;
height: 2em;
@include after {
position: absolute;
bottom: 0;
left: 0;
font-size: 1.5em;
}
&.happy {
@include after {
content: $happy-icon;
opacity: 0.5;
}
}
&.unhappy {
cursor: pointer;
@include after {
content: $angry-icon;
@include _(transform-origin, bottom);
@include _(animation, unhappy ease-in-out 1s infinite alternate both);
}
}
ul {
@include hover-info;
}
li {
white-space: nowrap;
margin: 0 0 0 1em;
&:first-child:last-child {
list-style: none;
margin: 0;
}
}
&:hover, &:focus {
ul {
display: block;
}
}
}
#admin-housing, #admin-schedule { #admin-housing, #admin-schedule {
.guests-housed { .guests-housed {
margin-bottom: 1em; margin-bottom: 1em;
@ -831,13 +908,13 @@ nav.sub-menu {
&.happy { &.happy {
@include after { @include after {
content: '\1F60D'; content: $love-icon;
} }
} }
&.unhappy { &.unhappy {
@include after { @include after {
content: '\1F61E'; content: $unhappy-icon;
} }
} }
} }
@ -886,45 +963,6 @@ nav.sub-menu {
overflow: auto; overflow: auto;
} }
.guest-notes {
position: relative;
float: left;
margin-top: -0.2em;
margin-right: 0.25em;
cursor: pointer;
@include after {
content: '\1F4C4';
width: 2em;
height: 2em;
}
.notes {
@include hover-info;
top: auto;
bottom: 100%;
right: auto;
min-width: 25em;
p {
font-size: 1.125em;
&:first-child {
margin-top: 0;
}
&:last-child {
margin-bottom: 0;
}
}
}
&:hover {
.notes {
display: block;
}
}
}
.address { .address {
margin-top: 1em; margin-top: 1em;
text-align: right; text-align: right;
@ -964,51 +1002,6 @@ nav.sub-menu {
td { td {
vertical-align: middle; vertical-align: middle;
} }
.state {
position: relative;
font-family: inherit;
padding: 0;
position: relative;
width: 2em;
height: 2em;
@include after {
position: absolute;
bottom: 0;
left: 0;
font-size: 1.5em;
}
&.unhappy {
cursor: pointer;
@include after {
@include _(transform-origin, bottom);
@include _(animation, unhappy ease-in-out 1s infinite alternate both);
}
}
ul {
@include hover-info;
}
li {
white-space: nowrap;
margin: 0 0 0 1em;
&:first-child:last-child {
list-style: none;
margin: 0;
}
}
&:hover {
ul {
display: block;
}
}
}
} }
#workshop-selector { #workshop-selector {
@ -1364,6 +1357,85 @@ nav.sub-menu {
#admin-schedule { #admin-schedule {
#schedule-preview {
overflow: visible
}
table.schedule {
td.workshop {
vertical-align: top;
text-align: left;
position: relative;
.event-detail-link {
width: auto;
font-size: 1.25em;
}
}
.status {
display: inline-block;
text-align: left;
float: right;
font-size: 0.9em;
margin-top: 0.5em;
}
.conflict-score {
text-align: right;
.title {
@include font-family(secondary);
}
}
.admin-status {
position: absolute;
top: 0;
right: 0.25em;
ul {
width: 15em;
}
+ .event-detail-link {
padding-right: 1em;
}
}
.admin-notes {
@include after {
font-size: 1.25em;
}
}
.workshop-container {
padding-bottom: 4em;
}
.deschedule-workshop {
position: absolute;
right: 0.5em;
bottom: 0.5em;
left: 0.5em;
}
form {
margin-top: 0;
button {
margin-top: 0.5em;
float: left;
z-index: 1;
opacity: 0.5;
&:hover, &:focus {
opacity: 1;
}
}
}
}
.workshops-to-schedule { .workshops-to-schedule {
@include _-(display, flex); @include _-(display, flex);
@include _(flex-wrap, wrap); @include _(flex-wrap, wrap);

69
app/assets/stylesheets/_application.scss

@ -2136,70 +2136,6 @@ table.schedule {
align-items: center; align-items: center;
@include not-link-like; @include not-link-like;
.details {
flex: 1;
}
}
.status {
display: inline-block;
text-align: left;
float: right;
font-size: 0.9em;
margin-top: 0.5em;
}
.conflict-score {
text-align: right;
.title {
@include font-family(secondary);
}
}
.errors {
position: relative;
border-top: 0.1rem solid $dark-gray;
margin-top: 0.5em;
padding-top: 0.25em;
@include before {
content: '!';
display: inline-block;
position: absolute;
z-index: 1;
top: 0;
left: -1.2em;
width: 1em;
color: $white;
@include font-family(secondary);
}
@include after {
content: '';
position: absolute;
top: 0.1em;
left: -1.333em;
width: 0;
height: 0;
font-size: 1.25em;
border: 0.5em solid;
border-left-color: transparent;
border-right-color: transparent;
border-width: 0 0.5em 0.75em;
color: darken($colour-2, 25%);
}
}
#main .columns & form {
margin-top: 0;
button {
margin-top: 0.5em;
float: left;
z-index: 1;
}
} }
} }
} }
@ -3510,9 +3446,10 @@ body.policy .policy-agreement ul {
} }
.nav { .nav {
display: block;
@include _-(display, flex);
position: static; position: static;
font-size: 1.75em; font-size: 1.75em;
display: block;
text-align: center; text-align: center;
background-color: transparent; background-color: transparent;
@include _(box-shadow, none); @include _(box-shadow, none);
@ -3520,6 +3457,8 @@ body.policy .policy-agreement ul {
.nav a { .nav a {
&[class] { &[class] {
@include _(flex, 1);
white-space: nowrap;
width: auto; width: auto;
float: none; float: none;
overflow: visible; overflow: visible;

8
app/assets/stylesheets/_settings.scss

@ -39,6 +39,14 @@ $link-colour: darken($colour-1, 13%);
$selected-colour: rgba($blue, 0.5); $selected-colour: rgba($blue, 0.5);
$note-icon: '\1F4C4';
$down-icon: '';
$up-icon: '';
$happy-icon: '\1F601';
$unhappy-icon: '\1F61E';
$love-icon: '\1F60D';
$angry-icon: '\1F621';
@mixin default-box-shadow($direction: top, $distance: 1, $inset: false, $additional-shadow: false) { @mixin default-box-shadow($direction: top, $distance: 1, $inset: false, $additional-shadow: false) {
@if capable_of(box-shadow) { @if capable_of(box-shadow) {
$offset: 0.2em; $offset: 0.2em;

4
app/controllers/application_controller.rb

@ -492,6 +492,8 @@ class ApplicationController < BaseController
@schedule[day][:times] = data[:times].sort.to_h @schedule[day][:times] = data[:times].sort.to_h
@schedule[day][:locations] ||= {} @schedule[day][:locations] ||= {}
# sort the locations by name
@schedule[day][:locations] = @schedule[day][:locations].sort_by { |event_id, event| event.present? ? event.title.downcase : '' }.to_h
# add an empty block if no workshops are scheduled on this day yet # add an empty block if no workshops are scheduled on this day yet
@schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty? @schedule[day][:locations][0] = :add if do_analyze || @schedule[day][:locations].empty?
@ -537,7 +539,7 @@ class ApplicationController < BaseController
location: location, location: location,
workshop: workshop_i, workshop: workshop_i,
i18nVars: { i18nVars: {
need: need.to_s, need: I18n.t("workshop.options.amenity.#{need}"),
location: location.title, location: location.title,
workshop_title: workshop_i.title workshop_title: workshop_i.title
} }

19
app/helpers/widgets_helper.rb

@ -138,17 +138,14 @@ module WidgetsHelper
other = (guest[:guest].housing_data || {})['other'] other = (guest[:guest].housing_data || {})['other']
other.strip! if other.present? other.strip! if other.present?
if other.present? name_html += admin_notes(other) if other.present?
name_html += content_tag :div, (content_tag :div, paragraph(other), class: 'notes').html_safe, class: 'guest-notes'
end
guest_rows += content_tag :tr, id: "hosted-guest-#{guest_id}" do guest_rows += content_tag :tr, id: "hosted-guest-#{guest_id}" do
(content_tag :td, name_html.html_safe) + (content_tag :td, name_html.html_safe) +
(content_tag :td do (content_tag :td do
(guest[:guest].from + (guest[:guest].from +
(content_tag :a, (_'actions.workshops.Remove'), href: '#', class: 'remove-guest', data: { guest: guest_id })).html_safe (content_tag :a, (_'actions.workshops.Remove'), href: '#', class: 'remove-guest', data: { guest: guest_id })).html_safe
end) + end) + admin_status(status_html, :td)
(content_tag :td, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy])
end end
end end
@ -163,7 +160,7 @@ module WidgetsHelper
status_html = '' status_html = ''
if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present? if @housing_data[id][:warnings].present? && @housing_data[id][:warnings][:space].present? && @housing_data[id][:warnings][:space][area].present?
@housing_data[id][:warnings][:space][area].each do |w| @housing_data[id][:warnings][:space][area].each do |w|
status_html += content_tag(:li, _("warnings.messages.housing.space.#{w.to_s}")) status_html += content_tag(:li, _("warnings.messages.housing.space.#{w.to_s}", ))
end end
end end
if status_html.present? if status_html.present?
@ -178,7 +175,7 @@ module WidgetsHelper
html += content_tag :tr do html += content_tag :tr do
(content_tag :th, (_"forms.labels.generic.#{area}"), colspan: 2) + (content_tag :th, (_"forms.labels.generic.#{area}"), colspan: 2) +
(content_tag :th, status_html.html_safe, class: [:state, status_html.present? ? :unhappy : :happy]) admin_status(status_html, :th)
end end
html += guest_rows html += guest_rows
html += content_tag :tr, class: 'place-guest' do html += content_tag :tr, class: 'place-guest' do
@ -194,6 +191,14 @@ module WidgetsHelper
content_tag :table, html.html_safe, class: 'host-table' content_tag :table, html.html_safe, class: 'host-table'
end end
def admin_notes(notes)
content_tag :div, (content_tag :div, paragraph(notes), class: 'notes').html_safe, class: 'admin-notes', tabindex: -1
end
def admin_status(status_html, tag = :div)
content_tag tag, status_html.html_safe, class: "admin-status state #{status_html.present? ? 'un' : ''}happy", tabindex: -1
end
def host_guests_widget(registration) def host_guests_widget(registration)
html = '' html = ''
classes = ['host'] classes = ['host']

44
app/views/conference_administration/_schedule.html.haml

@ -29,27 +29,29 @@
- workshop = status = nil - workshop = status = nil
%td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }} %td{class: [time_data[:type], workshop.present? ? :filled : :open], rowspan: rowspan, data: workshop.present? ? nil : { block: time_data[:item][:block], day: day, location: id }}
- if workshop.present? && workshop.event_location.present? - if workshop.present? && workshop.event_location.present?
= link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do .workshop-container
.details - if @can_edit
.title=_!workshop.title -if strip_tags(workshop.notes).strip.present?
%template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }} = admin_notes(workshop.notes)
%h1.title=_!workshop.title - if status[:errors].present?
%p.address = admin_status content_tag(:ul, (status[:errors].collect { |error| (_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars])}.join).html_safe).html_safe
= _!("#{workshop.event_location.title}:") = link_to view_workshop_path(@conference.slug, workshop.id), class: 'event-detail-link' do
= location_link workshop.event_location .details
.workshop-description= richtext workshop.info, 1 .title=_!workshop.title
- if @can_edit %template.event-details{data: { href: view_workshop_path(@conference.slug, workshop.id) }}
= form_tag administration_update_path(conference.slug, @admin_step), class: 'deschedule-workshop' do %h1.title=_!workshop.title
.status %p.address
.conflict-score = _!("#{workshop.event_location.title}:")
%span.title Conflicts: = location_link workshop.event_location
%span.value="#{status[:conflict_score]} / #{workshop.interested.size}" .workshop-description= richtext workshop.info, 1
- if status[:errors].present? - if @can_edit
.errors = form_tag administration_update_path(conference.slug, @admin_step), class: 'deschedule-workshop' do
- status[:errors].each do |error| .status
.error=_"errors.messages.schedule.#{error[:name].to_s}", vars: error[:i18nVars] .conflict-score
= hidden_field_tag :id, workshop.id %span.title Conflicts:
= button :deschedule, value: :deschedule_workshop, class: [:delete, :small] %span.value="#{status[:conflict_score]} / #{workshop.interested.size}"
= hidden_field_tag :id, workshop.id
= button :deschedule, value: :deschedule_workshop, class: [:delete, :small]
- elsif @can_edit - elsif @can_edit
.title="Block #{time_data[:item][:block] + 1}" .title="Block #{time_data[:item][:block] + 1}"
- elsif time_data[:type] != :nil - elsif time_data[:type] != :nil

4
config/locales/en.yml

@ -2630,6 +2630,10 @@ en:
projector: Projector projector: Projector
sound: Sound System sound: Sound System
tools: Tools tools: Tools
amenity:
projector: a projector
sound: a sound system
tools: tools
space: space:
meeting_room: Meeting Room meeting_room: Meeting Room
outdoor_meeting: Outdoor Space outdoor_meeting: Outdoor Space

3
config/locales/fr.yml

@ -1716,6 +1716,9 @@ fr:
Leave: Se retirer Leave: Se retirer
Make_Owner: Changer de responsable Make_Owner: Changer de responsable
Remove: Supprimer Remove: Supprimer
conference:
edit_registration: Mon inscription
Translate: Modifier la version %{language}
datetime: datetime:
distance_in_words: distance_in_words:
x_days: x_days:

Loading…
Cancel
Save