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

chore: trigger releases #480

Merged
merged 2 commits into from
Oct 31, 2023
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
5 changes: 5 additions & 0 deletions .changeset/chilly-lizards-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@carrot-kpi/ui": patch
---

Initialize min and max date if missing
5 changes: 5 additions & 0 deletions .changeset/pretty-planets-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@carrot-kpi/react": minor
---

Improve typings for serializable KPI token and oracle states
5 changes: 5 additions & 0 deletions .changeset/young-lobsters-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@carrot-kpi/host-frontend": minor
---

Integrate new React library KPI token and oracle state typings
12 changes: 6 additions & 6 deletions packages/frontend/src/pages/create-with-template-id/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
KPITokenCreationForm,
useIPFSGatewayURL,
usePreferDecentralization,
type SerializableObject,
} from "@carrot-kpi/react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
Expand All @@ -16,9 +17,8 @@ import { useInvalidateLatestKPITokens } from "../../hooks/useInvalidateLatestKPI
import { Layout } from "../../components/layout";
import { Permissioned } from "../../components/permissioned";
import { useIsCreatorAllowed } from "../../hooks/useIsCreatorAllowed";
import type { Serializable } from "@carrot-kpi/react";

export const CreateWithTemplateId = () => {
export function CreateWithTemplateId<S extends SerializableObject<S>>() {
const { i18n, t } = useTranslation();
const { state } = useLocation();
const navigate = useNavigate();
Expand All @@ -39,10 +39,10 @@ export const CreateWithTemplateId = () => {
const [formKey, setFormKey] = useState(0);
const [draftState, setDraftState] = useState<{
templateId?: number;
state: Serializable;
state: S;
}>({
templateId: undefined,
state: {},
state: {} as S,
});

const { allowed: creatorAllowed, loading: loadingPermission } =
Expand Down Expand Up @@ -133,7 +133,7 @@ export const CreateWithTemplateId = () => {
templateId,
]);

const handleChange = useCallback((state: Serializable) => {
const handleChange = useCallback((state: S) => {
setDraftState((prevState) => ({
templateId: prevState.templateId,
state,
Expand Down Expand Up @@ -209,4 +209,4 @@ export const CreateWithTemplateId = () => {
</div>
</Layout>
);
};
}
4 changes: 2 additions & 2 deletions packages/react/src/components/kpi-token-creation-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import React from "react";
import type { ReactElement } from "react";
import type {
KPITokenCreationFormProps,
Serializable,
SerializableObject,
} from "../types/templates";
import { TemplateComponent } from "./template-component";

export function KPITokenCreationForm<S extends Serializable = Serializable>({
export function KPITokenCreationForm<S extends SerializableObject<S>>({
template,
fallback,
error,
Expand Down
7 changes: 5 additions & 2 deletions packages/react/src/components/oracle-creation-form.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import React from "react";
import type { ReactElement } from "react";
import type { OracleCreationFormProps, Serializable } from "../types/templates";
import type {
OracleCreationFormProps,
SerializableObject,
} from "../types/templates";
import { TemplateComponent } from "./template-component";

export function OracleCreationForm<S extends Serializable = Serializable>({
export function OracleCreationForm<S extends SerializableObject<S>>({
template,
fallback,
error,
Expand Down
19 changes: 13 additions & 6 deletions packages/react/src/hooks/useTemplateModule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ import { useStagingMode } from "./useStagingMode";
import { useNetwork } from "wagmi";
import type {
RemoteComponentProps,
SerializableObject,
TemplateEntity,
TemplateType,
} from "../types/templates";

type ComponentType<
E extends TemplateEntity,
T extends TemplateType,
> = FunctionComponent<RemoteComponentProps<E, T>>;
S extends SerializableObject<S>,
> = FunctionComponent<RemoteComponentProps<E, T, S>>;

interface CachedModule<E extends TemplateEntity, T extends TemplateType> {
Component: ComponentType<E, T>;
interface CachedModule<
E extends TemplateEntity,
T extends TemplateType,
S extends SerializableObject<S>,
> {
Component: ComponentType<E, T, S>;
bundle: TemplateBundle;
}

Expand All @@ -38,15 +44,16 @@ interface TemplateModuleParams<E, T> {
export const useTemplateModule = <
E extends TemplateEntity,
T extends TemplateType,
S extends SerializableObject<S>,
>(
params: TemplateModuleParams<E, T>,
): {
loading: boolean;
Component: ComponentType<E, T> | null;
Component: ComponentType<E, T, S> | null;
bundle: TemplateBundle | null;
} => {
const { entity, type, entry, template } = params;
const MODULE_CACHE = useRef<Record<string, CachedModule<E, T>>>({});
const MODULE_CACHE = useRef<Record<string, CachedModule<E, T, S>>>({});

const customBaseURL = useSelector<
State,
Expand Down Expand Up @@ -75,7 +82,7 @@ export const useTemplateModule = <

const [loadingExport, setLoadingExport] = useState(false);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const [Component, setComponent] = useState<ComponentType<E, T> | null>(
const [Component, setComponent] = useState<ComponentType<E, T, S> | null>(
entry && MODULE_CACHE.current[entry]
? () => MODULE_CACHE.current[entry].Component
: null,
Expand Down
57 changes: 32 additions & 25 deletions packages/react/src/types/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,22 @@ import { ResolvedTemplate } from "@carrot-kpi/sdk";
import type { ReactElement, ReactNode } from "react";
import type { Hex } from "viem";

export type Serializable =
| null
export type Serializable<T> = T extends
| string
| number
| boolean
| { [key: string | symbol | number]: Serializable }
| Serializable[];
| null
| undefined
? T
: T extends object
? { [K in keyof T]: Serializable<T[K]> }
: T extends Array<infer U>
? Array<Serializable<U>>
: never;

export type SerializableObject<T extends object> = {
[K in keyof T]: Serializable<T[K]>;
};

export type TemplateEntity = "kpiToken" | "oracle";

Expand Down Expand Up @@ -54,49 +63,47 @@ export interface OracleInitializationBundle {
export type OracleInitializationBundleGetter =
() => Promise<OracleInitializationBundle>;

export type OracleChangeCallback<S extends Serializable = Serializable> = (
export type OracleChangeCallback<S extends SerializableObject<S>> = (
internalState: S,
initializationBundleGetter?: OracleInitializationBundleGetter,
) => void;

export interface AdditionalRemoteOracleCreationFormProps<
S extends Serializable = Serializable,
> {
export type AdditionalRemoteOracleCreationFormProps<
S extends SerializableObject<S>,
> = {
state: S;
kpiToken?: Partial<KPIToken>;
onChange: OracleChangeCallback<S>;
navigate: NavigateFunction;
onTx: <T extends TxType>(tx: Tx<T>) => void;
}
};

export type OracleRemoteCreationFormProps<
S extends Serializable = Serializable,
> = BaseRemoteTemplateComponentProps &
AdditionalRemoteOracleCreationFormProps<S>;
export type OracleRemoteCreationFormProps<S extends SerializableObject<S>> =
BaseRemoteTemplateComponentProps &
AdditionalRemoteOracleCreationFormProps<S>;

export type KPITokenChangeCallback<S extends Serializable = Serializable> = (
export type KPITokenChangeCallback<S extends SerializableObject<S>> = (
state: S,
) => void;

export type OracleCreationFormProps<S extends Serializable = Serializable> =
export type OracleCreationFormProps<S extends SerializableObject<S>> =
TemplateComponentProps & AdditionalRemoteOracleCreationFormProps<S>;

export interface AdditionalRemoteKPITokenCreationFormProps<
S extends Serializable = Serializable,
> {
export type AdditionalRemoteKPITokenCreationFormProps<
S extends SerializableObject<S>,
> = {
state: S;
onChange: KPITokenChangeCallback<S>;
onCreate: () => void;
navigate: NavigateFunction;
onTx: <T extends TxType>(tx: Tx<T>) => void;
}
};

export type KPITokenRemoteCreationFormProps<
S extends Serializable = Serializable,
> = BaseRemoteTemplateComponentProps &
AdditionalRemoteKPITokenCreationFormProps<S>;
export type KPITokenRemoteCreationFormProps<S extends SerializableObject<S>> =
BaseRemoteTemplateComponentProps &
AdditionalRemoteKPITokenCreationFormProps<S>;

export type KPITokenCreationFormProps<S extends Serializable = Serializable> =
export type KPITokenCreationFormProps<S extends SerializableObject<S>> =
TemplateComponentProps & AdditionalRemoteKPITokenCreationFormProps<S>;

export interface AdditionalRemoteOraclePageProps {
Expand Down Expand Up @@ -125,7 +132,7 @@ export type KPITokenPageProps = TemplateComponentProps &
export type RemoteComponentProps<
E extends TemplateEntity,
T extends TemplateType,
S extends Serializable = Serializable,
S extends SerializableObject<S>,
> = E extends "kpiToken"
? T extends "creationForm"
? KPITokenRemoteCreationFormProps<S>
Expand Down
7 changes: 5 additions & 2 deletions packages/ui/src/components/date-time-input/picker/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,21 @@ export const DateTimePicker = ({
max: maxDate,
}: DateTimePickerProps) => {
const [min, setMin] = useState(minDate);
const [max] = useState(maxDate);
const [max, setMax] = useState(maxDate);

// avoid inconsistent min and max values
useEffect(() => {
if (!min || !dayjs(min).isValid()) setMin(minDate);
if (!max || !dayjs(max).isValid()) setMax(maxDate);

if (dayjs(min).isAfter(dayjs(max))) {
setMin(max);
console.warn("inconsistent min and max values", {
min: min?.toISOString(),
max: max?.toISOString(),
});
}
}, [min, max]);
}, [min, max, minDate, maxDate]);

// in case a value change happened, check if we're still
// alright with validation and rectify if needed
Expand Down