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

Another chunk of lint issues #45

Merged
merged 3 commits into from
Jan 23, 2025
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
2 changes: 1 addition & 1 deletion src/components/FullPlayground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,7 @@ export function ThemedAppView(props: { datastore: DataStore }) {
>(undefined);

const conductValidation = () => {
validationService.conductValidation((validated: boolean) => {
validationService.conductValidation(() => {
return false;
});
};
Expand Down
26 changes: 15 additions & 11 deletions src/playground-ui/ConfirmDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ import DialogTitle from "@material-ui/core/DialogTitle";
import TextField from "@material-ui/core/TextField";
import React, { useState } from "react";

export type ConfirmValue = "undefined" | "load" | "replace" | "nevermind"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the generics in this and ConfirmDialogProvider were around taking these value values and making sure that they were tracked by the typesystem. I got to a place where typescript was complaining that two apparently-identical types were distinct and therefore not assignable to each other. I made the decision that it wasn't worth the complexity, in favor of explicitly typing the ConfirmValue.

The downside of this approach is that this enumeration needs to change every time that a new desired value for value is added, but given the way we're matching on the values, that's probably okay.

All other changes in these files are propagating this change.


/**
* ConfirmDialogButton is a button in the confirm dialog.
*/
export interface ConfirmDialogButton<B extends string> {
export interface ConfirmDialogButton {
/**
* title is the title of the button.
*/
Expand All @@ -20,7 +22,7 @@ export interface ConfirmDialogButton<B extends string> {
/**
* value is the value to given to the callback if the button is clicked.
*/
value: B
value?: ConfirmValue

/**
* color is the color of the button. Default is `default`.
Expand All @@ -38,12 +40,12 @@ export interface ConfirmDialogButton<B extends string> {
isEnabled?: (promptValue?: string) => boolean
}

export type ConfirmCallback<B extends string> = (value: B, promptValue?: string) => void;
export type ConfirmCallback = (value: ConfirmValue, promptValue?: string) => void;

/**
* ConfirmDialogProps are the props for the confirm dialog.
*/
export interface ConfirmDialogProps<B extends string> {
export interface ConfirmDialogProps {
/**
* isOpen indicates whether the ConfirmDialog is currently open.
*/
Expand All @@ -54,7 +56,7 @@ export interface ConfirmDialogProps<B extends string> {
* returns the value clicked. If the [X] is clicked, the `value` will be
* undefined.
*/
handleComplete: ConfirmCallback<B>
handleComplete: ConfirmCallback

/**
* title is the title of the confirm.
Expand All @@ -69,7 +71,7 @@ export interface ConfirmDialogProps<B extends string> {
/**
* buttons are the buttons on the confirm dialog.
*/
buttons: ConfirmDialogButton<B>[]
buttons: ConfirmDialogButton[]


/**
Expand Down Expand Up @@ -97,13 +99,15 @@ const useStyles = makeStyles((theme: Theme) =>
* title="My confirm" content="Hi there!"
* buttons={[{"title": "Close", "value": undefined}]}/>
*/
export function ConfirmDialog<B extends string>(props: ConfirmDialogProps<B>) {
export function ConfirmDialog(props: ConfirmDialogProps) {
const [promptValue, setPromptValue] = useState('');
const classes = useStyles();

const handleComplete = (value: any) => {
props.handleComplete(value as B, promptValue);
setPromptValue('');
const handleComplete = (value: ConfirmValue | undefined) => {
if (value) {
props.handleComplete(value, promptValue);
setPromptValue('');
}
};

return <Dialog
Expand All @@ -124,7 +128,7 @@ export function ConfirmDialog<B extends string>(props: ConfirmDialogProps<B>) {
</DialogContentText>
</DialogContent>
<DialogActions>
{props.buttons.map((button: ConfirmDialogButton<B>, index: number) => {
{props.buttons.map((button: ConfirmDialogButton, index: number) => {
return <Button key={index} variant={button.variant}
onClick={() => handleComplete(button.value)}
color={button.color}
Expand Down
59 changes: 33 additions & 26 deletions src/playground-ui/ConfirmDialogProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,78 +1,85 @@
import React, {
PropsWithChildren,
import {
useCallback,
useContext,
useState,
createContext,
type ReactNode,
} from "react";
import {
ConfirmCallback,
ConfirmDialog,
ConfirmDialogButton,
type ConfirmValue
} from "./ConfirmDialog";

export interface ConfirmProps<B extends string> {
export interface ConfirmProps {
/**
* title is the title of the confirm.
*/
title: React.ReactNode;
title: ReactNode;

/**
* content is the content of the confirm.
*/
content: React.ReactNode;
content: ReactNode;

/**
* buttons are the buttons on the confirm dialog.
*/
buttons: ConfirmDialogButton<B>[];
buttons: ConfirmDialogButton[];

/**
* withPrompt, if specified, indicates a prompt should be displayed with
* the given string as the placeholder.
*/
withPrompt?: string;

children?: ReactNode;
}

export type ShowConfirm = <B extends string>(
props: ConfirmProps<B>,
callback: ShowConfirmCallback<B>
) => any;
export type ShowConfirmCallback<B extends string> = (
result: [B, string | undefined]
export type ShowConfirm = (
props: ConfirmProps,
callback: ShowConfirmCallback
) => void;
export type ShowConfirmCallback = (
result: [ConfirmValue, string | undefined]
) => void;

const ConfirmDialogContext = React.createContext<ShowConfirm | undefined>(
const ConfirmDialogContext = createContext<ShowConfirm | undefined>(
undefined
);

/**
* ConfirmDialogProvider provides the confirm dialog UI.
*/
export function ConfirmDialogProvider(props: PropsWithChildren<any>) {
const [confirmProps, setConfirmProps] = useState<ConfirmProps<string>>({
export function ConfirmDialogProvider(props: { children: ReactNode }) {
// TODO: this is likely derived state and should be passed through.
const [confirmProps, setConfirmProps] = useState<ConfirmProps>({
title: "",
content: "",
buttons: [],
});
const [isConfirmOpen, setIsConfirmOpen] = useState(false);
// TODO: this should be a useCallback, probably
const [confirmCallback, setConfirmCallback] = useState<{
callback: ConfirmCallback<string> | undefined;
callback: ConfirmCallback | undefined;
}>({ callback: undefined });

const showConfirm = <B extends string>(
props: ConfirmProps<B>,
callback: ShowConfirmCallback<B>
// TODO: this should be memoized.
const showConfirm = (
props: ConfirmProps,
callback: ShowConfirmCallback
) => {
setConfirmProps(props);
setConfirmCallback({
callback: (value: string, promptValue?: string) => {
callback([value as B, promptValue]);
callback: (value: ConfirmValue, promptValue?: string) => {
callback([value, promptValue]);
},
});
setIsConfirmOpen(true);
};

const handleCompleted = (value: string, promptValue?: string) => {
const handleCompleted = (value: ConfirmValue, promptValue?: string) => {
if (confirmCallback.callback !== undefined) {
confirmCallback.callback(value, promptValue);
}
Expand All @@ -81,7 +88,7 @@ export function ConfirmDialogProvider(props: PropsWithChildren<any>) {

return (
<>
<ConfirmDialog<string>
<ConfirmDialog
isOpen={isConfirmOpen}
handleComplete={handleCompleted}
{...confirmProps}
Expand Down Expand Up @@ -111,10 +118,10 @@ export function useConfirmDialog() {
}

const showConfirm = useCallback(
<B extends string>(props: ConfirmProps<B>) => {
const promise = new Promise<[B, string?]>(
(props: ConfirmProps) => {
const promise = new Promise<[ConfirmValue, string?]>(
(
resolve: (value: [B, string?] | PromiseLike<[B, string?]>) => void
resolve: (value: [ConfirmValue, string?] | PromiseLike<[ConfirmValue, string?]>) => void
) => {
showConfirmCallback(props, resolve);
}
Expand Down
2 changes: 1 addition & 1 deletion src/playground-ui/DiscordChatCrate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ const loadFromCDN = () =>
script.src = CDN_URL;
document.head.appendChild(script);

script.onload = () => resolve((window as any).Crate);
script.onload = () => resolve(window.Crate);
script.onerror = () => reject('Failed to load Crate!');
});

Expand Down
15 changes: 9 additions & 6 deletions src/playground-ui/GoogleAnalyticsHook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useEffect } from 'react';

declare global {
interface Window {
gtag: (kind: string, subkind: any, data?: Record<string, any>) => any
dataLayer: any[];
gtag: (kind: string, subkind: object | string, data?: Record<string, object | string | boolean>) => object
dataLayer: object[];
}
}

Expand Down Expand Up @@ -36,6 +36,9 @@ export const useGoogleAnalytics = (measurementId?: string) => {
if (measurementId && !tagInjected) {
// Configure Tags Manager.
window.dataLayer = window.dataLayer || [];
// As of 2025-01 we're probably going to get rid of this file soon in favor
// of GTM.
// eslint-disable-next-line prefer-rest-params
window.gtag = window.gtag || function () { window.dataLayer.push(arguments) };
window.gtag('js', new Date());
window.gtag('config', measurementId);
Expand All @@ -54,25 +57,25 @@ export const useGoogleAnalytics = (measurementId?: string) => {
}
});

const pushEvent = (eventName: string, eventParams: Record<string, any>) => {
const pushEvent = (eventName: string, eventParams: Record<string, object | string | boolean>) => {
if (!tagInjected) {
return
}
window.gtag('event', eventName, eventParams);
};

const setValue = (valueKey: string, value: Record<string, any>) => {
const setValue = (valueKey: string, value: Record<string, object>) => {
if (!tagInjected) {
return
}
window.gtag('set', valueKey, value);
};

const setUser = (userData: Record<string, any>) => {
const setUser = (userData: Record<string, object>) => {
if (userSet) { return; }
setValue('user', userData);
userSet = true;
};

return { initialized: !!measurementId, setValue: setValue, pushEvent: pushEvent, setUser: setUser };
};
};
4 changes: 2 additions & 2 deletions src/playground-ui/TabPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ export interface TabPanelProps {
/**
* index is the index for which, if the value matches, the tab is displayed.
*/
index: any;
index: string;

/**
* value is the current tab value.
*/
value: any;
value: string;

/**
* className is the custom classname for the TabPanel.
Expand Down
12 changes: 8 additions & 4 deletions src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
export {}

declare module '*.yaml' {
const data: any
const data: object
export default data
}

declare module '*.md' {
const data: any
const data: object
export default data
}

Expand All @@ -18,13 +18,17 @@ declare module 'string.prototype.replaceall' {
}

declare module 'visjs-network' {
const data: any
const data: object
export default data
}

declare global {
interface Window {
// TODO: type this based on what's in wasm_exec.js
Go: any;
Go: new () => {
importObject: WebAssembly.Imports;
run: (instance: object) => void;
};
Crate: new (options: Options) => Crate;
Comment on lines +28 to +32
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds some window typing for our Go and discord Crate usages.

}
}
Loading