<commit_before>
$("#flashTeamPauseBtn").click(function(){

 	var bodyText = document.getElementById("confirmActionText");
    //updateStatus();
    bodyText.innerHTML = "Are you sure you want to edit the team?";

    var confirmStartTeamBtn = document.getElementById("confirmButton");
    confirmStartTeamBtn.innerHTML = "Edit";

    $("#confirmButton").attr("class","btn btn-success");
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Edit Team?";
    $('#confirmAction').modal('show');

    document.getElementById("confirmButton").onclick=function(){pauseFlashTeam()};

});

function pauseFlashTeam(){
	$('#confirmAction').modal('hide');

	$("#flashTeamPauseBtn").css('display', 'none');
    $("#flashTeamResumeBtn").css('display', '');

	flashTeamsJSON["paused"]=true;

    logActivity("pauseFlashTeam() - Before Update Status",'Edit Team - Before Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
	updateStatus();

    //draw events in editable mode (show collaboration and handoff buttons, show drag handles etc.)
    enableTeamEditing();
    //drawEvents(true);
    logActivity("pauseFlashTeam() - After Update Status",'Edit Team - After Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

}

$("#flashTeamResumeBtn").click(function(){

 	var bodyText = document.getElementById("confirmActionText");
    //updateStatus();
    bodyText.innerHTML = "Are you sure you want to save the changes?";

    var confirmStartTeamBtn = document.getElementById("confirmButton");
    confirmStartTeamBtn.innerHTML = "Save";

    $("#confirmButton").attr("class","btn btn-success");
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Save Team?";
    $('#confirmAction').modal('show');

    document.getElementById("confirmButton").onclick=function(){resumeFlashTeam()};

});

function resumeFlashTeam(){
	$('#confirmAction').modal('hide');

	$("#flashTeamPauseBtn").css('display', '');
    $("#flashTeamResumeBtn").css('display', 'none');

	flashTeamsJSON["paused"]=false;

    logActivity("resumeFlashTeam() - Before Update Status",'Save Edited Team - Before Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
	updateStatus();

    //Hide handoff and collaboration buttons on the events.
    //drawEvents(false);
    disableTeamEditing();

    logActivity("resumeFlashTeam() - After Update Status",'Save Edited Team - After Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
}

$("#workerEditTeamBtn").click(function(){
    logActivity("$('#workerEditTeamBtn').click(function()",'Clicked Request Change to Team Button', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('-- SELECT REQUEST TYPE --');
});

$("#request-change-task-not-ready").click(function(){
    logActivity("$('#request-change-task-not-ready').click(function()","Clicked 'Task is Not Ready to Start' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Task Not Ready');
});

$("#request-change-edit-task").click(function(){
    logActivity("$('#request-change-edit-task').click(function()","Clicked 'I want to edit the task' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Edit a Task');
});

$("#request-change-more-time").click(function(){
    logActivity("$('#request-change-more-time').click(function()","Clicked 'I need more time' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Need More Time');
});

$("#requestEditSubmitBtn").click(function(){

    var selected = $('#request-edit-dropdown').val();

    var form_content = 'Type of Change: ' + selected;
    form_content += '
 Name of Requester: ' + chat_name;
    form_content += '
 Role of Requester: ' + chat_role;
    form_content += '

';

    if (selected == 'Add a Task'){

        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Duration: ' + $("#event-request-hours").val() + ' Hours  '
                + $("#event-request-minutes").val() + ' Minutes
'
                + 'Description: ' + $("#event-request-description").val();
    }else if (selected == 'Edit a Task'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of changes to task: ' + $("#event-request-description").val();
    }else if (selected == 'Task Not Ready'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of why task is not ready and the requested changes: ' + $("#event-request-description").val();
    }else if (selected == 'Need More Time'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of how much more time you need and why: ' + $("#event-request-description").val();
    }
    else{
        form_content += 'Description of changes you would like to make to the team: ' + $('#request-edit-form-text').val();
    }

    var edit_request_text = form_content;

    logActivity("$('#requestEditSubmitBtn').click(function()",'Clicked Submit Button to Submit Request to Change Team - Type of Change: ' + selected, new Date().getTime(), current_user, chat_name, team_id, form_content);

    var url = '/flash_teams/' + flash_team_id + '/send_edit_team_request';

    var request = $.ajax({
        url: url,
        type: "post",
        data: {editRequestText : edit_request_text }
        }); //end var request

        request.done(function( data ) {
            $("#request-edit-help-block").css('display','none');
            $("#request-edit-dropdown").css('display','none');
            $('#request-edit-form-content').html('Your request was sent to the project owner for review.

' + edit_request_text );
            $("#requestEditSubmitBtn").css('display', 'none');
            $("#request-edit-modal-cancel").html("Close");
        }); //end ajax call
});

$('#request-edit-dropdown').change(function(){

    var selected = $('#request-edit-dropdown').val();

    updateRequestChangeModal(selected);

    logActivity("$('#request-edit-dropdown').click(function()",'Selected the following type of change to request from dropdown: ' + selected, new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

});

$(".request-edit-modal-cancel").click(function(){
    logActivity("$('#request-edit-modal-cancel').click(function()",'Closed the Request Change Modal', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
});

function updateRequestChangeModal(selected){

    var content;
    var disabled;

    $('#request-edit-dropdown').val(selected);

    if (selected == '-- SELECT REQUEST TYPE --'){
        content = '
Please select which type of change you would like to make.
';
        disabled = true;
    }else if (selected == 'Add a Task'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Task Name">
'
                + 'Duration: <input type="number" class="request-change-input" id="event-request-hours" value="" min="0" placeholder="00" style="margin-left: 10px; width:36px;"/> Hours'
                + '<input type = "number" class="request-change-input" id="event-request-minutes" value="" placeholder="00" style=" margin-left: 15px; width:36px" min="0" step="15" max="45"/> Minutes
'
                + 'Description:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Description of task" id="event-request-description"></textarea>';
        disabled = false;
    }else if (selected == 'Task Not Ready'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Task to Change">
'
                + 'Description of why task is not ready and the requested changes:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe why the task is not ready to be started and what changes need to be made to the task or workflow" id="event-request-description"></textarea>';

        disabled = false;
    }else if (selected == 'Need More Time'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Task to Change">
'
                + 'Description of how much more time you need and why:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe how much more time you need to complete the task and why" id="event-request-description"></textarea>';
        disabled = false;
    }
    else if (selected == 'Edit an Event'){
        content = 'Event Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Event to Change">
'
                + 'Description of changes to task:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe what changes you would like to make to the task" id="event-request-description"></textarea>';
        disabled = false;
    }
    else{
        content = '
Description of changes you would like to make to the team:
'
                +  '<textarea class="request-change-input input-block-level" rows="5" id="request-edit-form-text" value="" placeholder="Describe what changes you would like to make to the team"></textarea>';
        disabled = false;
    }

    $("#requestEditSubmitBtn").prop("disabled", disabled);
    $('#request-edit-form-content').html(content);

    $("#request-edit-help-block").css('display','');
    $("#request-edit-dropdown").css('display','');
    $("#requestEditSubmitBtn").css('display', '');
    $("#request-edit-modal-cancel").html("Cancel");
    $('#workerRequestEdit').modal('show');
}

<commit_msg>minor text changes<commit_after>
$("#flashTeamPauseBtn").click(function(){

 	var bodyText = document.getElementById("confirmActionText");
    //updateStatus();
    bodyText.innerHTML = "Are you sure you want to edit the team?";

    var confirmStartTeamBtn = document.getElementById("confirmButton");
    confirmStartTeamBtn.innerHTML = "Edit";

    $("#confirmButton").attr("class","btn btn-success");
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Edit Team?";
    $('#confirmAction').modal('show');

    document.getElementById("confirmButton").onclick=function(){pauseFlashTeam()};

});

function pauseFlashTeam(){
	$('#confirmAction').modal('hide');

	$("#flashTeamPauseBtn").css('display', 'none');
    $("#flashTeamResumeBtn").css('display', '');

	flashTeamsJSON["paused"]=true;

    logActivity("pauseFlashTeam() - Before Update Status",'Edit Team - Before Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
	updateStatus();

    //draw events in editable mode (show collaboration and handoff buttons, show drag handles etc.)
    enableTeamEditing();
    //drawEvents(true);
    logActivity("pauseFlashTeam() - After Update Status",'Edit Team - After Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

}

$("#flashTeamResumeBtn").click(function(){

 	var bodyText = document.getElementById("confirmActionText");
    //updateStatus();
    bodyText.innerHTML = "Are you sure you want to save the changes?";

    var confirmStartTeamBtn = document.getElementById("confirmButton");
    confirmStartTeamBtn.innerHTML = "Save";

    $("#confirmButton").attr("class","btn btn-success");
    var label = document.getElementById("confirmActionLabel");
    label.innerHTML = "Save Team?";
    $('#confirmAction').modal('show');

    document.getElementById("confirmButton").onclick=function(){resumeFlashTeam()};

});

function resumeFlashTeam(){
	$('#confirmAction').modal('hide');

	$("#flashTeamPauseBtn").css('display', '');
    $("#flashTeamResumeBtn").css('display', 'none');

	flashTeamsJSON["paused"]=false;

    logActivity("resumeFlashTeam() - Before Update Status",'Save Edited Team - Before Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
	updateStatus();

    //Hide handoff and collaboration buttons on the events.
    //drawEvents(false);
    disableTeamEditing();

    logActivity("resumeFlashTeam() - After Update Status",'Save Edited Team - After Update Status', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
}

$("#workerEditTeamBtn").click(function(){
    logActivity("$('#workerEditTeamBtn').click(function()",'Clicked Request Change to Team Button', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('-- SELECT REQUEST TYPE --');
});

$("#request-change-task-not-ready").click(function(){
    logActivity("$('#request-change-task-not-ready').click(function()","Clicked 'Task is Not Ready to Start' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Task Not Ready');
});

$("#request-change-edit-task").click(function(){
    logActivity("$('#request-change-edit-task').click(function()","Clicked 'I want to edit the task' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Edit a Task');
});

$("#request-change-more-time").click(function(){
    logActivity("$('#request-change-more-time').click(function()","Clicked 'I need more time' link in sidebar", new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

    updateRequestChangeModal('Need More Time');
});

$("#requestEditSubmitBtn").click(function(){

    var selected = $('#request-edit-dropdown').val();

    var form_content = 'Type of Change: ' + selected;
    form_content += '
 Name of Requester: ' + chat_name;
    form_content += '
 Role of Requester: ' + chat_role;
    form_content += '

';

    if (selected == 'Add a Task'){

        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Duration: ' + $("#event-request-hours").val() + ' Hours  '
                + $("#event-request-minutes").val() + ' Minutes
'
                + 'Description: ' + $("#event-request-description").val();
    }else if (selected == 'Edit a Task'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of changes to task: ' + $("#event-request-description").val();
    }else if (selected == 'Task Not Ready'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of why task is not ready and the requested changes: ' + $("#event-request-description").val();
    }else if (selected == 'Need More Time'){
        form_content += 'Task Name: ' + $("#event-request-name").val()
                + '
'
                + 'Description of how much more time you need and why: ' + $("#event-request-description").val();
    }
    else{
        form_content += 'Description of changes you would like to make to the team: ' + $('#request-edit-form-text').val();
    }

    var edit_request_text = form_content;

    logActivity("$('#requestEditSubmitBtn').click(function()",'Clicked Submit Button to Submit Request to Change Team - Type of Change: ' + selected, new Date().getTime(), current_user, chat_name, team_id, form_content);

    var url = '/flash_teams/' + flash_team_id + '/send_edit_team_request';

    var request = $.ajax({
        url: url,
        type: "post",
        data: {editRequestText : edit_request_text }
        }); //end var request

        request.done(function( data ) {
            $("#request-edit-help-block").css('display','none');
            $("#request-edit-dropdown").css('display','none');
            $('#request-edit-form-content').html('Your request was sent to the project owner for review.

' + edit_request_text );
            $("#requestEditSubmitBtn").css('display', 'none');
            $("#request-edit-modal-cancel").html("Close");
        }); //end ajax call
});

$('#request-edit-dropdown').change(function(){

    var selected = $('#request-edit-dropdown').val();

    updateRequestChangeModal(selected);

    logActivity("$('#request-edit-dropdown').click(function()",'Selected the following type of change to request from dropdown: ' + selected, new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);

});

$(".request-edit-modal-cancel").click(function(){
    logActivity("$('#request-edit-modal-cancel').click(function()",'Closed the Request Change Modal', new Date().getTime(), current_user, chat_name, team_id, flashTeamsJSON);
});

function updateRequestChangeModal(selected){

    var content;
    var disabled;

    $('#request-edit-dropdown').val(selected);

    if (selected == '-- SELECT REQUEST TYPE --'){
        content = '
Please select which type of change you would like to make.
';
        disabled = true;
    }else if (selected == 'Add a Task'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Task Name">
'
                + 'Duration: <input type="number" class="request-change-input" id="event-request-hours" value="" min="0" placeholder="00" style="margin-left: 10px; width:36px;"/> Hours'
                + '<input type = "number" class="request-change-input" id="event-request-minutes" value="" placeholder="00" style=" margin-left: 15px; width:36px" min="0" step="15" max="45"/> Minutes
'
                + 'Description:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Description of task" id="event-request-description"></textarea>';
        disabled = false;
    }else if (selected == 'Task Not Ready'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Task to Change">
'
                + 'Description of why task is not ready and the requested changes:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe why the task is not ready to be started and what changes need to be made to the task or workflow" id="event-request-description"></textarea>';

        disabled = false;
    }else if (selected == 'Need More Time'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Task to Change">
'
                + 'Description of how much more time you need and why:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe how much more time you need to complete the task and why" id="event-request-description"></textarea>';
        disabled = false;
    }
    else if (selected == 'Edit a Task'){
        content = 'Task Name: <input type="text" class="request-change-input input-xlarge" id="event-request-name" value="" placeholder="Name of Task to Change">
'
                + 'Description of changes to task:
 <textarea class="request-change-input input-block-level" rows="5" value="" placeholder="Describe what changes you would like to make to the task" id="event-request-description"></textarea>';
        disabled = false;
    }
    else{
        content = '
Description of changes you would like to make to the team:
'
                +  '<textarea class="request-change-input input-block-level" rows="5" id="request-edit-form-text" value="" placeholder="Describe what changes you would like to make to the team"></textarea>';
        disabled = false;
    }

    $("#requestEditSubmitBtn").prop("disabled", disabled);
    $('#request-edit-form-content').html(content);

    $("#request-edit-help-block").css('display','');
    $("#request-edit-dropdown").css('display','');
    $("#requestEditSubmitBtn").css('display', '');
    $("#request-edit-modal-cancel").html("Cancel");
    $('#workerRequestEdit').modal('show');
}

<|endoftext|>


<commit_before>import * as Filters from './Filters';

export const SOMERVILLE = 'somerville';
export const NEW_BEDFORD = 'new_bedford';
export const BEDFORD = 'bedford';
export const DEMO = 'demo';

export function hasStudentPhotos(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === NEW_BEDFORD) return false;
  return false;
}

// See also specialEducation.js
const ORDERED_DISABILITY_VALUES_MAP = {
  [NEW_BEDFORD]: [
    "Does Not Apply",
    "Low-Less Than 2hrs/week",
    "Low-2+ hrs/week",
    "Moderate",
    "High"
  ],
  [SOMERVILLE]: [
    // also include null
    'Low < 2',
    'Low >= 2',
    'Moderate',
    'High'
  ]
};

export function orderedDisabilityValues(districtKey) {
  return ORDERED_DISABILITY_VALUES_MAP[districtKey] || [];
}

// Includes if they "exited" the 504
export function hasInfoAbout504Plan(maybeStudent504Field) {
  if (maybeStudent504Field === undefined) return false;
  if (maybeStudent504Field === null) return false;
  if (maybeStudent504Field === '') return false;
  if (maybeStudent504Field === '504') return true; // Somerville
  if (maybeStudent504Field === 'Not 504') return false; // Somerville
  if (maybeStudent504Field === 'NotIn504') return false; // Somerville & New Bedford
  if (maybeStudent504Field === 'Exited') return true; // New Bedford
  if (maybeStudent504Field === 'Active') return true; // New Bedford

  return true;
}

// Renders a table for `SlicePanels` that works differently for different
// districts.
export function renderSlicePanelsDisabilityTable(districtKey, options = {}) {
  const {createItemFn, renderTableFn} = options;

  const key = 'sped_level_of_need';
  const itemsFromValues = orderedDisabilityValues(districtKey).map(value => {
    return createItemFn(value, Filters.Equal(key, value));
  });

  // Somerville uses a null value for no disability, while New Bedford
  // uses a separate value to describe that explicitly.
  const items = (districtKey === SOMERVILLE)
    ? [createItemFn('None', Filters.Null(key))].concat(itemsFromValues)
    : itemsFromValues;
  return renderTableFn({items, title: 'Disability'});
}

// Check educator labels to see if the educator should be shown
// info about students in their courses with low grades.
export function shouldShowLowGradesBox(educatorLabels) {
  return (educatorLabels.indexOf('should_show_low_grades_box') !== -1);
}

const ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE = {
  'pic': 10,
  'cap': 100,
  'brn': 200,
  'hea': 300,
  'kdy': 300,
  'afas': 300,
  'escs': 300,
  'wsns': 300,
  'whcs': 300,
  'nw': 400,
  'shs': 500,
  'fc': 500,
  'sped': 600
};

export function sortSchoolSlugsByGrade(districtKey, slugA, slugB) {
  if (districtKey === SOMERVILLE) {
    return ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE[slugA] - ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE[slugB];
  }

  return slugA.localeCompare(slugB);
}

export function supportsHouse(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === BEDFORD) return true;
  if (districtKey === DEMO) return true;
  return false;
}

// This only applies to Somerville HS.
export function shouldDisplayHouse(school) {
  return (school && school.local_id === 'SHS');
}

export function somervilleHouses() {
  return [
    'Beacon',
    'Broadway',
    'Elm',
    'Highland'
  ];
}

export function supportsCounselor(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === DEMO) return true;
  return false;
}

// This only applies to high schools.
export function shouldDisplayCounselor(school) {
  return (school && school.school_type === 'HS');
}

export function supportsSpedLiaison(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === DEMO) return true;
  return false;
}

export function supportsExcusedAbsences(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === BEDFORD) return true;
  if (districtKey === NEW_BEDFORD) return true;
  if (districtKey === DEMO) return true;
  return false;
}

// What is the eventNoteTypeId to use in user-facing text about how to support
// students with high absences?
export function eventNoteTypeIdForAbsenceSupportMeeting(districtKey) {
  if (districtKey === NEW_BEDFORD) return 400; // bbst
  if (districtKey === SOMERVILLE) return 300; // sst

  return 300;
}

// What choices do educators have for taking notes in the product?
export function takeNotesChoices(districtKey) {
  if (districtKey === SOMERVILLE || districtKey === DEMO) {
    return {
      leftEventNoteTypeIds: [300, 301, 302, 304],
      rightEventNoteTypeIds: [305, 306, 307]
    };
  }

  if (districtKey === NEW_BEDFORD) {
    return {
      leftEventNoteTypeIds: [400, 302, 304],
      rightEventNoteTypeIds: []
    };
  }

  throw new Error(`unsupported districtKey: ${districtKey}`);
}

// In tables of students, what eventNoteTypeIds should be shown as columns with notes
// about those students?
export function studentTableEventNoteTypeIds(districtKey, schoolType) {
  if (districtKey === NEW_BEDFORD) return [400];

  const isSomervilleOrDemo = (districtKey === SOMERVILLE || districtKey === DEMO);
  if (isSomervilleOrDemo && schoolType === 'HS') return [300, 305, 306, 307];
  // Includes elementary/middle, Capuano early childhood, and SPED.
  if (isSomervilleOrDemo) return [300, 301];

  throw new Error(`unsupported districtKey: ${districtKey}`);
}

<commit_msg>Fix bug in PerDistrict about showing excused absences on absences page<commit_after>import * as Filters from './Filters';

export const SOMERVILLE = 'somerville';
export const NEW_BEDFORD = 'new_bedford';
export const BEDFORD = 'bedford';
export const DEMO = 'demo';

export function hasStudentPhotos(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === NEW_BEDFORD) return false;
  return false;
}

// See also specialEducation.js
const ORDERED_DISABILITY_VALUES_MAP = {
  [NEW_BEDFORD]: [
    "Does Not Apply",
    "Low-Less Than 2hrs/week",
    "Low-2+ hrs/week",
    "Moderate",
    "High"
  ],
  [SOMERVILLE]: [
    // also include null
    'Low < 2',
    'Low >= 2',
    'Moderate',
    'High'
  ]
};

export function orderedDisabilityValues(districtKey) {
  return ORDERED_DISABILITY_VALUES_MAP[districtKey] || [];
}

// Includes if they "exited" the 504
export function hasInfoAbout504Plan(maybeStudent504Field) {
  if (maybeStudent504Field === undefined) return false;
  if (maybeStudent504Field === null) return false;
  if (maybeStudent504Field === '') return false;
  if (maybeStudent504Field === '504') return true; // Somerville
  if (maybeStudent504Field === 'Not 504') return false; // Somerville
  if (maybeStudent504Field === 'NotIn504') return false; // Somerville & New Bedford
  if (maybeStudent504Field === 'Exited') return true; // New Bedford
  if (maybeStudent504Field === 'Active') return true; // New Bedford

  return true;
}

// Renders a table for `SlicePanels` that works differently for different
// districts.
export function renderSlicePanelsDisabilityTable(districtKey, options = {}) {
  const {createItemFn, renderTableFn} = options;

  const key = 'sped_level_of_need';
  const itemsFromValues = orderedDisabilityValues(districtKey).map(value => {
    return createItemFn(value, Filters.Equal(key, value));
  });

  // Somerville uses a null value for no disability, while New Bedford
  // uses a separate value to describe that explicitly.
  const items = (districtKey === SOMERVILLE)
    ? [createItemFn('None', Filters.Null(key))].concat(itemsFromValues)
    : itemsFromValues;
  return renderTableFn({items, title: 'Disability'});
}

// Check educator labels to see if the educator should be shown
// info about students in their courses with low grades.
export function shouldShowLowGradesBox(educatorLabels) {
  return (educatorLabels.indexOf('should_show_low_grades_box') !== -1);
}

const ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE = {
  'pic': 10,
  'cap': 100,
  'brn': 200,
  'hea': 300,
  'kdy': 300,
  'afas': 300,
  'escs': 300,
  'wsns': 300,
  'whcs': 300,
  'nw': 400,
  'shs': 500,
  'fc': 500,
  'sped': 600
};

export function sortSchoolSlugsByGrade(districtKey, slugA, slugB) {
  if (districtKey === SOMERVILLE) {
    return ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE[slugA] - ORDERED_SOMERVILLE_SCHOOL_SLUGS_BY_GRADE[slugB];
  }

  return slugA.localeCompare(slugB);
}

export function supportsHouse(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === BEDFORD) return true;
  if (districtKey === DEMO) return true;
  return false;
}

// This only applies to Somerville HS.
export function shouldDisplayHouse(school) {
  return (school && school.local_id === 'SHS');
}

export function somervilleHouses() {
  return [
    'Beacon',
    'Broadway',
    'Elm',
    'Highland'
  ];
}

export function supportsCounselor(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === DEMO) return true;
  return false;
}

// This only applies to high schools.
export function shouldDisplayCounselor(school) {
  return (school && school.school_type === 'HS');
}

export function supportsSpedLiaison(districtKey) {
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === DEMO) return true;
  return false;
}

export function supportsExcusedAbsences(districtKey) {
  if (districtKey === NEW_BEDFORD) return false;

  if (districtKey === BEDFORD) return true;
  if (districtKey === SOMERVILLE) return true;
  if (districtKey === DEMO) return true;

  return false;
}

// What is the eventNoteTypeId to use in user-facing text about how to support
// students with high absences?
export function eventNoteTypeIdForAbsenceSupportMeeting(districtKey) {
  if (districtKey === NEW_BEDFORD) return 400; // bbst
  if (districtKey === SOMERVILLE) return 300; // sst

  return 300;
}

// What choices do educators have for taking notes in the product?
export function takeNotesChoices(districtKey) {
  if (districtKey === SOMERVILLE || districtKey === DEMO) {
    return {
      leftEventNoteTypeIds: [300, 301, 302, 304],
      rightEventNoteTypeIds: [305, 306, 307]
    };
  }

  if (districtKey === NEW_BEDFORD) {
    return {
      leftEventNoteTypeIds: [400, 302, 304],
      rightEventNoteTypeIds: []
    };
  }

  throw new Error(`unsupported districtKey: ${districtKey}`);
}

// In tables of students, what eventNoteTypeIds should be shown as columns with notes
// about those students?
export function studentTableEventNoteTypeIds(districtKey, schoolType) {
  if (districtKey === NEW_BEDFORD) return [400];

  const isSomervilleOrDemo = (districtKey === SOMERVILLE || districtKey === DEMO);
  if (isSomervilleOrDemo && schoolType === 'HS') return [300, 305, 306, 307];
  // Includes elementary/middle, Capuano early childhood, and SPED.
  if (isSomervilleOrDemo) return [300, 301];

  throw new Error(`unsupported districtKey: ${districtKey}`);
}

<|endoftext|>


<commit_before>// A model class for RESTful resources
Ember.Resource = Ember.Object.extend({
  name:       Ember.required(),
  properties: Ember.required(),
  url:        Ember.required(),

  data: function() {
    var ret = {},
        prop;

    ret[this.name] = {};
    for(var i = 0; i < this.properties.length; i++) {
      prop = this.properties[i];
      ret[this.name][prop] = this.get(prop);
    }
    return ret;
  },

  save: function() {
    var self = this,
        isNew = (this.get('id') === undefined);

    return jQuery.ajax({
      url: this._url(),
      data: this.data(),
      dataType: 'json',
      type: (isNew ? 'POST' : 'PUT'),
      success: function(data) {
        if (data)
          self.setProperties(data);
      }
    });
  },

  destroy: function() {
    var self = this;

    return jQuery.ajax({
      url: this._url(),
      dataType: 'json',
      type: 'DELETE'
    });
  },

  _url: function() {
    var url = this.url,
        id = this.get('id');

    if (id !== undefined)
      return url + '/' + id;
    else
      return url;
  }
});

// A controller for RESTful resources
//
// Override this controller and include the following:
//
// * `type` -- an Ember.Resource class; the class must have a 'data' property that
//      returns a json representation of the object
// * `url` -- (optional) the base url of the resource (e.g. '/contacts')
Ember.ResourceController = Ember.ArrayController.extend({
  type:     Ember.required(),
  content:  [],

  load: function(json) {
    this.pushObject(this.get('type').create(json));
  },

  loadAll: function(jsonArray) {
    for (var i=0; i < jsonArray.length; i++)
      this.load(jsonArray[i]);
  },

  refresh: function() {
    var self = this;

    jQuery.getJSON(this._url(), function(data) {
      self.set("content", []);
      self.loadAll(data);
    });
  },

  create: function(data) {
    var self = this;
    var resource = this.get('type').create(data);

    return resource
      .save()
      .done(function() {
        self.pushObject(resource);
      });
  },

  destroy: function(resource) {
    var self = this;

    return resource
      .destroy()
      .done(function() {
        self.removeObject(resource);
      });
  },

  _url: function() {
    if (this.url === undefined)
      return this.get('type').prototype.url;
    else
      return this.url;
  }
});
<commit_msg>filled out comments<commit_after>// A model class for RESTful resources
//
// Extend this class and define the following:
//
// * `name` -- the name used to contain the serialized data in this object's json
//      representation
// * `properties` -- an array of property names to be returned in this object's
//      json representation
// * `url` -- (optional) the base url of the resource (e.g. '/contacts/active');
//      will default to the `url` for `type`
//
Ember.Resource = Ember.Object.extend({
  name:       Ember.required(),
  properties: Ember.required(),
  url:        Ember.required(),

  data: function() {
    var ret = {},
        prop;

    ret[this.name] = {};
    for(var i = 0; i < this.properties.length; i++) {
      prop = this.properties[i];
      ret[this.name][prop] = this.get(prop);
    }
    return ret;
  },

  save: function() {
    var self = this,
        isNew = (this.get('id') === undefined);

    return jQuery.ajax({
      url: this._url(),
      data: this.data(),
      dataType: 'json',
      type: (isNew ? 'POST' : 'PUT'),
      success: function(data) {
        if (data)
          self.setProperties(data);
      }
    });
  },

  destroy: function() {
    var self = this;

    return jQuery.ajax({
      url: this._url(),
      dataType: 'json',
      type: 'DELETE'
    });
  },

  _url: function() {
    var url = this.url,
        id = this.get('id');

    if (id !== undefined)
      return url + '/' + id;
    else
      return url;
  }
});

// A controller for RESTful resources
//
// Extend this class and define the following:
//
// * `type` -- an Ember.Resource class; the class must have a 'data' property that
//      returns a json representation of the object
// * `url` -- (optional) the base url of the resource (e.g. '/contacts/active');
//      will default to the `url` for `type`
//
Ember.ResourceController = Ember.ArrayController.extend({
  type:     Ember.required(),
  content:  [],

  load: function(json) {
    this.pushObject(this.get('type').create(json));
  },

  loadAll: function(jsonArray) {
    for (var i=0; i < jsonArray.length; i++)
      this.load(jsonArray[i]);
  },

  refresh: function() {
    var self = this;

    jQuery.getJSON(this._url(), function(data) {
      self.set("content", []);
      self.loadAll(data);
    });
  },

  create: function(data) {
    var self = this;
    var resource = this.get('type').create(data);

    return resource
      .save()
      .done(function() {
        self.pushObject(resource);
      });
  },

  destroy: function(resource) {
    var self = this;

    return resource
      .destroy()
      .done(function() {
        self.removeObject(resource);
      });
  },

  _url: function() {
    if (this.url === undefined)
      return this.get('type').prototype.url;
    else
      return this.url;
  }
});
<|endoftext|>


<commit_before>Jsonix.Class = function() {
	var Class = function() {
		this.initialize.apply(this, arguments);
	};
	var extended = {};
	var empty = function() {
	};
	var parent, initialize, Type;
	for ( var i = 0, len = arguments.length; i < len; ++i) {
		Type = arguments[i];
		if (typeof Type == "function") {
			// make the class passed as the first argument the superclass
			if (i === 0 && len > 1) {
				initialize = Type.prototype.initialize;
				// replace the initialize method with an empty function,
				// because we do not want to create a real instance here
				Type.prototype.initialize = empty;
				// the line below makes sure that the new class has a
				// superclass
				extended = new Type();
				// restore the original initialize method
				if (initialize === undefined) {
					delete Type.prototype.initialize;
				} else {
					Type.prototype.initialize = initialize;
				}
			}
			// get the prototype of the superclass
			parent = Type.prototype;
		} else {
			// in this case we're extending with the prototype
			parent = Type;
		}
		Jsonix.Util.extend(extended, parent);
	}
	Class.prototype = extended;
	return Class;
};
<commit_msg>Minor changes.<commit_after>Jsonix.Class = function() {
	var Class = function() {
		this.initialize.apply(this, arguments);
	};
	var extended = {};
	var empty = function() {
	};
	var parent, initialize, Type;
	for (var i = 0, len = arguments.length; i < len; ++i) {
		Type = arguments[i];
		if (typeof Type == "function") {
			// make the class passed as the first argument the superclass
			if (i === 0 && len > 1) {
				initialize = Type.prototype.initialize;
				// replace the initialize method with an empty function,
				// because we do not want to create a real instance here
				Type.prototype.initialize = empty;
				// the line below makes sure that the new class has a
				// superclass
				extended = new Type();
				// restore the original initialize method
				if (initialize === undefined) {
					delete Type.prototype.initialize;
				} else {
					Type.prototype.initialize = initialize;
				}
			}
			// get the prototype of the superclass
			parent = Type.prototype;
		} else {
			// in this case we're extending with the prototype
			parent = Type;
		}
		Jsonix.Util.extend(extended, parent);
	}
	Class.prototype = extended;
	return Class;
};
<|endoftext|>


<commit_before>require('consoloid-framework/Consoloid/Service/AsyncRPC/Response');
require('consoloid-framework/Consoloid/Service/AsyncRPC/BasePeer');
require('consoloid-framework/Consoloid/Service/ServiceContainer');
require('consoloid-framework/Consoloid/Service/ChainedContainer');
require('../ServerSideContainer');
require('../AsyncRPCPeer');
require('../AsyncRPCRequest');
require('consoloid-framework/Consoloid/Test/UnitTest');
describeUnitTest('Consoloid.Server.AsyncRPCPeer', function() {
  var
    handler,
    socketMock,
    req;

  beforeEach(function() {
    req = {
      callId: 1,
      sessionID: 'session_id',
      service: 'testService',
      method: 'asyncMethod',
      args: []
    }

    socketMock = {
      emit: sinon.spy(),
      on: sinon.spy(),
      id: 'socket_id'
    };

    defineClass('Consoloid.Server.TestedAsyncRPCPeer', 'Consoloid.Server.AsyncRPCPeer', {
      _setupListeners: sinon.spy()
    });
    handler = env.create('Consoloid.Server.TestedAsyncRPCPeer', {
      socket: socketMock
    });
  });

  describe('#__construct()', function() {
    it('should bind events by calling _setUpListeners()', function() {
      handler._setupListeners.calledOnce.should.be.true;
    });
  });

  describe('#_handleSharedServiceCallRequest(req)', function() {
    beforeEach(function() {
      handler.__registerToPool = sinon.stub();
    });

    it('should atempt to register to pool', function() {
      handler._handleSharedServiceCallRequest(req);

      handler.__registerToPool.calledOnce.should.be.ok;
    });

    it('should throw error if request does not include session id', function() {
      (function() {
        handler._handleSharedServiceCallRequest(
          {callId: 1, service: 'service', method: 'method', args: ['test', ['test']]}
        );
      }).should.throwError('Shared async call request requires sessionID.');
    });

    it('should call service method using Router::callMethodOnService method', function() {
      env.addServiceMock('router', {
        callMethodOnService: sinon.spy()
      });

      env.addServiceMock('session_store', {
        getContainer: sinon.stub().returns({ get: sinon.stub().returns('serviceInstance') })
      });

      env.addServiceMock('testService', {
        asyncMethod: sinon.spy()
      });

      handler._handleSharedServiceCallRequest(req);

      env.container.get('router').callMethodOnService.calledOnce.should.be.true;
      env.container.get('router').callMethodOnService.args[0][0].should.equal('testService');
      (env.container.get('router').callMethodOnService.args[0][1] instanceof Consoloid.Server.AsyncRPCRequest).should.be.ok;
      env.container.get('router').callMethodOnService.args[0][2].should.equal('serviceInstance');
    });
  });

  describe('#_handleServiceCallRequest(req)', function() {
    beforeEach(function() {
      req.instanceId = 12;
      handler.__registerToPool = sinon.stub();

      env.addServiceMock('router', {
        callServiceInstance: sinon.mock()
      });

      env.addServiceMock('testService', {
        asyncMethod: sinon.spy()
      });
    });

    it('should atempt to register to pool', function() {
      handler._handleServiceCallRequest(req);

      handler.__registerToPool.calledOnce.should.be.ok;
    });

    it('should throw error when the request does not contain required arguments', function() {
      (function() {
        handler._handleServiceCallRequest(
          { callId: 1 }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session' }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session', instanceId: 12 }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session', instanceId: 12, method: 'method' }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');
    });

    it('should call service method using Router::callMethodOnService method', function() {
      handler._handleServiceCallRequest(req);

      env.container.get('router').callServiceInstance.calledOnce.should.be.true;
      var actualReq = env.container.get('router').callServiceInstance.args[0][0];
      actualReq.param('callId').should.be.eql(1);
      actualReq.param('instanceId').should.be.eql(12);
      actualReq.param('sessionID').should.be.eql('session_id');
      actualReq.param('service').should.be.eql('testService');
      actualReq.param('method').should.be.eql('asyncMethod');
    });
  });

  describe('#__registerToPool(sessionID)', function() {
    var
      pool;
    beforeEach(function() {
      pool = {
        addPeerToSession: sinon.stub()
      }
      env.addServiceMock('async_rpc_connection_pool', pool);
    });

    it("should register itself to the pool according to session and socket id on first request", function() {
      handler.__registerToPool('session_id');

      pool.addPeerToSession.calledOnce.should.be.ok;
      pool.addPeerToSession.args[0][0].should.equal('session_id');
      pool.addPeerToSession.args[0][1].should.equal('socket_id');

      handler.__registerToPool('session_id');
      handler.__registerToPool('session_id');
      pool.addPeerToSession.calledOnce.should.be.ok;
    });

    it("should throw on new sessionID when it's not the first request", function() {
      handler.__registerToPool('session_id');

      req.sessionID = 'something_id';
      (function() {
        handler._validateSharedCallRequest('session_id');
      }).should.throwError()
    });
  });
});
<commit_msg>Consoloid.Server.AsyncRPCPeerTest typo fix<commit_after>require('consoloid-framework/Consoloid/Service/AsyncRPC/Response');
require('consoloid-framework/Consoloid/Service/AsyncRPC/BasePeer');
require('consoloid-framework/Consoloid/Service/ServiceContainer');
require('consoloid-framework/Consoloid/Service/ChainedContainer');
require('../ServerSideContainer');
require('../AsyncRPCPeer');
require('../AsyncRPCRequest');
require('consoloid-framework/Consoloid/Test/UnitTest');
describeUnitTest('Consoloid.Server.AsyncRPCPeer', function() {
  var
    handler,
    socketMock,
    req;

  beforeEach(function() {
    req = {
      callId: 1,
      sessionID: 'session_id',
      service: 'testService',
      method: 'asyncMethod',
      args: []
    }

    socketMock = {
      emit: sinon.spy(),
      on: sinon.spy(),
      id: 'socket_id'
    };

    defineClass('Consoloid.Server.TestedAsyncRPCPeer', 'Consoloid.Server.AsyncRPCPeer', {
      _setupListeners: sinon.spy()
    });
    handler = env.create('Consoloid.Server.TestedAsyncRPCPeer', {
      socket: socketMock
    });
  });

  describe('#__construct()', function() {
    it('should bind events by calling _setUpListeners()', function() {
      handler._setupListeners.calledOnce.should.be.true;
    });
  });

  describe('#_handleSharedServiceCallRequest(req)', function() {
    beforeEach(function() {
      handler.__registerToPool = sinon.stub();
    });

    it('should attempt to register to pool', function() {
      handler._handleSharedServiceCallRequest(req);

      handler.__registerToPool.calledOnce.should.be.ok;
    });

    it('should throw error if request does not include session id', function() {
      (function() {
        handler._handleSharedServiceCallRequest(
          {callId: 1, service: 'service', method: 'method', args: ['test', ['test']]}
        );
      }).should.throwError('Shared async call request requires sessionID.');
    });

    it('should call service method using Router::callMethodOnService method', function() {
      env.addServiceMock('router', {
        callMethodOnService: sinon.spy()
      });

      env.addServiceMock('session_store', {
        getContainer: sinon.stub().returns({ get: sinon.stub().returns('serviceInstance') })
      });

      env.addServiceMock('testService', {
        asyncMethod: sinon.spy()
      });

      handler._handleSharedServiceCallRequest(req);

      env.container.get('router').callMethodOnService.calledOnce.should.be.true;
      env.container.get('router').callMethodOnService.args[0][0].should.equal('testService');
      (env.container.get('router').callMethodOnService.args[0][1] instanceof Consoloid.Server.AsyncRPCRequest).should.be.ok;
      env.container.get('router').callMethodOnService.args[0][2].should.equal('serviceInstance');
    });
  });

  describe('#_handleServiceCallRequest(req)', function() {
    beforeEach(function() {
      req.instanceId = 12;
      handler.__registerToPool = sinon.stub();

      env.addServiceMock('router', {
        callServiceInstance: sinon.mock()
      });

      env.addServiceMock('testService', {
        asyncMethod: sinon.spy()
      });
    });

    it('should attempt to register to pool', function() {
      handler._handleServiceCallRequest(req);

      handler.__registerToPool.calledOnce.should.be.ok;
    });

    it('should throw error when the request does not contain required arguments', function() {
      (function() {
        handler._handleServiceCallRequest(
          { callId: 1 }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session' }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session', instanceId: 12 }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');

      (function() {
        handler._handleServiceCallRequest(
          { callId: 1, sessionID: 'session', instanceId: 12, method: 'method' }
        );
      }).should.throwError('Async call request requires callId, sessionID, instanceId and method name with arguments.');
    });

    it('should call service method using Router::callMethodOnService method', function() {
      handler._handleServiceCallRequest(req);

      env.container.get('router').callServiceInstance.calledOnce.should.be.true;
      var actualReq = env.container.get('router').callServiceInstance.args[0][0];
      actualReq.param('callId').should.be.eql(1);
      actualReq.param('instanceId').should.be.eql(12);
      actualReq.param('sessionID').should.be.eql('session_id');
      actualReq.param('service').should.be.eql('testService');
      actualReq.param('method').should.be.eql('asyncMethod');
    });
  });

  describe('#__registerToPool(sessionID)', function() {
    var
      pool;
    beforeEach(function() {
      pool = {
        addPeerToSession: sinon.stub()
      }
      env.addServiceMock('async_rpc_connection_pool', pool);
    });

    it("should register itself to the pool according to session and socket id on first request", function() {
      handler.__registerToPool('session_id');

      pool.addPeerToSession.calledOnce.should.be.ok;
      pool.addPeerToSession.args[0][0].should.equal('session_id');
      pool.addPeerToSession.args[0][1].should.equal('socket_id');

      handler.__registerToPool('session_id');
      handler.__registerToPool('session_id');
      pool.addPeerToSession.calledOnce.should.be.ok;
    });

    it("should throw on new sessionID when it's not the first request", function() {
      handler.__registerToPool('session_id');

      req.sessionID = 'something_id';
      (function() {
        handler._validateSharedCallRequest('session_id');
      }).should.throwError()
    });
  });
});
<|endoftext|>


<commit_before>import React from 'react';
import Relay from 'react-relay';
import shallowCompare from 'react-addons-shallow-compare';

import AnchoredPopover from '../shared/Popover/anchored';
import Button from '../shared/Button';
import Spinner from '../shared/Spinner';
import UserAvatar from '../shared/UserAvatar';

import FlashesStore from '../../stores/FlashesStore';

import EmailCreateMutation from '../../mutations/EmailCreate';
import NoticeDismissMutation from '../../mutations/NoticeDismiss';

class AvatarWithEmailPrompt extends React.Component {
  static propTypes = {
    build: React.PropTypes.shape({
      createdBy: React.PropTypes.shape({
        email: React.PropTypes.string
      })
    }).isRequired,
    viewer: React.PropTypes.shape({
      emails: React.PropTypes.shape({
        edges: React.PropTypes.arrayOf(
          React.PropTypes.shape({
            node: React.PropTypes.shape({
              address: React.PropTypes.string,
              verified: React.PropTypes.bool
            })
          })
        )
      }).isRequired,
      notice: React.PropTypes.shape({
        dismissedAt: React.PropTypes.string
      })
    }).isRequired,
    relay: React.PropTypes.object
  };

  state = {
    isAddingEmail: false
  };

  getUserEmailInformation(email) {
    const userEmails = this.props.viewer.emails.edges;

    let isCurrentUsers = false;
    let isVerified = false;

    const foundEmail = userEmails.find(
      ({ node: { address: userEmail } }) => (
        userEmail.toLowerCase() === email.toLowerCase()
      )
    );

    if (foundEmail) {
      isCurrentUsers = true;
      isVerified = foundEmail.verified;
    }

    return { isCurrentUsers, isVerified };
  }

  isCurrentUsersEmail(email) {
    return this.getUserEmailInformation(email).isCurrentUsers;
  }

  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState);
  }

  componentWillReceiveProps(nextProps) {
    const { createdBy } = nextProps.build;

    if (createdBy && createdBy.email && !this.isCurrentUsersEmail(createdBy.email)) {
      this.props.relay.setVariables({
        isTryingToPrompt: true,
        emailForPrompt: createdBy.email.toLowerCase()
      });
    }
  }

  handleDismissClick = () => {
    const mutation = new NoticeDismissMutation({ viewer: this.props.viewer, notice: this.props.viewer.notice });

    Relay.Store.commitUpdate(mutation, { onFailure: this.handleMutationFailure });
  };

  handleMutationFailure = (transaction) => {
    this.setState({ isAddingEmail: false });

    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());
  };

  handleAddEmailClick = () => {
    this.setState({ isAddingEmail: true });

    const mutation = new EmailCreateMutation({ address: this.props.build.createdBy.email, viewer: this.props.viewer });

    Relay.Store.commitUpdate(mutation, { onSuccess: this.handleEmailAddedSuccess, onFailure: this.handleMutationFailure });
  };

  handleEmailAddedSuccess = () => {
    this.setState({ isAddingEmail: false });
  };

  renderContent() {
    const {
      build: {
        createdBy: {
          email
        }
      },
      relay: {
        variables: {
          isTryingToPrompt
        }
      },
      viewer: {
        notice
      }
    } = this.props;
    const wrapperClassName = 'center px3 py2';

    // There won't be an email address if this build was created by a
    // registered user or if this build just has no owner (perhaps it was
    // created by Buildkite)
    if (!email) {
      return null;
    }

    // If we haven't decided to send a query for this yet, don't show anything!
    if (!isTryingToPrompt) {
      return null;
    }

    // If the user has seen the notice and has been dismissed
    if (notice && notice.dismissedAt) {
      return null;
    }

    if (this.state.isAddingEmail) {
      return (

          <Spinner />

            Adding Email…

      );
    }

    const emailInfo = this.getUserEmailInformation(email);

    if (emailInfo.isCurrentUsers) {
      if (emailInfo.isVerified) {
        return null;
      }

      return (

            Verify your email

            We’ve sent a verification link to {email}. Click the link to add the email to your account.

          <Button
            className="block mt2"
            theme="default"
            outline={true}
            style={{ width: '100%' }}
            onClick={this.handleResendVerificationClick}
          >
            Resend Verification Email
          </Button>

      );
    }

    // Otherwise, we've got an unknown (to Buildkite) email address on our hands!
    return (

          Unknown email address

          If {email} is your email address, add it to your account to have builds appear in My Builds, customize your email settings, and more. Learn more

        <Button
          className="block my2"
          style={{ width: '100%' }}
          onClick={this.handleAddEmailClick}
        >
          Add {email}
        </Button>
        <Button
          className="block"
          theme="default"
          outline={true}
          style={{ width: '100%' }}
          onClick={this.handleDismissClick}
        >
          Dismiss
        </Button>

    );
  }

  render() {
    const { build } = this.props;

    const avatar = (
      <UserAvatar
        user={build.createdBy}
        style={{ width: 32, height: 32 }}
      />
    );

    const content = this.renderContent();

    if (content) {
      return (
        <AnchoredPopover
          alwaysShow={true}
          width={400}
        >
          {avatar}
          {content}
        </AnchoredPopover>
      );
    }

    return avatar;
  }
}

export default Relay.createContainer(AvatarWithEmailPrompt, {
  initialVariables: {
    emailForPrompt: null,
    isTryingToPrompt: false
  },

  fragments: {
    build: () => Relay.QL`
      fragment on Build {
        createdBy {
          ...on UnregisteredUser {
            email
            name
            avatar {
              url
            }
          }
          ...on User {
            name
            avatar {
              url
            }
          }
        }
      }
    `,
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${EmailCreateMutation.getFragment('viewer')}
        emails(first: 50) {
          edges {
            node {
              address
              verified
            }
          }
        }
        notice(namespace: NOTICE_NAMESPACE_EMAIL_SUGGESTION, scope: $emailForPrompt) @include(if: $isTryingToPrompt) {
          ${NoticeDismissMutation.getFragment('notice')}
          dismissedAt
        }
      }
    `
  }
});
<commit_msg>Pad "adding email" message to align with prompt<commit_after>import React from 'react';
import Relay from 'react-relay';
import shallowCompare from 'react-addons-shallow-compare';

import AnchoredPopover from '../shared/Popover/anchored';
import Button from '../shared/Button';
import Spinner from '../shared/Spinner';
import UserAvatar from '../shared/UserAvatar';

import FlashesStore from '../../stores/FlashesStore';

import EmailCreateMutation from '../../mutations/EmailCreate';
import NoticeDismissMutation from '../../mutations/NoticeDismiss';

class AvatarWithEmailPrompt extends React.Component {
  static propTypes = {
    build: React.PropTypes.shape({
      createdBy: React.PropTypes.shape({
        email: React.PropTypes.string
      })
    }).isRequired,
    viewer: React.PropTypes.shape({
      emails: React.PropTypes.shape({
        edges: React.PropTypes.arrayOf(
          React.PropTypes.shape({
            node: React.PropTypes.shape({
              address: React.PropTypes.string,
              verified: React.PropTypes.bool
            })
          })
        )
      }).isRequired,
      notice: React.PropTypes.shape({
        dismissedAt: React.PropTypes.string
      })
    }).isRequired,
    relay: React.PropTypes.object
  };

  state = {
    isAddingEmail: false
  };

  getUserEmailInformation(email) {
    const userEmails = this.props.viewer.emails.edges;

    let isCurrentUsers = false;
    let isVerified = false;

    const foundEmail = userEmails.find(
      ({ node: { address: userEmail } }) => (
        userEmail.toLowerCase() === email.toLowerCase()
      )
    );

    if (foundEmail) {
      isCurrentUsers = true;
      isVerified = foundEmail.verified;
    }

    return { isCurrentUsers, isVerified };
  }

  isCurrentUsersEmail(email) {
    return this.getUserEmailInformation(email).isCurrentUsers;
  }

  shouldComponentUpdate(nextProps, nextState) {
    return shallowCompare(this, nextProps, nextState);
  }

  componentWillReceiveProps(nextProps) {
    const { createdBy } = nextProps.build;

    if (createdBy && createdBy.email && !this.isCurrentUsersEmail(createdBy.email)) {
      this.props.relay.setVariables({
        isTryingToPrompt: true,
        emailForPrompt: createdBy.email.toLowerCase()
      });
    }
  }

  handleDismissClick = () => {
    const mutation = new NoticeDismissMutation({ viewer: this.props.viewer, notice: this.props.viewer.notice });

    Relay.Store.commitUpdate(mutation, { onFailure: this.handleMutationFailure });
  };

  handleMutationFailure = (transaction) => {
    this.setState({ isAddingEmail: false });

    FlashesStore.flash(FlashesStore.ERROR, transaction.getError());
  };

  handleAddEmailClick = () => {
    this.setState({ isAddingEmail: true });

    const mutation = new EmailCreateMutation({ address: this.props.build.createdBy.email, viewer: this.props.viewer });

    Relay.Store.commitUpdate(mutation, { onSuccess: this.handleEmailAddedSuccess, onFailure: this.handleMutationFailure });
  };

  handleEmailAddedSuccess = () => {
    this.setState({ isAddingEmail: false });
  };

  renderContent() {
    const {
      build: {
        createdBy: {
          email
        }
      },
      relay: {
        variables: {
          isTryingToPrompt
        }
      },
      viewer: {
        notice
      }
    } = this.props;
    const wrapperClassName = 'center px3 py2';

    // There won't be an email address if this build was created by a
    // registered user or if this build just has no owner (perhaps it was
    // created by Buildkite)
    if (!email) {
      return null;
    }

    // If we haven't decided to send a query for this yet, don't show anything!
    if (!isTryingToPrompt) {
      return null;
    }

    // If the user has seen the notice and has been dismissed
    if (notice && notice.dismissedAt) {
      return null;
    }

    if (this.state.isAddingEmail) {
      return (

          <Spinner />

            Adding Email…

      );
    }

    const emailInfo = this.getUserEmailInformation(email);

    if (emailInfo.isCurrentUsers) {
      if (emailInfo.isVerified) {
        return null;
      }

      return (

            Verify your email

            We’ve sent a verification link to {email}. Click the link to add the email to your account.

          <Button
            className="block mt2"
            theme="default"
            outline={true}
            style={{ width: '100%' }}
            onClick={this.handleResendVerificationClick}
          >
            Resend Verification Email
          </Button>

      );
    }

    // Otherwise, we've got an unknown (to Buildkite) email address on our hands!
    return (

          Unknown email address

          If {email} is your email address, add it to your account to have builds appear in My Builds, customize your email settings, and more. Learn more

        <Button
          className="block my2"
          style={{ width: '100%' }}
          onClick={this.handleAddEmailClick}
        >
          Add {email}
        </Button>
        <Button
          className="block"
          theme="default"
          outline={true}
          style={{ width: '100%' }}
          onClick={this.handleDismissClick}
        >
          Dismiss
        </Button>

    );
  }

  render() {
    const { build } = this.props;

    const avatar = (
      <UserAvatar
        user={build.createdBy}
        style={{ width: 32, height: 32 }}
      />
    );

    const content = this.renderContent();

    if (content) {
      return (
        <AnchoredPopover
          alwaysShow={true}
          width={400}
        >
          {avatar}
          {content}
        </AnchoredPopover>
      );
    }

    return avatar;
  }
}

export default Relay.createContainer(AvatarWithEmailPrompt, {
  initialVariables: {
    emailForPrompt: null,
    isTryingToPrompt: false
  },

  fragments: {
    build: () => Relay.QL`
      fragment on Build {
        createdBy {
          ...on UnregisteredUser {
            email
            name
            avatar {
              url
            }
          }
          ...on User {
            name
            avatar {
              url
            }
          }
        }
      }
    `,
    viewer: () => Relay.QL`
      fragment on Viewer {
        ${EmailCreateMutation.getFragment('viewer')}
        emails(first: 50) {
          edges {
            node {
              address
              verified
            }
          }
        }
        notice(namespace: NOTICE_NAMESPACE_EMAIL_SUGGESTION, scope: $emailForPrompt) @include(if: $isTryingToPrompt) {
          ${NoticeDismissMutation.getFragment('notice')}
          dismissedAt
        }
      }
    `
  }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import userHelpers from '../../utils/userHelpers';

class Contribution extends Component {
  constructor(props) {
    super(props);

    this.state = {
      userEmail: '',
      userName: '',
      userLocation: '',
      isTraveling: null,
    };

    this._onCheckBoxClick = this._onCheckBoxClick.bind(this);
  }

  componentDidMount() {
    if (this.props.bringer) {
      userHelpers.getAnyUserById(this.props.bringer)
      .then((user) => {
        this.setState({
          userEmail: user.data.email,
          userName: user.data.username,
          isTraveling: user.data.is_traveling,
          userLocation: user.data.location,
        });
      });
    }
  }

  // componentWillUpdate() {
  //   if (this.props.bringer) {
  //     userHelpers.getAnyUserById(this.props.bringer)
  //     .then((user) => {
  //       this.setState({
  //         userEmail: user.data.email,
  //         userName: user.data.username,
  //         isTraveling: user.data.is_traveling,
  //         userLocation: user.data.location,
  //       });
  //     });
  //   }
  // }

  _onCheckBoxClick(e) {
    this.props._onCheckBoxClick(e, this.props.index);
  }

  render() {
    return (

          {
            !this.props.bringer ?

              <input
                type="checkbox"
                onChange={this._onCheckBoxClick}
              />

          :
            null
          }

{this.props.item}

          { /* If there is a note, provide a note section */
            this.props.notes &&

                {this.props.notes}

          }

        { /* If user is bringing item, display message, also checking all fields are avialble */
          this.props.bringer && this.state.userName && this.state.isTraveling !== null && this.state.userLocation &&

Contributor:

              {this.state.userName}, {this.state.isTraveling ? 'a traveler' : ''} from {this.state.userLocation}

        }

    );
  }
}

export default Contribution;

<commit_msg>(fix) recursive ajax calls to in unique event view<commit_after>import React, { Component } from 'react';
import userHelpers from '../../utils/userHelpers';

class Contribution extends Component {
  constructor(props) {
    super(props);

    this.state = {
      userEmail: '',
      userName: '',
      userLocation: '',
      isTraveling: null,
    };

    this._onCheckBoxClick = this._onCheckBoxClick.bind(this);
  }

  componentDidMount() {
    if (this.props.bringer) {
      userHelpers.getAnyUserById(this.props.bringer)
      .then((user) => {
        this.setState({
          userEmail: user.data.email,
          userName: user.data.username,
          isTraveling: user.data.is_traveling,
          userLocation: user.data.location,
        });
      });
    }
  }

  _onCheckBoxClick(e) {
    this.props._onCheckBoxClick(e, this.props.index);
  }

  render() {
    return (

          {
            !this.props.bringer ?

              <input
                type="checkbox"
                onChange={this._onCheckBoxClick}
              />

          :
            null
          }

{this.props.item}

          { /* If there is a note, provide a note section */
            this.props.notes &&

                {this.props.notes}

          }

        { /* If user is bringing item, display message, also checking all fields are avialble */
          this.props.bringer && this.state.userName && this.state.isTraveling !== null && this.state.userLocation &&

Contributor:

              {this.state.userName}, {this.state.isTraveling ? 'a traveler' : ''} from {this.state.userLocation}

        }

    );
  }
}

export default Contribution;

<|endoftext|>


<commit_before>// forest change
import treeLoss from 'components/widgets/forest-change/tree-loss';
import treeLossPct from 'components/widgets/forest-change/tree-loss-pct';
import treeLossGlobal from 'components/widgets/forest-change/tree-loss-global';
import treeLossRanked from 'components/widgets/forest-change/tree-loss-ranked';
import faoDeforest from 'components/widgets/forest-change/fao-deforest';
import faoReforest from 'components/widgets/forest-change/fao-reforest';
import treeCoverGain from 'components/widgets/forest-change/tree-cover-gain';
import treeGainLocated from 'components/widgets/forest-change/tree-gain-located';
import treeLossLocated from 'components/widgets/forest-change/tree-loss-located';
import treeLossPlantations from 'components/widgets/forest-change/tree-loss-plantations';
import treeLossTsc from 'components/widgets/forest-change/tree-loss-tsc';
import treeCoverGainSimple from 'components/widgets/forest-change/tree-cover-gain-simple';
import glads from 'components/widgets/forest-change/glads';
import gladAlerts from 'components/widgets/forest-change/glad-alerts';
import gladRanked from 'components/widgets/forest-change/glad-ranked';

// fires
import firesWithin from 'components/widgets/fires/fires-within';
import firesAlerts from 'components/widgets/fires/fires-alerts';
import firesAlertsCumulative from 'components/widgets/fires/fires-alerts-cumulative';
import firesAlertsHistorical from 'components/widgets/fires/fires-alerts-historical';
import firesAlertsHistoricalDaily from 'components/widgets/fires/fires-alerts-historical-daily';
import firesRanked from 'components/widgets/fires/fires-ranked';

// land cover
import treeCover from 'components/widgets/land-cover/tree-cover';
import treeCover2000 from 'components/widgets/land-cover/tree-cover-2000';
import treeCover2010 from 'components/widgets/land-cover/tree-cover-2010';
import treeCoverRanked from 'components/widgets/land-cover/tree-cover-ranked';
import treeCoverPlantations from 'components/widgets/land-cover/tree-cover-plantations';
import rankedPlantations from 'components/widgets/land-cover/ranked-plantations';
import faoCover from 'components/widgets/land-cover/fao-cover';
import globalLandCover from 'components/widgets/land-cover/global-land-cover';
import intactTreeCover from 'components/widgets/land-cover/intact-tree-cover';
import primaryForest from 'components/widgets/land-cover/primary-forest';
import treeCoverLocated from 'components/widgets/land-cover/tree-cover-located';
import USLandCover from 'components/widgets/land-cover/us-land-cover';

// Climate
import emissions from 'components/widgets/climate/emissions';
import woodyBiomass from 'components/widgets/climate/whrc-biomass/';
import soilBiomass from 'components/widgets/climate/soil-organic';
import emissionsDeforestation from 'components/widgets/climate/emissions-deforestation';
import emissionsPlantations from 'components/widgets/climate/emissions-plantations';
import futureCarbonGains from 'components/widgets/climate/future-carbon-gains';
import cumulativeEmissions from 'components/widgets/climate/cumulative-emissions';
import carbonStock from 'components/widgets/climate/carbon-stock';

// Land Use
import economicImpact from 'components/widgets/land-use/economic-impact';
import forestryEmployment from 'components/widgets/land-use/forestry-employment';
import traseCommodities from 'components/widgets/land-use/trase-commodities';

export default {
  // forest change
  treeLoss,
  treeLossPct,
  treeLossGlobal,
  treeLossRanked,
  faoDeforest,
  faoReforest,
  treeCoverGain,
  treeGainLocated,
  treeLossLocated,
  treeLossPlantations,
  treeLossTsc,
  treeCoverGainSimple,
  glads,
  gladAlerts,
  gladRanked,

  // fires
  firesWithin,
  firesAlerts,
  firesAlertsCumulative,
  firesAlertsHistorical,
  firesRanked,
  firesAlertsHistoricalDaily,

  // land cover
  treeCover,
  treeCover2000,
  treeCover2010,
  treeCoverRanked,
  rankedPlantations,
  USLandCover,
  treeCoverPlantations,
  faoCover,
  globalLandCover,
  intactTreeCover,
  primaryForest,
  treeCoverLocated,
  // climate
  emissions,
  emissionsDeforestation,
  emissionsPlantations,
  woodyBiomass,
  soilBiomass,
  futureCarbonGains,
  cumulativeEmissions,
  carbonStock,
  // land use
  economicImpact,
  forestryEmployment,
  traseCommodities
};
<commit_msg>add widgets back to manifest<commit_after>// forest change
import treeLoss from 'components/widgets/forest-change/tree-loss';
import treeLossPct from 'components/widgets/forest-change/tree-loss-pct';
import treeLossGlobal from 'components/widgets/forest-change/tree-loss-global';
import treeLossRanked from 'components/widgets/forest-change/tree-loss-ranked';
import faoDeforest from 'components/widgets/forest-change/fao-deforest';
import faoReforest from 'components/widgets/forest-change/fao-reforest';
import treeCoverGain from 'components/widgets/forest-change/tree-cover-gain';
import treeGainLocated from 'components/widgets/forest-change/tree-gain-located';
import treeLossLocated from 'components/widgets/forest-change/tree-loss-located';
import treeLossPlantations from 'components/widgets/forest-change/tree-loss-plantations';
import treeLossTsc from 'components/widgets/forest-change/tree-loss-tsc';
import treeCoverGainSimple from 'components/widgets/forest-change/tree-cover-gain-simple';
import glads from 'components/widgets/forest-change/glads';
import gladAlerts from 'components/widgets/forest-change/glad-alerts';
import gladRanked from 'components/widgets/forest-change/glad-ranked';
import fires from 'components/widgets/forest-change/fires';
import firesAlertsOld from 'components/widgets/forest-change/fires-alerts';
import firesRankedOld from 'components/widgets/forest-change/fires-ranked';

// fires
import firesWithin from 'components/widgets/fires/fires-within';
import firesAlerts from 'components/widgets/fires/fires-alerts';
import firesAlertsCumulative from 'components/widgets/fires/fires-alerts-cumulative';
import firesAlertsHistorical from 'components/widgets/fires/fires-alerts-historical';
import firesAlertsHistoricalDaily from 'components/widgets/fires/fires-alerts-historical-daily';
import firesRanked from 'components/widgets/fires/fires-ranked';

// land cover
import treeCover from 'components/widgets/land-cover/tree-cover';
import treeCover2000 from 'components/widgets/land-cover/tree-cover-2000';
import treeCover2010 from 'components/widgets/land-cover/tree-cover-2010';
import treeCoverRanked from 'components/widgets/land-cover/tree-cover-ranked';
import treeCoverPlantations from 'components/widgets/land-cover/tree-cover-plantations';
import rankedPlantations from 'components/widgets/land-cover/ranked-plantations';
import faoCover from 'components/widgets/land-cover/fao-cover';
import globalLandCover from 'components/widgets/land-cover/global-land-cover';
import intactTreeCover from 'components/widgets/land-cover/intact-tree-cover';
import primaryForest from 'components/widgets/land-cover/primary-forest';
import treeCoverLocated from 'components/widgets/land-cover/tree-cover-located';
import USLandCover from 'components/widgets/land-cover/us-land-cover';

// Climate
import emissions from 'components/widgets/climate/emissions';
import woodyBiomass from 'components/widgets/climate/whrc-biomass/';
import soilBiomass from 'components/widgets/climate/soil-organic';
import emissionsDeforestation from 'components/widgets/climate/emissions-deforestation';
import emissionsPlantations from 'components/widgets/climate/emissions-plantations';
import futureCarbonGains from 'components/widgets/climate/future-carbon-gains';
import cumulativeEmissions from 'components/widgets/climate/cumulative-emissions';
import carbonStock from 'components/widgets/climate/carbon-stock';

// Land Use
import economicImpact from 'components/widgets/land-use/economic-impact';
import forestryEmployment from 'components/widgets/land-use/forestry-employment';
import traseCommodities from 'components/widgets/land-use/trase-commodities';

export default {
  // forest change
  treeLoss,
  treeLossPct,
  treeLossGlobal,
  treeLossRanked,
  faoDeforest,
  faoReforest,
  treeCoverGain,
  treeGainLocated,
  treeLossLocated,
  treeLossPlantations,
  treeLossTsc,
  treeCoverGainSimple,
  glads,
  gladAlerts,
  gladRanked,
  fires,
  firesAlertsOld,
  firesRankedOld,

  ...process.env.FEATURE_ENV === 'staging' && {
    // fires
    firesWithin,
    firesAlerts,
    firesAlertsCumulative,
    firesAlertsHistorical,
    firesRanked,
    firesAlertsHistoricalDaily
  },

  // land cover
  treeCover,
  treeCover2000,
  treeCover2010,
  treeCoverRanked,
  rankedPlantations,
  USLandCover,
  treeCoverPlantations,
  faoCover,
  globalLandCover,
  intactTreeCover,
  primaryForest,
  treeCoverLocated,
  // climate
  emissions,
  emissionsDeforestation,
  emissionsPlantations,
  woodyBiomass,
  soilBiomass,
  futureCarbonGains,
  cumulativeEmissions,
  carbonStock,
  // land use
  economicImpact,
  forestryEmployment,
  traseCommodities
};
<|endoftext|>


<commit_before>'use strict';

var htmlToUnicode = require('../../gl3d/lib/html2unicode');
var str2RGBArray = require('../../gl3d/lib/str2rgbarray');

function Axes2DOptions(scene) {
  this.title = '';

  this.gl = scene.gl;
  this.pixelRatio = scene.pixelRatio;

  this.screenBox = [0,0,1,1];
  this.viewBox   = [0,0,1,1];
  this.dataBox   = [-1,-1,1,1];

  this.borderLineEnable = [false,false,false,false];
  this.borderLineWidth = [1,1,1,1];
  this.borderLineColor = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];

  this.ticks = [[], []];
  this.tickEnable = [true, true, false, false];
  this.tickPad   = [15,15,15,15];
  this.tickAngle = [0,0,0,0];
  this.tickColor = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];
  this.tickMarkWidth = [0,0,0,0];
  this.tickMarkLength = [0,0,0,0];

  this.labels = ['x', 'y'];
  this.labelEnable = [true,true,false,false];
  this.labelAngle  = [0,Math.PI/2,0,3.0*Math.PI/2];
  this.labelPad    = [15,15,15,15];
  this.labelSize   = [12,12];
  this.labelFont   = ['sans-serif', 'sans-serif'];
  this.labelColor  = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];

  this.title       = '';
  this.titleEnable = true;
  this.titleCenter = [0,0,0,0];
  this.titleAngle  = 0;
  this.titleColor  = [0,0,0,1];
  this.titleFont   = 'sans-serif';
  this.titleSize   = 18;

  this.gridLineEnable = [true,true];
  this.gridLineColor  = [
    [0,0,0,0.5],
    [0,0,0,0.5]
  ];
  this.gridLineWidth  = [1,1];

  this.zeroLineEnable = [true,true];
  this.zeroLineWidth  = [1,1];
  this.zeroLineColor  = [
    [0,0,0,1],
    [0,0,0,1]
  ];
}

var proto = Axes2DOptions.prototype;

var AXES = [ 'xaxis', 'yaxis' ];

proto.merge = function(options) {

  //Titles are rendered in SVG
  this.titleEnable = false;

  for(var i=0; i<2; ++i) {
    var ax = options[AXES[i]];

    for(var j=0; j<=2; j+=2) {
      this.labels[i+j]     = htmlToUnicode(ax.title);
      this.labelEnable[i+j] = false;
      this.labelColor[i+j] = str2RGBArray(ax.titlefont.color);
      this.labelFont[i+j]  = ax.titlefont.family;
      this.labelSize[i+j]  = ax.titlefont.size;

      this.tickColor[i+j] = str2RGBArray(ax.tickcolor);

      if(ax.tickangle === 'auto') {
        this.tickAngle[i+j] = 0;
      } else {
        this.tickAngle[i+j] = -ax.tickangle;
      }

      this.borderLineEnable[i+j] = ax.showline;
      this.borderLineColor[i+j] = str2RGBArray(ax.linecolor);
      this.borderLineWidth[i+j] = ax.linewidth;
    }

    this.tickEnable[i]     = ax.showticklabels;
    this.labelEnable[i]    = ax.showticklabels;
    this.tickMarkLength[i] = ax.ticklen;
    this.tickMarkWidth[i]  = ax.tickwidth;

    this.gridLineEnable[i]  = ax.showgrid;
    this.gridLineColor[i]   = str2RGBArray(ax.gridcolor);
    this.gridLineWidth[i]   = ax.gridwidth;

    this.zeroLineEnable[i]  = ax.zeroline;
    this.zeroLineColor[i]   = str2RGBArray(ax.zerolinecolor);
    this.zeroLineWidth[i]   = ax.zerolinewidth;
  }
};

function createAxes2D(scene) {
  return new Axes2DOptions(scene);
}

module.exports = createAxes2D;
<commit_msg>remove 'Click to enter title' placeholder axis title<commit_after>'use strict';

var htmlToUnicode = require('../../gl3d/lib/html2unicode');
var str2RGBArray = require('../../gl3d/lib/str2rgbarray');

function Axes2DOptions(scene) {
  this.title = '';

  this.gl = scene.gl;
  this.pixelRatio = scene.pixelRatio;

  this.screenBox = [0,0,1,1];
  this.viewBox   = [0,0,1,1];
  this.dataBox   = [-1,-1,1,1];

  this.borderLineEnable = [false,false,false,false];
  this.borderLineWidth = [1,1,1,1];
  this.borderLineColor = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];

  this.ticks = [[], []];
  this.tickEnable = [true, true, false, false];
  this.tickPad   = [15,15,15,15];
  this.tickAngle = [0,0,0,0];
  this.tickColor = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];
  this.tickMarkWidth = [0,0,0,0];
  this.tickMarkLength = [0,0,0,0];

  this.labels = ['x', 'y'];
  this.labelEnable = [true,true,false,false];
  this.labelAngle  = [0,Math.PI/2,0,3.0*Math.PI/2];
  this.labelPad    = [15,15,15,15];
  this.labelSize   = [12,12];
  this.labelFont   = ['sans-serif', 'sans-serif'];
  this.labelColor  = [
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1],
    [0,0,0,1]
  ];

  this.title       = '';
  this.titleEnable = true;
  this.titleCenter = [0,0,0,0];
  this.titleAngle  = 0;
  this.titleColor  = [0,0,0,1];
  this.titleFont   = 'sans-serif';
  this.titleSize   = 18;

  this.gridLineEnable = [true,true];
  this.gridLineColor  = [
    [0,0,0,0.5],
    [0,0,0,0.5]
  ];
  this.gridLineWidth  = [1,1];

  this.zeroLineEnable = [true,true];
  this.zeroLineWidth  = [1,1];
  this.zeroLineColor  = [
    [0,0,0,1],
    [0,0,0,1]
  ];
}

var proto = Axes2DOptions.prototype;

var AXES = [ 'xaxis', 'yaxis' ];

proto.merge = function(options) {

  //Titles are rendered in SVG
  this.titleEnable = false;

  for(var i=0; i<2; ++i) {
    var ax = options[AXES[i]];
    var axTitle = /Click to enter .+ title/.test(ax.title) ?
        '' :
        ax.title;

    for(var j=0; j<=2; j+=2) {
      this.labels[i+j]     = htmlToUnicode(axTitle);
      this.labelEnable[i+j] = false;
      this.labelColor[i+j] = str2RGBArray(ax.titlefont.color);
      this.labelFont[i+j]  = ax.titlefont.family;
      this.labelSize[i+j]  = ax.titlefont.size;

      this.tickColor[i+j] = str2RGBArray(ax.tickcolor);

      if(ax.tickangle === 'auto') {
        this.tickAngle[i+j] = 0;
      } else {
        this.tickAngle[i+j] = -ax.tickangle;
      }

      this.borderLineEnable[i+j] = ax.showline;
      this.borderLineColor[i+j] = str2RGBArray(ax.linecolor);
      this.borderLineWidth[i+j] = ax.linewidth;
    }

    this.tickEnable[i]     = ax.showticklabels;
    this.labelEnable[i]    = ax.showticklabels;
    this.tickMarkLength[i] = ax.ticklen;
    this.tickMarkWidth[i]  = ax.tickwidth;

    this.gridLineEnable[i]  = ax.showgrid;
    this.gridLineColor[i]   = str2RGBArray(ax.gridcolor);
    this.gridLineWidth[i]   = ax.gridwidth;

    this.zeroLineEnable[i]  = ax.zeroline;
    this.zeroLineColor[i]   = str2RGBArray(ax.zerolinecolor);
    this.zeroLineWidth[i]   = ax.zerolinewidth;
  }
};

function createAxes2D(scene) {
  return new Axes2DOptions(scene);
}

module.exports = createAxes2D;
<|endoftext|>


<commit_before>import { bindActionCreators } from 'redux';
import { createElement, PureComponent } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { COUNTRY } from 'pages/country/router';
import isEqual from 'lodash/isEqual';

import {
  getAdminsOptions,
  getActiveAdmin,
  getAdminsSelected
} from 'pages/country/widget/widget-selectors';
import { format } from 'd3-format';

import * as actions from './header-actions';
import reducers, { initialState } from './header-reducers';

import HeaderComponent from './header-component';

const mapStateToProps = ({ countryData, location, header }) => {
  const {
    isCountriesLoading,
    isRegionsLoading,
    isSubRegionsLoading
  } = countryData;
  const {
    isExtentLoading,
    isPlantationsLossLoading,
    isTotalLossLoading
  } = header;
  const countryDataLoading =
    isCountriesLoading || isRegionsLoading || isSubRegionsLoading;
  const headerDataLoading =
    isExtentLoading || isPlantationsLossLoading || isTotalLossLoading;
  const adminData = {
    countries: countryData.countries,
    regions: countryData.regions,
    subRegions: countryData.subRegions
  };
  return {
    isLoading: countryDataLoading || headerDataLoading,
    locationOptions: getAdminsOptions({
      ...adminData,
      location: location.payload
    }),
    settings: header.settings,
    location: location.payload,
    locationNames: getAdminsSelected({
      ...adminData,
      location: location.payload
    }),
    activeLocation: getActiveAdmin({ location: location.payload }),
    data: header.data
  };
};

const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      handleCountryChange: country => ({
        type: COUNTRY,
        payload: { country: country.value }
      }),
      handleRegionChange: (country, region) => ({
        type: COUNTRY,
        payload: { country: country.value, region: region.value }
      }),
      handleSubRegionChange: (country, region, subRegion) => ({
        type: COUNTRY,
        payload: {
          country: country.value,
          region: region.value,
          subRegion: subRegion.value
        }
      }),
      ...actions
    },
    dispatch
  );

class HeaderContainer extends PureComponent {
  componentDidMount() {
    const {
      location,
      settings,
      getTotalExtent,
      getTotalLoss,
      getPlantationsLoss
    } = this.props;
    getTotalExtent({ ...location, ...settings });
    getTotalLoss({ ...location, ...settings });
    getPlantationsLoss({ ...location, ...settings, indicator: 'plantations' });
    if (location.region) {
      getTotalExtent({ ...location, ...settings });
    }
    if (location.subRegion) {
      getTotalExtent({ ...location, ...settings });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { location, settings } = nextProps;
    const { getTotalExtent, getTotalLoss, getPlantationsLoss } = this.props;

    if (!isEqual(location, this.props.location)) {
      getTotalExtent({ ...nextProps.location, ...settings });
      getTotalLoss({ ...nextProps.location, ...settings });
      getPlantationsLoss({
        ...nextProps.location,
        ...settings,
        indicator: 'plantations'
      });
    }
  }

  getHeaderDescription = () => {
    const { locationNames, data } = this.props;
    const extent = format('.2s')(data.extent);
    const percentageCover = format('.1f')(data.extent / data.totalArea * 100);
    const lossWithOutPlantations = format('.2s')(
      data.totalLoss.area - (data.plantationsLoss.area || 0)
    );
    const emissionsWithoutPlantations = format('.2s')(
      data.totalLoss.emissions - (data.plantationsLoss.emissions || 0)
    );
    const location = locationNames.current && locationNames.current.label;
    let firstSentence = '';
    let secondSentence = '';
    if (data.extent > 0) {
      firstSentence = `
        In 2010, ${location} had ${extent}ha of tree cover, extending over ${percentageCover}% of its land area.
      `;
    } else {
      firstSentence = `
        In 2010, ${location} had no tree cover.
      `;
    }
    if (data.extent > 0 && data.totalLoss.area) {
      secondSentence = `
        In ${
          data.totalLoss.year
        }, it lost ${lossWithOutPlantations}ha of forest ${
          data.plantationsLoss.area ? 'excluding tree plantations' : ''
        }, equivalent to ${emissionsWithoutPlantations}tonnes of CO₂ of emissions.
      `;
    }
    return `${firstSentence} ${secondSentence}`;
  };

  render() {
    return createElement(HeaderComponent, {
      ...this.props,
      getHeaderDescription: this.getHeaderDescription
    });
  }
}

HeaderContainer.propTypes = {
  location: PropTypes.object.isRequired,
  locationNames: PropTypes.object.isRequired,
  getTotalExtent: PropTypes.func.isRequired,
  getTotalLoss: PropTypes.func.isRequired,
  getPlantationsLoss: PropTypes.func.isRequired,
  data: PropTypes.object.isRequired,
  settings: PropTypes.object.isRequired
};

export { actions, reducers, initialState };

export default connect(mapStateToProps, mapDispatchToProps)(HeaderContainer);
<commit_msg>header sentence breaking when no plantations<commit_after>import { bindActionCreators } from 'redux';
import { createElement, PureComponent } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { COUNTRY } from 'pages/country/router';
import isEqual from 'lodash/isEqual';

import {
  getAdminsOptions,
  getActiveAdmin,
  getAdminsSelected
} from 'pages/country/widget/widget-selectors';
import { format } from 'd3-format';

import * as actions from './header-actions';
import reducers, { initialState } from './header-reducers';

import HeaderComponent from './header-component';

const mapStateToProps = ({ countryData, location, header }) => {
  const {
    isCountriesLoading,
    isRegionsLoading,
    isSubRegionsLoading
  } = countryData;
  const {
    isExtentLoading,
    isPlantationsLossLoading,
    isTotalLossLoading
  } = header;
  const countryDataLoading =
    isCountriesLoading || isRegionsLoading || isSubRegionsLoading;
  const headerDataLoading =
    isExtentLoading || isPlantationsLossLoading || isTotalLossLoading;
  const adminData = {
    countries: countryData.countries,
    regions: countryData.regions,
    subRegions: countryData.subRegions
  };
  return {
    isLoading: countryDataLoading || headerDataLoading,
    locationOptions: getAdminsOptions({
      ...adminData,
      location: location.payload
    }),
    settings: header.settings,
    location: location.payload,
    locationNames: getAdminsSelected({
      ...adminData,
      location: location.payload
    }),
    activeLocation: getActiveAdmin({ location: location.payload }),
    data: header.data
  };
};

const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      handleCountryChange: country => ({
        type: COUNTRY,
        payload: { country: country.value }
      }),
      handleRegionChange: (country, region) => ({
        type: COUNTRY,
        payload: { country: country.value, region: region.value }
      }),
      handleSubRegionChange: (country, region, subRegion) => ({
        type: COUNTRY,
        payload: {
          country: country.value,
          region: region.value,
          subRegion: subRegion.value
        }
      }),
      ...actions
    },
    dispatch
  );

class HeaderContainer extends PureComponent {
  componentDidMount() {
    const {
      location,
      settings,
      getTotalExtent,
      getTotalLoss,
      getPlantationsLoss
    } = this.props;
    getTotalExtent({ ...location, ...settings });
    getTotalLoss({ ...location, ...settings });
    getPlantationsLoss({ ...location, ...settings, indicator: 'plantations' });
    if (location.region) {
      getTotalExtent({ ...location, ...settings });
    }
    if (location.subRegion) {
      getTotalExtent({ ...location, ...settings });
    }
  }

  componentWillReceiveProps(nextProps) {
    const { location, settings } = nextProps;
    const { getTotalExtent, getTotalLoss, getPlantationsLoss } = this.props;

    if (!isEqual(location, this.props.location)) {
      getTotalExtent({ ...nextProps.location, ...settings });
      getTotalLoss({ ...nextProps.location, ...settings });
      getPlantationsLoss({
        ...nextProps.location,
        ...settings,
        indicator: 'plantations'
      });
    }
  }

  getHeaderDescription = () => {
    const { locationNames, data } = this.props;
    const extent = format('.2s')(data.extent);
    const percentageCover = format('.1f')(data.extent / data.totalArea * 100);
    const lossWithOutPlantations = format('.2s')(
      data.totalLoss.area - (data.plantationsLoss.area || 0)
    );
    const emissionsWithoutPlantations = format('.2s')(
      data.totalLoss.emissions - (data.plantationsLoss.emissions || 0)
    );
    const location = locationNames.current && locationNames.current.label;
    let firstSentence = '';
    let secondSentence = '';
    if (data.extent > 0) {
      firstSentence = `
        In 2010, ${location} had ${extent}ha of tree cover, extending over ${percentageCover}% of its land area.
      `;
    } else {
      firstSentence = `
        In 2010, ${location} had no tree cover.
      `;
    }
    if (data.extent > 0 && data.totalLoss.area) {
      secondSentence = `
        In ${
          data.totalLoss.year
        }, it lost ${lossWithOutPlantations}ha of forest${
          data.plantationsLoss.area ? ' excluding tree plantations' : ''
        }, equivalent to ${emissionsWithoutPlantations}tonnes of CO₂ of emissions.
      `;
    }
    return `${firstSentence} ${secondSentence}`;
  };

  render() {
    return createElement(HeaderComponent, {
      ...this.props,
      getHeaderDescription: this.getHeaderDescription
    });
  }
}

HeaderContainer.propTypes = {
  location: PropTypes.object.isRequired,
  locationNames: PropTypes.object.isRequired,
  getTotalExtent: PropTypes.func.isRequired,
  getTotalLoss: PropTypes.func.isRequired,
  getPlantationsLoss: PropTypes.func.isRequired,
  data: PropTypes.object.isRequired,
  settings: PropTypes.object.isRequired
};

export { actions, reducers, initialState };

export default connect(mapStateToProps, mapDispatchToProps)(HeaderContainer);
<|endoftext|>