diff --git a/Makefile b/Makefile
index f907d04118..4f9d0a6a1c 100644
--- a/Makefile
+++ b/Makefile
@@ -59,6 +59,7 @@ db_create_test:
# docker-compose run --no-deps -e RAILS_ENV=test --entrypoint "rake db:drop" app
docker-compose run --no-deps -e RAILS_ENV=test --entrypoint "rake db:create" app
docker-compose run --no-deps -e RAILS_ENV=test --entrypoint "rake db:schema:load" app
+ # docker exec -it mongo mongo --authenticationDatabase admin --host localhost -u mongo -p 123456789 oscar_history_test --eval "db.dropUser('oscar'); db.createUser({user: 'oscar', pwd: '123456789', roles: [{role: 'readWrite', db: 'oscar_history_test'}]});"
docker-compose exec -T mongo mongo --authenticationDatabase admin --host localhost -u mongo -p 123456789 oscar_history_test --eval "db.dropUser('oscar'); db.createUser({user: 'oscar', pwd: '123456789', roles: [{role: 'readWrite', db: 'oscar_history_test'}]});"
# If the container is NOT running and you want to get a bash terminal then run this command
diff --git a/app/assets/images/cb_dmat/1-5-years.png b/app/assets/images/cb_dmat/1-5-years.png
new file mode 100755
index 0000000000..e6daaa5c55
Binary files /dev/null and b/app/assets/images/cb_dmat/1-5-years.png differ
diff --git a/app/assets/images/cb_dmat/1-year.png b/app/assets/images/cb_dmat/1-year.png
new file mode 100755
index 0000000000..ec10e41b5e
Binary files /dev/null and b/app/assets/images/cb_dmat/1-year.png differ
diff --git a/app/assets/images/cb_dmat/12-months.png b/app/assets/images/cb_dmat/12-months.png
new file mode 100755
index 0000000000..7c2b6dc0e3
Binary files /dev/null and b/app/assets/images/cb_dmat/12-months.png differ
diff --git a/app/assets/images/cb_dmat/18-months.png b/app/assets/images/cb_dmat/18-months.png
new file mode 100755
index 0000000000..989f4d60ca
Binary files /dev/null and b/app/assets/images/cb_dmat/18-months.png differ
diff --git a/app/assets/images/cb_dmat/2-5-years.png b/app/assets/images/cb_dmat/2-5-years.png
new file mode 100755
index 0000000000..215438da80
Binary files /dev/null and b/app/assets/images/cb_dmat/2-5-years.png differ
diff --git a/app/assets/images/cb_dmat/2-years.png b/app/assets/images/cb_dmat/2-years.png
new file mode 100755
index 0000000000..f858bd79cb
Binary files /dev/null and b/app/assets/images/cb_dmat/2-years.png differ
diff --git a/app/assets/images/cb_dmat/3-months.png b/app/assets/images/cb_dmat/3-months.png
new file mode 100755
index 0000000000..c6e90b319e
Binary files /dev/null and b/app/assets/images/cb_dmat/3-months.png differ
diff --git a/app/assets/images/cb_dmat/3-years.png b/app/assets/images/cb_dmat/3-years.png
new file mode 100755
index 0000000000..04c36e138b
Binary files /dev/null and b/app/assets/images/cb_dmat/3-years.png differ
diff --git a/app/assets/images/cb_dmat/4-years.png b/app/assets/images/cb_dmat/4-years.png
new file mode 100755
index 0000000000..cf578d81ab
Binary files /dev/null and b/app/assets/images/cb_dmat/4-years.png differ
diff --git a/app/assets/images/cb_dmat/5-years.png b/app/assets/images/cb_dmat/5-years.png
new file mode 100755
index 0000000000..b5a346b8d3
Binary files /dev/null and b/app/assets/images/cb_dmat/5-years.png differ
diff --git a/app/assets/images/cb_dmat/6-months.png b/app/assets/images/cb_dmat/6-months.png
new file mode 100755
index 0000000000..08279bf0a2
Binary files /dev/null and b/app/assets/images/cb_dmat/6-months.png differ
diff --git a/app/assets/images/cb_dmat/6-years.png b/app/assets/images/cb_dmat/6-years.png
new file mode 100755
index 0000000000..cf578d81ab
Binary files /dev/null and b/app/assets/images/cb_dmat/6-years.png differ
diff --git a/app/assets/images/cb_dmat/9-months.png b/app/assets/images/cb_dmat/9-months.png
new file mode 100755
index 0000000000..e6daaa5c55
Binary files /dev/null and b/app/assets/images/cb_dmat/9-months.png differ
diff --git a/app/assets/javascripts/advanced_filter_builder.coffee b/app/assets/javascripts/advanced_filter_builder.coffee
index ddd5792b05..131937fe6e 100644
--- a/app/assets/javascripts/advanced_filter_builder.coffee
+++ b/app/assets/javascripts/advanced_filter_builder.coffee
@@ -14,6 +14,7 @@ class CIF.AdvancedFilterBuilder
window.customGroup["#{addRule.id}"] = addRule if window.customGroup["#{addRule.id}"] == undefined
$('#builder_group_0').find('.rules-group-body .btn-custom-group').hide()
+ $('#builder_group_0').find('.rules-group-body .btn-default-group').hide()
$(@element.selector).on 'beforeDeleteGroup.queryBuilder', (parent, group) ->
if $('body#clients-index').length
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 8de48b902a..b517172cd4 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -128,6 +128,7 @@
//= require settings/research_module
//= require settings/client_forms
//= require settings/integration
+//= require settings/risk_assessment
//= require settings/customize_case_note
//= require prevent_required_file_uploader
//= require format_special_characters
@@ -148,3 +149,4 @@
//= require case_conferences/form
//= require internal_referrals/form
//= require service_receives/form
+//= require screening_assessments/form
diff --git a/app/assets/javascripts/application_with_pack.js b/app/assets/javascripts/application_with_pack.js
new file mode 100644
index 0000000000..9b3f02faae
--- /dev/null
+++ b/app/assets/javascripts/application_with_pack.js
@@ -0,0 +1,62 @@
+// FRAMEWORK
+//= require jquery
+//= require jquery_ujs
+//= require jquery-ui
+//= require bootstrap-sprockets
+//= require jquery.steps.min
+//= require jquery.validate
+//= require jquery.validate.additional-methods
+//= require jquery.nicescroll.min
+
+//= require editable/bootstrap-editable
+//= require editable/rails
+//= require jQuery.print
+
+//= require image_upload_previewer/image_upload_previewer
+//= require image_upload
+//= require bootstrap-datepicker/core
+//= require bootstrap-datepicker/locales/bootstrap-datepicker.en-GB.js
+//= require datepicker
+//= require metisMenu/jquery.metisMenu.js
+//= require lodash/lodash.min.js
+// require query_builder/query-builder.standalone.min.js
+//= require jquery.extendext
+//= require doT
+//= require query-builder
+
+//remove query_builder/utils, query_builder/model and query_builder/plugin bcuz conflict with form-builder select option not show
+
+//= require moment
+//= require fullcalendar
+//= require bootstrap_file_input/purify.min.js
+//= require bootstrap_file_input/fileinput.js
+//= require bootstrap_file_input/fa/theme.min.js
+//= require bootstrap_file_input/explorer/theme.min.js
+
+// WRAPBOOTSTRAP
+//= require iCheck/icheck.min.js
+//= require wrapbootstrap/inspinia.js
+//= require slimscroll/jquery.slimscroll.min.js
+//= require toastr/toastr.min.js
+//= require bootstrap-tour/bootstrap-tour.js
+
+// LADDA
+//= require ladda/spin.min
+//= require ladda/ladda.min
+//= require ladda/ladda.jquery.min
+
+//LOAD MODULE
+//= require namespace
+//= require util
+//= require initializer
+//= require common
+//= require jquery.infinitescroll.min
+//= require footable.all.min
+
+//APPLICATION JS
+//= require calendars/index
+//= require clients/index
+//= require report_creator
+//= require clients/show
+//= require clients/form
+//= require clients/book
diff --git a/app/assets/javascripts/assessments/form.coffee b/app/assets/javascripts/assessments/form.coffee
index 78f952832f..7c8bfad766 100644
--- a/app/assets/javascripts/assessments/form.coffee
+++ b/app/assets/javascripts/assessments/form.coffee
@@ -1,5 +1,6 @@
CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.AssessmentsUpdate = do ->
_init = ->
+ window.domainOptionScores = {}
forms = $('form.assessment-form')
for form in forms
@@ -73,7 +74,7 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
currentTabLabels = $(@).siblings()
currentTabLabels.removeClass('active-label')
-
+ domainOptionScores[@.dataset.domainId] = @.dataset.score
$('.score_option').removeClass('is_error')
labelColors = 'btn-danger btn-warning btn-primary btn-success btn-secondary'
currentTabLabels.removeClass(labelColors)
@@ -85,6 +86,7 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
$($(@).siblings().get(-1)).val(score)
$('.score_option input').attr('required','required')
+
$('.col-xs-12').on 'click', '.score_option label', ->
return if $(@).closest(".root-wizard").attr("id") == 'readonly-rootwizard'
@@ -149,7 +151,7 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
currentTab = "#{rootId}-p-#{currentIndex}"
domainId = $("#{currentTab}").find('.score_option').data('domain-id')
- return true if _disableRequiredFields() || rootId == '#readonly-rootwizard'
+ return true if _disableRequiredFields() || rootId == '#readonly-rootwizard' || domainId == undefined
form.validate().settings.ignore = ':disabled,:hidden'
form.valid()
@@ -167,7 +169,8 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
_formEdit(rootId, currentIndex)
$('a#btn-save').show()
- if currentStep.hasClass('domain-last') or $(rootId).find('a[href="#finish"]:visible').length
+ if (currentStep.hasClass('domain-last') or $(rootId).find('a[href="#finish"]:visible').length)
+ _setTotalRiskAssessment()
if $(rootId).find('a[href="#finish"]:visible').length
console.log 'hiding save button'
$("#{rootId} a[href='#save']").hide()
@@ -179,9 +182,7 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
form.validate().settings.ignore = ':disabled'
form.valid()
- currentStep = $("#{rootId}-p-" + currentIndex)
-
- _filedsValidator(currentIndex,newIndex)
+ _filedsValidator(currentIndex, newIndex)
onFinished: ->
return if rootId == '#readonly-rootwizard'
@@ -191,6 +192,20 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
$('.actions a:contains("Done")').removeAttr('href')
form.submit()
+ _setTotalRiskAssessment = ->
+ scoreColors = $('.score_option.with-def')[0].dataset
+ total = 0
+ $.each $('.risk-assessment-domain-score'), (index, element) ->
+ scoreValue = domainOptionScores[element.dataset.domainId]
+ if !_.isEmpty(domainOptionScores) && scoreValue
+ color = scoreColors["score-#{scoreValue}"]
+ $(element).addClass("btn-#{color || 'primary'}")
+ $(element).html(scoreValue)
+ total += parseInt($(element).html())
+
+ total = Math.round(parseFloat(total) / $('.risk-assessment-domain-score').length)
+ $('#btn-total').html(total) if total != 0
+
_appendSaveButton = ->
if $('#rootwizard').find('a[href="#finish"]:visible').length == 0 && $("#btn-save").length == 0
$('#rootwizard').find("[aria-label=Pagination]").append("
")
@@ -227,36 +242,38 @@ CIF.AssessmentsNew = CIF.AssessmentsEdit = CIF.AssessmentsCreate = CIF.Assessmen
scoreOption = $("#{currentTab} .score_option.without-def")
chosenScore = scoreOption.find('label input:checked').val()
- scoreColor = scoreOption.data("score-#{chosenScore}")
- scoreOption.find("label label:contains(#{chosenScore})").addClass("label-default active-label")
-
- btnScore = scoreOption.find('input:hidden').val()
- $(scoreOption.find("div[data-score='#{btnScore}']").get(0)).addClass("btn-secondary")
- domainName = $(@).data('goal-option')
- name = 'assessment[assessment_domains_attributes]['+ "#{currentIndex}" +'][goal_required]\']'
- radioName = '\'' + name
- goalRequiredValue = $("input[name=#{radioName}:checked").val()
- select = $(currentTab).find('textarea.goal')
-
- if scoreColor == 'primary'
- if goalRequiredValue == 'false'
- $(select).val('')
- $(select).prop('readonly', true)
- $(select).addClass('valid')
- else if goalRequiredValue == 'true'
- $(select).prop('readonly', false)
- $(select).removeClass('valid')
- $(select).addClass('valid') if $(select).val() != ''
- else
- if $(select).val() != ''
- $(select).addClass('valid')
+ if chosenScore
+ scoreColor = scoreOption.data("score-#{chosenScore}")
+ scoreOption.find("label label:contains(#{chosenScore})").addClass("label-default active-label")
+
+ btnScore = scoreOption.find('input:hidden').val()
+ $(scoreOption.find("div[data-score='#{btnScore}']").get(0)).addClass("btn-secondary")
+ domainName = $(@).data('goal-option')
+ name = 'assessment[assessment_domains_attributes]['+ "#{currentIndex}" +'][goal_required]\']'
+ radioName = '\'' + name
+ goalRequiredValue = $("input[name=#{radioName}:checked").val()
+ select = $(currentTab).find('textarea.goal')
+
+ if scoreColor == 'primary'
+ if goalRequiredValue == 'false'
+ $(select).val('')
+ $(select).prop('readonly', true)
+ $(select).addClass('valid')
+ else if goalRequiredValue == 'true'
+ $(select).prop('readonly', false)
+ $(select).removeClass('valid')
+ $(select).addClass('valid') if $(select).val() != ''
else
- $(select).removeClass('valid').addClass('required')
+ if $(select).val() != ''
+ $(select).addClass('valid')
+ else
+ $(select).removeClass('valid').addClass('required')
_filedsValidator = (currentIndex, newIndex ) ->
- return true if _disableRequiredFields()
-
currentTab = "#rootwizard-p-#{currentIndex}"
+
+ return true if _disableRequiredFields() || $("#{currentTab}.domain-client-wellbeing-score").length
+
scoreOption = $("#{currentTab} .score_option")
reason = $("#{currentTab} .reason").val()
return false unless reason
diff --git a/app/assets/javascripts/client_advance_search.coffee b/app/assets/javascripts/client_advance_search.coffee
index 845bfe4db5..429f566e5d 100644
--- a/app/assets/javascripts/client_advance_search.coffee
+++ b/app/assets/javascripts/client_advance_search.coffee
@@ -3,6 +3,7 @@ class CIF.ClientAdvanceSearch
@filterTranslation = ''
@customFormSelected = []
@programSelected = []
+ @assessmentSelected = ''
optionTranslation = $('#opt-group-translation')
@enrollmentCheckbox = $('#enrollment-checkbox')
@@ -16,6 +17,7 @@ class CIF.ClientAdvanceSearch
@ENROLLMENT_URL = '/api/client_advanced_searches/get_enrollment_field'
@TRACKING_URL = '/api/client_advanced_searches/get_tracking_field'
@EXIT_PROGRAM_URL = '/api/client_advanced_searches/get_exit_program_field'
+ @PROGRAM_STREAM_URL = '/api/client_advanced_searches/get_program_stream_search_field'
@DOMAIN_SCORES_TRANSLATE = $(optionTranslation).data('csiDomainScores')
@BASIC_FIELD_TRANSLATE = $(optionTranslation).data('basicFields')
@@ -34,6 +36,7 @@ class CIF.ClientAdvanceSearch
setValueToBuilderSelected: ->
@customFormSelected = $('#custom-form-data').data('value')
@programSelected = $('#program-stream-data').data('value')
+ @assessmentSelected = $('#assessment-form-data').data('value')
@wizardCustomFormSelected = $('#wizard-custom-form-data').data('value')
@wizardProgramSelected = $('#wizard-program-stream-data').data('value')
@@ -92,11 +95,11 @@ class CIF.ClientAdvanceSearch
initSelect2: ->
- $('#custom-form-select, #wizard-custom-form-select, #program-stream-select, #wizard-program-stream-select, #quantitative-case-select').select2()
+ $('#custom-form-select, #wizard-custom-form-select, #program-stream-select, #wizard-program-stream-select, #quantitative-case-select, #assessment-select').select2()
$('#builder select').select2()
$('#wizard-builder select').select2()
setTimeout ( ->
- ids = ['#custom-form-select', '#wizard-custom-form-select', '#program-stream-select', '#wizard-program-stream-select', '#quantitative-case-select', '#wizard-builder', '#builder']
+ ids = ['#custom-form-select', '#wizard-custom-form-select', '#program-stream-select', '#wizard-program-stream-select', '#quantitative-case-select', '#wizard-builder', '#builder', '#assessment-select']
$.each ids, (index, item) ->
$("#{item} .rule-filter-container select").select2(width: '250px')
$("#{item} .rule-operator-container select, .rule-value-container select").select2(width: 'resolve')
@@ -119,6 +122,7 @@ class CIF.ClientAdvanceSearch
wizardBasicQueryRules = $('#wizard-builder').data('basic-search-rules')
unless basicQueryRules == undefined or _.isEmpty(basicQueryRules.rules)
self.handleAddHotlineFilter()
+ console.log(basicQueryRules, 'basic query')
$('#builder').queryBuilder('setRules', basicQueryRules)
unless wizardBasicQueryRules == undefined or _.isEmpty(wizardBasicQueryRules.rules)
$('#wizard-builder').queryBuilder('setRules', wizardBasicQueryRules)
@@ -147,6 +151,11 @@ class CIF.ClientAdvanceSearch
$('#custom-form-column').removeClass('hidden')
$('#wizard-custom-form .loader').addClass('hidden')
+ assessmentSelectChange: ->
+ self = @
+ $('.main-report-builder .assessment-form-wrapper select').on 'select2-selecting', (element) ->
+ self.assessmentSelected = element.val
+
addCustomBuildersFields: (ids, url, loader=undefined) ->
self = @
action = _.last(url.split('/'))
@@ -231,6 +240,36 @@ class CIF.ClientAdvanceSearch
$('#custom-form-checkbox').on 'ifChecked', ->
$('.custom-form').show()
+ handleHideAssessmentSelect: ->
+ self = @
+ $('#assessment-checkbox').on 'ifUnchecked', ->
+ ruleFiltersSelect = $('.main-report-builder .rule-container .rule-filter-container select')
+ ruleFiltersSelect.select2('destroy')
+ ruleFiltersSelect.parents('.rule-container').find('.rule-header button').trigger('click')
+ self.assessmentSelected = ''
+ $('.assessment-form').hide()
+ $('#builder').queryBuilder('removeFilter', ['assessment_condition_last_two','assessment_condition_first_last'])
+ $('button[data-add="rule"]').trigger('click')
+ self.initSelect2()
+ return
+
+ handleShowAssessmentSelect: ->
+ self = @
+ if $('#assessment-checkbox').prop('checked')
+ $('.assessment-form').show()
+ $('#assessment-checkbox').on 'ifChecked', ->
+ $('.assessment-form').show()
+ self.assessmentSelected = $('select.assessment-select').val()
+ $.ajax
+ url: self.PROGRAM_STREAM_URL
+ data: { assesment_checked: true }
+ method: 'GET'
+ success: (response) ->
+ fieldList = response.client_advanced_searches
+ $('#builder').queryBuilder('addFilter', fieldList)
+ self.initSelect2()
+ return
+
######################################################################################################################
customFormSelectRemove: ->
@@ -258,6 +297,19 @@ class CIF.ClientAdvanceSearch
if $('#wizard_custom_form_filter').is(':checked')
self.handleRemoveFilterBuilder(removeValue, self.CUSTOM_FORM_TRANSLATE, '#wizard-builder')
+ assessmentSelectRemove: ->
+ self = @
+ $('.main-report-builder .assessment-form-wrapper select').on 'select2-removed', (element) ->
+ $.map self.assessmentSelected, (val, i) ->
+ if parseInt(val) == parseInt(element.val) then self.assessmentSelected.splice(i, 1)
+
+ removeActiveClientProgramOption: ->
+ $('.main-report-builder .rule-container .rule-filter-container select').select2('destroy')
+ $('.main-report-builder .rule-container').find('.rule-header button').trigger('click')
+ $('button[data-add="rule"]').trigger('click')
+ $('#builder').queryBuilder('removeFilter', ['active_client_program'])
+ @.initSelect2()
+
handleRemoveFilterBuilder: (resourceName, resourcelabel, elementBuilder = '#builder') ->
self = @
if elementBuilder == '#builder'
@@ -323,6 +375,7 @@ class CIF.ClientAdvanceSearch
$('.main-report-builder .program-association, .main-report-builder .program-stream').hide()
$('.main-report-builder .program-association input[type="checkbox"]').iCheck('uncheck')
$('.main-report-builder select.program-stream-select').select2("val", "")
+ self.removeActiveClientProgramOption()
handleProgramSelectChange: ->
self = @
@@ -330,6 +383,9 @@ class CIF.ClientAdvanceSearch
programId = psElement.val
self.programSelected.push programId
$('.main-report-builder .program-association').show()
+ if self.programSelected.length == 1
+ self.addCustomBuildersFields(self.programSelected, self.PROGRAM_STREAM_URL, self.LOADER)
+
if $('#enrollment-checkbox').is(':checked')
self.LOADER.start()
self.addCustomBuildersFields(programId, self.ENROLLMENT_URL, self.LOADER)
@@ -679,6 +735,9 @@ class CIF.ClientAdvanceSearch
programStreamAssociation = $('.main-report-builder .program-association')
$(programStreamAssociation).find('.i-checks').iCheck('uncheck')
$(programStreamAssociation).hide()
+
+ if self.programSelected.length == 0
+ self.removeActiveClientProgramOption()
$('#report-builder-wizard .program-stream-select').on 'select2-removed', (element) ->
programName = element.choice.text
@@ -808,6 +867,7 @@ class CIF.ClientAdvanceSearch
builderForm = '.main-report-builder'
programValues = if self.programSelected.length > 0 then "[#{self.programSelected}]"
customFormValues = if self.customFormSelected.length > 0 then "[#{self.customFormSelected}]"
+ assessmentValues = if self.assessmentSelected.length > 0 then "[#{self.assessmentSelected}]"
else
builderElement = '#wizard-builder'
builderForm = '#report-builder-wizard'
@@ -823,6 +883,7 @@ class CIF.ClientAdvanceSearch
self.setValueToProgramAssociation()
$('#client_advanced_search_custom_form_selected').val(customFormValues)
$('#client_advanced_search_program_selected').val(programValues)
+ $('#client_advanced_search_assessment_selected').val(assessmentValues)
if $('#quantitative-type-checkbox').prop('checked') then $('#client_advanced_search_quantitative_check').val(1)
if $('#wizard_quantitative_filter').prop('checked') then $('#client_advanced_search_wizard_quantitative_check').val(1)
if $('#wizard_custom_form_filter').prop('checked') then $('#client_advanced_search_wizard_custom_form_check').val(1)
diff --git a/app/assets/javascripts/clients/index.coffee b/app/assets/javascripts/clients/index.coffee
index 81572ed8c4..8893923be4 100644
--- a/app/assets/javascripts/clients/index.coffee
+++ b/app/assets/javascripts/clients/index.coffee
@@ -58,10 +58,31 @@ CIF.ClientsIndex = do ->
_addTourTip(tour)
_extendDataTableSort()
_addDataTableToAssessmentScoreData()
+ _addDataTableToTableSummary()
_removeReferralDataColumnsInWizardClientColumn()
_handleShowCustomFormSelect()
_reOrderRuleContainer()
_initHelpTextPophover()
+ _initClientColumnFilter()
+
+ _initClientColumnFilter = ->
+ searchBox = $('.client-column ul.columns-visibility #column-search-box')
+ searchBox.keyup ->
+ valThis = $(this).val().toLowerCase()
+ if valThis == ''
+ $('.client-column ul.columns-visibility > li').show()
+ else
+ $('.client-column ul.columns-visibility > li:not(:first-child)').each ->
+ text = $(this).text().toLowerCase()
+ if text.indexOf(valThis) >= 0 then $(this).show() else $(this).hide()
+ return
+ return
+
+ $('.client-column ul.columns-visibility .btn-clear-text').click ->
+ searchBox.val ''
+ searchBox.focus()
+ $('.client-column ul.columns-visibility > li').show()
+ return
_reOrderRuleContainer = ->
$.each $('.csi-group .rules-list'), (index, item)->
@@ -93,12 +114,20 @@ CIF.ClientsIndex = do ->
_addDataTableToAssessmentScoreData = ->
fileName = $('.assessment-domain-score').data('filename')
- _handleAjaxRequestToAssessment("#csi-assessment-score", fileName)
- _handleAjaxRequestToAssessment("#custom-assessment-score", fileName) if $("#custom-assessment-score")
+ _handleAjaxRequestToAssessment("#csi-assessment-score", fileName) if $("#csi-assessment-score").length
+ _handleAjaxRequestToAssessment("#custom-assessment-score", fileName) if $("#custom-assessment-score").length
$('.assessment-domain-score').on 'shown.bs.modal', (e) ->
$($.fn.dataTable.tables(true)).DataTable().columns.adjust()
return
+ _addDataTableToTableSummary = ->
+ fileName = $('.table-summary').data('filename')
+ _handleDataTable("#table-summary-age", fileName)
+ _handleDataTable("#table-summary-referral-category", fileName)
+ $('.table-summary').on 'shown.bs.modal', (e) ->
+ $($.fn.dataTable.tables(true)).DataTable().columns.adjust()
+ return
+
_handleAjaxRequestToAssessment = (tableId, fileName)->
url = $("#{tableId} .api-assessment-path").data('assessment-params')
columns = $("#{tableId} .assessment-domain-headers").data('headers')
@@ -109,7 +138,10 @@ CIF.ClientsIndex = do ->
processing: true
serverSide: true
sServerMethod: 'POST'
- ajax: url
+ ajax:
+ url: url
+ error: (jqXHR, textStatus, errorThrown) ->
+ console.log("Datatable Ajax Error:", errorThrown)
oLanguage: {
sProcessing: ""
}
@@ -143,6 +175,35 @@ CIF.ClientsIndex = do ->
$(tableId).css 'width': '100%'
return
+ _handleDataTable = (tableId, fileName)->
+ table = $(tableId).DataTable
+ autoWidth:true
+ bFilter: false
+ bPaginate: false
+ info: false
+ ordering: false
+ processing: true
+ oLanguage: {
+ sProcessing: ""
+ }
+ scrollX: true
+ dom: 'lBrtip'
+ buttons: [{
+ filename: fileName
+ extend: 'excelHtml5'
+ customize: ( xlsx ) ->
+ sheet = xlsx.xl.worksheets['sheet1.xml']
+ $('row:last c:first', sheet).attr('s', '2')
+ text: ' Excel Export'
+ exportOptions: modifier:
+ search: 'applied'
+ order: 'applied'
+ }],
+ 'drawCallback': (oSettings) ->
+ $('.dataTables_scrollHeadInner').css 'width': '100%'
+ $(tableId).css 'width': '100%'
+ return
+
_handleShowCustomFormSelect = ->
if $('#wizard-referral-data .referral-data-column .i-checks').is(':checked')
$('#wizard-referral-data').show()
@@ -182,6 +243,7 @@ CIF.ClientsIndex = do ->
onInit: ->
$('ul[role="tablist"]').hide()
+ $('ul.table-summary-tab[role="tablist"]').show()
$('.actions a[href="#finish"]').attr('id', 'wizard-search')
_handleReportBuilderWizardDisplayBtns()
_handleQueryFilters('#wizard_custom_form_filter', '#wizard-custom-form-select')
@@ -435,6 +497,8 @@ CIF.ClientsIndex = do ->
advanceFilter.customFormSelectChange()
advanceFilter.customFormSelectRemove()
advanceFilter.handleHideCustomFormSelect()
+ advanceFilter.assessmentSelectChange()
+ advanceFilter.assessmentSelectRemove()
advanceFilter.handleShowProgramStreamFilter()
advanceFilter.handleHideProgramStreamSelect()
@@ -473,6 +537,9 @@ CIF.ClientsIndex = do ->
advanceFilter.removeOperatorInWizardBuilder()
advanceFilter.handleHotlineFilter()
+ advanceFilter.handleShowAssessmentSelect()
+ advanceFilter.handleHideAssessmentSelect()
+
_handleColumnVisibilityParams = ->
$('button#search').on 'click', ->
allCheckboxes = $('#client-search-form, #client-advance-search-wizard').find('#new_client_grid ul input[type=checkbox]')
diff --git a/app/assets/javascripts/screening_assessments/form.coffee b/app/assets/javascripts/screening_assessments/form.coffee
new file mode 100644
index 0000000000..41fae46ff1
--- /dev/null
+++ b/app/assets/javascripts/screening_assessments/form.coffee
@@ -0,0 +1,69 @@
+CIF.Screening_assessmentsNew = CIF.Screening_assessmentsCreate = CIF.Screening_assessmentsUpdate = CIF.Screening_assessmentsEdit = do ->
+ _init = ->
+ _handleMileStoneAgeSelect()
+ _initDatePicker()
+ _cocoonCallback()
+ _handleCheckBox()
+ _handleFormSubmitting()
+
+ _handleMileStoneAgeSelect = ->
+ mileStoneAge = $('#screening_assessment_client_milestone_age').val()
+ _removeClassFieldSet(mileStoneAge)
+
+ $('#screening_assessment_client_milestone_age').on 'change', ->
+ $('fieldset').addClass('hidden')
+ $('fieldset input[type="hidden"]').val('true')
+
+ value = @.value
+ _removeClassFieldSet(value)
+
+ _removeClassFieldSet = (value)->
+ _handleCheckBox()
+ $("fieldset[data-developmental-marker-screening-assessment-name='#{value}']").removeClass('hidden')
+ $("fieldset[data-developmental-marker-screening-assessment-name='#{value}'] input").removeAttr('disabled')
+ $("fieldset[data-developmental-marker-screening-assessment-name='#{value}'] input[type='hidden']").val('false')
+
+ _initDatePicker = ->
+ $('.date-picker').datepicker
+ autoclose: true,
+ format: 'yyyy-mm-dd',
+ todayHighlight: true,
+ disableTouchKeyboard: true,
+ startDate: '1899,01,01',
+ todayBtn: true,
+ .attr('readonly', 'true').css('background-color','#ffffff').keypress (e) ->
+ if e.keyCode == 8
+ e.preventDefault()
+ return
+
+ _cocoonCallback = ->
+ $('#tasks').on 'cocoon:after-insert', ->
+ _initDatePicker()
+
+ _handleCheckBox = ->
+ $('#tasks').removeClass('hide') unless _.every(_isInputRadioAllChecked())
+
+ $(document).on 'change', 'fieldset input:radio:visible', (event) ->
+ if !eval(event.target.value)
+ $('#tasks').removeClass('hide')
+ else
+ $('#tasks').addClass('hide') if _.every(_isInputRadioAllChecked())
+
+ _isInputRadioAllChecked = ->
+ nameAttributes = $('fieldset input:radio:visible').map( ->
+ $(this).prop('name')
+ ).get()
+
+ nameValue = _.uniq(nameAttributes).map (element) ->
+ "input:radio[name='" + element + "']"
+
+ nameValue.map (value) ->
+ $(value).prop('checked')
+
+ _handleFormSubmitting = ->
+ $("form#screening-assessment").on 'submit', (e)->
+ e.preventDefault()
+ $("#tasks .nested-fields .row").remove() if _.every(_isInputRadioAllChecked())
+ @.submit()
+
+ { init: _init }
diff --git a/app/assets/javascripts/settings/risk_assessment.coffee b/app/assets/javascripts/settings/risk_assessment.coffee
new file mode 100644
index 0000000000..f21656f936
--- /dev/null
+++ b/app/assets/javascripts/settings/risk_assessment.coffee
@@ -0,0 +1,53 @@
+CIF.SettingsRisk_assessment = do ->
+ _init = ->
+ _initICheckBox()
+ _handleSettingAssessmentTypeNameChange()
+ _tinyMCE()
+
+ _initICheckBox = ->
+ if $('#setting_enabled_risk_assessment').is(':checked')
+ $('#assessment-type-name').show()
+ $('#guidance').show()
+ else
+ $(".domain-checkbox-wrapper").hide()
+ $('#assessment-type-name').hide()
+ $('#guidance').hide()
+
+ $('.i-checks').iCheck(
+ checkboxClass: 'icheckbox_square-green'
+ radioClass: 'iradio_square-green'
+ ).on('ifChecked', ->
+ $('#assessment-type-name').show()
+ $('#guidance').show()
+ _showHideDomainCheckBox($('#setting_assessment_type_name:visible').val())
+ ).on 'ifUnchecked', ->
+ return if @.id.match(/setting_selected_domain_ids/) && @.id.match(/setting_selected_domain_ids/).length
+
+ $(".domain-checkbox-wrapper").hide()
+ $('#assessment-type-name').hide()
+ $('#guidance').hide()
+
+ _handleSettingAssessmentTypeNameChange = ->
+ $(".domain-checkbox-wrapper").hide()
+ _showHideDomainCheckBox($('#setting_assessment_type_name:visible').val())
+ $('#setting_assessment_type_name').on 'change', (e) ->
+ $(".domain-checkbox-wrapper").hide()
+ _showHideDomainCheckBox(e.target.value)
+
+ _showHideDomainCheckBox = (value) ->
+ if value == 'csi'
+ $("##{value}").show()
+ else
+ $("#custom-domain-#{value}").show()
+
+ return
+
+ _tinyMCE = ->
+ tinymce.init
+ selector: 'textarea.tinymce'
+ plugins: 'lists'
+ width : '100%'
+ toolbar: 'bold italic numlist bullist'
+ menubar: false
+
+ { init: _init }
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 17269cfafc..0c52bc604a 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -97,4 +97,6 @@
@import "care_plans/*";
@import "family_advanced_searches/*";
@import "service_deliveries/*";
-@import "case_conferences/*";
\ No newline at end of file
+@import "case_conferences/*";
+@import "datatable/*";
+@import "screening_assessments/form";
diff --git a/app/assets/stylesheets/assessments/form.scss b/app/assets/stylesheets/assessments/form.scss
index c2de7579c4..6738b3db0c 100644
--- a/app/assets/stylesheets/assessments/form.scss
+++ b/app/assets/stylesheets/assessments/form.scss
@@ -1,4 +1,5 @@
-.wizard, .tabcontrol {
+.wizard,
+.tabcontrol {
overflow: initial;
}
@@ -7,7 +8,9 @@ body[id='assessments-create'],
body[id='assessments-edit'],
body[id='assessments-update'] {
#readonly-rootwizard {
- textarea.disabled, textarea:disabled {
+
+ textarea.disabled,
+ textarea:disabled {
color: black !important;
}
}
@@ -44,34 +47,43 @@ body[id='assessments-update'] {
.steps {
display: none;
}
+
.content {
background-color: #fff;
margin: 0;
+
.body {
width: 100%;
padding: 0;
+
label {
margin-bottom: 0;
}
+
input {
display: inline-block;
}
}
}
+
.actions {
padding: 20px 0;
}
}
- .margin-title{
+
+ .margin-title {
margin-left: 10px;
}
- .button{
+
+ .button {
width: 110px;
}
+
.assessment-domain-item {
span {
margin-left: 30px;
margin-right: 30px;
+
input {
margin-right: 10px;
}
@@ -85,81 +97,102 @@ body[id='assessments-update'] {
}
}
}
- #rootwizard{
- .content{
+
+ #rootwizard {
+ .content {
height: auto;
}
}
- .tasks-list{
+
+ .tasks-list {
margin-top: 16px;
padding: 0px;
}
- ol li.list-group-item{
+
+ ol li.list-group-item {
list-style: decimal inside;
display: list-item;
}
+
.assessment_assessment_domains_reason {
margin-top: 5px;
+
textarea {
height: 120px;
}
}
+
.well {
max-height: 400px;
overflow: scroll;
ul {
margin-left: 25px;
+
li {
line-height: 30px;
}
}
}
- .wizard > .actions .disabled a{
+ .wizard>.actions .disabled a {
border: 1px solid #acb3ac;
border-radius: 3px;
text-align: center;
display: inline;
}
- .wizard > .actions a{
+
+ .wizard>.actions a {
text-align: center;
display: inline;
border-radius: 3px;
}
+
.wrap-text-style {
white-space: normal;
text-align: center;
}
- .score_option.is_error{
+
+ .score_option.is_error {
border: 1px solid #a94442;
border-radius: 2px;
}
+
.score_option {
border: 1px solid #fff;
padding: 8px 3px 8px 3px;
- span{
+
+ span {
padding: 0 20px 0 0;
}
- em{
+
+ em {
display: none !important;
}
+
text-align: center;
- label, input {
- display:block-inline;
+
+ label,
+ input {
+ display: block-inline;
}
+
input[type="radio"] {
- opacity:0.011;
- z-index:100;
+ opacity: 0.011;
+ z-index: 100;
}
- input[type="radio"]:checked + label {
+
+ input[type="radio"]:checked+label {
color: #fff;
}
- input[type="radio"]:checked + em + label {
+
+ input[type="radio"]:checked+em+label {
color: #fff;
}
- label{
+
+ label {
font-size: 16px;
+
.collection_radio_buttons {
padding: 8px;
border: 1px solid #CCC;
@@ -169,21 +202,26 @@ body[id='assessments-update'] {
height: 40px;
border-radius: 5px;
}
+
label:hover {
- background:#DDD;
+ background: #DDD;
}
}
}
- textarea.error{
+
+ textarea.error {
border: 1px solid #a94442;
}
- em.error{
+
+ em.error {
color: #a94442;
font-size: 14px;
font-weight: normal;
- padding:3px;
- text-align:left;;
+ padding: 3px;
+ text-align: left;
+ ;
}
+
.padding-bottom {
padding-bottom: 140px;
}
@@ -193,11 +231,12 @@ body[id='assessments-update'] {
padding: 15px;
}
- @media only screen and (max-device-width : 767px){
+ @media only screen and (max-device-width : 767px) {
.assessment-domain-item {
span {
margin-left: 0;
margin-right: 0;
+
input {
margin-right: 10px;
}
@@ -211,14 +250,18 @@ body[id='assessments-update'] {
}
}
}
+
.score_option {
padding: 8px 0 8px 0;
- span{
+
+ span {
padding: 0 0 0 0;
}
}
}
- .links img, .nested-fields img {
+
+ .links img,
+ .nested-fields img {
width: 150px;
cursor: pointer;
}
@@ -232,14 +275,15 @@ body[id='assessments-update'] {
width: 150px;
}
- .image-title{
+ .image-title {
width: 70%;
}
- .table.attachment-table tbody>tr>td{
+ .table.attachment-table tbody>tr>td {
vertical-align: top;
}
- .table.attachment-table tbody>tr>td.vert-align{
+
+ .table.attachment-table tbody>tr>td.vert-align {
vertical-align: middle;
}
@@ -247,8 +291,10 @@ body[id='assessments-update'] {
border: 1px solid #999999;
}
- .goal-required-option, .task-required-option {
+ .goal-required-option,
+ .task-required-option {
display: inline;
+
span {
display: inline-block;
margin-right: 20px;
@@ -269,9 +315,8 @@ body[id='assessments-update'] {
display: inline-flex;
align-items: center;
}
- .tasks-list {
- }
+ .tasks-list {}
}
}
@@ -280,3 +325,8 @@ body[id='assessments-update'] {
margin-right: 5px;
}
}
+
+.domai-name-score-wrapper {
+ display: flex;
+ align-items: center;
+}
diff --git a/app/assets/stylesheets/case_notes/form.scss b/app/assets/stylesheets/case_notes/form.scss
index 2c45b68ace..bf7ae99493 100644
--- a/app/assets/stylesheets/case_notes/form.scss
+++ b/app/assets/stylesheets/case_notes/form.scss
@@ -112,6 +112,10 @@ body[id=case_notes-create] {
}
.panel-heading .popover-content {
- color: black !important
+ color: black !important;
+
+ label.boolean {
+ font-weight: bold;
+ }
}
}
diff --git a/app/assets/stylesheets/case_notes/index.scss b/app/assets/stylesheets/case_notes/index.scss
index ce8ae44672..809d27317f 100644
--- a/app/assets/stylesheets/case_notes/index.scss
+++ b/app/assets/stylesheets/case_notes/index.scss
@@ -49,4 +49,12 @@ body[id='case_notes-index'] {
margin-bottom: 5px;
}
}
+
+ .accordion-toggle .glyphicon {
+ transition: .3s transform ease-in-out;
+ }
+
+ .accordion-toggle.collapsed .glyphicon {
+ transform: rotate(-450deg);
+ }
}
diff --git a/app/assets/stylesheets/client_advanced_searches/index.scss b/app/assets/stylesheets/client_advanced_searches/index.scss
index c0100f4351..8c5996cbaa 100644
--- a/app/assets/stylesheets/client_advanced_searches/index.scss
+++ b/app/assets/stylesheets/client_advanced_searches/index.scss
@@ -58,7 +58,7 @@ body[id='client_advanced_searches-index'] {
display: none;
}
- .custom-form, .program-stream, .selected-custom-form, .program-association {
+ .custom-form, .program-stream, .selected-custom-form, .program-association, .assessment-form {
display: none;
}
diff --git a/app/assets/stylesheets/clients/client_grid.scss b/app/assets/stylesheets/clients/client_grid.scss
index f506cfc9f3..3798543e34 100644
--- a/app/assets/stylesheets/clients/client_grid.scss
+++ b/app/assets/stylesheets/clients/client_grid.scss
@@ -248,11 +248,14 @@ body[id="client_advanced_searches-index"] {
}
ul.check-columns-visibility {
padding-left: 0;
+ li:first-child {
+ padding: 0 8px 15px 8px;
+ }
li {
list-style: none;
}
.columns-visibility {
- height: 250px;
+ max-height: 250px;
width: 390px;
overflow-y: scroll;
padding-top: 10px;
diff --git a/app/assets/stylesheets/clients/form.scss b/app/assets/stylesheets/clients/form.scss
index c6da20e2fa..4c6c9bac67 100644
--- a/app/assets/stylesheets/clients/form.scss
+++ b/app/assets/stylesheets/clients/form.scss
@@ -1,15 +1,25 @@
-body[id='clients-new'], body[id='clients-create'],
-body[id='clients-edit'], body[id='clients-update']{
- .wizard > .content > .body {
- #getting_started, #living_detail, #other_detail, #specific_point {
+body[id='clients-new'],
+body[id='clients-create'],
+body[id='clients-edit'],
+body[id='clients-update'] {
+ .wizard>.content>.body {
+
+ #getting_started,
+ #living_detail,
+ #other_detail,
+ #specific_point {
position: relative;
+
input[type='radio'] {
display: inline-block;
}
}
}
- .wizard > .actions a[href="#finish"], .wizard > .actions a[href="#finish"]:hover, .wizard > .actions a[href="#finish"]:active {
- background: #1ab394;
+
+ .wizard>.actions a[href="#finish"],
+ .wizard>.actions a[href="#finish"]:hover,
+ .wizard>.actions a[href="#finish"]:active {
+ background: #1ab394;
}
.remove-files-wrapper {
@@ -32,6 +42,7 @@ body[id='clients-edit'], body[id='clients-update']{
.content.clearfix {
background-color: inherit;
+
section {
padding: 0;
width: 100%;
@@ -42,7 +53,7 @@ body[id='clients-edit'], body[id='clients-update']{
margin-top: 30px;
}
- .icheckbox_square-green{
+ .icheckbox_square-green {
margin-right: 10px;
}
@@ -52,9 +63,11 @@ body[id='clients-edit'], body[id='clients-update']{
display: inline-block;
margin-right: 20px;
}
+
label {
- padding-left: 0;
+ padding-left: 0;
}
+
.iradio_square-green {
margin-right: 5px;
}
@@ -63,20 +76,25 @@ body[id='clients-edit'], body[id='clients-update']{
.disabled {
color: #333 !important;
}
- .input-group-addon.what3words{
+
+ .input-group-addon.what3words {
padding: 2px;
}
- .what3words-image{
+
+ .what3words-image {
height: 17%;
}
- .save-edit-client{
+
+ .save-edit-client {
margin-top: -67px;
}
- .cancel-client-button{
+
+ .cancel-client-button {
position: relative;
}
- .consent-forms, .house_number {
+ .consent-forms,
+ .house_number {
clear: both;
}
@@ -85,15 +103,18 @@ body[id='clients-edit'], body[id='clients-update']{
pointer-events: none;
cursor: not-allowed;
}
- .warning-message{
+
+ .warning-message {
text-align: left;
font-weight: bold;
}
- .ref-source-cat-reminder{
+
+ .ref-source-cat-reminder {
color: red;
}
- #step-2, #step-4 {
+ #step-2,
+ #step-5 {
display: none;
}
}
@@ -102,7 +123,7 @@ body[id='clients-edit'], body[id='clients-update']{
margin-bottom: 5px;
}
-#family-option{
+#family-option {
margin-top: 10px;
margin-left: 12px;
}
@@ -119,37 +140,46 @@ body[id='clients-edit'], body[id='clients-update']{
height: 0;
overflow: hidden;
z-index: 999999;
- &:after, &:before {
+
+ &:after,
+ &:before {
box-sizing: border-box;
display: none;
}
+
&.is-active {
background-color: rgba(0, 0, 0, 0.85);
width: 100%;
height: 100%;
left: 0;
top: 0;
- &:after, &:before {
+
+ &:after,
+ &:before {
display: block;
}
}
+
&[data-text]:before {
position: fixed;
left: 0;
top: 50%;
color: currentColor;
- font-family: Helvetica,Arial,sans-serif;
+ font-family: Helvetica, Arial, sans-serif;
text-align: center;
width: 100%;
font-size: 14px;
}
+
&[data-text=""]:before {
content: "Loading";
}
+
&[data-text] {
&:not([data-text=""]):before {
content: attr(data-text);
}
+
&[data-blink]:before {
animation: blink 1s linear infinite alternate;
}
@@ -182,6 +212,7 @@ body[id='clients-edit'], body[id='clients-update']{
&[data-text]:before {
top: calc(50% - 63px);
}
+
&:after {
content: "";
position: fixed;
@@ -194,22 +225,27 @@ body[id='clients-edit'], body[id='clients-update']{
left: calc(50% - 24px);
animation: rotation 1s linear infinite;
}
+
&[data-half]:after {
border-right-color: transparent;
}
+
&[data-inverse]:after {
animation-direction: reverse;
}
}
.loader-double {
- &:after, &:before {
+
+ &:after,
+ &:before {
content: "";
position: fixed;
border-radius: 50%;
border: 8px solid;
animation: rotation 1s linear infinite;
}
+
&:after {
width: 48px;
height: 48px;
@@ -218,6 +254,7 @@ body[id='clients-edit'], body[id='clients-update']{
top: calc(50% - 24px);
left: calc(50% - 24px);
}
+
&:before {
width: 64px;
height: 64px;
@@ -234,6 +271,7 @@ body[id='clients-edit'], body[id='clients-update']{
top: calc(50% - 40px);
color: #1ab394;
}
+
&:after {
content: "";
position: fixed;
@@ -247,9 +285,11 @@ body[id='clients-edit'], body[id='clients-update']{
box-shadow: inset 0 10px 0 hsla(0, 0%, 100%, 0.2), 0 0 0 5px rgba(0, 0, 0, 0.2);
animation: moveBar 1.5s linear infinite reverse;
}
+
&[data-rounded]:after {
border-radius: 15px;
}
+
&[data-inverse]:after {
animation-direction: normal;
}
@@ -271,22 +311,27 @@ body[id='clients-edit'], body[id='clients-update']{
width: 200px;
background-color: #000;
}
- &:after, &:before {
+
+ &:after,
+ &:before {
content: "";
height: 20px;
position: absolute;
top: calc(50% - 10px);
left: calc(50% - 100px);
}
+
&:after {
width: 50px;
background-color: #f19;
animation: moveBarPingPong .5s linear infinite alternate;
}
+
&[data-rounded] {
&:before {
border-radius: 10px;
}
+
&:after {
border-radius: 50%;
width: 20px;
@@ -360,6 +405,7 @@ body[id='clients-edit'], body[id='clients-update']{
&[data-text]:before {
color: #1ab394;
}
+
&:after {
content: "";
position: absolute;
@@ -386,9 +432,11 @@ body[id='clients-edit'], body[id='clients-update']{
z-index: 1;
animation: kickBall 1s infinite alternate ease-in both;
}
+
&[data-shadow]:before {
box-shadow: inset -5px -5px 10px 0 rgba(0, 0, 0, 0.5);
}
+
&:after {
content: "";
position: absolute;
@@ -448,7 +496,7 @@ body[id='clients-edit'], body[id='clients-update']{
content: "";
color: #fff;
font-size: 12px;
- font-family: Helvetica,Arial,sans-serif;
+ font-family: Helvetica, Arial, sans-serif;
text-align: center;
line-height: 120px;
position: fixed;
@@ -463,9 +511,11 @@ body[id='clients-edit'], body[id='clients-update']{
background: radial-gradient(circle at 50% 90%, rgba(0, 0, 0, 0.5) 6px, transparent 0), linear-gradient(0deg, #fd0 22px, transparent 0), linear-gradient(0deg, rgba(0, 0, 0, 0.5) 22px, rgba(0, 0, 0, 0.5));
animation: shake 2s cubic-bezier(0.36, 0.07, 0.19, 0.97) both infinite;
}
+
&[data-screen=""]:after {
content: "Loading";
}
+
&:not([data-screen=""]):after {
content: attr(data-screen);
}
@@ -525,16 +575,19 @@ body[id='clients-edit'], body[id='clients-update']{
border-radius: 50%;
margin: -60px 0 0 -60px;
background: linear-gradient(180deg, transparent 50%, #f5f5f5 0), linear-gradient(90deg, transparent 55px, #2ecc71 0, #2ecc71 65px, transparent 0), linear-gradient(180deg, #f5f5f5 50%, #f5f5f5 0);
- box-shadow: inset 0 0 0 10px #f5f5f5,0 0 0 5px #555,0 0 0 10px #7b7b7b;
+ box-shadow: inset 0 0 0 10px #f5f5f5, 0 0 0 5px #555, 0 0 0 10px #7b7b7b;
animation: rotation infinite 2s linear;
}
- &:after, &:before {
+
+ &:after,
+ &:before {
content: "";
position: fixed;
left: 50%;
top: 50%;
overflow: hidden;
}
+
&:after {
width: 60px;
height: 40px;
@@ -554,11 +607,12 @@ body[id='clients-edit'], body[id='clients-update']{
margin-top: -35px;
font-size: 70px;
text-align: center;
- font-family: Helvetica,Arial,sans-serif;
+ font-family: Helvetica, Arial, sans-serif;
overflow: hidden;
line-height: 1.2;
content: "Loading";
}
+
&:before {
position: fixed;
width: 100%;
@@ -566,36 +620,44 @@ body[id='clients-edit'], body[id='clients-update']{
margin-top: -35px;
font-size: 70px;
text-align: center;
- font-family: Helvetica,Arial,sans-serif;
+ font-family: Helvetica, Arial, sans-serif;
overflow: hidden;
line-height: 1.2;
content: "Loading";
color: #666;
}
+
&:after {
color: #fff;
height: 0;
animation: curtain 1s linear infinite alternate both;
}
+
&[data-curtain-text]:not([data-curtain-text=""]) {
- &:after, &:before {
+
+ &:after,
+ &:before {
content: attr(data-curtain-text);
}
}
+
&[data-brazilian] {
&:before {
color: #f1c40f;
}
+
&:after {
color: #2ecc71;
}
}
+
&[data-colorful] {
&:before {
animation: maskColorful 2s linear infinite alternate both;
}
+
&:after {
- animation: curtain 1s linear infinite alternate both,maskColorful-front 2s 1s linear infinite alternate both;
+ animation: curtain 1s linear infinite alternate both, maskColorful-front 2s 1s linear infinite alternate both;
color: #000;
}
}
@@ -651,7 +713,9 @@ body[id='clients-edit'], body[id='clients-update']{
.loader-music {
- &:after, &:before {
+
+ &:after,
+ &:before {
content: "";
position: fixed;
width: 240px;
@@ -664,59 +728,70 @@ body[id='clients-edit'], body[id='clients-update']{
line-height: 240px;
color: #fff;
font-size: 40px;
- font-family: Helvetica,Arial,sans-serif;
+ font-family: Helvetica, Arial, sans-serif;
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
letter-spacing: -1px;
}
+
&:after {
backface-visibility: hidden;
}
+
&[data-hey-oh] {
&:after {
box-shadow: 0 0 0 10px;
}
+
&:before {
box-shadow: 0 0 0 10px;
background-color: #fff;
color: #000;
- animation: coinBack 2.5s linear infinite,oh 5s 1.25s linear infinite both;
+ animation: coinBack 2.5s linear infinite, oh 5s 1.25s linear infinite both;
}
+
&:after {
background-color: #000;
- animation: coin 2.5s linear infinite,hey 5s linear infinite both;
+ animation: coin 2.5s linear infinite, hey 5s linear infinite both;
}
}
+
&[data-no-cry] {
&:after {
background: linear-gradient(45deg, #009b3a 50%, #fed100 51%);
box-shadow: 0 0 0 10px #000;
}
+
&:before {
background: linear-gradient(45deg, #009b3a 50%, #fed100 51%);
box-shadow: 0 0 0 10px #000;
- animation: coinBack 2.5s linear infinite,cry 5s 1.25s linear infinite both;
+ animation: coinBack 2.5s linear infinite, cry 5s 1.25s linear infinite both;
}
+
&:after {
- animation: coin 2.5s linear infinite,no 5s linear infinite both;
+ animation: coin 2.5s linear infinite, no 5s linear infinite both;
}
}
+
&[data-we-are] {
&:before {
- animation: coinBack 2.5s linear infinite,theWorld 5s 1.25s linear infinite both;
+ animation: coinBack 2.5s linear infinite, theWorld 5s 1.25s linear infinite both;
background: radial-gradient(ellipse at center, #4ecdc4 0, #556270);
}
+
&:after {
- animation: coin 2.5s linear infinite,weAre 5s linear infinite both;
+ animation: coin 2.5s linear infinite, weAre 5s linear infinite both;
background: radial-gradient(ellipse at center, #26d0ce 0, #1a2980);
}
}
+
&[data-rock-you] {
&:before {
- animation: coinBack 2.5s linear infinite,rockYou 5s 1.25s linear infinite both;
+ animation: coinBack 2.5s linear infinite, rockYou 5s 1.25s linear infinite both;
background: #444;
}
+
&:after {
- animation: coin 2.5s linear infinite,weWill 5s linear infinite both;
+ animation: coin 2.5s linear infinite, weWill 5s linear infinite both;
background: #96281b;
}
}
@@ -880,6 +955,7 @@ body[id='clients-edit'], body[id='clients-update']{
z-index: 1;
animation: movePokeball 1s linear infinite both;
}
+
&:after {
content: "";
position: absolute;
@@ -891,9 +967,9 @@ body[id='clients-edit'], body[id='clients-update']{
background-color: #fff;
border-radius: 50%;
z-index: 2;
- animation: movePokeball 1s linear infinite both,flashPokeball .5s infinite alternate;
+ animation: movePokeball 1s linear infinite both, flashPokeball .5s infinite alternate;
border: 2px solid #000;
- box-shadow: 0 0 0 5px #fff,0 0 0 10px #000;
+ box-shadow: 0 0 0 5px #fff, 0 0 0 10px #000;
}
}
@@ -928,7 +1004,9 @@ body[id='clients-edit'], body[id='clients-update']{
.loader-bouncing {
- &:after, &:before {
+
+ &:after,
+ &:before {
content: "";
width: 20px;
height: 20px;
@@ -939,10 +1017,12 @@ body[id='clients-edit'], body[id='clients-update']{
background-color: #fff;
animation: kick .6s infinite alternate;
}
+
&:after {
margin-left: -30px;
animation: kick .6s infinite alternate;
}
+
&:before {
animation-delay: .2s;
}
@@ -960,13 +1040,15 @@ body[id='clients-edit'], body[id='clients-update']{
}
}
-body[id='clients-new'] .disabled, body[id='clients-create'] .disabled,
-body[id='clients-edit'] .disabled, body[id='clients-update'] .disabled {
+body[id='clients-new'] .disabled,
+body[id='clients-create'] .disabled,
+body[id='clients-edit'] .disabled,
+body[id='clients-update'] .disabled {
color: #fff !important;
pointer-events: none;
}
-#client-confirmation{
+#client-confirmation {
.modal-dialog {
width: 100%;
margin: 0 auto;
@@ -978,7 +1060,8 @@ body[id='clients-edit'] .disabled, body[id='clients-update'] .disabled {
.modal-content {
border-radius: 0;
- overflow:auto;
+ overflow: auto;
}
}
+
//end css loader
diff --git a/app/assets/stylesheets/clients/index.scss b/app/assets/stylesheets/clients/index.scss
index 71a8f0dcb3..167fba6df8 100644
--- a/app/assets/stylesheets/clients/index.scss
+++ b/app/assets/stylesheets/clients/index.scss
@@ -193,7 +193,8 @@ body[id='clients-index'] {
display: none;
}
- .client-column-picker, .custom-form, .program-stream, .selected-custom-form, .program-association, #wizard-referral-data, #wizard-program-stream, #wizard-custom-form {
+ .client-column-picker, .custom-form, .program-stream, .selected-custom-form, .program-association,
+ #wizard-referral-data, #wizard-program-stream, #wizard-custom-form, .assessment-form {
display: none;
}
diff --git a/app/assets/stylesheets/common_index.scss b/app/assets/stylesheets/common_index.scss
index 4d2ae6f510..63f448e84a 100644
--- a/app/assets/stylesheets/common_index.scss
+++ b/app/assets/stylesheets/common_index.scss
@@ -3,17 +3,20 @@
border-radius: 1px !important;
box-shadow: none !important;
}
+
.datepicker table tr td.active.active,
.datepicker table tr td.active:hover:hover {
background-color: #1ab394;
background-image: none;
color: white;
}
+
.select2-results .select2-highlighted,
.select2-highlighted:hover {
background-color: #1ab394;
color: white;
}
+
.select2-container .select2-choices .select2-search-field input,
.select2-container .select2-choice,
.select2-container .select2-choices {
@@ -21,63 +24,78 @@
box-shadow: none !important;
border-radius: 1px !important;
}
+
.select2-drop-active {
border: 1px solid #1ab394 !important;
border-top: none !important;
box-shadow: none !important;
}
+
.datepicker.datepicker-dropdown.dropdown-menu {
z-index: 330000 !important;
}
+
.ibox-title span {
font-size: 12px;
}
+
.select2-container-active .select2-choice,
.select2-container-multi.select2-container-active .select2-choices {
box-shadow: none !important;
border: 1px solid #1ab394 !important;
border-radius: 1px !important;
}
-#toast-container > div {
+
+#toast-container>div {
width: 400px !important;
}
+
.btn-back-default {
color: #756e6c !important;
background: white;
border: 1px solid #e7eaec;
}
+
.line-border {
border-top: 1px solid #86898c;
}
+
.log-min {
background: white;
border: 3px solid white;
padding: 1px;
border-radius: 50% 50%;
}
+
.img-circle {
background: white;
border: 10px solid white;
width: 100px;
}
+
.btn-back-default:hover {
color: #756e6c;
}
+
.min-margin-layout {
margin-top: 16px;
}
+
.boolean.optional {
padding: 0;
}
-.ibox-title > h5,
-.panel-heading > h5 {
+
+.ibox-title>h5,
+.panel-heading>h5 {
font-size: 16px;
font-weight: 600;
color: #6b6a6c;
}
+
.mini-margin {
margin-top: 16px;
}
+
.bg {
background: white;
}
@@ -106,6 +124,7 @@
display: block;
height: 60px;
margin-top: -7px;
+
img {
margin: 0;
width: 30px;
@@ -117,6 +136,7 @@
.notify-margin {
margin-left: 20px;
}
+
.chevron-progess-note {
margin-right: -16px;
}
@@ -140,6 +160,7 @@
.staging-identifier {
background: #c52f24;
+
.message-staging {
color: #fff;
margin: 0;
@@ -152,12 +173,15 @@
.record-count {
margin: 15px 0;
}
+
.custom_column_manage {
width: 20%;
}
+
.custom_column_name {
width: 40%;
}
+
.custom_column_description {
width: 40%;
}
@@ -199,11 +223,13 @@ ul.dropdown-menu.dropdown-alerts {
.notification-text-color {
color: #1ab394;
}
+
.fcf_ngo {
margin-top: 40px;
font-size: 20px;
color: grey;
}
+
.align-link {
margin-top: -18px;
margin-bottom: -18px;
@@ -221,6 +247,7 @@ ul.dropdown-menu.dropdown-alerts {
.dropdown-menu li a {
padding: 0 5px;
min-height: 0;
+
img {
margin-right: 3px;
}
@@ -252,6 +279,7 @@ span.input-group-addon {
}
@media print {
+
body,
p,
label,
@@ -296,3 +324,22 @@ span.input-group-addon {
.nowrap {
white-space: nowrap;
}
+
+fieldset.fieldset-border {
+ border: solid 1px #DDD !important;
+ padding: 0 10px 10px 10px;
+ border-bottom: none;
+ margin-bottom: 25px;
+ border-radius: 4px;
+
+ legend.legend-border {
+ width: auto !important;
+ border: none;
+ }
+
+ span {
+ label.collection_radio_buttons {
+ margin-left: 5px;
+ }
+ }
+}
diff --git a/app/assets/stylesheets/datatable/table.scss b/app/assets/stylesheets/datatable/table.scss
new file mode 100644
index 0000000000..9e4b515741
--- /dev/null
+++ b/app/assets/stylesheets/datatable/table.scss
@@ -0,0 +1,12 @@
+table {
+ &.table-bordered {
+ border-right-width: 0;
+ &.dataTable {
+ th, td {
+ &:last-child {
+ border-right-width: 1px;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/screening_assessments/form.scss b/app/assets/stylesheets/screening_assessments/form.scss
new file mode 100644
index 0000000000..7b460d588c
--- /dev/null
+++ b/app/assets/stylesheets/screening_assessments/form.scss
@@ -0,0 +1,8 @@
+body[id='screening_assessments-new'],
+body[id='screening_assessments-create'],
+body[id='screening_assessments-edit'],
+body[id='screening_assessments-update'] {
+ .collection_radio_buttons {
+ margin-left: 5px;
+ }
+}
diff --git a/app/classes/ability.rb b/app/classes/ability.rb
index e7fbfc3b5f..e923d91f7d 100644
--- a/app/classes/ability.rb
+++ b/app/classes/ability.rb
@@ -54,6 +54,7 @@ def initialize(user)
can :manage, Enrollment
can :manage, Community
can :manage, EnrollmentTracking
+ can :manage, ScreeningAssessment, clients: { case_worker_clients: { user_id: user.id } }
family_ids = user.families.ids
family_ids << CaseWorkerFamily.where(user_id: user.id).pluck(:family_id)
@@ -94,6 +95,7 @@ def initialize(user)
can :manage, Enrollment
can :manage, Community
can :manage, EnrollmentTracking
+ can :manage, ScreeningAssessment, clients: { case_worker_clients: { user_id: user.id } }
family_ids = user.families.ids
family_ids += User.joins(:clients).where(id: subordinate_users).where.not(clients: { current_family_id: nil }).select('clients.current_family_id AS client_current_family_id').map(&:client_current_family_id)
@@ -125,6 +127,7 @@ def initialize(user)
cannot [:edit, :update], ReferralSource
cannot :destroy, Client
can :manage, Family
+ can :manage, ScreeningAssessment, clients: { case_worker_clients: { user_id: user.id } }
end
cannot :read, Community if Setting.cache_first.hide_community?
diff --git a/app/classes/advanced_searches/client_association_filter.rb b/app/classes/advanced_searches/client_association_filter.rb
index 933c040a26..1b9c94da83 100644
--- a/app/classes/advanced_searches/client_association_filter.rb
+++ b/app/classes/advanced_searches/client_association_filter.rb
@@ -118,6 +118,20 @@ def get_sql
values = care_plan_counter
when 'care_plan_completed_date'
values = date_query(Client, @clients, :care_plans, 'care_plans.created_at')
+ when 'number_client_referred_gatekeeping'
+ values = number_client_referred_gatekeeping_query
+ when 'number_client_billable'
+ values = number_client_billable_query
+ when 'active_client_program'
+ values = active_client_program_query
+ when 'assessment_condition_last_two'
+ values = assessment_condition_last_two_query
+ when 'assessment_condition_first_last'
+ values = assessment_condition_first_last_query
+ when 'client_rejected'
+ values = get_rejected_clients
+ when 'incomplete_care_plan'
+ values = incomplete_care_plan_query
end
{ id: sql_string, values: values }
end
@@ -1114,5 +1128,274 @@ def referred_in_out_query(referral_scope)
end
clients.ids
end
+
+ def number_client_referred_gatekeeping_query
+ clients = @clients.where(referral_source_category_id: ReferralSource.gatekeeping_mechanism.ids).distinct
+
+ case @operator
+ when 'equal'
+ client_ids = clients.where('date(initial_referral_date) = ?', @value.to_date ).distinct.ids
+ when 'not_equal'
+ client_ids = clients.where('date(initial_referral_date) != ?', @value.to_date ).distinct.ids
+ when 'between'
+ client_ids = clients.where("date(initial_referral_date) BETWEEN ? AND ? ", @value[0].to_date, @value[1].to_date).distinct.ids
+ when 'less'
+ client_ids = clients.where('date(initial_referral_date) < ?', @value.to_date ).distinct.ids
+ when 'less_or_equal'
+ client_ids = clients.where('date(initial_referral_date) <= ?', @value.to_date ).distinct.ids
+ when 'greater'
+ client_ids = clients.where('date(initial_referral_date) > ?', @value.to_date ).distinct.ids
+ when 'greater_or_equal'
+ client_ids = clients.where('date(initial_referral_date) >= ?', @value.to_date ).distinct.ids
+ when 'is_empty'
+ client_ids = clients.where('initial_referral_date IS NULL').distinct.ids
+ when 'is_not_empty'
+ client_ids = clients.where('initial_referral_date IS NOT NULL').distinct.ids
+ end
+ clients = client_ids.present? ? client_ids : []
+ end
+
+ def number_client_billable_query
+ value = @value.kind_of?(Array) ? @value[0] : @value.to_date
+ clients = @clients.joins(:enter_ngos).includes(:exit_ngos).where('(exit_ngos.exit_date IS NULL OR date(exit_ngos.exit_date) >= ?)', value).distinct
+
+ case @operator
+ when 'equal'
+ client_ids = clients.where('date(enter_ngos.accepted_date) = ?', @value.to_date).distinct.ids
+ when 'not_equal'
+ client_ids = clients.where('date(enter_ngos.accepted_date) != ?', @value.to_date).distinct.ids
+ when 'between'
+ client_ids = clients.where("date(enter_ngos.accepted_date) <= ?", @value[1]).distinct.ids
+ when 'less'
+ client_ids = clients.where('date(enter_ngos.accepted_date) < ?', @value.to_date).distinct.ids
+ when 'less_or_equal'
+ client_ids = clients.where('date(enter_ngos.accepted_date) <= ?', @value.to_date).distinct.ids
+ when 'greater'
+ client_ids = clients.where('date(enter_ngos.accepted_date) > ?', @value.to_date).distinct.ids
+ when 'greater_or_equal'
+ client_ids = clients.where('date(enter_ngos.accepted_date) >= ?', @value.to_date).distinct.ids
+ when 'is_empty'
+ client_ids = clients.where('enter_ngos.accepted_date IS NULL').distinct.ids
+ when 'is_not_empty'
+ client_ids = clients.where('enter_ngos.accepted_date IS NOT NULL').distinct.ids
+ end
+ clients = client_ids.present? ? client_ids : []
+ end
+
+ def get_rejected_clients
+ client_ids = []
+ clients = @clients.joins(:exit_ngos).where(:exit_ngos => {:exit_circumstance => 'Rejected Referral'}).distinct
+
+ case @operator
+ when 'equal'
+ client_ids = clients.where('date(exit_ngos.exit_date) = ?', @value.to_date ).distinct.ids
+ when 'not_equal'
+ client_ids = clients.where('date(exit_ngos.exit_date) != ?', @value.to_date ).distinct.ids
+ when 'between'
+ client_ids = clients.where("date(exit_ngos.exit_date) BETWEEN ? AND ?", @value[0], @value[1]).distinct.ids
+ when 'less'
+ client_ids = clients.where('date(exit_ngos.exit_date) < ?', @value.to_date ).distinct.ids
+ when 'less_or_equal'
+ client_ids = clients.where('date(exit_ngos.exit_date) <= ?', @value.to_date ).distinct.ids
+ when 'greater'
+ client_ids = clients.where('date(exit_ngos.exit_date) > ?', @value.to_date ).distinct.ids
+ when 'greater_or_equal'
+ client_ids = clients.where('date(exit_ngos.exit_date) >= ?', @value.to_date ).distinct.ids
+ when 'is_empty'
+ client_ids = clients.where('exit_ngos.exit_date IS NULL').distinct.ids
+ when 'is_not_empty'
+ client_ids = clients.where('exit_ngos.exit_date IS NOT NULL').distinct.ids
+ end
+ clients = client_ids
+ end
+
+ def active_client_program_between(start_date, end_date, clientIds)
+ enrollments = ClientEnrollment.where(:client_id => clientIds)
+ client_ids = []
+ enrollments.each do |enrollment|
+ enrollment_date = enrollment.enrollment_date
+
+ if enrollment.leave_program.present?
+ exit_date = enrollment.leave_program.exit_date
+ if enrollment_date < start_date || enrollment_date.between?(start_date, end_date)
+ client_ids << enrollment.client_id if exit_date.between?(start_date, end_date) || exit_date > end_date
+ end
+ else
+ client_ids << enrollment.client_id if enrollment_date.between?(start_date, end_date) || enrollment_date < start_date
+ end
+ end
+ client_ids
+ end
+
+ def active_client_program_query
+ clientIds = []
+ JSON.parse($param_rules[:program_selected]).each do |program|
+ tmpClientIds = @clients.joins(:client_enrollments).where(:client_enrollments => {:status => 'Active', :program_stream_id => program}).ids
+ if clientIds.empty?
+ clientIds = tmpClientIds
+ else
+ clientIds = clientIds & tmpClientIds
+ end
+ end
+
+ condition = ''
+ start_date = @value.kind_of?(Array) ? @value[0].to_date : @value.to_date
+
+ case @operator
+ when 'equal'
+ condition = "date(client_enrollments.enrollment_date) = '#{start_date}'"
+ when 'not_equal'
+ condition = "date(client_enrollments.enrollment_date) != '#{start_date}'"
+ when 'between'
+ condition = "date(client_enrollments.enrollment_date) <= '#{@value[1].to_date}'"
+ when 'less'
+ condition = "date(client_enrollments.enrollment_date) < '#{start_date}'"
+ when 'less_or_equal'
+ condition = "date(client_enrollments.enrollment_date) <= '#{start_date}'"
+ when 'greater'
+ condition = "date(client_enrollments.enrollment_date) > '#{start_date}'"
+ when 'greater_or_equal'
+ condition = "date(client_enrollments.enrollment_date) >= '#{start_date}'"
+ when 'is_empty'
+ condition = "client_enrollments.enrollment_date IS NULL"
+ when 'is_not_empty'
+ condition = "client_enrollments.enrollment_date IS NOT NULL"
+ end
+
+ enrollments = ClientEnrollment.where(:client_id => clientIds).where(condition)
+ client_ids = []
+ enrollments.each do |enrollment|
+ if enrollment.leave_program.present? && start_date != nil
+ exit_date = enrollment.leave_program.exit_date
+ client_ids << enrollment.client_id if exit_date >= start_date
+ else
+ client_ids << enrollment.client_id
+ end
+ end
+ client_ids
+
+ clients = client_ids.present? ? client_ids : []
+ end
+
+ def assessment_condition_last_two_query
+ case @value.downcase
+ when 'better'
+ client_ids = client_assessment_compare_next_last(:>, $param_rules[:assessment_selected])
+ when 'same'
+ client_ids = client_assessment_compare_next_last(:==, $param_rules[:assessment_selected])
+ when 'worse'
+ client_ids = client_assessment_compare_next_last(:<, $param_rules[:assessment_selected])
+ end
+ clients = client_ids.present? ? client_ids : []
+ end
+
+ def assessment_condition_first_last_query
+ case @value.downcase
+ when 'better'
+ client_ids = client_assessment_compare_first_last(:>, $param_rules[:assessment_selected])
+ when 'same'
+ client_ids = client_assessment_compare_first_last(:==, $param_rules[:assessment_selected])
+ when 'worse'
+ client_ids = client_assessment_compare_first_last(:<, $param_rules[:assessment_selected])
+ end
+ clients = client_ids.present? ? client_ids : []
+ end
+
+ def client_assessment_compare_first_last(compare, selectedAssessment)
+ client_ids = []
+ clients = @clients.joins(:assessments).where(assessments: { completed: true })
+ conditionString = ""
+ if selectedAssessment.present?
+ assessments = JSON.parse(selectedAssessment)
+ assessmentId = assessments.first
+
+ if assessmentId == 0
+ clients = clients.where("assessments.default = true").distinct
+ domains = Domain.csi_domains
+ clients.each do |client|
+ last_assessment = client.assessments.defaults.most_recents.first
+ first_assessment = client.assessments.defaults.most_recents.last
+ if (client.assessments.defaults.length > 1)
+ client_ids << client.id if assessment_total_score(last_assessment, domains).public_send(compare, assessment_total_score(first_assessment, domains))
+ end
+ end
+ else
+ assessments = Assessment.completed.joins(:domains).where(client_id: clients.ids).where("domains.custom_assessment_setting_id IN (#{assessmentId})").distinct
+
+ assessments.group_by { |assessment| assessment.client_id }.each do |client_id, _assessments|
+ next if _assessments.size < 2
+
+ first_assessment = _assessments.sort_by(&:id).first
+ last_assessment = _assessments.sort_by(&:id).last
+
+ first_assessment_domain_scores = first_assessment.assessment_domains.pluck(:score).sum.to_f
+ last_assessment_domain_scores = last_assessment.assessment_domains.pluck(:score).sum.to_f
+
+ first_average_score = (first_assessment_domain_scores / first_assessment.assessment_domains.size).round
+ last_average_score = (last_assessment_domain_scores / last_assessment.assessment_domains.size).round
+ client_ids << client_id if last_average_score.public_send(compare, first_average_score)
+ end
+ end
+ end
+ client_ids
+ end
+
+ def client_assessment_compare_next_last(compare, selectedAssessment)
+ client_ids = []
+ clients = @clients.joins(:assessments).where(assessments: { completed: true })
+ conditionString = ""
+ if selectedAssessment.present?
+ assessments = JSON.parse(selectedAssessment)
+ assessmentId = assessments.first
+
+ if assessmentId == 0
+ domains = Domain.csi_domains
+ clients = clients.where("assessments.default = true").distinct
+ clients.each do |client|
+ last_assessment = client.assessments.defaults.most_recents.first
+ next_assessment = client.assessments.defaults.length > 1 ? client.assessments.defaults.most_recents.fetch(1) : last_assessment
+ if (client.assessments.defaults.length > 1)
+ client_ids << client.id if assessment_total_score(last_assessment, domains).public_send(compare, assessment_total_score(next_assessment, domains))
+ end
+ end
+ else
+ assessments = Assessment.completed.joins(:domains).where(client_id: clients.ids).where("domains.custom_assessment_setting_id IN (#{assessmentId})").distinct
+
+ assessments.group_by { |assessment| assessment.client_id }.each do |client_id, _assessments|
+ next if _assessments.size < 2
+
+ before_last_assessment = _assessments.sort_by(&:id).fetch(_assessments.size - 2)
+ last_assessment = _assessments.sort_by(&:id).last
+
+ before_last_assessment_domain_scores = before_last_assessment.assessment_domains.pluck(:score).sum.to_f
+ last_assessment_domain_scores = last_assessment.assessment_domains.pluck(:score).sum.to_f
+
+ before_last_assessment_average_score = (before_last_assessment_domain_scores / before_last_assessment.assessment_domains.size).round
+ last_average_score = (last_assessment_domain_scores / last_assessment.assessment_domains.size).round
+ client_ids << client_id if last_average_score.public_send(compare, before_last_assessment_average_score)
+ end
+ end
+ end
+ client_ids
+ end
+
+ def assessment_total_score(assessment, domains)
+ assessment_domain_hash = AssessmentDomain.where(assessment_id: assessment.id).pluck(:domain_id, :score).to_h if assessment.assessment_domains.present?
+ domain_scores = domains.ids.map { |domain_id| assessment_domain_hash.present? ? ["domain_#{domain_id}", assessment_domain_hash[domain_id]] : ["domain_#{domain_id}", ''] }
+ total = 0
+ if assessment_domain_hash.present?
+ assessment_domain_hash.each do |index, value|
+ total += value.nil? ? 0 : value
+ end
+ end
+ (total.fdiv(domain_scores.length())).round()
+ end
+
+ def incomplete_care_plan_query
+ clients = @clients.joins(:care_plans).where(care_plans: { completed: false }).distinct
+
+ client_ids = clients.ids
+ clients = client_ids.present? ? client_ids : []
+ end
end
end
diff --git a/app/classes/advanced_searches/client_base_sql_builder.rb b/app/classes/advanced_searches/client_base_sql_builder.rb
index 64ae60d434..70827a92b1 100644
--- a/app/classes/advanced_searches/client_base_sql_builder.rb
+++ b/app/classes/advanced_searches/client_base_sql_builder.rb
@@ -12,7 +12,10 @@ class ClientBaseSqlBuilder
'referee_name', 'referee_phone', 'referee_email', 'carer_name', 'carer_phone', 'carer_email',
'client_phone', 'client_email_address', 'phone_owner', 'referee_relationship', 'active_clients',
'care_plan_counter', 'care_plan_completed_date', 'completed_date', 'custom_completed_date', 'carer_relationship_to_client',
- 'referred_in', 'referred_out', 'family_type', 'ratanak_achievement_program_staff_client_ids', 'mo_savy_officials'
+ 'ratanak_achievement_program_staff_client_ids', 'mo_savy_officials',
+ 'referred_in', 'referred_out', 'family_type', 'active_client_program',
+ 'number_client_referred_gatekeeping', 'number_client_billable', 'assessment_condition_last_two',
+ 'assessment_condition_first_last', 'client_rejected', 'incomplete_care_plan'
]
BLANK_FIELDS = ['created_at', 'date_of_birth', 'initial_referral_date', 'follow_up_date', 'has_been_in_orphanage', 'has_been_in_government_care', 'province_id', 'referral_source_id', 'birth_province_id', 'received_by_id', 'followed_up_by_id', 'district_id', 'subdistrict_id', 'township_id', 'state_id', 'commune_id', 'village_id', 'referral_source_category_id', 'arrival_at']
diff --git a/app/classes/advanced_searches/client_fields.rb b/app/classes/advanced_searches/client_fields.rb
index 0d1ffbfa65..b90548969c 100644
--- a/app/classes/advanced_searches/client_fields.rb
+++ b/app/classes/advanced_searches/client_fields.rb
@@ -9,25 +9,41 @@ class ClientFields
def initialize(options = {})
@user = options[:user]
@pundit_user = options[:pundit_user]
+ @program_stream_ids = options[:program_stream_ids]
address_translation
end
def render
+ common_group = format_header('common_searches')
group = format_header('basic_fields')
+ care_plan_group = format_header('care_plan')
referee_group = format_header('referee')
carer_group = format_header('carer')
legal_docs = format_header('legal_documents')
+ case_history_group = format_header('case_history')
+ family_group = format_header('family')
+ case_note_group = format_header('case_note')
+ other_group = format_header('other')
number_fields = number_type_list.map { |item| AdvancedSearches::FilterTypes.number_options(item, format_header(item), group) }
+ number_fields += case_history_number_type_list.map { |item| AdvancedSearches::FilterTypes.number_options(item, format_header(item), case_history_group) }
text_fields = text_type_list.map { |item| AdvancedSearches::FilterTypes.text_options(item, format_header(item), group) }
- text_fields << referee_text_fields.map { |item| AdvancedSearches::FilterTypes.text_options(item, format_header(item), referee_group) }
- text_fields << carer_text_fields.map { |item| AdvancedSearches::FilterTypes.text_options(item, format_header(item), carer_group) }
- date_picker_fields = date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), group) }
- date_picker_fields += [['no_case_note_date', I18n.t('advanced_search.fields.no_case_note_date')]].map{ |item| AdvancedSearches::CsiFields.date_between_only_options(item[0], item[1], group) }
+ date_picker_fields = common_search_date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), common_group) }
+ date_picker_fields += date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), group) }
+ date_picker_fields += case_history_date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), case_history_group) }
+ date_picker_fields += case_note_date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), case_note_group) }
+ date_picker_fields += [['no_case_note_date', I18n.t('advanced_search.fields.no_case_note_date')]].map{ |item| AdvancedSearches::CsiFields.date_between_only_options(item[0], item[1], case_note_group) }
date_picker_fields += mapping_care_plan_date_lable_translation
+ date_picker_fields += other_date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), other_group) }
drop_list_fields = drop_down_type_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, group) }
+ drop_list_fields += care_plan_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, care_plan_group) }
+ drop_list_fields += referee_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, referee_group) }
drop_list_fields += carer_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, carer_group) }
drop_list_fields += legal_docs_dropdown.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, legal_docs) }
+ drop_list_fields += family_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, family_group) }
+ drop_list_fields += case_history_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, case_history_group) }
+ drop_list_fields += case_note_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, case_note_group) }
+ drop_list_fields += other_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, other_group) }
csi_options = AdvancedSearches::CsiFields.render
school_grade_options = AdvancedSearches::SchoolGradeFields.render
default_domain_scores_options = enable_default_assessment? ? AdvancedSearches::DomainScoreFields.render : []
@@ -43,73 +59,67 @@ def render
private
def number_type_list
- ['family_id', 'age', 'time_in_cps', 'time_in_ngo', 'referred_in', 'referred_out']
+ ['family_id', 'age']
+ end
+
+ def case_history_number_type_list
+ ['referred_in', 'referred_out', 'time_in_ngo', 'time_in_cps']
end
def text_type_list
[
- 'given_name', 'family_name', 'flight_nb',
- 'local_given_name', 'local_family_name', 'family', 'slug', 'school_name',
- 'other_info_of_exit', 'exit_note', 'main_school_contact', 'what3words', 'kid_id', 'code',
- 'client_phone', 'client_email_address', *setting_country_fields[:text_fields]
+ 'given_name', 'flight_nb','local_given_name', 'slug', 'what3words', 'kid_id', 'code',
+ 'client_email_address', *setting_country_fields[:text_fields]
].compact
end
- def referee_text_fields
- ['referee_name', 'referee_phone', 'referee_email']
- end
-
- def carer_text_fields
- ['carer_name', 'carer_phone', 'carer_email']
+ def referee_dropdown_list
+ [
+ ['referral_source_category_id', referral_source_category_options],
+ ['referral_source_id', referral_source_options],
+ ['referee_relationship', get_sql_referee_relationship]
+ ]
end
def current_user
@pundit_user
end
+ def common_search_date_type_list
+ ['number_client_referred_gatekeeping', 'number_client_billable', 'client_rejected', 'active_clients']
+ end
+
def date_type_list
[
- 'date_of_birth', 'initial_referral_date', 'follow_up_date', 'exit_date', 'accepted_date',
- 'case_note_date', 'created_at', 'date_of_referral', 'active_clients', 'arrival_at'
+ 'date_of_birth', 'date_of_referral'
].compact
end
+ def case_history_date_type_list
+ ['initial_referral_date', 'follow_up_date', 'accepted_date', 'exit_date']
+ end
+
+ def case_note_date_type_list
+ ['case_note_date']
+ end
+
+ def other_date_type_list
+ ['created_at']
+ end
+
def drop_down_type_list
+ yes_option = { true: 'Yes' }
yes_no_options = { true: 'Yes', false: 'No' }
fields = [
['location_of_concern', Client.cache_location_of_concern],
- ['created_by', user_select_options ],
['gender', gender_list],
['status', client_status],
- ['agency_name', agencies_options],
- ['received_by_id', received_by_options],
- ['referral_source_id', referral_source_options],
- ['followed_up_by_id', followed_up_by_options],
- ['has_been_in_government_care', yes_no_options],
- ['has_overdue_assessment', yes_no_options],
- ['has_overdue_forms', yes_no_options],
- ['has_overdue_task', yes_no_options],
- ['no_case_note', yes_no_options],
- ['has_been_in_orphanage', yes_no_options],
- ['user_id', user_select_options],
['ratanak_achievement_program_staff_client_ids', user_select_options],
['mo_savy_officials', mo_savy_officials_options],
- ['donor_name', donor_options],
- ['active_program_stream', active_program_options],
- ['enrolled_program_stream', enrolled_program_options],
- ['case_note_type', case_note_type_options],
- ['exit_reasons', exit_reasons_options],
- ['exit_circumstance', {'Exited Client': 'Exited Client', 'Rejected Referral': 'Rejected Referral'}],
*rated_id_poor,
*setting_country_fields[:drop_down_fields],
- ['referred_to', referral_to_options],
- ['referred_from', referral_from_options],
- ['referral_source_category_id', referral_source_category_options],
- ['type_of_service', get_type_of_services],
- ['referee_relationship', get_sql_referee_relationship],
['address_type', get_sql_address_types],
['phone_owner', get_sql_phone_owner],
- ['family_type', family_type_list]
].compact
end
@@ -118,12 +128,62 @@ def legal_docs_dropdown
legal_doc_fields.map{|field| [field, yes_no_options] }
end
+ def care_plan_dropdown_list
+ yes_option = { true: 'Yes' }
+ [
+ ['incomplete_care_plan', yes_option]
+ ]
+ end
+
def carer_dropdown_list
[
['carer_relationship_to_client', list_carer_client_relations]
]
end
+ def family_dropdown_list
+ [
+ ['family_type', family_type_list]
+ ]
+ end
+
+ def case_history_dropdown_list
+ yes_no_options = { true: 'Yes', false: 'No' }
+ [
+ ['user_id', user_select_options],
+ ['exit_circumstance', {'Exited Client': 'Exited Client', 'Rejected Referral': 'Rejected Referral'}],
+ ['followed_up_by_id', followed_up_by_options],
+ ['referred_from', referral_from_options],
+ ['referred_to', referral_to_options],
+ ['exit_reasons', exit_reasons_options],
+ ['received_by_id', received_by_options],
+ ['active_program_stream', active_program_options],
+ ['enrolled_program_stream', enrolled_program_options],
+ ['donor_name', donor_options],
+ ['has_been_in_orphanage', yes_no_options],
+ ['has_been_in_government_care', yes_no_options],
+ ]
+ end
+
+ def case_note_dropdown_list
+ yes_no_options = { true: 'Yes', false: 'No' }
+ [
+ ['case_note_type', case_note_type_options],
+ ['no_case_note', yes_no_options],
+ ]
+ end
+
+ def other_dropdown_list
+ yes_no_options = { true: 'Yes', false: 'No' }
+ [
+ ['agency_name', agencies_options],
+ ['created_by', user_select_options ],
+ ['type_of_service', get_type_of_services],
+ ['has_overdue_forms', yes_no_options],
+ ['has_overdue_task', yes_no_options],
+ ]
+ end
+
def field_settings
@field_settings = FieldSetting.cache_all
end
diff --git a/app/classes/advanced_searches/common_fields.rb b/app/classes/advanced_searches/common_fields.rb
new file mode 100644
index 0000000000..0814cd3061
--- /dev/null
+++ b/app/classes/advanced_searches/common_fields.rb
@@ -0,0 +1,36 @@
+module AdvancedSearches
+ class CommonFields
+
+ include AdvancedSearchHelper
+
+ def initialize(program_ids = nil, assessment_checked = false)
+ @program_ids = program_ids
+ @assessment_checked = assessment_checked
+
+ address_translation
+ end
+
+ def render
+ common_group = format_header('common_searches')
+
+ date_picker_fields = @program_ids.nil? ? [] : common_search_date_type_list.map { |item| AdvancedSearches::FilterTypes.date_picker_options(item, format_header(item), common_group) }
+ drop_down_fields = @assessment_checked ? common_search_dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, common_group) } : []
+
+ results = date_picker_fields + drop_down_fields
+
+ results.sort_by { |f| f[:label].downcase }
+ end
+
+ def common_search_date_type_list
+ ['active_client_program']
+ end
+
+ def common_search_dropdown_list
+ better_same_worse_options = { better: 'Better', same: 'The same', worse: 'Worse' }
+ [
+ ['assessment_condition_last_two', better_same_worse_options],
+ ['assessment_condition_first_last', better_same_worse_options]
+ ]
+ end
+ end
+end
diff --git a/app/classes/advanced_searches/csi_fields.rb b/app/classes/advanced_searches/csi_fields.rb
index f349f7abe6..3c5095a1bb 100644
--- a/app/classes/advanced_searches/csi_fields.rb
+++ b/app/classes/advanced_searches/csi_fields.rb
@@ -7,9 +7,8 @@ def self.render
address_translation
csi_group = format_header('custom_csi_group')
csi_domain_options = number_type_list.map { |item| number_filter_type(item, format_header(item), csi_group) }
- assessment_completed = [['assessment_completed', I18n.t('clients.index.assessment_completed', assessment: I18n.t('clients.show.assessment'))]].map{ |item| date_between_only_options(item[0], item[1], csi_group) }
date_nearest = ['Date Nearest'].map{ |item| date_nearest(item.downcase.gsub(' ', '_'), item, csi_group) }
- (assessment_completed + csi_domain_options + date_nearest).sort_by { |f| f[:label].downcase }
+ (csi_domain_options + date_nearest).sort_by { |f| f[:label].downcase }
end
private
@@ -43,13 +42,13 @@ def self.date_picker_options(field_name, label, group)
}
end
- def self.date_between_only_options(field_name, label, group)
+ def self.date_nearest(field_name, label, group)
{
id: field_name,
optgroup: group,
label: label,
type: 'date',
- operators: ['between'],
+ operators: ['equal'],
plugin: 'datepicker',
plugin_config: {
format: 'yyyy-mm-dd',
@@ -60,14 +59,23 @@ def self.date_between_only_options(field_name, label, group)
}
end
+ def self.number_filter_type(field_name, label, group)
+ {
+ id: field_name,
+ optgroup: group,
+ label: label,
+ type: 'integer',
+ operators: ['equal']
+ }
+ end
- def self.date_nearest(field_name, label, group)
+ def self.date_between_only_options(field_name, label, group)
{
id: field_name,
optgroup: group,
label: label,
type: 'date',
- operators: ['equal'],
+ operators: ['between'],
plugin: 'datepicker',
plugin_config: {
format: 'yyyy-mm-dd',
@@ -77,15 +85,5 @@ def self.date_nearest(field_name, label, group)
}
}
end
-
- def self.number_filter_type(field_name, label, group)
- {
- id: field_name,
- optgroup: group,
- label: label,
- type: 'integer',
- operators: ['equal']
- }
- end
end
end
diff --git a/app/classes/advanced_searches/custom_domain_score_fields.rb b/app/classes/advanced_searches/custom_domain_score_fields.rb
index 3789238f65..f28e01950f 100644
--- a/app/classes/advanced_searches/custom_domain_score_fields.rb
+++ b/app/classes/advanced_searches/custom_domain_score_fields.rb
@@ -10,7 +10,7 @@ def self.render(domain_type = 'client')
assessment_completed_date = ['custom_completed_date'].map{ |item| date_picker_options(item, format_header(item), domain_score_group) }
date_of_assessments = ['custom_assessment_created_date'].map{ |item| date_picker_options(item, format_header(item), domain_score_group) }
all_custom_domains = ['All Custom Domains'].map { |item| number_filter_type(item.downcase.gsub(' ', '_'), domain_score_format(item), domain_score_group) }
- all_custom_domains + custom_assessments + date_of_assessments + assessment_completed_date + csi_domain_options
+ (custom_assessments + date_of_assessments + assessment_completed_date + csi_domain_options + all_custom_domains).sort_by { |f| f[:label].downcase }
end
private
diff --git a/app/classes/advanced_searches/domain_score_fields.rb b/app/classes/advanced_searches/domain_score_fields.rb
index 1e20638b6c..866261c622 100644
--- a/app/classes/advanced_searches/domain_score_fields.rb
+++ b/app/classes/advanced_searches/domain_score_fields.rb
@@ -9,7 +9,9 @@ def self.render
date_of_assessments = [['date_of_assessments', I18n.t('clients.index.date_of_assessment', assessment: I18n.t('clients.show.assessment'))]].map{ |item| date_picker_options(item[0], item[1], domain_score_group) }
completed_date_assessments = [['completed_date', I18n.t('advanced_search.fields.assessment_completed_date', assessment: I18n.t('clients.show.assessment'))]].map{ |item| date_picker_options(item[0], item[1], domain_score_group) }
all_domains = ['All Domains'].map { |item| number_filter_type(item.downcase.gsub(' ', '_'), domain_score_format(item), domain_score_group) }
- all_domains + date_of_assessments + completed_date_assessments + csi_domain_options
+ drop_list_fields = dropdown_list.map { |item| AdvancedSearches::FilterTypes.drop_list_options(item.first, format_header(item.first), item.last, domain_score_group) }
+ assessment_completed = [['assessment_completed', I18n.t('clients.index.assessment_completed', assessment: I18n.t('clients.show.assessment'))]].map{ |item| date_between_only_options(item[0], item[1], domain_score_group) }
+ (csi_domain_options + date_of_assessments + completed_date_assessments + all_domains + drop_list_fields).sort_by { |f| f[:label].downcase }
end
private
@@ -53,5 +55,29 @@ def self.number_filter_type(field_name, label, group)
operators: ['equal', 'not_equal', 'less', 'less_or_equal', 'greater', 'greater_or_equal', 'between', 'is_empty', 'is_not_empty', 'average', 'assessment_has_changed', 'assessment_has_not_changed', 'month_has_changed', 'month_has_not_changed']
}
end
+
+ def self.dropdown_list
+ yes_no_options = { true: 'Yes', false: 'No' }
+ [
+ ['has_overdue_assessment', yes_no_options],
+ ].compact
+ end
+
+ def self.date_between_only_options(field_name, label, group)
+ {
+ id: field_name,
+ optgroup: group,
+ label: label,
+ type: 'date',
+ operators: ['between'],
+ plugin: 'datepicker',
+ plugin_config: {
+ format: 'yyyy-mm-dd',
+ todayBtn: 'linked',
+ todayHighlight: true,
+ autoclose: true
+ }
+ }
+ end
end
end
diff --git a/app/classes/advanced_searches/filter_types.rb b/app/classes/advanced_searches/filter_types.rb
index ba77d89c02..d399b971bb 100644
--- a/app/classes/advanced_searches/filter_types.rb
+++ b/app/classes/advanced_searches/filter_types.rb
@@ -1,6 +1,6 @@
module AdvancedSearches
class FilterTypes
- OVERDUE_FIELDS = %w(has_overdue_assessment has_overdue_forms has_overdue_task no_case_note)
+ OVERDUE_FIELDS = %w(has_overdue_assessment has_overdue_forms has_overdue_task no_case_note assessment_condition_last_two assessment_condition_first_last incomplete_care_plan)
def self.text_options(field_name, label, group)
{
id: field_name,
diff --git a/app/classes/advanced_searches/quantitative_case_fields.rb b/app/classes/advanced_searches/quantitative_case_fields.rb
index 396512f348..8954860d92 100644
--- a/app/classes/advanced_searches/quantitative_case_fields.rb
+++ b/app/classes/advanced_searches/quantitative_case_fields.rb
@@ -18,7 +18,6 @@ def render
quantitative_type_ids = @user.quantitative_type_permissions.readable.pluck(:quantitative_type_id)
quantitative_types = QuantitativeType.cach_by_quantitative_type_ids(quantitative_type_ids)
end
-
quantitative_cases = quantitative_types.map do |qt|
if qt.select_option?
AdvancedSearches::FilterTypes.drop_list_options(
diff --git a/app/classes/risk_assessment_reducer.rb b/app/classes/risk_assessment_reducer.rb
new file mode 100644
index 0000000000..1f46e1cf20
--- /dev/null
+++ b/app/classes/risk_assessment_reducer.rb
@@ -0,0 +1,19 @@
+class RiskAssessmentReducer
+ attr_reader :type, :risk_assessment, :risk_assessment_params
+ def initialize(client, risk_assessment_params, type = 'create')
+ @risk_assessment = client.risk_assessment.present? ? client.risk_assessment : client.build_risk_assessment(risk_assessment_params)
+ @risk_assessment_params = risk_assessment_params
+ @type = type if risk_assessment_params[:assessment_date].present?
+ end
+
+ def store
+ case type
+ when 'create'
+ risk_assessment.save
+ when 'update'
+ risk_assessment.persisted? ? risk_assessment.update_attributes(risk_assessment_params) : risk_assessment.save
+ else
+ false
+ end
+ end
+end
diff --git a/app/classes/tracking_datatable.rb b/app/classes/tracking_datatable.rb
index 8076f6dc43..b62e0c8d7b 100644
--- a/app/classes/tracking_datatable.rb
+++ b/app/classes/tracking_datatable.rb
@@ -24,7 +24,7 @@ def sort_column
def fetch_trackings
program_stream_ids = ClientEnrollment.active.pluck(:program_stream_id).uniq
- Tracking.unscoped.includes(:client_enrollments, :program_stream).where(program_streams: { id: program_stream_ids }).order("lower(#{sort_column}) #{sort_direction}").page(page).per(per_page)
+ Tracking.unscoped.includes(:client_enrollments, :program_stream).where(program_streams: { id: program_stream_ids }).order("lower(#{sort_column}), trackings.id #{sort_direction}").page(page).per(per_page)
end
def columns
diff --git a/app/controllers/api/application_controller.rb b/app/controllers/api/application_controller.rb
index 4ac4f3f1fc..b885b13b16 100644
--- a/app/controllers/api/application_controller.rb
+++ b/app/controllers/api/application_controller.rb
@@ -1,7 +1,10 @@
module Api
class ApplicationController < ActionController::Base
+ include LocaleConcern
+
before_action :authenticate_user!
before_action :set_paper_trail_whodunnit
+ before_action :set_locale
private
diff --git a/app/controllers/api/client_advanced_searches_controller.rb b/app/controllers/api/client_advanced_searches_controller.rb
index a389afe391..3a46fca6c1 100644
--- a/app/controllers/api/client_advanced_searches_controller.rb
+++ b/app/controllers/api/client_advanced_searches_controller.rb
@@ -29,5 +29,12 @@ def get_exit_program_field
advanced_filter_exit_program_field = AdvancedSearches::ExitProgramFields.new(program_stream_ids).render
render json: advanced_filter_exit_program_field
end
+
+ def get_program_stream_search_field
+ program_stream_ids = params[:ids]
+ assessment_checked = params[:assesment_checked]
+ advanced_filter_common_field = AdvancedSearches::CommonFields.new(program_stream_ids, assessment_checked).render
+ render json: advanced_filter_common_field
+ end
end
end
diff --git a/app/controllers/api/clients_controller.rb b/app/controllers/api/clients_controller.rb
index 69f9a5c306..abf9827f3c 100644
--- a/app/controllers/api/clients_controller.rb
+++ b/app/controllers/api/clients_controller.rb
@@ -63,6 +63,11 @@ def create
end
end
+ if risk_assessment_params
+ risk_assessment = RiskAssessmentReducer.new(client, risk_assessment_params, 'create')
+ risk_assessment.store
+ end
+
render json: { slug: client.slug, id: client.id }, status: :ok
else
render json: client.errors, status: :unprocessable_entity
@@ -71,7 +76,6 @@ def create
def update
client = Client.find(params[:client][:id] || params[:id])
-
if params[:client][:id]
referee = Referee.find_or_create_by(id: client.referee_id)
referee.update_attributes(referee_params)
@@ -93,6 +97,11 @@ def update
end
end
+ if risk_assessment_params
+ risk_assessment = RiskAssessmentReducer.new(client, risk_assessment_params, 'update')
+ risk_assessment.store
+ end
+
if params[:client][:assessment_id]
assessment = Assessment.find(params[:client][:assessment_id])
else
@@ -147,11 +156,11 @@ def client_params
params[:client][:mo_savy_officials_attributes] = {}
params[:mosavy_officials].each_with_index do |item, index|
- params[:client][:mo_savy_officials_attributes] [index.to_s] = item
+ params[:client][:mo_savy_officials_attributes][index.to_s] = item
end
end
- client_params = params.require(:client).permit(
+ client_param = params.require(:client).permit(
:slug, :archived_slug, :code, :name_of_referee, :main_school_contact, :rated_for_id_poor, :what3words, :status, :country_origin,
:kid_id, :assessment_id, :given_name, :family_name, :local_given_name, :local_family_name, :gender, :date_of_birth,
:birth_province_id, :initial_referral_date, :referral_source_id, :telephone_number,
@@ -246,25 +255,18 @@ def client_params
field_settings.each do |field_setting|
next if field_setting.group != 'client' || field_setting.required? || field_setting.visible?
- client_params.except!(field_setting.name.to_sym) unless field_setting.name == 'gender'
+ client_param.except!(field_setting.name.to_sym) unless field_setting.name == 'gender'
end
if params[:family_member]
- client_params[:family_member_attributes] = params[:family_member].permit([:id, :family_id])
+ client_param[:family_member_attributes] = params[:family_member].permit([:id, :family_id])
- if client_params[:family_member_attributes].present?
- client_params[:family_member_attributes][:_destroy] = 1 if client_params.dig(:family_member_attributes, :family_id).blank?
+ if client_param[:family_member_attributes].present?
+ client_param[:family_member_attributes][:_destroy] = 1 if client_param.dig(:family_member_attributes, :family_id).blank?
end
end
- Client::LEGAL_DOC_FIELDS.each do |attachment_field|
- doc_field = attachment_field.gsub('_files', '')
- remove_field = "remove_#{attachment_field}"
-
- # client_params[remove_field.to_sym] = true if client_params[doc_field.to_sym].in?([false, 'false'])
- end
-
- client_params
+ client_param
end
def referee_params
@@ -281,6 +283,17 @@ def carer_params
)
end
+ def risk_assessment_params
+ return if params.dig(:risk_assessment).nil?
+ params.require(:risk_assessment).permit(
+ :assessment_date, :other_protection_concern_specification, :client_perspective, :has_known_chronic_disease,
+ :has_disability, :has_hiv_or_aid, :known_chronic_disease_specification, :disability_specification, :hiv_or_aid_specification,
+ :relevant_referral_information, :level_of_risk, :history_of_disability_id, :history_of_harm_id, :history_of_high_risk_behaviour_id,
+ :history_of_family_separation_id, protection_concern: [],
+ tasks_attributes: [:id, :name, :expected_date, :client_id, :_destroy]
+ )
+ end
+
def find_client_in_organization
results = []
similar_fields = Client.find_shared_client(params)
@@ -299,11 +312,16 @@ def data
assessment_data.each do |assessment|
assessment_domain_hash = AssessmentDomain.where(assessment_id: assessment.id).pluck(:domain_id, :score).to_h if assessment.assessment_domains.present?
domain_scores = domains.ids.map { |domain_id| assessment_domain_hash.present? ? ["domain_#{domain_id}", assessment_domain_hash[domain_id]] : ["domain_#{domain_id}", ''] }
+ total = 0
+ assessment_domain_hash.each do |index, value|
+ total += value || 0
+ end
client_hash = { slug: assessment.client.slug,
name: assessment.client.en_and_local_name,
- 'assessment-number': assessment.client.assessments.count,
- date: assessment.created_at.strftime('%d %B %Y')
+ 'assessment-number': assessment.client.assessments.where(default: params[:default]).count,
+ date: assessment.created_at.strftime('%d %B %Y'),
+ 'average-score': total == 0 ? nil : (total.fdiv(domain_scores.length())).round()
}
client_hash.merge!(domain_scores.to_h)
client_data << client_hash
@@ -320,6 +338,9 @@ def fetch_assessments
assessments = Assessment.joins(:client).where(default: params[:default], client_id: params[:client_ids].split('/'))
assessments = assessments.includes(:assessment_domains).order("#{sort_column} #{sort_direction}").references(:assessment_domains, :client)
+ basic_rules = $param_rules.present? && $param_rules[:basic_rules] ? $param_rules[:basic_rules] : $param_rules
+ @basic_rules = basic_rules.is_a?(Hash) ? basic_rules : JSON.parse(basic_rules || "{}").with_indifferent_access
+
assessment_data = params[:length] != '-1' ? assessments.page(page).per(per_page) : assessments
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index dfa6a03b6d..3fa2e9fb45 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -1,5 +1,7 @@
class ApplicationController < ActionController::Base
include Pundit
+ include LocaleConcern
+
protect_from_forgery with: :null_session, except: :index, if: proc { |c| c.request.format == 'application/json' }
before_action :store_user_location!, if: :storable_location?
before_action :configure_permitted_parameters, if: :devise_controller?
@@ -87,19 +89,6 @@ def find_association
@province = Province.cached_order_name
end
- def set_locale
- local = I18n.locale
- local = current_user.preferred_language if user_signed_in?
- local = params[:locale] if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
-
- if detect_browser.present?
- flash.clear
- flash[:alert] = detect_browser
- end
-
- I18n.locale = local
- end
-
def override_translation
I18n.backend.reload! if request.get? && request.format.html?
end
@@ -121,13 +110,6 @@ def after_sign_in_path_for(_resource_or_scope)
stored_location_string && stored_location_string.gsub(/locale\=(en|km|my)/, "locale=#{locale}") || dashboards_path(locale: current_user&.preferred_language || 'en') || super
end
- def detect_browser
- lang = params[:locale] || locale.to_s
- if browser.firefox? && browser.platform.mac? && lang == 'km'
- "Khmer fonts for Firefox do not render correctly. Please use Google Chrome browser instead if you intend to use OSCaR in Khmer language."
- end
- end
-
def storable_location?
request.get? && is_navigational_format? && !devise_controller? && !request.xhr?
end
diff --git a/app/controllers/assessments_controller.rb b/app/controllers/assessments_controller.rb
index b4356c60da..716951a53f 100644
--- a/app/controllers/assessments_controller.rb
+++ b/app/controllers/assessments_controller.rb
@@ -134,8 +134,8 @@ def authorize_assessment
end
def assessment_params
- default_params = params.require(:assessment).permit(:default, :case_conference_id, :custom_assessment_setting_id, assessment_domains_attributes: [:id, :domain_id, :score, :reason, :goal, :goal_required, :required_task_last])
- default_params = params.require(:assessment).permit(:default, :case_conference_id, :custom_assessment_setting_id, assessment_domains_attributes: [:id, :domain_id, :score, :reason, :goal, :goal_required, :required_task_last, attachments: []]) if action_name == 'create'
+ default_params = params.require(:assessment).permit(:default, :case_conference_id, :custom_assessment_setting_id, :level_of_risk, :description, assessment_domains_attributes: [:id, :domain_id, :score, :reason, :goal, :goal_required, :required_task_last])
+ default_params = params.require(:assessment).permit(:default, :case_conference_id, :custom_assessment_setting_id, :level_of_risk, :description, assessment_domains_attributes: [:id, :domain_id, :score, :reason, :goal, :goal_required, :required_task_last, attachments: []]) if action_name == 'create'
default_params
end
diff --git a/app/controllers/case_notes_controller.rb b/app/controllers/case_notes_controller.rb
index ec13b1efd7..7e832382c9 100644
--- a/app/controllers/case_notes_controller.rb
+++ b/app/controllers/case_notes_controller.rb
@@ -41,6 +41,7 @@ def create
add_more_attachments(params[:case_note][:attachments]) if params.dig(:case_note, :attachments)
@case_note.complete_tasks(params[:case_note][:case_note_domain_groups_attributes], current_user.id) if params.dig(:case_note, :case_note_domain_groups_attributes)
create_bulk_task(params[:task], @case_note) if params.has_key?(:task)
+ @case_note.complete_screening_tasks(params) if params[:case_note].has_key?(:tasks_attributes)
create_task_task_progress_notes
if params[:from_controller] == "dashboards"
@@ -78,6 +79,7 @@ def update
@case_note.complete_tasks(params[:case_note][:case_note_domain_groups_attributes], current_user.id)
end
create_bulk_task(params[:task], @case_note) if params.has_key?(:task)
+ @case_note.complete_screening_tasks(params) if params[:case_note].has_key?(:tasks_attributes)
create_task_task_progress_notes
delete_events if session[:authorization]
redirect_to client_case_notes_path(@client), notice: t('.successfully_updated')
diff --git a/app/controllers/client/tasks_controller.rb b/app/controllers/client/tasks_controller.rb
index 381cb807c3..2e080be11b 100644
--- a/app/controllers/client/tasks_controller.rb
+++ b/app/controllers/client/tasks_controller.rb
@@ -6,7 +6,7 @@ class Client::TasksController < AdminController
before_action :find_task, only: [:edit, :update, :destroy]
def index
- @tasks = @client.tasks.includes(:domain)
+ @tasks = @client.tasks.includes(:taskable)
end
def create
@@ -99,8 +99,8 @@ def authorize_client
def find_calendars(task)
task_name = task.name
- domain = Domain.find(task.domain_id)
- title = "#{domain.name} - #{task_name}"
+ domain = Domain.find(task.domain_id) if task.domain_id
+ title = task.domain_id ? "#{domain.name} - #{task_name}" : task_name
start_date = task.expected_date
end_date = (start_date + 1.day).to_s
@calendars = Calendar.where(title: title, start_date: start_date, end_date: end_date)
diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb
index c141d72a23..0bbfc8cb09 100644
--- a/app/controllers/clients_controller.rb
+++ b/app/controllers/clients_controller.rb
@@ -8,7 +8,7 @@ class ClientsController < AdminController
before_action :assign_active_client_prams, only: :index
before_action :format_search_params, only: [:index]
before_action :get_quantitative_fields, :get_hotline_fields, :hotline_call_column, only: [:index]
- before_action :find_params_advanced_search, :get_custom_form, :get_program_streams, only: [:index]
+ before_action :find_params_advanced_search, :get_custom_form, :get_program_streams, :get_assessments, only: [:index]
before_action :get_custom_form_fields, :program_stream_fields, :custom_form_fields, :client_builder_fields, only: [:index]
before_action :basic_params, if: :has_params?, only: [:index]
before_action :build_advanced_search, only: [:index]
@@ -56,7 +56,7 @@ def show
format.html do
@referees = Referee.none_anonymouse.pluck(:id, :name).map{|id, name| { value: id, text: name } }
@current_provinces = Province.pluck(:id, :name).map{|id, name| { value: id, text: name } }
- @birth_provinces = @birth_provinces.map{|parent, children| children.map{|t, v| {value: v, text: t } } }.flatten
+ @birth_provinces = @birth_provinces.map{|parent, children| children.map{|t, v| { value: v, text: t } } }.flatten
custom_field_ids = @client.custom_field_properties.pluck(:custom_field_id)
if current_user.admin? || current_user.strategic_overviewer?
available_editable_forms = CustomField.all
@@ -129,6 +129,8 @@ def new
end
@client = Client.new(new_params.merge(local_given_name: first_name, local_family_name: last_name, gender: new_params[:gender]&.downcase))
+ @risk_assessment = @client.build_risk_assessment
+ @risk_assessment.tasks.build
end
end
@@ -141,6 +143,8 @@ def edit
attributes.merge!({ status: 'Referred' })
@client.attributes = attributes
end
+
+ @risk_assessment = @client.risk_assessment || @client.build_risk_assessment
end
def create
@@ -352,7 +356,7 @@ def country_address_fields
end
def initial_visit_client
- referrer = Rails.application.routes.recognize_path(request.referrer)
+ referrer = Rails.application.routes.recognize_path(request.referrer.gsub(/[a-z]{3,}\-/, '').gsub('/?', '?')) if request.referrer
return unless referrer.present?
white_list_referrers = %w[clients]
diff --git a/app/controllers/concerns/client_advanced_searches_concern.rb b/app/controllers/concerns/client_advanced_searches_concern.rb
index 3d195b6fac..b258deb403 100644
--- a/app/controllers/concerns/client_advanced_searches_concern.rb
+++ b/app/controllers/concerns/client_advanced_searches_concern.rb
@@ -91,7 +91,7 @@ def client_builder_fields
@builder_fields = @builder_fields + custom_form_fields if @advanced_search_params[:wizard_custom_form_check].present?
@builder_fields = @builder_fields + @quantitative_fields if @advanced_search_params[:wizard_quantitative_check].present?
else
- @builder_fields = get_client_basic_fields + custom_form_fields + program_stream_fields
+ @builder_fields = get_client_basic_fields + custom_form_fields + program_stream_fields + get_common_fields
@builder_fields = @builder_fields + @quantitative_fields if quantitative_check?
end
end
@@ -108,6 +108,12 @@ def get_client_basic_fields
AdvancedSearches::ClientFields.new(user: current_user, pundit_user: pundit_user).render
end
+ def get_common_fields
+ fields = program_stream_values.empty? ? [] : AdvancedSearches::CommonFields.new(program_stream_values).render
+ fields += assessment_values.empty? ? [] : AdvancedSearches::CommonFields.new(program_stream_values, true).render
+ fields
+ end
+
def get_hotline_fields
args = {
translation: get_basic_field_translations, number_field: [],
@@ -122,8 +128,8 @@ def get_hotline_fields
*get_dropdown_list(['phone_call_id', 'call_type', 'start_datetime', 'protection_concern_id', 'necessity_id']),
]
}
- hotline_fields = AdvancedSearches::AdvancedSearchFields.new('hotline', args).render
- @hotline_fields = get_client_hotline_fields + hotline_fields
+ hotline_fields = AdvancedSearches::AdvancedSearchFields.new('hotline', args).render
+ @hotline_fields = get_client_hotline_fields + hotline_fields
end
def get_client_hotline_fields
@@ -143,7 +149,6 @@ def get_client_hotline_fields
dropdown_list_option: dropdown_list_options
}
@client_hotline_fields = AdvancedSearches::AdvancedSearchFields.new('concern_basic_fields', args).render
-
end
def hotline_text_type_list
@@ -214,6 +219,18 @@ def quantitative_check?
@advanced_search_params.present? && @advanced_search_params[:quantitative_check].present?
end
+ def assessment_value?
+ @advanced_search_params.present? && @advanced_search_params[:assessment_selected].present?
+ end
+
+ def assessment_values
+ assessment_value? ? eval(@advanced_search_params[:assessment_selected]) : []
+ end
+
+ def get_assessments
+ @assessments = (Setting.cache_first.enable_default_assessment? ? [[0, Setting.cache_first.default_assessment]] : []) + CustomAssessmentSetting.all.where(enable_custom_assessment: true).pluck(:id, :custom_assessment_name).to_a
+ end
+
def has_params?
@advanced_search_params.present? && @advanced_search_params[:basic_rules].present?
end
diff --git a/app/controllers/concerns/family_advanced_searches_concern.rb b/app/controllers/concerns/family_advanced_searches_concern.rb
index 558b801b53..42efd05a51 100644
--- a/app/controllers/concerns/family_advanced_searches_concern.rb
+++ b/app/controllers/concerns/family_advanced_searches_concern.rb
@@ -78,7 +78,7 @@ def custom_form_values
end
def custom_form_fields
- @custom_form_fields = get_custom_form_fields + get_has_this_form_fields
+ @custom_form_fields = get_custom_form_fields + get_has_this_form_fields
end
def get_has_this_form_fields
diff --git a/app/controllers/concerns/locale_concern.rb b/app/controllers/concerns/locale_concern.rb
new file mode 100644
index 0000000000..1fa501f735
--- /dev/null
+++ b/app/controllers/concerns/locale_concern.rb
@@ -0,0 +1,20 @@
+module LocaleConcern
+ def set_locale
+ local = I18n.locale
+ local = params[:locale] if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
+
+ if detect_browser.present?
+ flash.clear
+ flash[:alert] = detect_browser
+ end
+
+ I18n.locale = local
+ end
+
+ def detect_browser
+ lang = params[:locale] || locale.to_s
+ if browser.firefox? && browser.platform.mac? && lang == 'km'
+ "Khmer fonts for Firefox do not render correctly. Please use Google Chrome browser instead if you intend to use OSCaR in Khmer language."
+ end
+ end
+end
diff --git a/app/controllers/screening_assessments_controller.rb b/app/controllers/screening_assessments_controller.rb
new file mode 100644
index 0000000000..dc5880c21d
--- /dev/null
+++ b/app/controllers/screening_assessments_controller.rb
@@ -0,0 +1,95 @@
+class ScreeningAssessmentsController < AdminController
+ load_and_authorize_resource params: :screening_assessment_params
+ before_action :find_screening_assessment, except: [:index, :new, :create]
+ before_action :find_client
+ before_action :find_previous_screening_assessment, only: [:new, :create, :edit, :update]
+
+ def index
+ @screening_assessments = @client.screening_assessments.accessible_by(current_ability)
+ end
+
+ def new
+ @screening_assessment = @client.screening_assessments.new
+ @screening_assessment.populate_developmental_markers
+ @screening_assessment.tasks.build(name: t('screening_assessments._attr.refer_to_specialist'))
+ end
+
+ def create
+ @screening_assessment = @client.screening_assessments.new(screening_assessment_params)
+ authorize_screening_assessment(@screening_assessment)
+ if @screening_assessment.save
+ redirect_to [@client, @screening_assessment], notice: t('successfully_created', klass: 'Screening Assessment')
+ else
+ @screening_assessment.populate_developmental_markers
+ flash[:alert] = @screening_assessment.errors.full_messages.join(', ')
+ render :new, screening_type: @screening_assessment.screening_type
+ end
+ end
+
+ def show
+ @developmental_marker_screening_assessments = @screening_assessment.developmental_marker_screening_assessments.includes(:developmental_marker)
+ @tasks = @screening_assessment.tasks
+ end
+
+ def edit
+ @developmental_marker_screening_assessments = @screening_assessment.developmental_marker_screening_assessments
+ maker_name = @screening_assessment.client_milestone_age
+ @screening_assessment.populate_developmental_markers(maker_name)
+ @screening_assessment.tasks.build(name: t('screening_assessments._attr.refer_to_specialist')) if @screening_assessment.tasks.blank?
+ end
+
+ def update
+ if @screening_assessment.update_attributes(screening_assessment_params)
+ redirect_to [@client, @screening_assessment], notice: t('successfully_updated', klass: 'Screening Assessment')
+ else
+ @screening_assessment.populate_developmental_markers
+ flash[:alert] = @screening_assessment.errors.full_messages.join(', ')
+ render :edit
+ end
+ end
+
+ def destroy
+ if @screening_assessment.destroy
+ redirect_to client_path(@client), notice: t('successfully_deleted', klass: 'Screening Assessment')
+ else
+ messages = @screening_assessment.errors.full_messages.uniq.join('\n')
+ redirect_to [@client, @screening_assessment], alert: messages
+ end
+ end
+
+ private
+
+ def authorize_screening_assessment(screening_assessment)
+ if @client.status == 'Exited'
+ raise Pundit::NotAuthorizedError
+ elsif screening_assessment.screening_type == 'one_off'
+ raise Pundit::NotAuthorizedError unless current_setting.cbdmat_one_off
+ elsif screening_assessment.screening_type == 'multiple'
+ raise Pundit::NotAuthorizedError unless current_setting.cbdmat_ongoing
+ end
+ end
+
+ def screening_assessment_params
+ params.require(:screening_assessment).permit(
+ :screening_assessment_date, :client_age, :visitor, :client_milestone_age, :note,
+ :smile_back_during_interaction, :follow_object_passed_midline, :turn_head_to_sound,
+ :head_up_45_degree, :screening_type, :client_id, attachments: [],
+ developmental_marker_screening_assessments_attributes: [
+ :id, :developmental_marker_id, :question_1, :question_2, :question_3, :question_4, :_destroy
+ ],
+ tasks_attributes: [:id, :client_id, :name, :expected_date, :completion_date, :taskable_id, :taskable_type, :relation, :_destroy]
+ )
+ end
+
+ def find_screening_assessment
+ @screening_assessment = ScreeningAssessment.find(params[:id])
+ end
+
+ def find_client
+ @client = Client.friendly.find(params[:client_id])
+ end
+
+ def find_previous_screening_assessment
+ @previous_screening_assessment = ScreeningAssessment.where(client_id: @client.id).where.not(id: @screening_assessment.id).last
+ end
+end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index af3afcfed5..2cd785aecc 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -1,4 +1,5 @@
class SessionsController < Devise::SessionsController
+ include LocaleConcern
before_action :set_whodunnit, :set_current_ngo, :detect_browser
after_action :increase_visit_count, only: :create
skip_before_action :set_locale, only: :create
@@ -15,14 +16,6 @@ def set_current_ngo
@current_ngo = Organization.current
end
- def detect_browser
- lang = params[:locale] || locale.to_s
- if browser.firefox? && browser.platform.mac? && lang == 'km'
- flash.clear
- flash[:alert] = "Application is not translated properly for Firefox on Mac, we're sorry to suggest to use Google Chrome browser instead."
- end
- end
-
def increase_visit_count
Visit.create(user: current_user)
end
diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb
index cec606be8a..a7633b3cbd 100644
--- a/app/controllers/settings_controller.rb
+++ b/app/controllers/settings_controller.rb
@@ -97,6 +97,17 @@ def limit_tracking_form
authorize @setting
end
+ def risk_assessment
+ authorize @setting
+ attribute = params[:setting]
+ if attribute && @setting.update_attributes(setting_params)
+ redirect_to :back, notice: t('successfully_updated', klass: t('settings.update.successfully_updated'))
+ else
+ flash[:alert] = @setting.errors.full_messages.join(", ") if @setting.errors.full_messages.any?
+ render :risk_assessment
+ end
+ end
+
private
def redirect_to_default
@@ -123,9 +134,10 @@ def setting_params
:internal_referral_limit, :internal_referral_frequency, :case_note_edit_limit, :case_note_edit_frequency,
:tracking_form_edit_limit, :tracking_form_edit_frequency, :disabled_future_completion_date, :disabled_task_date_field,
:disabled_add_service_received, :custom_field_limit, :custom_field_frequency, :test_client, :required_case_note_note,
- :hide_case_note_note,
+ :hide_case_note_note, :cbdmat_one_off, :cbdmat_ongoing, :enabled_risk_assessment, :assessment_type_name,
+ :level_of_risk_guidance,
client_default_columns: [], family_default_columns: [], community_default_columns: [],
- partner_default_columns: [], user_default_columns: [],
+ partner_default_columns: [], user_default_columns: [], selected_domain_ids: [],
custom_assessment_settings_attributes: [:id, :custom_assessment_name, :max_custom_assessment, :custom_assessment_frequency, :custom_age, :enable_custom_assessment, :_destroy])
end
diff --git a/app/grids/client_grid.rb b/app/grids/client_grid.rb
index d2153774ed..8ab34611d5 100644
--- a/app/grids/client_grid.rb
+++ b/app/grids/client_grid.rb
@@ -1168,9 +1168,9 @@ def call_fields
if fields.first == 'formbuilder'
if data == 'recent'
if fields.last == 'Has This Form'
- properties = object.custom_field_properties.cached_client_custom_field_properties_count(fields.second)
+ properties = object.custom_field_properties.cached_client_custom_field_properties_count(object, fields.second)
else
- properties = object.custom_field_properties.cached_client_custom_field_properties_order(fields.second)
+ properties = object.custom_field_properties.cached_client_custom_field_properties_order(object, fields.second)
properties = properties[format_field_value] if properties.present?
end
else
@@ -1178,14 +1178,14 @@ def call_fields
properties = [custom_form_with_has_form(object, fields).count]
else
if $param_rules
- custom_field_id = object.custom_fields.cached_client_custom_field_find_by(fields.second)
+ custom_field_id = object.custom_fields.cached_client_custom_field_find_by(object, fields.second)
basic_rules = $param_rules.present? && $param_rules[:basic_rules] ? $param_rules[:basic_rules] : $param_rules
basic_rules = basic_rules.is_a?(Hash) ? basic_rules : JSON.parse(basic_rules).with_indifferent_access
results = mapping_form_builder_param_value(basic_rules, 'formbuilder')
query_string = get_query_string(results, 'formbuilder', 'custom_field_properties.properties')
sql = query_string.reverse.reject(&:blank?).map{|sql| "(#{sql})" }.join(" AND ")
- properties = object.custom_field_properties.cached_client_custom_field_properties_properties_by(custom_field_id, sql, format_field_value)
+ properties = object.custom_field_properties.cached_client_custom_field_properties_properties_by(object, custom_field_id, sql, format_field_value)
properties = properties.blank? ? custom_form_with_has_form(object, fields).properties_by(format_field_value) : properties
else
properties = form_builder_query(object.custom_field_properties, fields.second, column_builder[:id].gsub('&qoute;', '"'), 'custom_field_properties.properties').properties_by(format_field_value)
@@ -1194,24 +1194,24 @@ def call_fields
end
elsif fields.first == 'enrollmentdate'
if data == 'recent'
- properties = date_format(object.client_enrollments.cached_client_order_enrollment_date(fields.second))
+ properties = date_format(object.client_enrollments.cached_client_order_enrollment_date(object, fields.second))
else
- properties = date_filter(object.client_enrollments.cached_client_enrollment_date_join(fields.second), fields.join('__')).map{|date| date_format(date.enrollment_date) }
+ properties = date_filter(object.client_enrollments.cached_client_enrollment_date_join(object, fields.second), fields.join('__')).map{|date| date_format(date.enrollment_date) }
end
elsif fields.first == 'enrollment'
if data == 'recent'
- properties = object.client_enrollments.cached_client_order_enrollment_date_properties(fields.second)
+ properties = object.client_enrollments.cached_client_order_enrollment_date_properties(object, fields.second)
properties = properties[format_field_value] if properties.present?
else
- properties = object.client_enrollments.cached_client_enrollment_date_join(fields.second).properties_by(format_field_value)
+ properties = object.client_enrollments.cached_client_enrollment_date_join(object, fields.second).properties_by(format_field_value)
end
elsif fields.first == 'tracking'
ids = object.client_enrollments.ids
if data == 'recent'
- properties = ClientEnrollmentTracking.cached_tracking_order_created_at(fields.third, ids)
+ properties = ClientEnrollmentTracking.cached_tracking_order_created_at(object, fields.third, ids)
properties = properties[format_field_value] if properties.present?
else
- client_enrollment_trackings = ClientEnrollmentTracking.cached_client_enrollment_tracking(fields.third, ids)
+ client_enrollment_trackings = ClientEnrollmentTracking.cached_client_enrollment_tracking(object, fields.third, ids)
properties = form_builder_query(client_enrollment_trackings, fields.first, column_builder[:id].gsub('&qoute;', '"')).properties_by(format_field_value, client_enrollment_trackings)
end
elsif fields.first == 'exitprogramdate'
diff --git a/app/grids/family_grid.rb b/app/grids/family_grid.rb
index 09853fcf8f..b5f4f40ee6 100644
--- a/app/grids/family_grid.rb
+++ b/app/grids/family_grid.rb
@@ -5,7 +5,7 @@ class FamilyGrid < BaseGrid
attr_accessor :dynamic_columns
scope do
- Family.includes({cases: [:client]}, :village, :commune, :district, :province).order(:name)
+ Family.order(:name)
end
filter(:name, :string, header: -> { I18n.t('datagrid.columns.families.name') }) do |value, scope|
@@ -78,19 +78,19 @@ def created_by
end
def commune_options
- Family.joins(:commune).map{|f| [f.commune.code_format, f.commune_id]}.uniq
+ scope.includes(:commune).references(:communes).map{|f| next unless f.commune; [f.commune.code_format, f.commune_id]}.uniq
end
def village_options
- Family.joins(:village).map{|f| [f.village.code_format, f.village_id]}.uniq
+ scope.includes(:village).references(:villages).map{|f| next unless f.village; [f.village.code_format, f.village_id]}.uniq
end
def province_options
- Family.province_are
+ scope.province_are
end
def district_options
- Family.joins(:district).pluck('districts.name', 'districts.id').uniq
+ scope.includes(:district).references(:districts).pluck('districts.name', 'districts.id').uniq
end
def gender_options
@@ -343,19 +343,19 @@ def filer_section(filter_name)
column(:phone_number, header: -> { I18n.t('datagrid.columns.families.phone_number') })
column(:street, header: -> { I18n.t('datagrid.columns.families.street') })
- column(:village_id, order: 'villages.name_kh', header: -> { I18n.t('datagrid.columns.families.village') }) do |object|
+ column(:village_id, preload: proc { |f| f.includes(:village) }, order: 'villages.name_kh', header: -> { I18n.t('datagrid.columns.families.village') }) do |object|
format(object.village.try(:code_format)) { |value| value }
end
- column(:commune_id, order: 'communes.name_kh', header: -> { I18n.t('datagrid.columns.families.commune') }) do |object|
+ column(:commune_id, preload: proc { |f| f.includes(:commune) }, order: 'communes.name_kh', header: -> { I18n.t('datagrid.columns.families.commune') }) do |object|
format(object.commune.try(:name)) { |value| value }
end
- column(:district_id, order: 'districts.name', header: -> { I18n.t('datagrid.columns.families.district') }) do |object|
+ column(:district_id, preload: proc { |f| f.includes(:district) }, order: 'districts.name', header: -> { I18n.t('datagrid.columns.families.district') }) do |object|
format(object.district_name) { |value| value }
end
- column(:province_id, order: 'provinces.name', header: -> { I18n.t('datagrid.columns.families.province') }) do |object|
+ column(:province_id, preload: proc { |f| f.includes(:province) }, order: 'provinces.name', header: -> { I18n.t('datagrid.columns.families.province') }) do |object|
format(object.province_name) { |value| value }
end
@@ -450,7 +450,7 @@ def filer_section(filter_name)
dynamic do
quantitative_type_readable_ids = current_user.quantitative_type_permissions.readable.pluck(:quantitative_type_id) unless current_user.nil?
-
+
QuantitativeType.cach_free_text_fields_by_visible_on('family').each do |qqt_free_text|
if current_user.nil? || quantitative_type_readable_ids.include?(qqt_free_text.id)
column(qqt_free_text.name.to_sym, class: 'quantitative-type', header: -> { qqt_free_text.name }, html: true) do |object|
diff --git a/app/helpers/advanced_search_helper.rb b/app/helpers/advanced_search_helper.rb
index 597e560963..635a1d4df9 100644
--- a/app/helpers/advanced_search_helper.rb
+++ b/app/helpers/advanced_search_helper.rb
@@ -15,6 +15,11 @@ def program_stream_values(report_builder = '#builder')
has_program_selected ? eval(advanced_search_params[:program_selected]) : []
end
+ def assessment_values(report_builder = '#builder')
+ has_assessment_selected = has_advanced_search? && advanced_search_params[:assessment_selected].present? && (advanced_search_params[:action_report_builder].present? ? report_builder == advanced_search_params[:action_report_builder] : true)
+ has_assessment_selected ? eval(advanced_search_params[:assessment_selected]) : []
+ end
+
def quantitative_check
has_advanced_search? && advanced_search_params[:quantitative_check].present? ? true : false
end
@@ -169,13 +174,25 @@ def format_header(key, group_name = 'client')
type_of_service: I18n.t('advanced_search.fields.type_of_service'),
hotline: I18n.t('datagrid.columns.calls.hotline'),
active_clients: I18n.t('advanced_search.fields.active_clients'),
+ active_client_program: I18n.t('advanced_search.fields.active_client_program'),
care_plan: I18n.t('advanced_search.fields.care_plan'),
arrival_at: I18n.t('clients.form.arrival_at'),
flight_nb: I18n.t('clients.form.flight_nb'),
ratanak_achievement_program_staff_client_ids: I18n.t('clients.form.ratanak_achievement_program_staff_client_ids'),
mo_savy_officials: I18n.t('clients.form.mosavy_official'),
**overdue_translations,
- **address_translation(group_name)
+ **address_translation(group_name),
+ number_client_referred_gatekeeping: I18n.t('advanced_search.fields.number_client_referred_gatekeeping'),
+ number_client_billable: I18n.t('advanced_search.fields.number_client_billable'),
+ assessment_condition_last_two: I18n.t('advanced_search.fields.assessment_condition_last_two'),
+ assessment_condition_first_last: I18n.t('advanced_search.fields.assessment_condition_first_last'),
+ client_rejected: I18n.t('advanced_search.fields.client_rejected'),
+ incomplete_care_plan: I18n.t('advanced_search.fields.incomplete_care_plan'),
+ case_history: I18n.t('default_family_fields.case_history'),
+ family: I18n.t('advanced_search.fields.family'),
+ case_note: I18n.t('dashboards.case_note_tab.case_note'),
+ other: I18n.t('advanced_search.fields.other'),
+ common_searches: I18n.t('advanced_search.fields.common_searches')
}
translations = label_translations(address_translation(group_name)).merge(translations)
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index ec6fd535bf..5fd67f3efb 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -192,6 +192,8 @@ def date_format(date)
end
def date_time_format(date_time)
+ return if date_time.nil?
+
date_time.in_time_zone('Bangkok').strftime('%d %B %Y %I:%M%p')
end
@@ -326,8 +328,8 @@ def forms_notification_label
end
end
- def whodunnit(type, id)
- user_id = PaperTrail::Version.find_by(event: 'create', item_type: type, item_id: id).try(:whodunnit)
+ def whodunnit(type, id, event='create')
+ user_id = PaperTrail::Version.find_by(event: event, item_type: type, item_id: id).try(:whodunnit)
if user_id.blank? || (user_id.present? && user_id.include?('@rotati'))
object = type.constantize.find(id)
user_id = object.has_attribute?(:user_id) ? object&.user_id : object.try(:parent)&.user_id
@@ -337,7 +339,11 @@ def whodunnit(type, id)
end
end
- User.find_by(id: user_id).try(:name) || ''
+ made_changed_by(user_id)
+ end
+
+ def made_changed_by(user_id)
+ User.find_by(id: user_id).try(:name) || 'User not found'
end
def khmer_dob_to_age(date)
@@ -454,4 +460,9 @@ def request_method
(['clients', 'families'].include?(params[:controller]) && params[:action] == 'index') ? 'Post' : 'Get'
end
+ def age_in_hash(dob)
+ now = Time.now.utc
+ distance_of_time_in_words_hash(now, dob)
+ end
+
end
diff --git a/app/helpers/assessment_helper.rb b/app/helpers/assessment_helper.rb
index 1754202d71..8f17ce54d4 100644
--- a/app/helpers/assessment_helper.rb
+++ b/app/helpers/assessment_helper.rb
@@ -112,10 +112,10 @@ def assess_header_mapping(default=true)
domains = default ? Domain.csi_domains.map{ |domain| ["domain_#{domain.id}", domain.name] } : Domain.custom_csi_domains.map{ |domain| ["domain_#{domain.id}", domain.name] }
domain_ids, domain_headers = domains.map(&:first), domains.map(&:last)
- assessment_headers = [t('.client_id'), t('.client_name'), t('.assessment_number', assessment: t('clients.show.assessment')), t('.assessment_date', assessment: t('clients.show.assessment'))]
+ assessment_headers = [t('.client_id'), t('.client_name'), t('.assessment_number', assessment: t('clients.show.assessment')), t('.assessment_date', assessment: t('clients.show.assessment')), t('.average_score', assessment: t('clients.show.assessment'))]
- assessment_domain_headers = ['slug', 'name', 'assessment-number', 'date']
- classNames = ['client-id', 'client-name', 'ssessment-number text-center', 'assessment-date', 'assessment-score text-center']
+ assessment_domain_headers = ['slug', 'name', 'assessment-number', 'date', 'average-score']
+ classNames = ['client-id', 'client-name', 'assessment-number text-center', 'assessment-date', 'average-score text-center', 'assessment-score text-center']
[*assessment_domain_headers, *domain_ids].zip(classNames, [*assessment_headers, *domain_headers]).map do |field_header, class_name, header_name|
{ title: header_name, data: field_header, className: class_name ? class_name : 'assessment-score text-center' }
@@ -354,5 +354,13 @@ def check_assessment_domain_exist?(assessment)
end
end
+ def calculate_domain_selected_domain_score(assessment)
+ sum = assessment.assessment_domains.inject(0) do |sum, ad|
+ sum + (current_setting.selected_domain_ids.compact.include?(ad.domain_id) && ad.score.present? ? ad.score : 0)
+ end
+
+ return sum if sum.zero?
+ (sum.to_f / current_setting.selected_domain_ids.compact.size).round
+ end
end
diff --git a/app/helpers/cache_helper.rb b/app/helpers/cache_helper.rb
index 3930dd8d3a..73161217cb 100644
--- a/app/helpers/cache_helper.rb
+++ b/app/helpers/cache_helper.rb
@@ -14,4 +14,4 @@ def setting_cache_key
def custom_fields_cache
[Apartment::Tenant.current, 'custom_fields']
end
-end
\ No newline at end of file
+end
diff --git a/app/helpers/care_plan_helper.rb b/app/helpers/care_plan_helper.rb
index d173fc5400..5e0469c4f0 100644
--- a/app/helpers/care_plan_helper.rb
+++ b/app/helpers/care_plan_helper.rb
@@ -67,6 +67,8 @@ def grid_object
end
def list_case_conference_domain_for_care_plan(assessment, ad)
+ return [] if assessment.case_conference.blank?
+
assessment.case_conference.case_conference_domains.find_by(domain_id: ad.object.domain_id).try(:case_conference_addressed_issues) || []
end
diff --git a/app/helpers/clients_helper.rb b/app/helpers/clients_helper.rb
index 84591894a5..eb69c3c01a 100644
--- a/app/helpers/clients_helper.rb
+++ b/app/helpers/clients_helper.rb
@@ -1,4 +1,57 @@
module ClientsHelper
+ include RiskAssessmentHelper
+
+ def client_form_data
+ {
+ translation: rails_i18n_translations, inlineHelpTranslation: JSON.parse(I18n.t('inline_help').to_json),
+ internationalReferredClient: international_referred_client, selectedCountry: selected_country,
+ client:
+ {
+ client: @client, ratanak_achievement_program_staff_client_ids: @client.ratanak_achievement_program_staff_client_ids,
+ user_ids: @client.user_ids, quantitative_case_ids: @client.quantitative_case_ids, agency_ids: @client.agency_ids,
+ donor_ids: @client.donor_ids, isTestClient: current_setting.test_client?, isForTesting: @client.for_testing?
+ },
+ client_quantitative_free_text_cases: get_or_build_client_quantitative_free_text_cases,
+ family_member: (@client.family_member || {}), moSAVYOfficials: @client.mo_savy_officials,
+ referee: @referee.as_json(methods: [:existing_referree]), carer: @carer , users: case_workers_option(@client.id),
+ referralSourceCategory: @referral_source_category, referralSource: ReferralSource.all, birthProvinces: @birth_provinces,
+ currentProvinces: @current_provinces || get_address('province'), districts: @districts.presence || get_address('district'),
+ subDistricts: @subdistricts, communes: @communes.presence || get_address('commune'), villages: @villages.presence || get_address('village'),
+ currentStates: @states, currentTownships: @townships, refereeTownships: @referee_townships, carerTownships: @carer_townships,
+ refereeDistricts: @referee_districts, refereeSubdistricts: @referee_subdistricts, refereeCommunes: @referee_communes,
+ refereeVillages: @referee_villages, carerDistricts: @carer_districts, carerSubdistricts: @carer_subdistricts, carerCommunes: @carer_communes,
+ carerVillages: @carer_villages, donors: @donors, agencies: @agencies,
+ quantitativeType: QuantitativeType.cach_by_visible_on('client'), quantitativeCase: QuantitativeCase.cache_all,
+ ratePoor: [
+ t('clients.level').values, Client::CLIENT_LEVELS
+ ].transpose,
+ schoolGrade: [
+ Client::GRADES, t('advanced_search.fields.school_grade_list').values
+ ].transpose,
+ families: @families, refereeRelationships: @referee_relationships,
+ clientRelationships: @client_relationships, callerRelationships: @caller_relationships,
+ addressTypes: @address_types, phoneOwners: @phone_owners, fieldsVisibility: fields_visibility,
+ requiredFields: required_legal_docs, current_organization: JSON.parse(current_organization.to_json),
+ brc_address: get_address_json, maritalStatuses: Client::MARITAL_STATUSES, nationalities: Client::NATIONALITIES,
+ ethnicities: Client::ETHNICITY, traffickingTypes: Client::TRAFFICKING_TYPES, brc_islands: Client::BRC_BRANCHES,
+ brc_resident_types: Client::BRC_RESIDENT_TYPES, brc_presented_ids: Client::BRC_PRESENTED_IDS,
+ brc_prefered_langs: Client::BRC_PREFERED_LANGS, customId1: custom_id_translation('custom_id1'),
+ customId2: custom_id_translation('custom_id2'), referees: Referee.where(anonymous: false),
+ protectionConcerns: I18n.locale == :km ? protection_concern_list_local : protection_concern_list,
+ historyOfHarms: history_of_harms, historyOfHighRiskBehaviours: history_of_high_risk_behaviours,
+ reasonForFamilySeparations: reason_for_family_separations, historyOfDisabilities: history_of_disabilities,
+ isRiskAssessmentEnabled: current_setting.enabled_risk_assessment,
+ riskAssessment: {
+ **@risk_assessment.try(:attributes).try(:symbolize_keys) || {},
+ labels: {
+ **I18n.t('risk_assessments._attr'),
+ **I18n.t('tasks')
+ },
+ tasks_attributes: @risk_assessment.try(:tasks) || []
+ }
+ }
+ end
+
def get_or_build_client_quantitative_free_text_cases
QuantitativeType.where(field_type: 'free_text').map do |qtt|
@client.client_quantitative_free_text_cases.find_or_initialize_by(quantitative_type_id: qtt.id)
@@ -1419,4 +1472,19 @@ def saved_search_column_visibility(field_key)
def legal_doc_fields
FieldSetting.cache_legal_doc_fields
end
+
+ def if_date_of_birth_blank(client)
+ return '#screening-tool-warning' if client.date_of_birth.blank?
+ screening_assessment = @client.screening_assessments.first
+ if screening_assessment && screening_assessment.screening_type == 'one_off'
+ client_screening_assessment_path(client, screening_assessment)
+ else
+ new_client_screening_assessment_path(client, screening_type: 'one_off')
+ end
+ end
+
+ def has_of_warning_model_if_dob_blank(client)
+ return { "data-target": "#screening-tool-warning", "data-toggle": "modal" } if client.date_of_birth.blank?
+ {}
+ end
end
diff --git a/app/helpers/domain_helper.rb b/app/helpers/domain_helper.rb
index 0c06527677..963e287639 100644
--- a/app/helpers/domain_helper.rb
+++ b/app/helpers/domain_helper.rb
@@ -1,9 +1,17 @@
module DomainHelper
def translate_domain_header(domain)
if I18n.locale == :km
- domain.local_description[/.*<\/strong>/].html_safe
+ domain.local_description[/.*<\/strong>/].try(:html_safe) || "#{t('domains.domain_list.domains')} : #{domain.name} (#{domain.identity})"
else
- "#{t('.domains')} : #{domain.name} (#{domain.identity})"
+ "#{t('domains.domain_list.domains')} : #{domain.name} (#{domain.identity})"
end
end
+
+ def mapping_domain_name_and_identity(domains)
+ domains.map{ |domain| [translate_domain_header(domain), domain.id] }
+ end
+
+ def custom_domain_groups
+ Domain.custom_csi_domains.group_by { |domain| domain.custom_assessment_setting_id }
+ end
end
diff --git a/app/helpers/risk_assessment_helper.rb b/app/helpers/risk_assessment_helper.rb
new file mode 100644
index 0000000000..48b181e986
--- /dev/null
+++ b/app/helpers/risk_assessment_helper.rb
@@ -0,0 +1,195 @@
+module RiskAssessmentHelper
+ def at_risk_en
+ [
+ 'At risk of neglect',
+ 'At risk of sexual exploitation',
+ 'At risk of online sexual exploitation',
+ 'At risk of substance abuse',
+ 'At risk of child kidnapping',
+ 'At risk of trafficking',
+ 'At risk of physical violence',
+ 'At risk of emotional violence',
+ 'At risk of sexual violence',
+ 'At risk of forced/child marriage',
+ 'At risk of child labour',
+ 'At risk of worst forms of child labour'
+ ]
+ end
+
+ def at_risk_km
+ [
+ 'ប្រឈមនឹងការមិនអើពើ',
+ 'ប្រឈមនឹងការកេងប្រវ័ញ្ចផ្លូវភេទ',
+ 'ប្រឈមនឹងការកេងប្រវ័ញ្ចផ្លូវភេទតាមប្រព័ន្ធអ៊ីនធរនេត',
+ 'ប្រឈមនឹងការញៀន',
+ 'ប្រឈមនឹងការចាប់ពង្រត់កុមារ',
+ 'ប្រឈមនឹងការជួញដូរ',
+ 'ប្រឈមនឹងអំពើហឹង្សាផ្លូវកាយ',
+ 'ប្រឈមនឹងអំពើហឹង្សាផ្លូវចិត្ត',
+ 'ប្រឈមអំពើហឹង្សាផ្លូវភេទ',
+ 'ប្រឈមនឹងការរៀបអាពាហ៍ពិពាហ៍កុមារ/បង្ខំ',
+ 'ប្រឈមនឹងពលកម្មកុមារ',
+ 'ប្រឈមនឹងទម្រង់ធ្ងន់ធ្ងរបំផុតនៃពលកម្មកុមារ'
+ ]
+ end
+
+ def experiencing_en
+ [
+ 'Experiencing neglect',
+ 'Experiencing sexual exploitation',
+ 'Experiencing online sexual exploitation',
+ 'Experiencing substance abuse',
+ 'Experiencing child kidnapping',
+ 'Experienced trafficking',
+ 'Experiencing physical violence',
+ 'Experiencing emotional violence',
+ 'Experienced sexual violence',
+ 'Experienced forced/child marriage',
+ 'Experiencing child labour',
+ 'Experiencing worst forms of child labour'
+ ]
+ end
+
+ def experiencing_km
+ [
+ 'ទទួលរងការមិនអើពើ',
+ 'ទទួលរងការកេងប្រវ័ញ្ចផ្លូវភេទ',
+ 'ទទួលរងការកេងប្រវ័ញ្ចផ្លូវភេទតាមប្រព័ន្ធអ៊ីនធរនេត',
+ 'ទទួលរងការញៀន',
+ 'ទទួលរងការចាប់ពង្រត់កុមារ',
+ 'ទទួលរងការជួញដូរ',
+ 'ទទួលរងអំពើហឹង្សាផ្លូវកាយ',
+ 'ទទួលរងអំពើហឹង្សាផ្លូវចិត្ត',
+ 'ទទួលរងអំពើហឹង្សាផ្លូវភេទ',
+ 'ទទួលរងការរៀបអាពាហ៍ពិពាហ៍កុមារ/បង្ខំ',
+ 'ទទួលរងពលកម្មកុមារ',
+ 'ទទួលរងទម្រង់ធ្ងន់ធ្ងរបំផុតនៃពលកម្មកុមារ'
+ ]
+ end
+
+ def other_form_en
+ [
+ 'Abandonment',
+ 'Separated',
+ 'Orphaned',
+ 'Unaccompanied',
+ 'In conflict with law',
+ 'Minority / Isolated community',
+ 'Delinquent behaviour',
+ 'Stigmatization',
+ 'Working or living on street',
+ 'Witness of violence',
+ 'Gambling issues',
+ 'Affected by migration',
+ 'Infected by COVID-19',
+ 'Affected by COVID-19',
+ 'Other'
+ ]
+ end
+
+ def other_form_km
+ [
+ 'ត្រូវបានបោះបង់ចោល',
+ 'បានបែកចេញ',
+ 'កំព្រា',
+ 'គ្មានមនុស្សពេញវ័យនៅជាមួយ',
+ 'មានទំនាស់នឹងច្បាប់',
+ 'ជនជាតិភាគតិច/សហគមន៍ឯកោ',
+ 'ឥរិយាបថទំនើង (ប្រព្រឹត្តខុសច្បាប់)',
+ 'រងការរើសអើង',
+ 'ធ្វើការ ឬរស់នៅតាមចិញ្ជើមផ្លូវ',
+ 'សាក្សីនៃអំពើហឹង្សា',
+ 'បញ្ហាល្បែងស៊ីសង',
+ 'ប៉ះពាល់ដោយចំណាកស្រុក',
+ 'ឆ្លងជង្ងឺកូវីដ-19',
+ 'ទទួលរងផលប៉ះពាល់ពីជម្ងឺកូវីដ-១៩',
+ 'បញ្ហាផ្សេងៗ'
+ ]
+ end
+
+ def protection_concern_list
+ [
+ {
+ label: 'At risk',
+ options: at_risk_en.zip(at_risk_en).map{ |k, v| { label: k, value: v } }
+ },
+ {
+ label: 'Experiencing/Experienced',
+ options: experiencing_en.zip(experiencing_en).map{ |k, v| { label: k, value: v } }
+ },
+ {
+ label: 'Other Form',
+ options: other_form_en.zip(other_form_en).map{ |k, v| { label: k, value: v } }
+ }
+ ]
+ end
+
+ def protection_concern_list_local
+ [
+ {
+ label: 'ការប្រឈម',
+ options: at_risk_km.zip(at_risk_en).map{ |k, v| { label: k, value: v } }
+ },
+ {
+ label: 'ទទួលរង/ធ្លាប់ឆ្លងកាត់',
+ options: experiencing_km.zip(experiencing_en).map{ |k, v| { label: k, value: v } }
+ },
+ {
+ label: 'ទម្រង់ផ្សេងៗ',
+ options: other_form_km.zip(other_form_en).map{ |k, v| { label: k, value: v } }
+ }
+ ]
+ end
+
+ def select_quantitative_type(value)
+ quantitative_types = QuantitativeType.cach_by_visible_on('client')
+ quantitative_type = quantitative_types.select{|qt| qt.name =~ /#{value}/ }.first
+ return [] if quantitative_type.blank?
+
+ quantitative_cases = select_quantitative_cases(quantitative_type.id)
+ quantitative_cases.map { |quantitative_case| [quantitative_case.value, quantitative_case.id] }
+ .map { |value, id| { label: split_quantitative_case_value(value), value: id } }
+ end
+
+ def split_quantitative_case_value(quantitative_case_value)
+ values = quantitative_case_value.split(' / ')
+ I18n.locale == :km ? values.first : values.last
+ end
+
+ def select_quantitative_cases(quantitative_type_id)
+ QuantitativeCase.cache_all.select{ |qc| qc.quantitative_type_id == quantitative_type_id }
+ end
+
+ def history_of_harms
+ select_quantitative_type('History of Harm')
+ end
+
+ def history_of_high_risk_behaviours
+ select_quantitative_type('History of high-risk behaviours')
+ end
+
+ def reason_for_family_separations
+ select_quantitative_type('Reason for Family Separation')
+ end
+
+ def history_of_disabilities
+ select_quantitative_type('History of disability')
+ end
+
+ def display_level_of_risk(level_of_risk)
+ return '' unless level_of_risk
+ color_hash = {'high' => 'danger', 'medium' => 'warning', 'low' => 'primary', 'no action' => 'success', 'pending_assessment' => 'default' }
+ content_tag(:a, class: "btn btn-#{color_hash[level_of_risk]}") do
+ level_of_risk.titleize
+ end
+ end
+
+ def level_of_risk_options
+ [
+ I18n.t('risk_assessments._attr.level_of_risks.high'),
+ I18n.t('risk_assessments._attr.level_of_risks.medium'),
+ I18n.t('risk_assessments._attr.level_of_risks.low'),
+ I18n.t('risk_assessments._attr.level_of_risks.no_action')
+ ].zip(['high', 'medium', 'low', 'no action'])
+ end
+end
diff --git a/app/helpers/screening_assessment_helper.rb b/app/helpers/screening_assessment_helper.rb
new file mode 100644
index 0000000000..37d9fc01bf
--- /dev/null
+++ b/app/helpers/screening_assessment_helper.rb
@@ -0,0 +1,19 @@
+module ScreeningAssessmentHelper
+ def field_to_local(object, field_name)
+ if I18n.locale == :km
+ object.public_send("#{field_name}_local")
+ else
+ object.public_send(field_name)
+ end
+ end
+
+ def date_of_birth_in_words(date_of_birth, locale = :en)
+ if date_of_birth.present?
+ age_hash = age_in_hash(date_of_birth)
+ age_in_words = time_ago_in_words(date_of_birth, include_seconds: false, locale: locale)
+ age_in_words.gsub(/,\s\d+\s(hour(s)?.*|ម៉ោង.*)/, '')
+ else
+ "No Date of Birth"
+ end
+ end
+end
diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb
index ffbedbaf46..efd6e0216a 100644
--- a/app/helpers/settings_helper.rb
+++ b/app/helpers/settings_helper.rb
@@ -1,2 +1,9 @@
module SettingsHelper
+ def collect_assessment_types
+ assessment_types = current_setting.enable_default_assessment ? [[I18n.t('risk_assessments._attr.client_status_index'), 'csi']] : []
+ CustomAssessmentSetting.only_enable_custom_assessment.pluck(:custom_assessment_name, :id).each do |arr|
+ assessment_types << arr
+ end
+ assessment_types
+ end
end
diff --git a/app/javascript/components/Commons/inputs/dateTimePicker.js b/app/javascript/components/Commons/inputs/dateTimePicker.js
index b0bfbe2153..f2e2a4ac7a 100644
--- a/app/javascript/components/Commons/inputs/dateTimePicker.js
+++ b/app/javascript/components/Commons/inputs/dateTimePicker.js
@@ -24,6 +24,8 @@ export default ({isError, required, label, onChange, value, T }) => {
{label}
{
{ existingFiles.length > 0 && showFilePond &&
- { renderExistingFiles(existingFiles) }
+ {/* { renderExistingFiles(existingFiles) } */}
{
{
const { onChange, options, inline, value, isError, required, disabled } = props
-
+ const [values, setValue] = useState(value)
const handleOnChange = event => {
+ setValue(event.value)
onChange({ data: event.value, type: 'radio' })
}
@@ -24,7 +25,7 @@ export default props => {
disabled={disabled}
required
value={option.value}
- checked={option.value === value}
+ checked={option.value === values}
onChange={handleOnChange}
/>
{option.label}
@@ -64,4 +65,4 @@ const customError = {
errorText: {
color: 'red'
}
-}
\ No newline at end of file
+}
diff --git a/app/javascript/components/Commons/inputs/select.js b/app/javascript/components/Commons/inputs/select.js
index cc8ef28744..bdf084fdb4 100644
--- a/app/javascript/components/Commons/inputs/select.js
+++ b/app/javascript/components/Commons/inputs/select.js
@@ -1,8 +1,9 @@
-import React from 'react'
+import React, { useEffect, useState } from 'react';
import Select from 'react-select'
export default props => {
- const { value, options, isMulti, isError, label, required, onChange, asGroup, T, hintText, inlineClassName, ...others } = props
+ const { value, options, isMulti, isError, label, required, onChange, asGroup, T, hintText, inlineClassName, inline, ...others } = props
+ const [selectedOption, setSelectedOption] = useState(null);
const getSeletedObject = () => {
if(options) {
@@ -21,6 +22,10 @@ export default props => {
}
}
+ useEffect(() => {
+ setSelectedOption(getSeletedObject())
+ }, []);
+
const handleChange = (selectedOption, { action, removedValue }) => {
let data
let removed = removedValue && removedValue.value
@@ -41,6 +46,7 @@ export default props => {
data = action === 'clear' ? null : selectedOption.value
}
+ setSelectedOption(selectedOption)
onChange({ data, removed, action, type: 'select', options: options, isMulti: isMulti })
}
@@ -51,50 +57,55 @@ export default props => {
)
return (
-
-
- {
- inlineClassName &&
- hintText &&
-
-
-
- }
-