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

Custom modules #2785

Open
wants to merge 48 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
37c0ef3
Add CustomModulesContainer to the TimetableContent
agnesnatasya Jul 15, 2020
7ce94e0
Add styling to CustomModulesContainer'
agnesnatasya Jul 15, 2020
1e35b4c
Add CustomModulesForm to add new customised modules
agnesnatasya Jul 15, 2020
45d87f2
Add styling to form
agnesnatasya Jul 15, 2020
a6924cc
Move the form out of the button in CustomModulesContainer'
agnesnatasya Jul 15, 2020
0ff5e0e
Add styling to input of CustomModulesForm
agnesnatasya Jul 15, 2020
371f32d
Form to add custom modules and handle on submit function
agnesnatasya Jul 15, 2020
bc7eced
Remove console log statement
agnesnatasya Jul 16, 2020
33c0c0e
remove console log statements from actions timetables
agnesnatasya Jul 16, 2020
1864ade
Map Dispatch to Props of Custom Modules Form and call AddModule action
agnesnatasya Jul 16, 2020
f3c2b1b
CustomModules Form to render CustomModuleTimetableForm
agnesnatasya Jul 16, 2020
2622afc
Add styling for input in CustomMOduleTimetableForm
agnesnatasya Jul 16, 2020
fe6e1fc
Add CustomMOduleTimetableForm to inset timetable data through form
agnesnatasya Jul 16, 2020
6131f6c
CustomMOdulesForm to render CustomModuleTimetableForm
agnesnatasya Jul 16, 2020
bd4d585
Declare Day as a constant of list days
agnesnatasya Jul 17, 2020
98a309e
Remove typo statement
agnesnatasya Jul 17, 2020
3bd4a58
Working downshift element to chosse from Dropdown
agnesnatasya Jul 17, 2020
6ab4260
Add styling to adding timetable
agnesnatasya Jul 17, 2020
29caa3a
CustomModulesForm declare callback function to set properties of the …
agnesnatasya Jul 17, 2020
44c2e65
Add styling for timetable form, responsive width for flex elements
agnesnatasya Jul 24, 2020
6686371
Add fields for custom module form
agnesnatasya Jul 24, 2020
7c18a50
Add margin to the button
agnesnatasya Jul 24, 2020
0327ae3
Responsive width of the form, using flex basis
agnesnatasya Jul 24, 2020
343fbd3
Add function to handle change on form
agnesnatasya Jul 24, 2020
e042896
Make downshift reflect selected value
agnesnatasya Jul 24, 2020
37fa523
Fix bug in handler functions for change in form input
agnesnatasya Jul 25, 2020
97161d0
Streamline definition of add custom module action
agnesnatasya Jul 26, 2020
30c03eb
Set reducer for case ADD_CUSTOM_MODULE action
agnesnatasya Jul 26, 2020
aceee7f
Remove dummy data from form
agnesnatasya Jul 26, 2020
e5bc996
Add module key to add custom module action
agnesnatasya Jul 27, 2020
5bc7ed1
ModuleBank reducer handles add custom module action
agnesnatasya Jul 27, 2020
4b872f9
Set the default weeks to be 1-13
agnesnatasya Jul 27, 2020
cca2bca
Add apostrophe to custom modules name, to handle conflict with curren…
agnesnatasya Jul 27, 2020
97475dc
In action of add custom module, check first whether there is an exist…
agnesnatasya Jul 27, 2020
e8ec45a
Add check if the current module code has existed in store
agnesnatasya Jul 27, 2020
85c3047
Add check whether the custom module code and title is already present
agnesnatasya Jul 28, 2020
0c01770
Add functions to handle change on form and change form to select not …
agnesnatasya Jul 28, 2020
1f5153b
Custom Modules form to still appear in vertical mode
agnesnatasya Jul 29, 2020
0ca523a
Redefine all downshift to a select element, give label, and handler f…
agnesnatasya Jul 29, 2020
7ca7bc9
Change to form and use HTML validation
agnesnatasya Jul 29, 2020
0148332
Make flex grow to be 0
agnesnatasya Jul 29, 2020
439f6b1
Delete CustomMOduleTimetableForm component
agnesnatasya Jul 29, 2020
aa281e5
Lint fix
agnesnatasya Jul 29, 2020
32a3fd2
Remove unneccessary styling
agnesnatasya Jul 29, 2020
a1194e5
Notification when clash module code to remove the last character
agnesnatasya Jul 29, 2020
4c8df8e
Change input to button for submit, rename variable according to review
agnesnatasya Aug 9, 2020
55c1b13
Remove unchanged state from state and put it when submitting form
agnesnatasya Aug 9, 2020
a32aace
Lint fix and add '-custom-module' suffix to the id to ensure it is un…
agnesnatasya Aug 9, 2020
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
60 changes: 59 additions & 1 deletion website/src/actions/timetables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
// Actions that should not be used directly outside of thunks
export const SET_TIMETABLE = 'SET_TIMETABLE' as const;
export const ADD_MODULE = 'ADD_MODULE' as const;
export const ADD_CUSTOM_MODULE = 'ADD_CUSTOM_MODULE' as const;
export const Internal = {
setTimetable(
semester: Semester,
Expand All @@ -40,13 +41,29 @@
},
};
},

addCustomModule(
semester: Semester,
moduleCode: ModuleCode,
moduleLessonConfig: ModuleLessonConfig,
module: Module,
) {
return {

Check warning on line 51 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L50-L51

Added lines #L50 - L51 were not covered by tests
type: ADD_CUSTOM_MODULE,
payload: {
semester,
moduleCode,
moduleLessonConfig,
module,
},
};
},
};

export function addModule(semester: Semester, moduleCode: ModuleCode) {
return (dispatch: Function, getState: GetState) =>
dispatch(fetchModule(moduleCode)).then(() => {
const module: Module = getState().moduleBank.modules[moduleCode];

if (!module) {
dispatch(
openNotification(`Cannot load ${moduleCode}`, {
Expand All @@ -67,6 +84,47 @@
});
}

export function addCustomModule(semester: Semester, moduleCode: ModuleCode, module: Module) {
return (dispatch: Function, getState: GetState) => {
const { modules } = getState().moduleBank;
if (Object.keys(modules).includes(moduleCode)) {
if (modules[moduleCode].title !== module.title) {
dispatch(

Check warning on line 92 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L87-L92

Added lines #L87 - L92 were not covered by tests
openNotification(`Module ${moduleCode.slice(0, -1)} exist with a different title`, {
action: {
text: '',
handler: () => dispatch(addCustomModule(semester, moduleCode, module)),

Check warning on line 96 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L96

Added line #L96 was not covered by tests
},
}),
);
return;

Check warning on line 100 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L100

Added line #L100 was not covered by tests
}
}

let customModule = module;

Check warning on line 104 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L104

Added line #L104 was not covered by tests

if (Object.keys(modules).includes(moduleCode)) {
const storedModule = modules[moduleCode];
const selectedSemester = getState().app.activeSemester;
const modifiedCurrentSemesterData = storedModule.semesterData.map((currentSemesterData) =>
currentSemesterData.semester === selectedSemester
? {

Check warning on line 111 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L106-L111

Added lines #L106 - L111 were not covered by tests
...currentSemesterData,
timetable: [
...currentSemesterData.timetable,
customModule.semesterData[0].timetable[0],
],
}
: currentSemesterData,

Check warning on line 118 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L118

Added line #L118 was not covered by tests
);
customModule = { ...storedModule, semesterData: modifiedCurrentSemesterData };

Check warning on line 120 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L120

Added line #L120 was not covered by tests
}
const lessons = getModuleTimetable(customModule, semester);
const moduleLessonConfig = randomModuleLessonConfig(lessons);
dispatch(Internal.addCustomModule(semester, moduleCode, moduleLessonConfig, customModule));

Check warning on line 124 in website/src/actions/timetables.ts

View check run for this annotation

Codecov / codecov/patch

website/src/actions/timetables.ts#L122-L124

Added lines #L122 - L124 were not covered by tests
};
}

export const REMOVE_MODULE = 'REMOVE_MODULE' as const;
export function removeModule(semester: Semester, moduleCode: ModuleCode) {
return {
Expand Down
10 changes: 10 additions & 0 deletions website/src/reducers/moduleBank.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
UPDATE_MODULE_TIMESTAMP,
SET_EXPORTED_DATA,
} from 'actions/constants';
import { ADD_CUSTOM_MODULE } from 'actions/timetables';
import { createMigrate, REHYDRATE } from 'redux-persist';
import { Module } from 'types/modules';
import { ModuleBank, ModuleList } from 'types/reducers';
Expand Down Expand Up @@ -53,6 +54,15 @@
},
};

case ADD_CUSTOM_MODULE:
return {

Check warning on line 58 in website/src/reducers/moduleBank.ts

View check run for this annotation

Codecov / codecov/patch

website/src/reducers/moduleBank.ts#L57-L58

Added lines #L57 - L58 were not covered by tests
...state,
modules: {
...state.modules,
[action.payload.moduleCode]: { ...action.payload.module, timestamp: Date.now() },
},
};

case UPDATE_MODULE_TIMESTAMP:
return {
...state,
Expand Down
6 changes: 4 additions & 2 deletions website/src/reducers/timetables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ColorMapping, TimetablesState } from 'types/reducers';
import config from 'config';
import {
ADD_MODULE,
ADD_CUSTOM_MODULE,
CHANGE_LESSON,
HIDE_LESSON_IN_TIMETABLE,
REMOVE_MODULE,
Expand Down Expand Up @@ -104,6 +105,7 @@ function semTimetable(

switch (action.type) {
case ADD_MODULE:
case ADD_CUSTOM_MODULE:
return {
...state,
[moduleCode]: action.payload.moduleLessonConfig,
Expand All @@ -129,6 +131,7 @@ function semColors(state: ColorMapping = defaultSemColorMap, action: Actions): C

switch (action.type) {
case ADD_MODULE:
case ADD_CUSTOM_MODULE:
return {
...state,
[moduleCode]: getNewColor(values(state)),
Expand All @@ -154,7 +157,6 @@ function semHiddenModules(state = defaultHiddenState, action: Actions) {
if (!action.payload) {
return state;
}

switch (action.type) {
case HIDE_LESSON_IN_TIMETABLE:
return [action.payload.moduleCode, ...state];
Expand Down Expand Up @@ -194,14 +196,14 @@ function timetables(
}

case ADD_MODULE:
case ADD_CUSTOM_MODULE:
case REMOVE_MODULE:
case SELECT_MODULE_COLOR:
case CHANGE_LESSON:
case SET_LESSON_CONFIG:
case HIDE_LESSON_IN_TIMETABLE:
case SHOW_LESSON_IN_TIMETABLE: {
const { semester } = action.payload;

return produce(state, (draft) => {
draft.lessons[semester] = semTimetable(draft.lessons[semester], action);
draft.colors[semester] = semColors(state.colors[semester], action);
Expand Down
10 changes: 10 additions & 0 deletions website/src/types/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,16 @@ export type Day =
| 'Saturday'
| 'Sunday';

export const Days: readonly Day[] = [
'Monday',
'Tuesday',
'Wednesday',
'Thursday',
'Friday',
'Saturday',
'Sunday',
];

export const WorkingDays: readonly Day[] = [
'Monday',
'Tuesday',
Expand Down
6 changes: 6 additions & 0 deletions website/src/views/timetable/CustomModulesContainer.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
@import '~styles/utils/modules-entry';

.titleBtn {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
52 changes: 52 additions & 0 deletions website/src/views/timetable/CustomModulesContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import * as React from 'react';
import classnames from 'classnames';
import { connect } from 'react-redux';

import CustomModulesForm from 'views/timetable/CustomModulesForm';
import styles from './CustomModulesContainer.scss';

type OwnProps = {
// Own props
semester: number;
};

type Props = OwnProps;

type State = {
showCustomModulesForm: boolean;
};

class CustomModulesAddContainer extends React.Component<Props, State> {
state = {

Check warning on line 20 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L20

Added line #L20 was not covered by tests
showCustomModulesForm: false,
};

onChange = () => {
if (this.state.showCustomModulesForm === true) {
this.setState({ showCustomModulesForm: false });

Check warning on line 26 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L24-L26

Added lines #L24 - L26 were not covered by tests
} else {
this.setState({ showCustomModulesForm: true });

Check warning on line 28 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L28

Added line #L28 was not covered by tests
}
};

render() {
return (

Check warning on line 33 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L32-L33

Added lines #L32 - L33 were not covered by tests
<div>
<button
type="button"
className={classnames(styles.titleBtn, 'btn-outline-primary btn btn-svg')}
onClick={this.onChange}
>
Add custom module to timetable
</button>
{this.state.showCustomModulesForm && <CustomModulesForm />}

Check warning on line 42 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L42

Added line #L42 was not covered by tests
</div>
);
}
}

function mapStateToProps() {
return {};

Check warning on line 49 in website/src/views/timetable/CustomModulesContainer.tsx

View check run for this annotation

Codecov / codecov/patch

website/src/views/timetable/CustomModulesContainer.tsx#L48-L49

Added lines #L48 - L49 were not covered by tests
}

export default connect(mapStateToProps, {})(CustomModulesAddContainer);
131 changes: 131 additions & 0 deletions website/src/views/timetable/CustomModulesForm.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
@import "./_variables.scss";
@import '~styles/utils/modules-entry';

$input-height: 2.75rem;
$module-list-height: 13.5rem;
$item-padding-vertical: 0.6rem;
$btn-margin: 0.5rem;


.titleIcon {
composes: svg svg-small from global;
}

.input {
composes: form-control from global;
width: 100%;
text-align: left;
white-space: nowrap;

&:not(:disabled) {
box-shadow: inset 2px 2px 4px rgba(#000, 0.1);

@include night-mode {
box-shadow: inset 2px 2px 4px rgba(#000, 0.9);
}
}
}

.submitBtn {
margin-top: 1rem;
}

.formGroup {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
margin-left: -$btn-margin; // Negate childrens' left margins

> * {
flex: 0 1 calc(33.333% - 1rem);
flex-grow: 1;
margin-bottom: $btn-margin;
margin-left: $btn-margin;
}

@include media-breakpoint-down(sm) {
> * {
flex: 0 1 calc(50% - 1rem);
}
}

@include media-breakpoint-down(xs) {
> * {
flex: 0 1 100%;
}
}

@include media-breakpoint-up(md) {
:global(.btn) {
padding: 0.25rem 0.75rem;
//font-size: $font-size-sm;
}
}

@include vertical-mode {
@include media-breakpoint-down(lg) {
> * {
flex: 0 1 calc(50% - 1rem);
}
}
}

}

// Two layout forms:
//
// 1. Left and right on one row, with space between two groups
// - md and above for horizontal
//
// 2. Left and right on 2 rows, full width (fullWidthGroup)
// - any size in vertical
// - sm and below for horizontal
@mixin fullWidthGroup {
.buttonGroup {
width: calc(100% + #{$btn-margin}); // Make full width and negate the left shifting caused by our margin-left
}
}

:global(.verticalMode) {
@include fullWidthGroup;
}

@include media-breakpoint-down(sm) {
@include fullWidthGroup;
}

.search {
label {
margin-bottom: 0;
font-weight: $font-weight-bold;
font-size: $font-size-s;
}

:global(.form-group) {
margin-bottom: 0;
}
}

.label {
margin: 0;
font-size: $font-size-xs;

&,
label,
input {
cursor: pointer;
}

&.enabled {
font-weight: bold;
color: theme-color();
}

:global(.text-muted) {
font-weight: normal;
}

@include touchscreen-only {
font-size: $font-size-sm;
}
}
Loading