Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
04950bc
(Nicolette & Sarah) Add recommendation score placeholder function #84
sarah12345 Apr 2, 2016
89112d8
Adds button and basic js method for recommended shifts
Apr 2, 2016
fd70b73
(Nicolette & Sarah) calculate newness score for person #84
sarah12345 Apr 2, 2016
2a20f13
Fixes html to properly wrap each shift
Apr 2, 2016
949af57
fixed css
Apr 2, 2016
371d9b0
Completes basic toggling of whole shifts regardless of recommendation
Apr 2, 2016
07b021c
Danie/Alyssa - update feature for recommended shifts
daniehacks Apr 2, 2016
7406685
remove recommendation score from shift, make a new model called shift…
sarah12345 Apr 2, 2016
f82322e
adds call to recommendation score calculator
alycit Apr 2, 2016
a756b90
Danie - removed extra data from shift factory
daniehacks Apr 2, 2016
d3919e6
Danie/Alyssa/Nina - added shift recommendation to top 5 shifts
daniehacks Apr 2, 2016
a90c56e
find calls_with_positive_response - wip (waiting for another commit f…
sarah12345 Apr 2, 2016
394a914
Nicolette & Amy | Create a method that calculates expected # of incid…
Apr 2, 2016
70c5826
Nicolette & Amy | Fix merge conflict in shift_recommendation_score
Apr 2, 2016
4ccc46d
cacluate shift rate of response - needs time calculation
sarah12345 Apr 2, 2016
38e14e3
Remove Step 3 From INSTALL.md
nchambe2 Apr 2, 2016
2487892
Nicolette && Amy | Add missing end keyword to shift recommendation score
nchambe2 Apr 2, 2016
54ca9b8
Nicolette && Amy | Fix merge conflict in shift_recommendation_score.rb
nchambe2 Apr 2, 2016
b2107d1
Nicolette && Amy | Create a spec for unique_shift
nchambe2 Apr 2, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ end


group :test do
gem 'byebug'
gem 'rspec', '~> 3.0'
gem 'rspec-rails'
gem 'rspec-activemodel-mocks'
Expand Down
3 changes: 0 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,3 @@ DEPENDENCIES
wkhtmltopdf-binary!
wkhtmltopdf-heroku!
zonebie

BUNDLED WITH
1.11.2
17 changes: 6 additions & 11 deletions INSTALL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,8 @@

$ curl -fsSL https://gist.github.com/mislav/055441129184a1512bb5.txt | rbenv install --patch 2.1.2

3. Open seeds.rb and edit the username and password in the last code
block of that file. The last few lines of seeds.rb create an example
/ test user. You're welcome to use those creds locally, but will
definitely want to change them for any production use. Be sure not
to store real creds in seeds.rb!

4. Run `./bin/setup` in the project directory
3. Run `./bin/setup` in the project directory

If you see an error about `capybara-webkit`, check your version of
`qmake`. You may want to follow the suggestion
Expand All @@ -39,7 +34,7 @@
successfully.


5. The setup script should create your db, but if it fails for
4. The setup script should create your db, but if it fails for
permission reasons, try the following, with your system username in
place of `myuser`:

Expand All @@ -58,7 +53,7 @@
postgres=# GRANT ALL ON DATABASE "arcdata-dev" TO myuser;
postgres=# \q
```
6. Try ./bin/setup again. If you get an error like:
5. Try ./bin/setup again. If you get an error like:

```
ActiveRecord::UnknownAttributeError: unknown attribute: password
Expand All @@ -78,9 +73,9 @@
$ ./bin/setup
```

7. Run `./bin/setup` again. Once it runs without errors, your app is set up.
6. Run `./bin/setup` again. Once it runs without errors, your app is set up.

8. Run `bundle exec unicorn -c unicorn.rb` to start the development
7. Run `bundle exec unicorn -c unicorn.rb` to start the development
server and visit [http://0.0.0.0:8080](http://0.0.0.0:8080) in your
browser. Login with the credentials you created in seeds.rb. The
defaults are `admin` and `test123`.
Expand All @@ -96,4 +91,4 @@ Twilio as part of testing.

Go to [Twilio](https://www.twilio.com/try-twilio) to sign up for a trial
account and verify your phone number. With a trial account, you'll only
be able to text yourself.
be able to text yourself.
28 changes: 24 additions & 4 deletions app/assets/javascripts/scheduler/calendar.js.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ class window.CalendarController
complete: (xhr, status) =>
this.reloadDate(date, period)

new PersonTypeaheadController $('#select-person'), ((id, record) => @params.person_id = id; this.reload()), 'select-person',
new PersonTypeaheadController $('#select-person'), ((id, record) => @params.person_id = id; this.reload()), 'select-person',
active: false
has_position: true

$(document).on 'click', '#highlighting-group > button', (evt) =>
active = if ($(evt.target).hasClass('active')) then false else true
$(evt.target).toggleClass('active', active)
$('.calendar-container').toggleClass($(evt.target).data('style'), active)
style = $(evt.target).data('style')
if style == 'highlight-recommended-shifts'
this.highlightRecommendedShifts(active)
else
$('.calendar-container').toggleClass($(evt.target).data('style'), active)

$(document).on 'click', '#select-shift-group > button', (evt) =>
$('#select-shift-group > button').removeClass('active')
Expand All @@ -60,6 +64,22 @@ class window.CalendarController
val[val.length] = $(el).val()
val

highlightRecommendedShifts: (toggleIndicator) ->
all_shift_scores = $('.shift[data-recommendation]')

sorted_shift_scores = all_shift_scores.sort (first_shift, second_shift) ->
first_score = parseInt($(first_shift).attr('data-recommendation'));
second_score = parseInt($(second_shift).attr('data-recommendation'));

if(second_score < first_score)
return -1;
else if(second_score > first_score)
return 1;
else
return 0;

sorted_shift_scores.slice(0,5).toggleClass("recommended", toggleIndicator);

renderArgs: () ->
@params

Expand Down Expand Up @@ -97,5 +117,5 @@ class window.CalendarController
$('tbody[data-week=' + date + ']').html(data)
when 'monthly'
$('.month').html(data)
else
$('.day[data-day=' + date + ']').html(data)
else
$('.day[data-day=' + date + ']').html(data)
36 changes: 31 additions & 5 deletions app/assets/stylesheets/scheduler/calendar.css.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ body.calendar {
table.calendar {
&.loading {
opacity: 0.5;

}
width: 100%;
td.day, td.week, td.month[colspan="1"] {
Expand All @@ -23,7 +23,7 @@ body.calendar {
width: 14.2%;
}
td.week {

}
td label {
font-size: inherit;
Expand All @@ -48,6 +48,10 @@ body.calendar {
}
}

.hightlight-recommended-shifts {

}

@mixin rotate($rot) {
-webkit-transform: rotate($rot);
-o-transform: rotate($rot);
Expand Down Expand Up @@ -81,11 +85,12 @@ body.calendar {
border-bottom-style: none;
}
}
th.date-header {
div.date-header, th.date-header {
font-size: 130%;
amax-width: 1em;
padding: 0;
text-align: center;
font-weight: bold;
}
tr.end-group {
td,th {
Expand All @@ -99,6 +104,27 @@ body.calendar {
afont-size: 125%;
line-height: 1.2;
}

.shift {
border-bottom: 1px dashed black;

div.shift-header-normal {
text-align: center;
font-size: 110%;
font-weight: bold;
}
}

.shift:last-child {
border-bottom: none;
}


.recommended {
border: 1px solid #fdad7c;
background-color: #fedcc7;
}

}

.calendar-spreadsheet {
Expand Down Expand Up @@ -168,7 +194,7 @@ body.calendar {
//border-bottom: 1px solid rgb(221,221,221);
}
}

}

thead {
Expand Down Expand Up @@ -279,4 +305,4 @@ body.steven {
}



8 changes: 6 additions & 2 deletions app/helpers/scheduler/calendar_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def render_shifts group, shifts, date, editable
end
end

def retrieve_recommendation_score(group, shifts, date)
Scheduler::ShiftRecommendationScore.get_score(shifts.first, group, date)
end

def group_to_period group
case group.period
when 'daily' then 'day'
Expand Down Expand Up @@ -71,10 +75,10 @@ def render_shift_assignment_info(editable, person, shift, shift_group, my_shifts
s << check_box_tag(shift.id.to_s, # Name
date.to_s, # Value
is_signed_up, # Checked?
id: cbid,
id: cbid,
class: 'shift-checkbox',
data: {
:assignment => this_assignment.try(:id),
:assignment => this_assignment.try(:id),
:period => period,
params: create_params(person, shift, shift_group, date)
}) << " "
Expand Down
12 changes: 11 additions & 1 deletion app/models/roster/person.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ class Roster::Person < ActiveRecord::Base
include Mappable

PHONE_TYPES = [:cell_phone, :home_phone, :work_phone, :alternate_phone, :sms_phone]
NEWNESS_LOW = 0.5
NEWNESS_MED = 0.7
NEWNESS_HIGH = 1.0

belongs_to :chapter, class_name: 'Roster::Chapter'
belongs_to :primary_county, class_name: 'Roster::County'
Expand All @@ -20,7 +23,7 @@ class Roster::Person < ActiveRecord::Base
belongs_to :alternate_phone_carrier, class_name: 'Roster::CellCarrier'
belongs_to :sms_phone_carrier, class_name: 'Roster::CellCarrier'

scope :name_contains, lambda {|query|
scope :name_contains, lambda {|query|
where{lower(first_name.op('||', ' ').op('||', last_name)).like("%#{query.downcase}%")}
}

Expand Down Expand Up @@ -193,4 +196,11 @@ def profile_complete?
def is_active?
vc_is_active or has_role 'always_active'
end

def newness_factor
opportunities = Incidents::ResponderAssignment.for_person(self).count
return NEWNESS_HIGH if opportunities < 5
return NEWNESS_MED if opportunities >= 5 && opportunities < 20
NEWNESS_LOW
end
end
1 change: 1 addition & 0 deletions app/models/scheduler/shift.rb
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,5 @@ def total_shifts_for_month(month)
def display_name
"#{shift_groups.first.try :chapter_id} - #{county.try(:abbrev)} #{name} - #{shift_groups.map(&:name).join ', '}"
end

end
47 changes: 47 additions & 0 deletions app/models/scheduler/shift_recommendation_score.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
class Scheduler::ShiftRecommendationScore

def self.get_score(shift, shift_group, date)
rand(5).to_i
end

def self.expected_number_of_incidents(unique_shift)
matching_incidents = Incidents::Incident
.where(:chapter => unique_shift[:chapter])
.where(:created_at => 12.months.ago..Time.now)
.where("EXTRACT(DOW from date) = :day", {day: unique_shift[:day]})
.where("EXTRACT(HOUR from created_at) BETWEEN :start AND :end", {start: unique_shift[:start_time], end: unique_shift[:end_time]}).count

return matching_incidents/52
end

def self.unique_shift(shift, shift_group, day)
generate_unique_shift = { day: day,
start_time: shift_group.start_offset/(60*60),
end_time: shift_group.end_offset/(60*60),
chapter: shift.chapter.name }
return generate_unique_shift
end

def self.shift_response_rate(shift, shift_group, date)
total_calls = total_calls(shift,shift_group,date)
return 0 if total_calls.zero?
calls_with_positive_response(shift,shift_group,date)/total_calls
end

private

def self.calls_with_positive_response(shift, shift_group, date)
Incidents::ResponderAssignment.
for_chapter(shift.chapter).
was_available.
#need to match day/time
count.to_f
end

def self.total_calls(shift, shift_group, date)
Incidents::ResponderAssignment.
for_chapter(shift.chapter).
#need to match day/time
count.to_f
end
end
19 changes: 9 additions & 10 deletions app/views/scheduler/calendar/_day.html.haml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%table.shifts
%tr
%th.date-header(colspan=2)=date.day
%div.shifts
%div
%div.date-header(colspan=2)=date.day
- calendar.daily_groups.each_with_index do |(group, shifts), group_idx|
- assignments = calendar.assignments_for_group_on_day group, date
-# cache [group, shifts, assignments, date, ajax_params] do
Expand All @@ -11,13 +11,12 @@
-if person
- my_shifts = calendar.my_shifts_for_group_on_day(group.id, date)
- group_class = my_shifts.present? ? 'my-shift' : ''
%tr
%th.shift-header-normal.shift-side{class: [group_class, is_last_group && 'last-group'], rowspan: shifts.count+1}=group.name
%th.shift-header-normal.shift-top{class: group_class}=group.name

- render_shifts group, shifts, date, editable do |idx, is_first, is_last, needs_signups, row_html|
%tr{class: [group_class, (!is_last_group && is_last && 'end-group')]}
%td{class: needs_signups&&'open'}=row_html
%div.shift{"data-recommendation" => retrieve_recommendation_score(group, shifts, date) }
%div.shift-header-normal.shift-top{class: group_class}=group.name

- render_shifts group, shifts, date, editable do |idx, is_first, is_last, needs_signups, row_html|
%div{class: [group_class, (!is_last_group && is_last && 'end-group')]}
%div{class: needs_signups&&'open'}=row_html

-if request.xhr?
:javascript
Expand Down
3 changes: 2 additions & 1 deletion app/views/scheduler/calendar/show.html.haml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
= provide :header do
%meta(name="pdfkit-orientation" content="Landscape")
#calendar-title=render 'title', month: @month

.calendar-config
.row
.col-sm-3
Expand All @@ -15,6 +15,7 @@
.btn-group-vertical.btn-block#highlighting-group
%button.btn.btn-default.btn-block.active{:"data-style" => "highlight-my-shifts"} My Shifts
%button.btn.btn-default.btn-block{:"data-style" => "highlight-open-shifts"} Open Shifts
%button.btn.btn-default.btn-block{:"data-style" => "highlight-recommended-shifts"} Recommended Shifts
.col-sm-3
%h5 Show Shifts For
.row
Expand Down
9 changes: 9 additions & 0 deletions spec/features/scheduler/view_recommended_shifts_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'spec_helper'

describe "View Recommended Shifts", type: :feature do

it "should show a Recommended Shifts button" do
visit "/scheduler/calendar/2016/april"
expect(page).to have_selector(:link_or_button, 'Recommended Shifts')
end
end
Loading