-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: schedule list item action menu (#230)
* feat: action menu for schedule list item * feat: schedule action menu functionality * feat: dialog provider popups for delete * feat: duplicate schedule satiesfies type * refactor: change non-null assertion to early return for rename schedule * refactor: move schedule list item dialog providers to util file * style: run prettier * chore: inline object with satisfies operator * fix: border issues * style: change popups to match figma * fix: update import for schedule list item dialog providers * style: change dropdown text style to match figma * fix: add back dialog context * style: rounded edges when hovering over action + soften border color * chore: cleanup and improve styling * fix: dialog in popupmain --------- Co-authored-by: doprz <52579214+doprz@users.noreply.github.com> Co-authored-by: Razboy20 <razboy20@gmail.com>
- Loading branch information
1 parent
9ec05ef
commit 15fc369
Showing
10 changed files
with
325 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore'; | ||
import { generateRandomId } from '@shared/util/random'; | ||
|
||
import handleDuplicate from './handleDuplicate'; | ||
|
||
/** | ||
* Creates a new schedule with the given name | ||
* @param scheduleName the name of the schedule to create | ||
* @returns undefined if successful, otherwise an error message | ||
*/ | ||
export default async function duplicateSchedule(scheduleId: string): Promise<string | undefined> { | ||
const schedules = await UserScheduleStore.get('schedules'); | ||
const schedule = schedules.find(schedule => schedule.id === scheduleId); | ||
|
||
if (schedule === undefined) { | ||
throw new Error(`Schedule ${scheduleId} does not exist`); | ||
} | ||
|
||
const updatedName = await handleDuplicate(schedule.name); | ||
|
||
schedules.push({ | ||
id: generateRandomId(), | ||
name: updatedName, | ||
courses: JSON.parse(JSON.stringify(schedule.courses)), | ||
hours: schedule.hours, | ||
updatedAt: Date.now(), | ||
} satisfies typeof schedule); | ||
|
||
await UserScheduleStore.set('schedules', schedules); | ||
return undefined; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore'; | ||
|
||
/** | ||
* Duplicates a new schedule with the given name. | ||
* Assumes that each schedule has a unique name. | ||
* @param scheduleName the name of the schedule to handle duplication for | ||
* @param schedules the list of UserSchedules to find existing names | ||
* @returns the new name for the schedule, of the form `{baseName}({index})` | ||
*/ | ||
export default async function handleDuplicate(scheduleName: string): Promise<string> { | ||
const schedules = await UserScheduleStore.get('schedules'); | ||
|
||
// No point in checking for duplicates if the name is unique | ||
if (schedules.find(schedule => schedule.name === scheduleName) === undefined) { | ||
return scheduleName; | ||
} | ||
|
||
// Regex for matching `{baseName}({index})`, where match[1] = baseName, match[2] = (index) | ||
const regex = /^(.+?)(\(\d+\))?$/; | ||
|
||
// Extract base name and existing index | ||
const match = scheduleName.match(regex); | ||
const baseName = match && match[1] ? match[1] : scheduleName; | ||
|
||
// Extract number from parentheses and increment | ||
let index = match && match[2] ? parseInt(match[2].slice(1, -1), 10) + 1 : 1; | ||
|
||
let newName: string; | ||
|
||
// Increment until an unused index is found | ||
do { | ||
newName = `${baseName} (${index++})`; | ||
// eslint-disable-next-line @typescript-eslint/no-loop-func | ||
} while (schedules.find(schedule => schedule.name === newName)); | ||
|
||
return newName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,21 +1,41 @@ | ||
import { UserScheduleStore } from '@shared/storage/UserScheduleStore'; | ||
|
||
import handleDuplicate from './handleDuplicate'; | ||
|
||
/** | ||
* Renames a schedule with the specified name to a new name. | ||
* @param scheduleId - The id of the schedule to be renamed. | ||
* @param newName - The new name for the schedule. | ||
* @returns A promise that resolves to a string if there is an error, or undefined if the schedule is renamed successfully. | ||
* @returns A promise that resolves to the new name if successful, otherwise undefined. | ||
*/ | ||
export default async function renameSchedule(scheduleId: string, newName: string): Promise<string | undefined> { | ||
const schedules = await UserScheduleStore.get('schedules'); | ||
|
||
const scheduleIndex = schedules.findIndex(schedule => schedule.id === scheduleId); | ||
if (scheduleIndex === -1) { | ||
return `Schedule ${scheduleId} does not exist`; | ||
return undefined; | ||
} | ||
const schedule = schedules[scheduleIndex]; | ||
if (schedule === undefined) { | ||
return undefined; | ||
} | ||
|
||
// if old name is of the form `{baseName}{index}` and newName === baseName, do nothing. | ||
const oldName = schedule.name; | ||
const regex = /^(.+?)(\(\d+\))?$/; | ||
const match = oldName?.match(regex); | ||
const baseName = match?.[1] ?? ''; | ||
const baseNameOfNewName = newName.match(regex)?.[1]; | ||
|
||
if (baseName === baseNameOfNewName) { | ||
return oldName; | ||
} | ||
|
||
const updatedName = await handleDuplicate(newName); | ||
|
||
schedules[scheduleIndex]!.name = newName; | ||
// schedules[scheduleIndex].updatedAt = Date.now(); | ||
schedule.name = updatedName; | ||
schedule.updatedAt = Date.now(); | ||
|
||
await UserScheduleStore.set('schedules', schedules); | ||
return undefined; | ||
return newName; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.