Skip to content

Commit

Permalink
Add a "service imported" animation
Browse files Browse the repository at this point in the history
The import process on production can go super fast so it's nice to have something more explicit
  • Loading branch information
underbluewaters committed Dec 11, 2023
1 parent 321181c commit 8b5027b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 4 deletions.
79 changes: 78 additions & 1 deletion packages/client/src/admin/data/arcgis/ArcGISCartModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ import {
useCreateBasemapMutation,
useImportArcGisServiceMutation,
} from "../../../generated/graphql";
import ReactDOM from "react-dom";
import {
MotionValue,
motion,
useMotionValue,
useTransform,
} from "framer-motion";

const requestManager = new ArcGISRESTServiceRequestManager();

Expand Down Expand Up @@ -675,7 +682,19 @@ export default function ArcGISCartModal({
},
refetchQueries: [DraftTableOfContentsDocument],
});
hideLoadingMessage();
updateLoadingMessage(
<div className="flex items-center space-x-2">
<div>{t("Service imported")}</div>
<FinishedImportAnimation
onAnimationComplete={() =>
setTimeout(() => {
hideLoadingMessage();
}, 500)
}
/>
</div>,
true
);
} catch (e) {
hideLoadingMessage();
alert(t("Error importing service"), {
Expand Down Expand Up @@ -977,3 +996,61 @@ function LoadingSkeleton() {
</div>
);
}

function CircularProgress({ progress }: { progress: MotionValue<number> }) {
const circleLength = useTransform(progress, [0, 100], [0, 1]);
const checkmarkPathLength = useTransform(progress, [0, 95, 100], [0, 0, 1]);
const circleColor = useTransform(
progress,
[0, 95, 100],
["#FFCC66", "#FFCC66", "#66BB66"]
);

return (
<motion.svg
xmlns="http://www.w3.org/2000/svg"
className="w-8 h-8"
viewBox="0 0 258 258"
>
{/* Check mark */}
<motion.path
transform="translate(60 85)"
d="M3 50L45 92L134 3"
fill="transparent"
stroke="#7BB86F"
strokeWidth={8}
style={{ pathLength: checkmarkPathLength }}
/>
{/* Circle */}
<motion.path
d="M 130 6 C 198.483 6 254 61.517 254 130 C 254 198.483 198.483 254 130 254 C 61.517 254 6 198.483 6 130 C 6 61.517 61.517 6 130 6 Z"
fill="transparent"
strokeWidth="8"
stroke={circleColor}
style={{
pathLength: circleLength,
}}
/>
</motion.svg>
);
}

function FinishedImportAnimation({
onAnimationComplete,
}: {
onAnimationComplete: () => void;
}) {
let progress = useMotionValue(90);
return (
<div className="inline-flex align-center">
<motion.div
initial={{ x: 0 }}
animate={{ x: 100 }}
style={{ x: progress }}
transition={{ duration: 1 }}
onAnimationComplete={onAnimationComplete}
/>
<CircularProgress progress={progress} />
</div>
);
}
10 changes: 7 additions & 3 deletions packages/client/src/components/useDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@ export default function useDialog() {
hideLoadingMessage: () => {
context.setState(ResetState);
},
updateLoadingMessage: (message: string) => {
updateLoadingMessage: (
message: string | ReactNode,
complete?: boolean
) => {
context.setState((prev) => {
return {
...prev,
description: message,
submitting: complete ? false : true,
};
});
},
Expand Down Expand Up @@ -139,7 +143,7 @@ type DialogContextState = {
type: "prompt" | "alert" | "confirm" | "loading" | "choice";
open: boolean;
message: string | ReactNode;
description?: string;
description?: string | ReactNode;
defaultValue?: string;
submitting: boolean;
onSubmit?: (value: string) => void | Promise<string | void>;
Expand Down Expand Up @@ -290,7 +294,7 @@ export function DialogProvider({ children }: { children?: ReactNode }) {
<div className="">
{state.type === "loading" && (
<div className="flex items-center justify-center p-4 space-x-2">
<Spinner />
{state.submitting ? <Spinner /> : ""}
<div>{state.description}</div>
</div>
)}
Expand Down

0 comments on commit 8b5027b

Please sign in to comment.