Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rtt 145 convert discussions and lectures #1817

Open
wants to merge 28 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e3b32fb
confirmation modal when conversion is required
eduranperez Jan 13, 2021
a622a6b
always fetch sections
eduranperez Jan 14, 2021
246ab75
dont compare against self for uniqueness
eduranperez Jan 14, 2021
1510d9c
reset original sequence pattern
eduranperez Jan 14, 2021
15d525d
show before and after sequence pattern in confirmation modal
eduranperez Jan 14, 2021
6ed6bac
fix padding
eduranperez Jan 14, 2021
7141ab3
example text
eduranperez Jan 14, 2021
ebb146d
compare with state instead of local scope var to check for change
eduranperez Jan 14, 2021
5d1548f
linting
eduranperez Jan 15, 2021
04b640f
change seat display for example
eduranperez Jan 19, 2021
0a7373a
clear section list on course update
eduranperez Jan 19, 2021
9088e7b
update sections array on FETCH_SECTIONS
eduranperez Jan 19, 2021
709e8f8
create new course
eduranperez Jan 21, 2021
9e9fb47
creating new offering
eduranperez Jan 21, 2021
acb01ee
update state with new course and section group
eduranperez Jan 21, 2021
da58093
update state properly after new offering creation. Switch selected r…
eduranperez Jan 22, 2021
00ce9a5
fix conditional displaying of text/examples
eduranperez Jan 23, 2021
78f4933
validate sequence pattern
eduranperez Jan 25, 2021
3687b1f
linting
eduranperez Jan 25, 2021
f041b16
remove console log, revert unused changes on course details
eduranperez Jan 25, 2021
fadb9c8
remove more console logs
eduranperez Jan 25, 2021
2c81be8
add details to description of actions and hightlight input field on i…
eduranperez Jan 25, 2021
065280b
alter wording
eduranperez Jan 26, 2021
6c2020f
only remove old sectiongroup from state if request succeeded
eduranperez Jan 26, 2021
cfd582c
ensure new offering would be unique
eduranperez Jan 27, 2021
807e4eb
update modal wording
eduranperez Jan 27, 2021
8dc806b
linting
eduranperez Jan 28, 2021
0e10b71
update wording, convert user input to uppercase
eduranperez Jan 28, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/course/courseApp.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import censusChart from './directives/censusChart.js';
import courseTable from './directives/courseTable.js';
import activeFilters from './directives/activeFilters/activeFilters.js';
import moveCourseModal from './directives/moveCourseModal/moveCourseModal.js';
import convertSectionsModal from './directives/convertSectionsModal/convertSectionsModal.js';

// Dependencies
var dependencies = [
Expand Down Expand Up @@ -88,6 +89,7 @@ const courseApp = angular.module("courseApp", dependencies) // eslint-disable-li
.directive('censusChart', censusChart)
.directive('courseTable', courseTable)
.directive('activeFilters', activeFilters)
.directive('convertSectionsModal', convertSectionsModal)
.constant('ActionTypes', {
INIT_STATE: "INIT_STATE",
NEW_COURSE: "NEW_COURSE",
Expand All @@ -97,6 +99,7 @@ const courseApp = angular.module("courseApp", dependencies) // eslint-disable-li
GET_COURSE_CENSUS: "GET_COURSE_CENSUS",
BEGIN_FETCH_CENSUS: "BEGIN_FETCH_CENSUS",
ADD_SECTION_GROUP: "ADD_SECTION_GROUP",
CREATE_SECTION_GROUP: "CREATE_SECTION_GROUP",
REMOVE_SECTION_GROUP: "REMOVE_SECTION_GROUP",
UPDATE_SECTION_GROUP: "UPDATE_SECTION_GROUP",
TOGGLE_TERM_FILTER: "TOGGLE_TERM_FILTER",
Expand Down Expand Up @@ -124,7 +127,8 @@ const courseApp = angular.module("courseApp", dependencies) // eslint-disable-li
CLOSE_COURSE_DELETION_MODAL: "CLOSE_COURSE_DELETION_MODAL",
TOGGLE_MOVE_COURSE_MODAL: "TOGGLE_MOVE_COURSE_MODAL",
DELETE_MULTIPLE_COURSES: "DELETE_MULTIPLE_COURSES",
MASS_ASSIGN_TAGS: "MASS_ASSIGN_TAGS"
MASS_ASSIGN_TAGS: "MASS_ASSIGN_TAGS",
TOGGLE_CONVERT_SECTIONS_MODAL: "TOGGLE_CONVERT_SECTIONS_MODAL"
});

export default courseApp;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.convert-sections-modal .convert-sections-modal-footer {
padding: 10px;
display: flex;
justify-content: flex-end;
padding-bottom: 15px;
padding-top: 15px;
}

.convert-sections-modal .convert-sections-warning {
padding: 20px;
}

.convert-sections-modal .sub-detail {
font-weight: bold;
font-size: 14px;
padding-top: 15px;
}

.convert-sections-modal .btn-default {
background-color: white;
margin-right: 10px;
}

.convertion-details {
display: flex;
}

.conversion-details-example {
flex: 50%;
}

.course-details_update-sequence {
width: 135px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<div class="convert-sections-modal">
<form role="form" class="form-horizontal">
<div class="convert-sections-warning">
<div >
<strong>New Sequence Pattern</strong>
<br />
<div class="course-details_update-sequence"
tooltip-append-to-body="true"
tooltip-placement="left"
uib-tooltip="{{ selectedEntity.sequencePatternTooltipMessage }}">
<ipa-input
value="selectedEntity.sequencePattern"
is-invalid="selectedEntity.sequencePattern && (!isValid() || !isUnique())"
on-update="updateSequencePattern()"
on-blur="updateSequencePattern()"
update-delay="50">
</ipa-input>
</div>
<div>
<br>
After conversion <strong>teaching assignments</strong> and the <strong>Live Data budget scenario</strong> will be updated to reflect the change.
<br>
<i>All non-live data budget scenarios will be updated <strong>unless</strong> they have a conflicting offering.</i>
<br>
<i>Budget requests will <strong>not</strong> be updated.</i>
<br><br>
Additionally, sections that belong to this course offering will be converted from <strong>{{isSeries() ? 'discussions to lectures' : 'lectures to discussions'}}</strong>
<br><br><b>For Example:</b><br><br>
<div class="convertion-details" ng-show="!isSeries()">
<div class="conversion-details-example">
<strong>Before</strong><br><br>
XYZ 10 - 001
<li>
Section 001: 100 Seats
</li>
</div>
<div class="conversion-details-example">
<strong>After</strong><br><br>
XYZ 10 - A
<li>
Section A01: 100 Seats
</li>
</div>
</div>
<div class="convertion-details" ng-show="isSeries()">
<div class="conversion-details-example">
<strong>Before</strong><br><br>
XYZ 10 - A
<li>
Section A01: 25 Seats
</li>
<li>
Section A02: 25 Seats
</li>
<li>
Section A03: 25 Seats
</li>
<li>
Section A04: 25 Seats
</li>
</div>
<div class="conversion-details-example">
<strong>After</strong><br><br>
XYZ 10 - 001
<li>
Section 001 Seats 100
</li>
</div>
</div>
</div>
</div>

<div class="convert-sections-modal-footer">
<button ng-click="close()"
type="button"
class="btn btn-default modal-button">
Cancel
</button>
<button ng-click="convertCourseOffering()"
ng-disabled="!isValid() || !isUnique()"
type="button"
class="btn btn-danger modal-button">
Convert
</button>
</div>
</form>
</div>
106 changes: 106 additions & 0 deletions app/course/directives/convertSectionsModal/convertSectionsModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import './convertSectionsModal.css';
import { isNumber, isLetter } from 'shared/helpers/types';

let convertSectionsModal = function (CourseActionCreators) {
return {
restrict: 'E',
template: require('./convertSectionsModal.html'),
replace: true,
scope: {
workgroupId: '<',
year: '<',
selectedEntity: '<',
isVisible: '=',
state: '='
},
link: function (scope) {

scope.convertCourseOffering = function () {
CourseActionCreators.convertCourseOffering(scope.workgroupId, scope.year, scope.selectedEntity, scope.selectedEntity.sequencePattern.toUpperCase());
scope.isVisible = false;
};

scope.close = function() {
scope.isVisible = false;
};

scope.isSeries = function () {
if (scope.selectedEntity){
let selectedEntity = scope.selectedEntity;
let course = scope.state.courses.list[selectedEntity.courseId];
if (course){
return course.isSeries();
} else {
return false;
}
}
return false;
};

scope.isValid = function () {
var isValid = false;
if (scope.selectedEntity && scope.selectedEntity.sequencePattern){
if (!scope.isSeries()){
if (scope.selectedEntity.sequencePattern.length === 1 && isLetter(scope.selectedEntity.sequencePattern[0].toUpperCase())){
scope.selectedEntity.sequencePatternTooltipMessage = null;
isValid = true;
} else {
scope.selectedEntity.sequencePatternTooltipMessage = "Sequence pattern format is incorrect. Valid format is '1 letter' (ex: 'A').";
isValid = false;
}
} else {
if (
scope.selectedEntity.sequencePattern.length === 3 &&
isNumber(scope.selectedEntity.sequencePattern[0]) &&
isNumber(scope.selectedEntity.sequencePattern[1]) &&
isNumber(scope.selectedEntity.sequencePattern[2])
){
scope.selectedEntity.sequencePatternTooltipMessage = null;
isValid = true;
} else {
scope.selectedEntity.sequencePatternTooltipMessage = "Sequence pattern format is incorrect. Valid format is '3 numbers' (ex: '002').";
isValid = false;
}
}
}
return isValid;
};

scope.isUnique = function () {
var isUnique = false;
if (scope.selectedEntity && scope.selectedEntity.sequencePattern){
var sectionGroup = scope.selectedEntity;
var course = course = scope.state.courses.list[sectionGroup.courseId];
var courseDescription = course.subjectCode + "-" + course.courseNumber + "-" + sectionGroup.sequencePattern.toUpperCase();
isUnique = true;
scope.selectedEntity.sequencePatternTooltipMessage = null;

scope.state.courses.ids.forEach(function(courseId) {
var c = scope.state.courses.list[courseId];
let cDescription = c.subjectCode + "-" + c.courseNumber + "-" + c.sequencePattern;

if (courseDescription == cDescription) {
scope.state.sectionGroups.ids.forEach(function(sectionGroupId) {
var sg = scope.state.sectionGroups.list[sectionGroupId];
if (sg.courseId == c.id && sg.termCode == sectionGroup.termCode){
scope.selectedEntity.sequencePatternTooltipMessage = "Sequence pattern already in use.";
isUnique = false;
}
});
}
});
}

return isUnique;
};

scope.updateSequencePattern = function(){
if (scope.selectedEntity.sequencePattern){
scope.selectedEntity.sequencePattern = scope.selectedEntity.sequencePattern.toUpperCase();
}
};
} // end link
};
};

export default convertSectionsModal;
2 changes: 1 addition & 1 deletion app/course/directives/courseDetails/courseDetails.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ <h4>
<ipa-input value="view.selectedEntity.sequencePattern"
on-update="updateSequencePattern()"
on-blur="updateSequencePattern()"
update-delay="50"
update-delay="1"
place-holder="sequenceNumberPlaceholder"
ng-if="!view.state.uiState.tableLocked"
is-invalid="courseDetails.sequencePatternTooltipMessage">
Expand Down
2 changes: 1 addition & 1 deletion app/course/directives/courseDetails/courseDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ let courseDetails = function (CourseActionCreators, SectionService) {
}

if (scope.isSequencePatternUnique(sequencePattern) == false) {
scope.courseDetails.sequencePatternTooltipMessage = "Sequence pattern already in use";
scope.courseDetails.sequencePatternTooltipMessage = "Sequence pattern already in use.";
return;
}

Expand Down
22 changes: 21 additions & 1 deletion app/course/directives/courseTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ let courseTable = function ($rootScope, $timeout, CourseActionCreators, $compile
ActionTypes.UPDATE_SECTION_GROUP,
ActionTypes.REMOVE_SECTION_GROUP,
ActionTypes.ADD_SECTION_GROUP,
ActionTypes.CREATE_SECTION_GROUP,
ActionTypes.DELETE_MULTIPLE_COURSES,
ActionTypes.MASS_ASSIGN_TAGS,
ActionTypes.CREATE_SECTION,
Expand All @@ -56,11 +57,30 @@ let courseTable = function ($rootScope, $timeout, CourseActionCreators, $compile
return;
}

if (data.action.type == ActionTypes.ADD_SECTION_GROUP) {
if (data.action.type == ActionTypes.ADD_SECTION_GROUP || data.action.type == ActionTypes.CREATE_SECTION_GROUP) {
// Indicate on the textbox that the sectionGroup is offered
$('tr[data-course-id="' + data.action.payload.sectionGroup.courseId + '"] td[data-term-code="' + data.action.payload.sectionGroup.termCode + '"]').addClass("is-offered"); // eslint-disable-line no-undef
$('tr[data-course-id="' + data.action.payload.sectionGroup.courseId + '"] td[data-term-code="' + data.action.payload.sectionGroup.termCode + '"] input').attr( 'placeholder', '0 planned seats' ); // eslint-disable-line
$('tr[data-course-id="' + data.action.payload.sectionGroup.courseId + '"] td[data-term-code="' + data.action.payload.sectionGroup.termCode + '"] input').attr( 'value', data.action.payload.sectionGroup.plannedSeats ); // eslint-disable-line

if (data.action.type == ActionTypes.CREATE_SECTION_GROUP){
scope.previouslySelectedCourseId = data.state.uiState.selectedCourseId;
scope.previouslySelectedTermCode = data.state.uiState.selectedTermCode;

// Remove existing highlighting
element.find('tbody > tr').removeClass("selected-tr");
element.find('tbody > tr > td').removeClass("selected-td");

data.state.uiState.selectedCourseId = data.action.payload.sectionGroup.courseId;
$('tr[data-course-id="' + data.state.uiState.selectedCourseId + '"] td[data-term-code="' + data.state.uiState.selectedTermCode + '"]').addClass("selected-td"); // eslint-disable-line no-undef

scope.manuallyDeselectAllCourseRows();
scope.manuallyToggleSelectedCourse(data.state.uiState.selectedCourseId);
CourseActionCreators.deselectAllCourseRows();
CourseActionCreators.toggleSelectCourse(data.state.uiState.selectedCourseId);

return;
}

return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.section-group-details__convert-offering-container {
margin-bottom: 20px
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,15 @@ <h4>
overflow-auto="true"
></ipa-dropdown>

<div class="section-group-details__convert-offering-container">
<button
class="btn btn-primary"
ng-click="convertOffering()"
ng-if="!isLocked()">
Convert to {{isSeries() ? "Lecture" : "Discussion"}}
</button>
</div>

<button
class="btn btn-danger"
ng-if="!isLocked()"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import './sectionGroupDetails.css';

let sectionGroupDetails = function (CourseActionCreators, Term) {
return {
restrict: 'E',
Expand Down Expand Up @@ -107,6 +109,10 @@ let sectionGroupDetails = function (CourseActionCreators, Term) {
let course = scope.view.state.courses.list[selectedEntity.courseId];
return course.isSeries();
};

scope.convertOffering = function (){
CourseActionCreators.toggleConvertSectionsModal();
};
}
};
};
Expand Down
Loading