Skip to content

Commit

Permalink
add google analytics context
Browse files Browse the repository at this point in the history
  • Loading branch information
asanchezyali committed Aug 14, 2023
1 parent c2a0ca1 commit 81fef28
Show file tree
Hide file tree
Showing 21 changed files with 429 additions and 26 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ Follow one,
# Run using the staging profile
docker-compose --profile=staging up
```
</details>

<details>
<summary><b><img src="https://user-images.githubusercontent.com/511499/117447182-29758200-af0b-11eb-97bd-58723fee62ab.png" alt="Docker" height="28px" align="top"/> <code>docker-compose</code></b> (Linux/Without Nvidia GPU) &nbsp;</summary>
<br/>

It emulates the use of AI pipeline when you don't have a GPU available. It returns fixed fake images from the models.
This is because it is mandatory to have GPU to use Generative AI. It's a good way to test the application locally
```bash
# Run using the no-gpu profile
docker-compose --profile=local up
```

</details>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@use "styles/colors";
@use "styles/media";
@use "styles/variables";


.cookiesContainer {
position: fixed;
bottom: 0;
left: 0;
width: 100vw;
min-height: 50px;
height: auto;
z-index: 999;
display: flex;
align-items: center;
justify-content: center;
background-color: rgba(0, 0, 0, 0.9);
padding: 20px;

@include media.mobile {
flex-direction: column;
justify-content: flex-start;
}

.textContainer {
width: 70%;
height: 100%;
display: flex;
align-items: center;

a {
display: block;
text-decoration: underline;
}

@include media.mobile {
width: 100%;
flex-direction: column;
align-items: flex-start;
}
}

.buttonsSection {
width: auto;
margin-left: 24px;
display: flex;
justify-content: space-between;
min-width: 400px;
padding-right: 24px;

@include media.mobile {
width: 100%;
flex-direction: column;
margin: 24px 0 0 0;
}

button {
:first-child {
margin-right: 24px !important;
}

@include media.mobile {
width: 100%;
margin: 8px !important;
}
}
}
}
66 changes: 66 additions & 0 deletions morpheus-client/components/CookiesConsent/CookiesConsent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useEffect, useState } from "react";
import { useAnalytics } from "@/context/GoogleAnalyticsContext";
import { deleteAllCookies, CookiesStatus } from "@/utils/cookies";
import { useLocalStorage } from "@/hooks/useLocalStorage";
import styles from "./CookiesConsent.module.scss";



const CookiesConsent = () => {
const [finalStatus, setFinalStatus] = useState("");
const { cookiesStatus, setCookiesStatus } = useAnalytics();

const [localCookies, setLocalCookies] = useLocalStorage<string | null>("cp:cookies", null);


useEffect(() => {
const newStatus = localCookies || cookiesStatus || "";
setFinalStatus(newStatus);
if (newStatus !== "") {
if (localCookies && localCookies !== "") setCookiesStatus(localCookies);
}
}, [localCookies, setCookiesStatus, cookiesStatus]);

const handleActionCookies = (event: any, status: string) => {
event.preventDefault();

if (status === CookiesStatus.Declined) {
deleteAllCookies();
}

setCookiesStatus(status);
setLocalCookies(status);
};

return finalStatus === "" ? (
<div className={styles.cookiesContainer}>
<div className={styles.textContainer}>
<p className="body-1 secondary">
This website uses cookies to ensure you get the best experience on our
website.
<a className="underline text-primary" target="_blank" href="">
Privacy Policy
</a>
</p>
</div>

<div className={styles.buttonsSection}>
<button
className="buttonSubmit"
onClick={(event) => handleActionCookies(event, CookiesStatus.Declined)}
>
Decline
</button>

<button
className="buttonSubmit"
onClick={(event) => handleActionCookies(event, CookiesStatus.Accepted)}
>
Accept
</button>
</div>
</div>
) : null;
};

export default CookiesConsent;
74 changes: 74 additions & 0 deletions morpheus-client/context/GoogleAnalyticsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { createContext, ReactNode, useContext, useEffect, useState } from "react";
import { useRouter } from "next/router";
import { analytics } from "../lib/firebaseClient";
import { logEvent } from "firebase/analytics";
import { CookiesStatus } from "@/utils/cookies";

export interface IAnalyticsContext {
analytics: any;
cookiesStatus: string;
setCookiesStatus: (accept: string) => void;
sendAnalyticsRecord: (type: string, message: any) => void;
}

const defaultState = {
analytics: undefined,
cookiesStatus: "",
setCookiesStatus: () => {},
sendAnalyticsRecord: () => {},
};

const AnalyticsContext = createContext<IAnalyticsContext>(defaultState);

const FirebaseTrackingProvider = (props: { children: ReactNode }) => {
const router = useRouter();
const [cookiesStatus, setCookiesStatus] = useState("");

useEffect(() => {
const handleRouteChange = (url: string) => {
if (cookiesStatus === CookiesStatus.Accepted && analytics) {
return;
}

logEvent(analytics, "page_view", {
page_location: url,
page_title: document?.title,
});
};

router.events.on("routeChangeStart", handleRouteChange);

return () => {
router.events.off("routeChangeStart", handleRouteChange);
};
}, [cookiesStatus, router.events]);

const sendAnalyticsRecord = (type: string, parameters: object) => {
if (cookiesStatus === CookiesStatus.Accepted && analytics) {
logEvent(analytics, type, parameters);
}
};

return (
<AnalyticsContext.Provider
value={{
analytics,
cookiesStatus,
setCookiesStatus,
sendAnalyticsRecord,
}}
>
{props.children}
</AnalyticsContext.Provider>
);
};

const useAnalytics = () => {
const context = useContext(AnalyticsContext);
if (context === undefined) {
throw new Error("useAnalytics must be used within a AnalyticsProvider");
}
return context;
};

export { FirebaseTrackingProvider, useAnalytics };
17 changes: 15 additions & 2 deletions morpheus-client/pages/404.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,28 @@
import { useCallback } from "react";
import { useCallback, useEffect } from "react";
import { useRouter } from "next/router";

import { CookiesStatus } from "@/utils/cookies";
import { useAnalytics } from "@/context/GoogleAnalyticsContext";
import MainContainer from "../layout/MainContainer/MainContainer";
import styles from "../styles/pages/Error.module.scss";

const Page400 = () => {
const { cookiesStatus, sendAnalyticsRecord } = useAnalytics();
const router = useRouter();

const handleClickToAction = useCallback(async () => {
await router.push("/");
}, [router]);

useEffect(() => {
if (cookiesStatus === CookiesStatus.Accepted) {
sendAnalyticsRecord("page_view", {
page_location: window.location.href,
page_title: document?.title,
page_name: "Error",
});
}
}, [cookiesStatus, sendAnalyticsRecord]);

return (
<MainContainer>
<div className={styles.mainContent}>
Expand Down
29 changes: 17 additions & 12 deletions morpheus-client/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import { AuthProvider } from "@/context/AuthContext";
import { DiffusionProvider } from "@/context/SDContext";
import { ControlNetProvider } from "@/context/CNContext";
import { ImagineProvider } from "@/context/ImagineContext";
import { FirebaseTrackingProvider } from "@/context/GoogleAnalyticsContext";
import { Toaster } from "@/components/ui/toaster";
import CookiesConsent from "@/components/CookiesConsent/CookiesConsent";

import "../App.scss";
import "../styles/globals.css";
Expand Down Expand Up @@ -123,18 +125,21 @@ const App: FC<AppProps> = ({ Component, pageProps }) => {
<meta name="google-site-verification" content="" />
</Head>

<ToastProvider>
<AuthProvider>
<DiffusionProvider>
<ControlNetProvider>
<ImagineProvider>
<Component {...pageProps} />
<Toaster />
</ImagineProvider>
</ControlNetProvider>
</DiffusionProvider>
</AuthProvider>
</ToastProvider>
<FirebaseTrackingProvider>
<ToastProvider>
<AuthProvider>
<DiffusionProvider>
<ControlNetProvider>
<ImagineProvider>
<Component {...pageProps} />
<CookiesConsent />
<Toaster />
</ImagineProvider>
</ControlNetProvider>
</DiffusionProvider>
</AuthProvider>
</ToastProvider>
</FirebaseTrackingProvider>
</Fragment>
);
};
Expand Down
20 changes: 18 additions & 2 deletions morpheus-client/pages/about.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { useEffect } from "react";

import { CookiesStatus } from "@/utils/cookies";
import { useAnalytics } from "@/context/GoogleAnalyticsContext";
import MainContainer from "../layout/MainContainer/MainContainer";
import FAQ from "../components/FAQ/FAQ";
import { AppLink } from "@/components/AppLink/AppLink";
Expand All @@ -12,6 +16,18 @@ import {
import styles from "../styles/pages/About.module.scss";

const About = () => {
const { cookiesStatus, sendAnalyticsRecord } = useAnalytics();

useEffect(() => {
if (cookiesStatus === CookiesStatus.Accepted) {
sendAnalyticsRecord("page_view", {
page_location: window.location.href,
page_title: document?.title,
page_name: "About",
});
}
}, [cookiesStatus, sendAnalyticsRecord]);

return (
<MainContainer showFooter={true} style={{ justifyContent: "center" }}>
<div className={styles.aboutContainer}>
Expand Down Expand Up @@ -57,13 +73,13 @@ const About = () => {
<p className="body-1 secondary">
We’re hoping to get some feedback from users like you! Do you find
this useful? Are there features missing from our{" "}
<a className="app-link body-1 main underline" href="#roadmap">
<a className="underline app-link body-1 main" href="#roadmap">
roadmap
</a>{" "}
that you would like to see? Run into any problems or bugs? We want
to hear about it! Contact us via{" "}
<a
className="body-1 main underline"
className="underline body-1 main"
href="mailto:[email protected]"
>
email
Expand Down
14 changes: 14 additions & 0 deletions morpheus-client/pages/gallery/[collectionId].tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import React, { Fragment, useEffect, useState } from "react";
import { NextPage } from "next";
import { useRouter } from "next/router";

import { CookiesStatus } from "@/utils/cookies";
import PrivateRoute from "@/components/Auth/PrivateRoute/PrivateRoute";
import Loader from "@/components/Loaders/LoaderCircle/Loader";
import CollectionForm from "@/components/CollectionForm/CollectionForm";
Expand All @@ -9,6 +11,7 @@ import ArtWorkList from "@/components/ArtWorkList/ArtWorkList";
import { getCollectionArtWorks } from "@/services/artworks";
import { deleteCollection, getCollectionDetails } from "@/services/collection";
import { useToastContext } from "@/context/ToastContext";
import { useAnalytics } from "@/context/GoogleAnalyticsContext";
import { ArtWork, Collection } from "@/models/models";
import styles from "@/styles/pages/CollectionDetails.module.scss";

Expand All @@ -22,6 +25,7 @@ const CollectionDetail: NextPage = () => {
const [isLoading, setIsLoading] = useState(false);
const [collection, setCollection] = useState<Collection>();
const [artWorks, setArtWorks] = useState<ArtWork[]>([]);
const { cookiesStatus, sendAnalyticsRecord } = useAnalytics();

useEffect(() => {
if (collectionId) {
Expand Down Expand Up @@ -52,6 +56,16 @@ const CollectionDetail: NextPage = () => {
}
}, [collectionId]);

useEffect(() => {
if (cookiesStatus === CookiesStatus.Accepted && collection) {
sendAnalyticsRecord("page_view", {
page_location: window.location.href,
page_title: document?.title,
page_name: `Collection ${collection?.name} detail`
});
}
}, [cookiesStatus, sendAnalyticsRecord, collection]);

const handleEdit = () => {
setShowForm(true);
};
Expand Down
Loading

0 comments on commit 81fef28

Please sign in to comment.