feat(course-teaser): moved course teaser functionality to util
Moved course teaser js functionality to frontend util; removed css class course-teaser and course-teaser div id; moved styling of course teaser from colonnade.lucius to course-teaser.scss of util
This commit is contained in:
parent
48113ebee0
commit
c99a3c7009
37
frontend/src/utils/course-teaser/course-teaser.js
Normal file
37
frontend/src/utils/course-teaser/course-teaser.js
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { Utility } from '../../core/utility';
|
||||||
|
import './course-teaser.scss';
|
||||||
|
|
||||||
|
var COURSE_TEASER_INITIALIZED_CLASS = 'course-teaser--initialized';
|
||||||
|
|
||||||
|
var COURSE_TEASER_EXPANDED_CLASS = 'course-teaser__expanded';
|
||||||
|
var COURSE_TEASER_CHEVRON_CLASS = 'course-teaser__chevron';
|
||||||
|
|
||||||
|
@Utility({
|
||||||
|
selector: '[uw-course-teaser]',
|
||||||
|
})
|
||||||
|
export class CourseTeaser {
|
||||||
|
|
||||||
|
_element;
|
||||||
|
|
||||||
|
constructor(element) {
|
||||||
|
if (!element) {
|
||||||
|
throw new Error('CourseTeaser utility cannot be setup without an element!');
|
||||||
|
}
|
||||||
|
if (element.classList.contains(COURSE_TEASER_INITIALIZED_CLASS)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this._element = element;
|
||||||
|
element.addEventListener('click', e => this._onToggleExpand(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
_onToggleExpand(event) {
|
||||||
|
var isLink = event.target.tagName.toLowerCase() === 'a';
|
||||||
|
var isChevron = event.target.classList.contains(COURSE_TEASER_CHEVRON_CLASS);
|
||||||
|
var isExpanded = event.target.classList.contains(COURSE_TEASER_EXPANDED_CLASS);
|
||||||
|
|
||||||
|
if ((!isExpanded && !isLink) || isChevron) {
|
||||||
|
this._element.classList.toggle(COURSE_TEASER_EXPANDED_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
8
frontend/src/utils/course-teaser/course-teaser.md
Normal file
8
frontend/src/utils/course-teaser/course-teaser.md
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# CourseTeaser
|
||||||
|
|
||||||
|
Handles expanding and collapsing single course teaser widgets on click.
|
||||||
|
|
||||||
|
## Example usage
|
||||||
|
```html
|
||||||
|
<div uw-course-teaser>
|
||||||
|
```
|
||||||
135
frontend/src/utils/course-teaser/course-teaser.scss
Normal file
135
frontend/src/utils/course-teaser/course-teaser.scss
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
[uw-course-teaser] {
|
||||||
|
display: grid;
|
||||||
|
grid-gap: 5px 7px;
|
||||||
|
grid-template-columns: 50px 120px 1fr;
|
||||||
|
padding: 10px;
|
||||||
|
/* background-color: var(--course-bg-color); */
|
||||||
|
transition: background-color .1s ease-out;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--course-bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
+ [uw-course-teaser] {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* chevron */
|
||||||
|
.course-teaser__chevron {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 10px;
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 2;
|
||||||
|
justify-self: center;
|
||||||
|
align-self: center;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
margin-top: -8px;
|
||||||
|
border-width: 0 3px 3px 0;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-color: var(--color-fontsec);
|
||||||
|
border-style: solid;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
transition: transform .2s ease-out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* semester */
|
||||||
|
.course-teaser__semester {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 1;
|
||||||
|
justify-self: end;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
a {
|
||||||
|
color: var(--color-fontsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* shorthand */
|
||||||
|
.course-teaser__shorthand {
|
||||||
|
grid-column: 2;
|
||||||
|
grid-row: 2;
|
||||||
|
justify-self: end;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* title */
|
||||||
|
.course-teaser__title {
|
||||||
|
grid-column: 3;
|
||||||
|
grid-row: 2;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
align-self: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* registration */
|
||||||
|
.course-teaser__registration {
|
||||||
|
grid-column: 4;
|
||||||
|
grid-row: 2;
|
||||||
|
justify-self: end;
|
||||||
|
align-self: baseline;
|
||||||
|
color: var(--color-fontsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* school */
|
||||||
|
.course-teaser__school-value {
|
||||||
|
grid-column: 3;
|
||||||
|
grid-row: 1;
|
||||||
|
align-self: end;
|
||||||
|
a {
|
||||||
|
color: var(--color-fontsec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* description */
|
||||||
|
.course-teaser__description {
|
||||||
|
grid-column: 3;
|
||||||
|
color: var(--color-fontsec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* subtitle */
|
||||||
|
.course-teaser__lecturer-label,
|
||||||
|
.course-teaser__duedate-label,
|
||||||
|
.course-teaser__school-label {
|
||||||
|
grid-column: 2;
|
||||||
|
justify-self: end;
|
||||||
|
color: var(--color-fontsec);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* hidden in closed state */
|
||||||
|
.course-teaser__duedate-label,
|
||||||
|
.course-teaser__duedate-value,
|
||||||
|
.course-teaser__description,
|
||||||
|
.course-teaser__registration {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* registered courses */
|
||||||
|
.course-teaser__registered {
|
||||||
|
.course-teaser__registration {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expanded courses */
|
||||||
|
.course-teaser__expanded {
|
||||||
|
max-height: 1000px;
|
||||||
|
|
||||||
|
.course-teaser__chevron::before {
|
||||||
|
transform: translateY(7px) rotate(225deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.course-teaser__school-label,
|
||||||
|
.course-teaser__school-value,
|
||||||
|
.course-teaser__duedate-label,
|
||||||
|
.course-teaser__duedate-value,
|
||||||
|
.course-teaser__description {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ import { InputUtils } from './inputs/inputs';
|
|||||||
import { MassInput } from './mass-input/mass-input';
|
import { MassInput } from './mass-input/mass-input';
|
||||||
import { Modal } from './modal/modal';
|
import { Modal } from './modal/modal';
|
||||||
import { Tooltip } from './tooltips/tooltips';
|
import { Tooltip } from './tooltips/tooltips';
|
||||||
|
import { CourseTeaser } from './course-teaser/course-teaser';
|
||||||
|
|
||||||
export const Utils = [
|
export const Utils = [
|
||||||
Alerts,
|
Alerts,
|
||||||
@ -23,4 +24,5 @@ export const Utils = [
|
|||||||
Modal,
|
Modal,
|
||||||
ShowHide,
|
ShowHide,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
|
CourseTeaser,
|
||||||
];
|
];
|
||||||
|
|||||||
@ -1035,14 +1035,13 @@ dbTable PSValidator{..} dbtable@DBTable{ dbtIdent = dbtIdent'@(toPathPiece -> db
|
|||||||
columnCount = olength64 $ getColonnade dbtColonnade
|
columnCount = olength64 $ getColonnade dbtColonnade
|
||||||
in case dbsTemplate of
|
in case dbsTemplate of
|
||||||
DBSTCourse c l r s -> do
|
DBSTCourse c l r s -> do
|
||||||
wRows <- forM (zip [0..length rows] rows) $ \(cid, row') -> let
|
wRows <- forM rows $ \row' -> let
|
||||||
Course{..} = row' ^. c . _entityVal
|
Course{..} = row' ^. c . _entityVal
|
||||||
lecturerUsers = row' ^. l
|
lecturerUsers = row' ^. l
|
||||||
courseLecturers = userSurname . entityVal <$> lecturerUsers
|
courseLecturers = userSurname . entityVal <$> lecturerUsers
|
||||||
isRegistered = row' ^. r
|
isRegistered = row' ^. r
|
||||||
courseSchoolName = schoolName $ row' ^. s . _entityVal
|
courseSchoolName = schoolName $ row' ^. s . _entityVal
|
||||||
courseSemester = (termToText . unTermKey) courseTerm
|
courseSemester = (termToText . unTermKey) courseTerm
|
||||||
courseId = tshow cid
|
|
||||||
in return $(widgetFile "table/course/course-teaser")
|
in return $(widgetFile "table/course/course-teaser")
|
||||||
|
|
||||||
return $(widgetFile "table/course/colonnade")
|
return $(widgetFile "table/course/colonnade")
|
||||||
|
|||||||
@ -9,139 +9,3 @@
|
|||||||
.scrolltable {
|
.scrolltable {
|
||||||
box-shadow: none!important;
|
box-shadow: none!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.course-teaser {
|
|
||||||
display: grid;
|
|
||||||
grid-gap: 5px 7px;
|
|
||||||
grid-template-columns: 50px 120px 1fr;
|
|
||||||
padding: 10px;
|
|
||||||
/* background-color: var(--course-bg-color); */
|
|
||||||
transition: background-color .1s ease-out;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: var(--course-bg-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
+ .course-teaser {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* chevron */
|
|
||||||
.course-teaser__chevron {
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 10px;
|
|
||||||
grid-column: 1;
|
|
||||||
grid-row: 2;
|
|
||||||
justify-self: center;
|
|
||||||
align-self: center;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
margin-top: -8px;
|
|
||||||
border-width: 0 3px 3px 0;
|
|
||||||
width: 8px;
|
|
||||||
height: 8px;
|
|
||||||
border-color: var(--color-fontsec);
|
|
||||||
border-style: solid;
|
|
||||||
transform: rotate(45deg);
|
|
||||||
transition: transform .2s ease-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* semester */
|
|
||||||
.course-teaser__semester {
|
|
||||||
grid-column: 2;
|
|
||||||
grid-row: 1;
|
|
||||||
justify-self: end;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
a {
|
|
||||||
color: var(--color-fontsec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* shorthand */
|
|
||||||
.course-teaser__shorthand {
|
|
||||||
grid-column: 2;
|
|
||||||
grid-row: 2;
|
|
||||||
justify-self: end;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* title */
|
|
||||||
.course-teaser__title {
|
|
||||||
grid-column: 3;
|
|
||||||
grid-row: 2;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
align-self: baseline;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* registration */
|
|
||||||
.course-teaser__registration {
|
|
||||||
grid-column: 4;
|
|
||||||
grid-row: 2;
|
|
||||||
justify-self: end;
|
|
||||||
align-self: baseline;
|
|
||||||
color: var(--color-fontsec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* school */
|
|
||||||
.course-teaser__school-value {
|
|
||||||
grid-column: 3;
|
|
||||||
grid-row: 1;
|
|
||||||
align-self: end;
|
|
||||||
a {
|
|
||||||
color: var(--color-fontsec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* description */
|
|
||||||
.course-teaser__description {
|
|
||||||
grid-column: 3;
|
|
||||||
color: var(--color-fontsec);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* subtitle */
|
|
||||||
.course-teaser__lecturer-label,
|
|
||||||
.course-teaser__duedate-label,
|
|
||||||
.course-teaser__school-label {
|
|
||||||
grid-column: 2;
|
|
||||||
justify-self: end;
|
|
||||||
color: var(--color-fontsec);
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* hidden in closed state */
|
|
||||||
.course-teaser__duedate-label,
|
|
||||||
.course-teaser__duedate-value,
|
|
||||||
.course-teaser__description,
|
|
||||||
.course-teaser__registration {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* registered courses */
|
|
||||||
.course-teaser__registered {
|
|
||||||
.course-teaser__registration {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* expanded courses */
|
|
||||||
.course-teaser__expanded {
|
|
||||||
max-height: 1000px;
|
|
||||||
|
|
||||||
.course-teaser__chevron::before {
|
|
||||||
transform: translateY(7px) rotate(225deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.course-teaser__school-label,
|
|
||||||
.course-teaser__school-value,
|
|
||||||
.course-teaser__duedate-label,
|
|
||||||
.course-teaser__duedate-value,
|
|
||||||
.course-teaser__description {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
<div .course-teaser :isRegistered:.course-teaser__registered #courseteaser-#{courseId} tabindex='1'>
|
<div uw-course-teaser :isRegistered:.course-teaser__registered tabindex='1'>
|
||||||
<div .course-teaser__chevron>
|
<div .course-teaser__chevron>
|
||||||
<div .course-teaser__semester>
|
<div .course-teaser__semester>
|
||||||
<a href=@{TermCourseListR courseTerm}>_{courseSemester}
|
<a href=@{TermCourseListR courseTerm}>_{courseSemester}
|
||||||
|
|||||||
@ -1,25 +0,0 @@
|
|||||||
var COURSE_TEASER_EXPANDED_CLASS = 'course-teaser__expanded';
|
|
||||||
var COURSE_TEASER_CHEVRON_CLASS = 'course-teaser__chevron';
|
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
|
||||||
var courseTeaserId = #{String courseId};
|
|
||||||
var courseTeaser = document.querySelector('#courseteaser-' + courseTeaserId);
|
|
||||||
|
|
||||||
courseTeaser.addEventListener('click', function(event) {
|
|
||||||
var isLink = event.target.tagName.toLowerCase() === 'a';
|
|
||||||
var isChevron = event.target.classList.contains(COURSE_TEASER_CHEVRON_CLASS);
|
|
||||||
var isExpanded = courseTeaser.classList.contains(COURSE_TEASER_EXPANDED_CLASS);
|
|
||||||
|
|
||||||
if ((!isExpanded && !isLink) || isChevron) {
|
|
||||||
courseTeaser.classList.toggle(COURSE_TEASER_EXPANDED_CLASS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
courseTeaser.addEventListener('keydown', function(event) {
|
|
||||||
var eventKey = event.key;
|
|
||||||
if (eventKey === ' ' || eventKey === 'Enter') {
|
|
||||||
event.preventDefault();
|
|
||||||
courseTeaser.classList.toggle(COURSE_TEASER_EXPANDED_CLASS);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user