it( 'should extend by several params in the correct order', () => { const target = { a: 0, b: 0 }; const ext1 = { b: 1, c: 1 }; const ext2 = { c: 2, d: 2 }; extend( target, ext1, ext2 ); expect( target ).to.have.property( 'a' ).to.equal( 0 ); expect( target ).to.have.property( 'b' ).to.equal( 1 ); expect( target ).to.have.property( 'c' ).to.equal( 2 ); expect( target ).to.have.property( 'd' ).to.equal( 2 ); } );
return o.x; }); sortedIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, "x"); /** * _.sortedLastIndexBy */ sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, function(o) { return o.x; }); sortedLastIndexBy([{ x: 4 }, { x: 5 }], { x: 4 }, "x"); /** * _.extend */ extend({ a: 1 }, { b: 2 }).a; extend({ a: 1 }, { b: 2 }).b; // $ExpectError property `c`. Property not found in object literal extend({ a: 1 }, { b: 2 }).c; // $ExpectError property `c`. Poperty not found in object literal assignIn({ a: 1 }, { b: 2 }).c; /** * _.xorBy */ xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); xorBy([{ x: 1 }], [{ x: 2 }, { x: 1 }], "x"); /** * _.zip */
constructor( $rootScope, $scope, $location, $routeParams, $filter, $q, Restangular, Scroll, Courses, ) { const originalDisplayLimit = 25; const year = new Date().getFullYear(); const upperYear = year + 1; let lowerYear = year; let url = {}; let courses = []; extend($scope, { coursesPerFetch: 100, courseSelected: 0, fetchNoMore: false, displayLimit: 25, filter: {}, filteredCourses: [], fetching: false, textModelOptions: { updateOn: 'default blur', debounce: { default: 200, blur: 0 }, }, orderBys: { /* eslint-disable key-spacing, no-multi-spaces */ code: ['code', '-year', '-term', 'course'], '-code': ['-code', '-year', '-term', 'course'], course: ['course', '-year', '-term'], '-course': ['-course', '-year', '-term'], teachers: ['teachers_str', '-year', '-term', 'course'], '-teachers': ['-teachers_str', '-year', '-term', 'course'], fields: ['fields_str', '-year', '-term', 'course'], '-fields': ['-fields_str', '-year', '-term', 'course'], time: ['year', '-term', 'course'], '-time': ['-year', '-term', 'course'], }, /* eslint-enable key-spacing, no-multi-spaces */ }); $scope.order = $scope.orderBys['-time']; /** * Extract the url parameters for use in a search query. */ const fetchParams = () => { const params = $routeParams; $scope.filter = { code: params.code, course: params.course, teachers_str: params.teacher, fields_str: params.field, 'fields_str#~': params.pm ? '(PM)' : null, }; if (!isUndefined(params.timeframe)) { $scope.timeframe = params.timeframe; params.timeframe = params.timeframe.toLowerCase(); if (params.timeframe.charAt(0) === 'w' || params.timeframe.charAt(0) === 's') { $scope.filter['term#='] = params.timeframe.charAt(0); params.timeframe = params.timeframe.slice(1); } // eslint-disable-next-line max-len const pattern = /(?:^(?:20)?(\d{2})$)|(?:(?:20)?(\d{2})([+-])(?:(?:20)?(\d{2}))?)|(?:([WS])S?(?:20)?(\d{2}))|([WS])/i; const r = compact(pattern.exec(trim(params.timeframe))); if (!isEmpty(r)) { if (isEmpty(r[2])) { $scope.filter['year#='] = `20${r[1]}`; } else if (r[2] === '+') { // year lower limit $scope.filter['year#<'] = `20${r[1]}`; } else if (r[2] === '-') { if (!isEmpty(r[3])) { // years range $scope.filter['year#<'] = `20${r[1]}`; $scope.filter['year#>'] = `20${r[3]}`; } else { // year upper limit $scope.filter['year#>'] = `20${r[1]}`; } } } } $scope.filter = pickBy($scope.filter); $scope.regulation_id = params.regulation ? parseInt(params.regulation, 10) : ''; }; /** * Updates all URL parameters using the information from the current filters. */ const refreshUrl = () => { const { filter, regulation_id, timeframe } = $scope; const { code, course, teachers_str, fields_str } = filter; url = { regulation: regulation_id, pm: !!filter['fields_str#~'], timeframe, code, course, teacher: teachers_str, field: fields_str, }; url = pickBy(url); $location.search(url); }; /** * Refreshes des course list with the new filters applied. * * TODO: unify with navbar.js */ const applyFilter = (justFetch, force) => { const { filter, orderBys, order, displayLimit, filteredCourses, regulation_id, } = $scope; const minYear = get(filter, 'year#=', get(filter, 'year#<', 1995)); if (!justFetch) { $scope.filteredCourses = $filter('courseFilter')(courses, filter); } if ($scope.fetching || lowerYear < minYear) { return; } if ( (order === orderBys.time && lowerYear > minYear) || displayLimit > (filteredCourses.length - 5) || force ) { $scope.fetching = true; lowerYear -= 2; Courses .fetch(regulation_id, lowerYear, upperYear, null) .then(newCourses => { courses = newCourses; $scope.fetching = false; applyFilter(); }); } }; /** * Watches the general filter object. Contains the code, title, teachers and * field of study input fields. */ $scope.$watch('filter', (next, current) => { if (next === current) { return; } applyFilter(); refreshUrl(); }, true); /** * Watches the "obligatory module" checkbox. */ $scope.$watch('pm', (next, current) => { if (isUndefined(next) || next === current) { return; } if (next) { $scope.filter['fields_str#~'] = '(PM)'; } else { delete $scope.filter['fields_str#~']; refreshUrl(); // delete does not trigger the filter watch } }); /** * Watches the timeframe input field. */ $scope.$watch('timeframe', (next, current) => { if (isUndefined(next) || next === current) { return; } refreshUrl(); // delete does not trigger the filter watch }); /** * Is triggered when the user changes the regulation input field. */ $scope.$watch('regulation_id', (next, current) => { if (isUndefined(next) || next === current) { return; } $scope.displayLimit = originalDisplayLimit; lowerYear = year - 1; $scope.filteredCourses = []; applyFilter(true); refreshUrl(); }); /** * Called when user explicitly clicks the "show more courses" button. This * won't be used in most cases because of infinite scrolling. */ $scope.scrollOn = amount => { if ($scope.displayLimit < $scope.filteredCourses.length) { $scope.displayLimit += isUndefined(amount) ? originalDisplayLimit : amount; } if ($scope.displayLimit > ($scope.filteredCourses.length - 50)) { applyFilter(true); } }; $scope.orderBy = order => { $scope.order = ($scope.order === $scope.orderBys[order]) ? $scope.orderBys[`-${order}`] : $scope.orderBys[order]; applyFilter(true, true); }; /** * Watch for route updates and refetch the course list if required */ $scope.$on('$routeUpdate', (event, route) => { if (route.params === url) { return; } fetchParams(); }); // get all regulations Restangular .all('regulations') .getList() .then(regulations => { const t = find(regulations, { regulation_id: 4 }); $scope.regulations = without(regulations, t); $scope.regulations.unshift({ regulation_id: '', regulation: 'All courses', }); fetchParams(); }); }
(updateWith(null, null, null, null): null); (values(null): Array<*>); (valuesIn(null): Array<*>); (without(): Array<*>); (words(null, null): Array<*>); (wrap(null, null): Function); (xor(): Array<*>); (xorBy(): Array<*>); (xorWith(): Array<*>); (zip(): Array<*>); (zipObject(null, null): {}); (zipObjectDeep(null, null): {}); (zipWith(): Array<*>); (entries(null): Array<*>); (entriesIn(null): Array<*>); (extend(): Object); (extendWith(): Object); (camelCase(null): ''); (capitalize(null): ''); (clamp(null, null, null): 0); (clone(null): null); (cloneDeep(null): null); (cloneDeepWith(null, null): null); (cloneWith(null, null): null); (deburr(null): ''); (defaultTo(null, null): null); (endsWith(null, null, null): false); (eq(null, null): boolean); (escape(null): ''); (escapeRegExp(null): ''); (find(null, null, null): void);