Skip to content

Commit

Permalink
feat(import): ✨ allow import of past assignments (#386)
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesNZL committed Jul 4, 2024
1 parent 0f22184 commit a6c6417
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 13 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ chmod +x /Users/YOUR_USERNAME/Downloads/Notion\ Canvas\ Assignment\ Import/Conte
| `Theme` | Whether to use `Light`/`Dark` mode, or use the browser's default (`System`) |
| `Show Advanced Options` | Whether to `Show`/`Hide` the **Advanced Options** |
| `Timezone` | The `TZ` timezone in which to parse and set all dates |
| `Assignments Without Due Dates` | Whether to `Import`, or `Ignore` Canvas assignments without a set due date |
| `Assignments Without Due Dates` | Whether to `Copy`, or `Ignore` Canvas assignments without a set due date |
| `Internal Integration Token` (**Safari only**) | The `Internal Integration Token` of your Notion integration |
| `Database` | The target Notion database |
| `Page 'Name' Property` | The name of the database `Title` property, used to set the assignment name |
Expand All @@ -252,6 +252,7 @@ chmod +x /Users/YOUR_USERNAME/Downloads/Notion\ Canvas\ Assignment\ Import/Conte
| `Due Date Property` | The name of a database Due property, used to set the assignment due date |
| `Date Span Property` | The name of a database Date Span property, used to set the date span of the assignment as `unlock date``due date` |
| `Canvas Category` | The value of a database Category property to categorise all Canvas assignments as |
| `Past Assignments` | Whether to `Import`, or `Ignore` assignments due in the past |
| `Name Changes` | Whether to `Import` (ie update the existing page) or `Ignore` Canvas changes to previously imported assignment names |
| `Points Changes` | Whether to `Import` (ie update the existing page) or `Ignore` Canvas changes to previously imported assignment points |
| `Unlock Date Changes` | Whether to `Import` (ie update the existing page) or `Ignore` Canvas changes to previously imported assignment unlock dates |
Expand Down
1 change: 1 addition & 0 deletions src/apis/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ export const Storage = <const>{
propertyValues: {
categoryCanvas: savedFields['notion.propertyValues.categoryCanvas'],
},
importPastDueDates: savedFields['notion.importPastDueDates'],
importChanges: {
name: savedFields['notion.importChanges.name'],
points: savedFields['notion.importChanges.points'],
Expand Down
28 changes: 26 additions & 2 deletions src/options/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export interface OptionConfiguration<T> {

function isOptionConfiguration(object: valueof<NestedConfigurationsOf<SavedOptions>> | OptionConfiguration<SupportedTypes>): object is OptionConfiguration<SupportedTypes> {
const configurationProperties: (keyof OptionConfiguration<SupportedTypes>)[] = ['defaultValue', 'input'];
return (<string[]>configurationProperties).every(key => Object.keys(object).includes(key));
return configurationProperties.every(key => Object.keys(object).includes(key));
}

type NestedConfigurationsOf<I> = {
Expand Down Expand Up @@ -98,6 +98,9 @@ interface InputElements {
'notion.propertyNames.due': 'notion-property-due';
'notion.propertyNames.span': 'notion-property-span';
'notion.propertyValues.categoryCanvas': 'notion-category-canvas';
'notion.importPastDueDates': 'past-due-dates';
ignorePastDueDates: 'ignore-past-due-dates';
importPastDueDates: 'import-past-due-dates';
'notion.importChanges.name': 'notion-changes-name';
noChangesName: 'no-changes-name-button';
yesChangesName: 'yes-changes-name-button';
Expand Down Expand Up @@ -132,7 +135,7 @@ export const CONFIGURATION: {
return Object.entries(valueObject)
.flatMap(([nestedKey, nestedValueObject]) => {
const nestedKeyPath = <keyof SavedFields | IncompleteFieldKey<typeof keyPath>>`${keyPath}.${nestedKey}`;
return flattenOptions<typeof keyPath>([nestedKeyPath, nestedValueObject]);
return flattenOptions<typeof nestedKeyPath>([nestedKeyPath, <valueof<typeof CONFIGURATION['OPTIONS']>>nestedValueObject]);
});
}

Expand Down Expand Up @@ -392,6 +395,27 @@ export const CONFIGURATION: {
},
},
},
importPastDueDates: {
defaultValue: false,
get input() {
delete (<Partial<typeof this>>this).input;
return this.input = SegmentedControl.getInstance<InputElementId, typeof this.defaultValue>({
id: 'past-due-dates',
segments: [
{
id: 'ignore-past-due-dates',
value: false,
default: true,
},
{
id: 'import-past-due-dates',
value: true,
showDependents: true,
},
],
});
},
},
importChanges: {
'name': {
defaultValue: true,
Expand Down
23 changes: 20 additions & 3 deletions src/options/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ <h3 class='advanced-options hidden'>Extension Popup</h3>
<section>
<h1>Canvas Configuration</h1>

<h3>Assignment Import</h3>
<h3>Assignment Copying</h3>
<div class='tile'>
<div class='segmented-control-group'>
<label class='required' for='missing-due-dates'>Assignments without due dates</label>
Expand All @@ -104,7 +104,7 @@ <h3>Assignment Import</h3>
<label for='ignore-missing-due-dates'>Ignore</label>

<input type='radio' name='missing-due-dates' value='import-missing-due-dates' id='import-missing-due-dates'>
<label for='import-missing-due-dates'>Import</label>
<label for='import-missing-due-dates'>Copy</label>
</div>
</div>
</div>
Expand Down Expand Up @@ -212,7 +212,24 @@ <h3 class='hidden'>Property Values</h3>
<button type='reset' id='options-restore-notion-property-values' class='button red hover row hidden'>Restore Defaults</button>
</div>

<h3 class='hidden'>Import Assignment Changes</h3>
<h2>Assignment Import</h2>
<h3>Filtering</h3>
<div class='tile'>
<div class='segmented-control-group'>
<label class='required' for='past-due-dates'>Past assignments</label>
<div class='segmented-control-wrapper'>
<div class='segmented-control row' id='past-due-dates'>
<input type='radio' name='past-due-dates' value='ignore-past-due-dates' id='ignore-past-due-dates'>
<label for='ignore-past-due-dates'>Ignore</label>

<input type='radio' name='past-due-dates' value='import-past-due-dates' id='import-past-due-dates'>
<label for='import-past-due-dates'>Import</label>
</div>
</div>
</div>
</div>

<h3 class='hidden'>Canvas Changes</h3>
<div class='tile hidden'>
<div class='segmented-control-group'>
<label class='required' for='notion-changes-name'>Name changes</label>
Expand Down
4 changes: 2 additions & 2 deletions src/options/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -531,14 +531,14 @@ const Konami = {
document.addEventListener('keydown', event => Konami.handler(event), false);

// ! alert for removal of status select property support
// @ts-expect-error
// @ts-expect-error Key has been removed.
Storage.getStorageKey('notion.propertyNames.status', false).then(value => {
if (value === false) return;

const deleteProperty = confirm('Prior support for a \'Status\' Notion property has been removed.\n\nPlease update your database to use the newly-released Notion built-in Status property.\n\nFor more information, visit the GitHub Repository.\n\nClick \'OK\' to hide this message forever.');

if (!deleteProperty) return;

// @ts-expect-error
// @ts-expect-error Key has been removed.
Storage.clearStorageKey('notion.propertyNames.status');
});
3 changes: 2 additions & 1 deletion src/popup/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function roundToNextHour(date: Date): Date {
}

function reformatDate(dateString: string | null, timeZone: string | null): string | null {
if (!dateString) return null
if (!dateString) return null;

/*
Problem: Notion does not convert times into the correct timezone,
Expand Down Expand Up @@ -89,6 +89,7 @@ function reformatDate(dateString: string | null, timeZone: string | null): strin
url: assignment.html_url,
available: (assignment.unlock_at)
? reformatDate(assignment.unlock_at, options.notion.timeZone)
// TODO: this will be broken for past assignments!
: reformatDate(roundToNextHour(timeNow).toISOString(), options.notion.timeZone),
due: reformatDate(assignment.due_at, options.notion.timeZone),
}));
Expand Down
2 changes: 1 addition & 1 deletion src/popup/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ export async function exportToNotion(): Promise<void | {
.flat()
.filter(assignment => {
if (!assignment.due) return canvasOptions.importMissingDueDates;
return Date.parse(assignment.due) > Date.now();
return (options.importPastDueDates) || (Date.parse(assignment.due) > Date.now());
})
.map(assignment => [assignment.url, new FetchedAssignment(assignment)])
);
Expand Down
4 changes: 2 additions & 2 deletions src/popup/popup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,15 +282,15 @@ buttons.clearStorage.addEventListener('click', () => {
SavedCoursesList.listCourses();

// ! alert for removal of status select property support
// @ts-expect-error
// @ts-expect-error Key has been removed.
Storage.getStorageKey('notion.propertyNames.status', false).then(value => {
if (value === false) return;

const deleteProperty = confirm('Prior support for a \'Status\' Notion property has been removed.\n\nPlease update your database to use the newly-released Notion built-in Status property.\n\nFor more information, visit the GitHub Repository.\n\nClick \'OK\' to hide this message forever.');

if (!deleteProperty) return;

// @ts-expect-error
// @ts-expect-error Key has been removed.
Storage.clearStorageKey('notion.propertyNames.status');
});

Expand Down
4 changes: 3 additions & 1 deletion src/types/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface RequiredFields {
'notion.accessToken': NullIfEmpty<string>;
'notion.databaseId': NullIfEmpty<string>;
'notion.propertyNames.name': NeverEmpty<string>;
'notion.importPastDueDates': boolean;
'notion.importChanges.name': boolean;
'notion.importChanges.points': boolean;
'notion.importChanges.available': boolean;
Expand Down Expand Up @@ -75,13 +76,14 @@ export type SavedOptions = {
propertyValues: {
categoryCanvas: OptionalFields['notion.propertyValues.categoryCanvas'];
},
importPastDueDates: RequiredFields['notion.importPastDueDates'];
importChanges: {
name: RequiredFields['notion.importChanges.name'];
points: RequiredFields['notion.importChanges.points'];
available: RequiredFields['notion.importChanges.available'];
due: RequiredFields['notion.importChanges.due'];
span: RequiredFields['notion.importChanges.span'];
}
},
courseEmojis: OptionalFields['notion.courseEmojis'];
},
};
Expand Down

0 comments on commit a6c6417

Please sign in to comment.