* feat: Imports to popupcourseblock.tsx * changing the blocks to accept parameters for clicking functionality which may or may not open the calendar * put the click parameter in the div of popupcourseblock * safely calling for onCourseClick in the event it is an undefined function * handled other calls of popupcourseblock with empty functions for now, and i think popupmain opens calendar now when the course block is clicked * feat: Testing out passing params to handleOpenCalendar * url that takes in params to open calendar with params * further work on url params; from popup main to handleopencalendar to calendar using urlsearchparams * feat: small calendar shifting after merge: * fix: merge handling and then references to new click parameter * fix: optional params * feat: split into two functions instead * fix: changing proper usage of handleOpenCalendarWithCourse * feat: show course popup when calendar opened * chore: remove useless commented out code * feat: close popup on calendar nav, fix build errors, remove useless comments/logs * chore: chromatic so dumb fr why aren't you chrome * fix: refactor listeners to build properly * feat: exit early when not in chrome extension * fix: function return type * fix: function return type x2 * fix: generic type for useState * refactor: extract calendar opening on click functions * refactor: chrome runtime mock, omit question mark if no query params, rename calendar event * refactor: move course click event into component directly instead of prop * refactor: removed useless wrapper functions, made popup course block more accessible * fix: i dont wanna talk about it --------- Co-authored-by: Samuel Gunter <sgunter@utexas.edu>
170 lines
6.7 KiB
TypeScript
170 lines
6.7 KiB
TypeScript
import type { Preview } from '@storybook/react';
|
|
import ExtensionRoot from '@views/components/common/ExtensionRoot/ExtensionRoot';
|
|
import React from 'react';
|
|
|
|
const preview: Preview = {
|
|
parameters: {
|
|
actions: { argTypesRegex: '^on[A-Z].*' },
|
|
controls: {
|
|
matchers: {
|
|
color: /(background|color)$/i,
|
|
date: /Date$/i,
|
|
},
|
|
},
|
|
},
|
|
decorators: [
|
|
Story => (
|
|
<React.StrictMode>
|
|
<ExtensionRoot>
|
|
<Story />
|
|
</ExtensionRoot>
|
|
</React.StrictMode>
|
|
),
|
|
],
|
|
};
|
|
|
|
let localData = {};
|
|
type ListenerFunction = (
|
|
changes: { [key: string]: chrome.storage.StorageChange },
|
|
areaName: chrome.storage.AreaName
|
|
) => void;
|
|
const localDataListeners = new Map<
|
|
ListenerFunction, // key to remove listener
|
|
(changes: { [key: string]: chrome.storage.StorageChange }) => void
|
|
>();
|
|
|
|
// mock chrome api
|
|
globalThis.chrome = {
|
|
storage: {
|
|
local: {
|
|
/**
|
|
* Removes all items from storage.
|
|
* @param callback Optional.
|
|
* Callback on success, or on failure (in which case runtime.lastError will be set).
|
|
*/
|
|
async clear() {
|
|
localData = {};
|
|
},
|
|
/**
|
|
* Gets one or more items from storage.
|
|
* @param keys A single key to get, list of keys to get, or a dictionary specifying default values.
|
|
* An empty list or object will return an empty result object. Pass in null to get the entire contents of storage.
|
|
* @return A Promise that resolves with an object containing items
|
|
*/
|
|
async get(keys?: string | string[] | { [key: string]: any } | null) {
|
|
if (keys === null) {
|
|
return localData;
|
|
}
|
|
if (Array.isArray(keys)) {
|
|
return keys.reduce((acc, key) => {
|
|
acc[key] = localData[key];
|
|
return acc;
|
|
}, {} as string); // funny types
|
|
}
|
|
if (typeof keys === 'string') {
|
|
return { [keys]: localData[keys] };
|
|
}
|
|
return keys;
|
|
},
|
|
/**
|
|
* Gets the amount of space (in bytes) being used by one or more items.
|
|
* @param keys Optional. A single key or list of keys to get the total usage for. An empty list will return 0. Pass in null to get the total usage of all of storage.
|
|
* @param callback Callback with the amount of space being used by storage, or on failure (in which case runtime.lastError will be set).
|
|
* Parameter bytesInUse: Amount of space being used in storage, in bytes.
|
|
*/
|
|
async getBytesInUse() {
|
|
return 0;
|
|
},
|
|
/**
|
|
* Removes one or more items from storage.
|
|
* @param keys A single key or a list of keys for items to remove.
|
|
* @param callback Optional.
|
|
* Callback on success, or on failure (in which case runtime.lastError will be set).
|
|
*/
|
|
async remove(keys: string | string[]) {
|
|
if (Array.isArray(keys)) {
|
|
keys.forEach(key => {
|
|
for (const listener of localDataListeners.values()) {
|
|
listener({ [key]: { oldValue: localData[key], newValue: undefined } });
|
|
}
|
|
|
|
delete localData[key];
|
|
});
|
|
} else {
|
|
for (const listener of localDataListeners.values()) {
|
|
listener({ [keys]: { oldValue: localData[keys], newValue: undefined } });
|
|
}
|
|
|
|
delete localData[keys];
|
|
}
|
|
},
|
|
/**
|
|
* Sets multiple items.
|
|
* @param items An object which gives each key/value pair to update storage with. Any other key/value pairs in storage will not be affected.
|
|
* Primitive values such as numbers will serialize as expected. Values with a typeof "object" and "function" will typically serialize to {}, with the exception of Array (serializes as expected), Date, and Regex (serialize using their String representation).
|
|
* @param callback Optional.
|
|
* Callback on success, or on failure (in which case runtime.lastError will be set).
|
|
*/
|
|
async set(items: { [key: string]: any }) {
|
|
for (const key in items) {
|
|
const oldValue = localData[key];
|
|
localData[key] = JSON.parse(JSON.stringify(items[key]));
|
|
|
|
for (const listener of localDataListeners.values()) {
|
|
listener({ [key]: { oldValue: oldValue, newValue: localData[key] } });
|
|
}
|
|
}
|
|
},
|
|
},
|
|
onChanged: {
|
|
/**
|
|
* Registers an event listener callback to an event.
|
|
* @param callback Called when an event occurs. The parameters of this function depend on the type of event.
|
|
*/
|
|
addListener(
|
|
listener: (
|
|
changes: { [key: string]: chrome.storage.StorageChange },
|
|
areaName: chrome.storage.AreaName
|
|
) => void
|
|
) {
|
|
localDataListeners.set(listener, (changes: { [key: string]: chrome.storage.StorageChange }) => {
|
|
listener(changes, 'local');
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Deregisters an event listener callback from an event.
|
|
* @param callback Listener that shall be unregistered.
|
|
*/
|
|
removeListener(listener: ListenerFunction) {
|
|
localDataListeners.delete(listener);
|
|
},
|
|
},
|
|
},
|
|
runtime: {
|
|
id: 'fake-id',
|
|
getManifest(): chrome.runtime.Manifest {
|
|
return {
|
|
manifest_version: 3,
|
|
name: 'fake-name',
|
|
version: '0.0.0',
|
|
};
|
|
},
|
|
onMessage: {
|
|
/**
|
|
* Registers an event listener callback to an event.
|
|
* @param callback Called when an event occurs. The parameters of this function depend on the type of event.
|
|
*/
|
|
addListener<T extends Function>(callback: T) {},
|
|
|
|
/**
|
|
* Deregisters an event listener callback from an event.
|
|
* @param callback Listener that shall be unregistered.
|
|
*/
|
|
removeListener<T extends Function>(callback: T) {},
|
|
},
|
|
},
|
|
} as typeof chrome;
|
|
|
|
export default preview;
|