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

fix: add copy, rename, and delete as unsaved actions properly #1091

Merged
merged 3 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 30 additions & 1 deletion apps/antalmanac/src/actions/ActionTypesStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,25 @@ export interface ClearScheduleAction {
type: 'clearSchedule';
}

export interface AddScheduleAction {
type: 'addSchedule';
newScheduleName: string;
}

export interface RenameScheduleAction {
type: 'renameSchedule';
scheduleIndex: number;
newScheduleName: string;
}

export interface DeleteScheduleAction {
type: 'deleteSchedule';
scheduleIndex: number;
}

export interface CopyScheduleAction {
type: 'copySchedule';
scheduleIndex: number;
newScheduleName: string;
}

Expand All @@ -77,6 +94,9 @@ export type ActionType =
| EditCustomEventAction
| ChangeCustomEventColorAction
| ClearScheduleAction
| AddScheduleAction
| RenameScheduleAction
| DeleteScheduleAction
| CopyScheduleAction
| ChangeCourseColorAction
| UndoAction;
Expand Down Expand Up @@ -158,8 +178,17 @@ class ActionTypesStore extends EventEmitter {
case 'clearSchedule':
AppStore.schedule.clearCurrentSchedule();
break;
case 'addSchedule':
AppStore.schedule.addNewSchedule(action.newScheduleName);
break;
case 'renameSchedule':
AppStore.schedule.renameSchedule(action.scheduleIndex, action.newScheduleName);
break;
case 'copySchedule':
AppStore.schedule.copySchedule(action.newScheduleName);
AppStore.schedule.copySchedule(action.scheduleIndex, action.newScheduleName);
break;
case 'deleteSchedule':
AppStore.schedule.deleteSchedule(action.scheduleIndex);
break;
default:
break;
Expand Down
8 changes: 4 additions & 4 deletions apps/antalmanac/src/actions/AppStoreActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,14 +250,14 @@ export const changeCourseColor = (sectionCode: string, term: string, newColor: s
AppStore.changeCourseColor(sectionCode, term, newColor);
};

export const copySchedule = (newScheduleName: string, options?: CopyScheduleOptions) => {
export const copySchedule = (scheduleIndex: number, newScheduleName: string, options?: CopyScheduleOptions) => {
logAnalytics({
category: analyticsEnum.addedClasses.title,
action: analyticsEnum.addedClasses.actions.COPY_SCHEDULE,
});

try {
AppStore.copySchedule(newScheduleName);
AppStore.copySchedule(scheduleIndex, newScheduleName);
options?.onSuccess(newScheduleName);
} catch (error) {
options?.onError(newScheduleName);
Expand All @@ -268,8 +268,8 @@ export const addSchedule = (scheduleName: string) => {
AppStore.addSchedule(scheduleName);
};

export const renameSchedule = (scheduleName: string, scheduleIndex: number) => {
AppStore.renameSchedule(scheduleName, scheduleIndex);
export const renameSchedule = (scheduleIndex: number, scheduleName: string) => {
AppStore.renameSchedule(scheduleIndex, scheduleName);
};

export const deleteSchedule = (scheduleIndex: number) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const ScheduleNameDialog = forwardRef((props: ScheduleNameDialogProps, ref) => {
onClose?.();

if (rename) {
renameSchedule(scheduleName, scheduleRenameIndex as number); // typecast works b/c this function only runs when `const rename = scheduleRenameIndex !== undefined` is true.
renameSchedule(scheduleRenameIndex as number, scheduleName); // typecast works b/c this function only runs when `const rename = scheduleRenameIndex !== undefined` is true.
} else {
addSchedule(scheduleName);
}
Expand Down
4 changes: 2 additions & 2 deletions apps/antalmanac/src/components/dialogs/AddSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {
const isDark = useThemeStore((store) => store.isDark);

const [name, setName] = useState(
AppStore.getNextScheduleName(AppStore.getDefaultScheduleName(), AppStore.getScheduleNames().length)
AppStore.getNextScheduleName(() => AppStore.getScheduleNames().length, AppStore.getDefaultScheduleName())
);

const handleCancel = () => {
Expand Down Expand Up @@ -48,7 +48,7 @@ function AddScheduleDialog({ onClose, onKeyDown, ...props }: DialogProps) {
};

const handleScheduleNamesChange = useCallback(() => {
setName(AppStore.getNextScheduleName(AppStore.getDefaultScheduleName(), AppStore.getScheduleNames().length));
setName(AppStore.getNextScheduleName(AppStore.getScheduleNames().length, AppStore.getDefaultScheduleName()));
}, []);

useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion apps/antalmanac/src/components/dialogs/CopySchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function CopyScheduleDialog(props: CopyScheduleDialogProps) {
}, [onClose]);

const handleCopy = useCallback(() => {
copySchedule(name);
copySchedule(index, name);
onClose?.({}, 'escapeKeyDown');
}, [onClose, name]);

Expand Down
2 changes: 1 addition & 1 deletion apps/antalmanac/src/components/dialogs/RenameSchedule.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ function RenameScheduleDialog(props: ScheduleNameDialogProps) {
}, []);

const submitName = useCallback(() => {
renameSchedule(name, index);
renameSchedule(index, name);
onClose?.({}, 'escapeKeyDown');
}, [onClose, name, index]);

Expand Down
35 changes: 29 additions & 6 deletions apps/antalmanac/src/stores/AppStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ import type {
ChangeCustomEventColorAction,
ClearScheduleAction,
CopyScheduleAction,
RenameScheduleAction,
DeleteScheduleAction,
ChangeCourseColorAction,
UndoAction,
AddScheduleAction,
} from '$actions/ActionTypesStore';
import { CalendarEvent, CourseEvent } from '$components/Calendar/CourseCalendarEvent';
import { SnackbarPosition } from '$components/NotificationSnackbar';
Expand Down Expand Up @@ -71,8 +74,8 @@ class AppStore extends EventEmitter {
}
}

getNextScheduleName(newScheduleName: string, scheduleIndex: number) {
return this.schedule.getNextScheduleName(newScheduleName, scheduleIndex);
getNextScheduleName(scheduleIndex: number, newScheduleName: string) {
return this.schedule.getNextScheduleName(scheduleIndex, newScheduleName);
}

getDefaultScheduleName() {
Expand Down Expand Up @@ -280,13 +283,26 @@ class AppStore extends EventEmitter {
// another key/value pair to keep track of the section codes for that schedule,
// and redirect the user to the new schedule
this.schedule.addNewSchedule(newScheduleName);
this.unsavedChanges = true;
const action: AddScheduleAction = {
type: 'addSchedule',
newScheduleName: newScheduleName,
};
actionTypesStore.autoSaveSchedule(action);
this.emit('scheduleNamesChange');
this.emit('currentScheduleIndexChange');
this.emit('scheduleNotesChange');
}

renameSchedule(scheduleName: string, scheduleIndex: number) {
this.schedule.renameSchedule(scheduleName, scheduleIndex);
renameSchedule(scheduleIndex: number, newScheduleName: string) {
this.schedule.renameSchedule(scheduleIndex, newScheduleName);
this.unsavedChanges = true;
const action: RenameScheduleAction = {
type: 'renameSchedule',
scheduleIndex: scheduleIndex,
newScheduleName: newScheduleName,
};
actionTypesStore.autoSaveSchedule(action);
this.emit('scheduleNamesChange');
}

Expand All @@ -295,11 +311,12 @@ class AppStore extends EventEmitter {
window.localStorage.removeItem('unsavedActions');
}

copySchedule(newScheduleName: string) {
this.schedule.copySchedule(newScheduleName);
copySchedule(scheduleIndex: number, newScheduleName: string) {
this.schedule.copySchedule(scheduleIndex, newScheduleName);
this.unsavedChanges = true;
const action: CopyScheduleAction = {
type: 'copySchedule',
scheduleIndex: scheduleIndex,
newScheduleName: newScheduleName,
};
actionTypesStore.autoSaveSchedule(action);
Expand Down Expand Up @@ -364,6 +381,12 @@ class AppStore extends EventEmitter {

deleteSchedule(scheduleIndex: number) {
this.schedule.deleteSchedule(scheduleIndex);
this.unsavedChanges = true;
const action: DeleteScheduleAction = {
type: 'deleteSchedule',
scheduleIndex: scheduleIndex,
};
actionTypesStore.autoSaveSchedule(action);
this.emit('scheduleNamesChange');
this.emit('currentScheduleIndexChange');
this.emit('addedCoursesChange');
Expand Down
24 changes: 13 additions & 11 deletions apps/antalmanac/src/stores/Schedules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class Schedules {
this.skeletonSchedules = [];
}

getNextScheduleName(newScheduleName: string, scheduleIndex: number) {
getNextScheduleName(scheduleIndex: number, newScheduleName: string) {
const scheduleNames = this.getScheduleNames();
scheduleNames.splice(scheduleIndex, 1);
let nextScheduleName = newScheduleName;
Expand Down Expand Up @@ -108,7 +108,7 @@ export class Schedules {
this.addUndoState();
const scheduleNoteId = Math.random();
this.schedules.push({
scheduleName: this.getNextScheduleName(newScheduleName, this.getNumberOfSchedules()),
scheduleName: this.getNextScheduleName(this.getNumberOfSchedules(), newScheduleName),
courses: [],
customEvents: [],
scheduleNoteId: scheduleNoteId,
Expand All @@ -122,9 +122,9 @@ export class Schedules {
* Rename schedule with the specified index.
* @param newScheduleName The name of the new schedule. If a schedule with the same name already exists, a number will be appended to the name.
*/
renameSchedule(newScheduleName: string, scheduleIndex: number) {
renameSchedule(scheduleIndex: number, newScheduleName: string) {
this.addUndoState();
this.schedules[scheduleIndex].scheduleName = this.getNextScheduleName(newScheduleName, scheduleIndex);
this.schedules[scheduleIndex].scheduleName = this.getNextScheduleName(scheduleIndex, newScheduleName);
}

/**
Expand All @@ -146,22 +146,22 @@ export class Schedules {
}

/**
* Copy the current schedule to a newly created schedule with the specified name.
* Copy the schedule at the provided index to a newly created schedule with the specified name.
*/
copySchedule(newScheduleName: string) {
copySchedule(scheduleIndex: number, newScheduleName: string) {
this.addNewSchedule(newScheduleName);
this.currentScheduleIndex = this.previousStates[this.previousStates.length - 1].scheduleIndex; // return to previous schedule index for copying
this.currentScheduleIndex = scheduleIndex; // temporarily set current schedule to the one being copied
const to = this.getNumberOfSchedules() - 1;

for (const course of this.getCurrentCourses()) {
this.addCourse(course, to, false);
}

for (const customEvent of this.getCurrentCustomEvents()) {
this.addCustomEvent(customEvent, [to]);
this.addCustomEvent(customEvent, [to], false);
}
this.currentScheduleIndex = this.previousStates[this.previousStates.length - 1].scheduleIndex; // return to previously selected schedule index
}

getCurrentCourses() {
return this.schedules[this.currentScheduleIndex]?.courses || [];
}
Expand Down Expand Up @@ -339,8 +339,10 @@ export class Schedules {
/**
* Adds a new custom event to given indices
*/
addCustomEvent(newCustomEvent: RepeatingCustomEvent, scheduleIndices: number[]) {
this.addUndoState();
addCustomEvent(newCustomEvent: RepeatingCustomEvent, scheduleIndices: number[], addUndoState = true) {
if (addUndoState) {
this.addUndoState();
}
for (const scheduleIndex of scheduleIndices) {
if (!this.doesCustomEventExistInSchedule(newCustomEvent.customEventID, scheduleIndex)) {
this.schedules[scheduleIndex].customEvents.push(newCustomEvent);
Expand Down
Loading