From 1a3e053eeac9cc6309708724594e9e0455c8a825 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Mon, 22 Apr 2024 20:26:50 -0400 Subject: [PATCH 01/24] create OSO functions, UI space --- .../grant-explorer/src/features/api/oso.ts | 67 +++++++++++++++++++ .../src/features/round/OSO/ImpactStats.tsx | 65 ++++++++++++++++++ .../src/features/round/ViewProjectDetails.tsx | 16 +++-- 3 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 packages/grant-explorer/src/features/api/oso.ts create mode 100644 packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts new file mode 100644 index 0000000000..c664566903 --- /dev/null +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -0,0 +1,67 @@ +import { useState } from "react"; +import useSWR from "swr"; +import { Hex } from "viem"; + +const osoUrl = process.env.REACT_APP_OSO_URL; + +export interface IOSOGrant { + uid: Hex; + projectUID: Hex; + communityUID: Hex; + title: string; + description: string; + createdAtMs: number; +} + +export function useOSO(projectId?: string) { + const [stats, setStats] = useState([]); + + const getStatsFor = async (projectRegistryId: string) => { + if (!osoUrl) throw new Error("Open Source Observer url not set."); + try { + const items: IOSOGrant[] = await fetch( + `${osoUrl}/grants/external-id/${projectRegistryId}` + ).then((res) => res.json()); + + if (!Array.isArray(items)) { + setStats([]); + return; + } + + const parsedItems = + items + .filter((grant) => grant.title) + .map((grant) => ({ + ...grant + })) + .sort((a, b) => b.createdAtMs - a.createdAtMs) || []; + + setStats(parsedItems); + } catch (e) { + console.error(`No grants found for project: ${projectRegistryId}`); + console.error(e); + setStats([]); + } + }; + + const { isLoading } = useSWR( + `${osoUrl}/grants/external-id/${projectId}`, + { + fetcher: async () => projectId && getStatsFor(projectId), + } + ); + + return { + /** + * Fetch GAP Indexer for grants for a project + * @param projectRegistryId registryId + */ + getStatsFor, + /** + * Grants for a project (loaded from GAP) + */ + stats, + isGapLoading: isLoading, + }; +} + diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx new file mode 100644 index 0000000000..d9a08260bf --- /dev/null +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -0,0 +1,65 @@ +import React from "react"; +//import { GrantItem } from "./GrantItem"; +import { IOSOGrant } from "../../api/oso"; +import { Flex, Link, Text } from "@chakra-ui/react"; +import { Stat } from "../ViewProjectDetails"; + +interface StatListProps { + stats: IOSOGrant; + } + +export const StatList: React.FC = ({ stats }) => { + return ( + stats.createdAtMs > 0 ? ( +
+ test +
+ ) : ( + + +
+ + Project age + +
+
+ + Total unique contributors +
+
+ + Velocity +
+
+ + Data provided by {" "} + + + opensource.observer + + + +
+ )); +}; diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index b24f2c404d..6624d4f4e2 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -34,6 +34,8 @@ import { useCartStorage } from "../../store"; import { Box, Skeleton, SkeletonText, Tab, Tabs } from "@chakra-ui/react"; import { GrantList } from "./KarmaGrant/GrantList"; import { useGap } from "../api/gap"; +import { StatList } from "./OSO/ImpactStats"; +import { useOSO } from "../api/oso"; import { ShoppingCartIcon } from "@heroicons/react/24/outline"; import { DataLayer, useDataLayer } from "data-layer"; import { DefaultLayout } from "../common/DefaultLayout"; @@ -122,6 +124,7 @@ export default function ViewProjectDetails() { round?.roundMetadata?.quadraticFundingConfig?.sybilDefense === true; const { grants } = useGap(projectToRender?.projectRegistryId as string); + const { stats } = useOSO(projectToRender?.projectRegistryId as string); const currentTime = new Date(); const isAfterRoundEndDate = @@ -202,11 +205,16 @@ export default function ViewProjectDetails() { ), }, { - name: "Milestone updates", - content: , + name: "Impact Measurement", + content: ( + + + + + ), }, ], - [grants, projectToRender, description] + [stats, grants, projectToRender, description] ); const handleTabChange = (tabIndex: number) => { @@ -589,7 +597,7 @@ export function ProjectStats() { ); } -function Stat({ +export function Stat({ value, children, isLoading, From e9674f5a484c9f8d0810dcd41ce3e9255864f7d1 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Wed, 24 Apr 2024 09:21:13 -0400 Subject: [PATCH 02/24] working minimal OSO stats --- package.json | 2 + .../grant-explorer/src/features/api/oso.ts | 84 ++++++++++++------- .../src/features/round/OSO/ImpactStats.tsx | 76 +++++++++-------- .../src/features/round/ViewProjectDetails.tsx | 2 +- pnpm-lock.yaml | 31 +++++++ 5 files changed, 127 insertions(+), 68 deletions(-) diff --git a/package.json b/package.json index 796c968903..cf356447ba 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,8 @@ }, "dependencies": { "concurrently": "^8.2.2", + "graphql": "^16.8.1", + "graphql-request": "^6.1.0", "prettier": "^3.0.3" }, "pnpm": { diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index c664566903..4fb2cc92e3 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -1,64 +1,84 @@ import { useState } from "react"; import useSWR from "swr"; import { Hex } from "viem"; +import { gql, GraphQLClient } from "graphql-request"; +import internal from "stream"; +import { date } from "zod"; -const osoUrl = process.env.REACT_APP_OSO_URL; +const osoApiKey = process.env.REACT_APP_OSO_API_KEY; +const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; +const graphQLClient = new GraphQLClient(osoUrl, { + headers: { + authorization: `Bearer ${osoApiKey}`, + }, +}) -export interface IOSOGrant { - uid: Hex; - projectUID: Hex; - communityUID: Hex; - title: string; - description: string; - createdAtMs: number; +export interface IOSOStats { + code_metrics_by_project: { + contributors : number; + first_commit_date : number; + } } -export function useOSO(projectId?: string) { - const [stats, setStats] = useState([]); +export function useOSO(projectTitle?: string) { + const emptyReturn : IOSOStats = { + code_metrics_by_project: + { + contributors : 0, + first_commit_date : 0 + } + }; + const [stats, setStats] = useState(emptyReturn); - const getStatsFor = async (projectRegistryId: string) => { + const getStatsFor = async (projectRegistryTitle: string) => { if (!osoUrl) throw new Error("Open Source Observer url not set."); + const query = gql`{ + code_metrics_by_project(where: {project_slug: {_eq: "${projectRegistryTitle}"}}) { + contributors + first_commit_date + } + }` + try { - const items: IOSOGrant[] = await fetch( - `${osoUrl}/grants/external-id/${projectRegistryId}` - ).then((res) => res.json()); + const items: IOSOStats = await graphQLClient.request(query) + console.log(items); - if (!Array.isArray(items)) { - setStats([]); + if (!Array.isArray(items.code_metrics_by_project)) { + setStats(emptyReturn); return; } - const parsedItems = - items - .filter((grant) => grant.title) - .map((grant) => ({ - ...grant - })) - .sort((a, b) => b.createdAtMs - a.createdAtMs) || []; + console.log(items.code_metrics_by_project[0].contributors); + const parsedItems : IOSOStats = { + code_metrics_by_project: + { + contributors : items.code_metrics_by_project[0].contributors, + first_commit_date : items.code_metrics_by_project[0].first_commit_date + } + }; + setStats(parsedItems); } catch (e) { - console.error(`No grants found for project: ${projectRegistryId}`); + console.error(`No stats found for project: ${projectRegistryTitle}`); console.error(e); - setStats([]); + setStats(emptyReturn); } }; - const { isLoading } = useSWR( - `${osoUrl}/grants/external-id/${projectId}`, - { - fetcher: async () => projectId && getStatsFor(projectId), + const { isLoading } = useSWR(osoUrl, { + fetcher: async () => projectTitle && getStatsFor(projectTitle), } ); return { /** - * Fetch GAP Indexer for grants for a project - * @param projectRegistryId registryId + * Fetch OSO for stats on a project + * @param projectRegistryTitle projectTitle */ getStatsFor, /** - * Grants for a project (loaded from GAP) + * Stats for a project (loaded from OSO) */ stats, isGapLoading: isLoading, diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index d9a08260bf..7fc8c070fe 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -1,65 +1,71 @@ import React from "react"; //import { GrantItem } from "./GrantItem"; -import { IOSOGrant } from "../../api/oso"; +import { IOSOStats } from "../../api/oso"; import { Flex, Link, Text } from "@chakra-ui/react"; import { Stat } from "../ViewProjectDetails"; -interface StatListProps { - stats: IOSOGrant; - } -export const StatList: React.FC = ({ stats }) => { +export const StatList = ({ stats }: { stats: IOSOStats }) => { return ( - stats.createdAtMs > 0 ? ( -
- test -
- ) : ( - - -
+ stats.code_metrics_by_project.contributors > 0 ? ( + + +
Project age -
-
+
+ } > Total unique contributors
-
+ } > Velocity
- Data provided by {" "} - - - opensource.observer - - + Data provided by {" "} + + + opensource.observer + + + ) : ( +
+ test +
)); }; + +function formatTimeAgo(dateString : number) { + const date = new Date(dateString); + const now = new Date(); + const diffTime = Math.abs(now.getTime() - date.getTime()); // Difference in milliseconds + const diffMonths = Math.round(diffTime / (1000 * 60 * 60 * 24 * 30)); // Convert to months + + if (diffMonths === 0) { + return 'This month'; + } else if (diffMonths === 1) { + return 'Last month'; + } else { + return `${diffMonths} months ago`; + } +} \ No newline at end of file diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index 6624d4f4e2..c7d3bd2563 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -124,7 +124,7 @@ export default function ViewProjectDetails() { round?.roundMetadata?.quadraticFundingConfig?.sybilDefense === true; const { grants } = useGap(projectToRender?.projectRegistryId as string); - const { stats } = useOSO(projectToRender?.projectRegistryId as string); + const { stats } = useOSO(projectToRender?.projectMetadata.title.toLowerCase() as string); const currentTime = new Date(); const isAfterRoundEndDate = diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca4c422e72..b4416cc05a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,12 @@ importers: concurrently: specifier: ^8.2.2 version: 8.2.2 + graphql: + specifier: ^16.8.1 + version: 16.8.1 + graphql-request: + specifier: ^6.1.0 + version: 6.1.0(graphql@16.8.1) prettier: specifier: ^3.0.3 version: 3.0.3 @@ -5511,6 +5517,14 @@ packages: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dev: false + /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.8.1 + dev: false + /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -17674,11 +17688,28 @@ packages: - encoding dev: false + /graphql-request@6.1.0(graphql@16.8.1): + resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} + peerDependencies: + graphql: 14 - 16 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.1) + cross-fetch: 3.1.8 + graphql: 16.8.1 + transitivePeerDependencies: + - encoding + dev: false + /graphql@16.8.0: resolution: {integrity: sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} dev: true + /graphql@16.8.1: + resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + dev: false + /gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} engines: {node: '>=10'} From 512e881c62ed90ce9bfb71eacb93c0a21f74399c Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Wed, 24 Apr 2024 16:14:37 -0400 Subject: [PATCH 03/24] fully working stats display --- .../grant-explorer/src/features/api/oso.ts | 130 +++++++++++++++--- .../src/features/round/OSO/ImpactStats.tsx | 25 +++- .../src/features/round/ViewProjectDetails.tsx | 2 +- 3 files changed, 131 insertions(+), 26 deletions(-) diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index 4fb2cc92e3..d96281b837 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -13,61 +13,151 @@ const graphQLClient = new GraphQLClient(osoUrl, { }, }) +interface IOSOId { + artifacts_by_project: { + project_id : Hex; + } +} + export interface IOSOStats { code_metrics_by_project: { contributors : number; first_commit_date : number; } + events_monthly_to_project: [ + { + bucket_month: number; + amount: number; + }, + { + bucket_month: number; + amount: number; + }, + { + bucket_month: number; + amount: number; + }, + { + bucket_month: number; + amount: number; + }, + { + bucket_month: number; + amount: number; + }, + { + bucket_month: number; + amount: number; + } + ] } -export function useOSO(projectTitle?: string) { +export function useOSO(projectGithub?: string) { const emptyReturn : IOSOStats = { code_metrics_by_project: { contributors : 0, first_commit_date : 0 - } + }, + events_monthly_to_project: [ + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + } + ] }; const [stats, setStats] = useState(emptyReturn); - const getStatsFor = async (projectRegistryTitle: string) => { + const getStatsFor = async (projectRegistryGithub: string) => { if (!osoUrl) throw new Error("Open Source Observer url not set."); - const query = gql`{ - code_metrics_by_project(where: {project_slug: {_eq: "${projectRegistryTitle}"}}) { - contributors - first_commit_date + + const queryId = gql`{ + artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} + distinct_on: project_id + ) { + project_id } }` try { - const items: IOSOStats = await graphQLClient.request(query) - console.log(items); + const idData: IOSOId = await graphQLClient.request(queryId) - if (!Array.isArray(items.code_metrics_by_project)) { + if (!Array.isArray(idData.artifacts_by_project)) { setStats(emptyReturn); return; } - console.log(items.code_metrics_by_project[0].contributors); - const parsedItems : IOSOStats = { - code_metrics_by_project: - { - contributors : items.code_metrics_by_project[0].contributors, - first_commit_date : items.code_metrics_by_project[0].first_commit_date - } + const parsedId : IOSOId = { + artifacts_by_project: idData.artifacts_by_project[0] }; + const queryStats = gql`{ + code_metrics_by_project(where: {project_id: {_eq: "${parsedId.artifacts_by_project.project_id}"}}) { + contributors + first_commit_date + } + events_monthly_to_project( + where: {project_id: {_eq: "${parsedId.artifacts_by_project.project_id}"}, event_type: {_eq: "COMMIT_CODE"}} + limit: 6 + order_by: {bucket_month: desc} + ) { + bucket_month + amount + } + }` + + const items: IOSOStats = await graphQLClient.request(queryStats) + console.log(items); + if (!Array.isArray(items.code_metrics_by_project)) { + setStats(emptyReturn); + return; + } + + console.log(items.events_monthly_to_project); + + if (items.events_monthly_to_project.length == 6) { + const parsedItems : IOSOStats = { + code_metrics_by_project: items.code_metrics_by_project[0], + events_monthly_to_project: items.events_monthly_to_project + } + setStats(parsedItems); + } else { + const parsedItems : IOSOStats = { + code_metrics_by_project: items.code_metrics_by_project[0], + events_monthly_to_project: emptyReturn.events_monthly_to_project + } + setStats(parsedItems); + } - setStats(parsedItems); } catch (e) { - console.error(`No stats found for project: ${projectRegistryTitle}`); + console.error(`No stats found for project: ${projectGithub}`); console.error(e); setStats(emptyReturn); } }; const { isLoading } = useSWR(osoUrl, { - fetcher: async () => projectTitle && getStatsFor(projectTitle), + fetcher: async () => projectGithub && getStatsFor(projectGithub), } ); diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index 7fc8c070fe..8bd7d4d9d8 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -27,14 +27,14 @@ export const StatList = ({ stats }: { stats: IOSOStats }) => { isLoading={false} value={`${stats.code_metrics_by_project.contributors}`} > - Total unique contributors + Unique code contributors
Velocity
@@ -42,7 +42,7 @@ export const StatList = ({ stats }: { stats: IOSOStats }) => { Data provided by {" "} - + opensource.observer @@ -50,7 +50,7 @@ export const StatList = ({ stats }: { stats: IOSOStats }) => {
) : (
- test +
)); }; @@ -66,6 +66,21 @@ function formatTimeAgo(dateString : number) { } else if (diffMonths === 1) { return 'Last month'; } else { - return `${diffMonths} months ago`; + return `${diffMonths} months`; + } +} + +function projectVelocity(stats : IOSOStats){ + const recentCommits = stats.events_monthly_to_project[0].amount + stats.events_monthly_to_project[1].amount + stats.events_monthly_to_project[2].amount; + const olderCommits = stats.events_monthly_to_project[3].amount + stats.events_monthly_to_project[4].amount + stats.events_monthly_to_project[5].amount; + + if (recentCommits == 0 && olderCommits == 0) { + return 'Unknown'; + } else if (recentCommits >= (1.5 * olderCommits)){ + return 'Increasing'; + } else if (recentCommits <= 0.5 * olderCommits){ + return 'Decreasing'; + } else { + return 'Steady'; } } \ No newline at end of file diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index c7d3bd2563..617ac2f970 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -124,7 +124,7 @@ export default function ViewProjectDetails() { round?.roundMetadata?.quadraticFundingConfig?.sybilDefense === true; const { grants } = useGap(projectToRender?.projectRegistryId as string); - const { stats } = useOSO(projectToRender?.projectMetadata.title.toLowerCase() as string); + const { stats } = useOSO(projectToRender?.projectMetadata.projectGithub?.toString() as string); const currentTime = new Date(); const isAfterRoundEndDate = From 52b6615a75a7d9cb3df162820532684638dedd9b Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Wed, 24 Apr 2024 22:43:30 -0400 Subject: [PATCH 04/24] finished OSO stats display --- packages/grant-explorer/.env.example | 4 +- .../grant-explorer/src/features/api/oso.ts | 8 +- .../features/round/KarmaGrant/GrantList.tsx | 3 +- .../src/features/round/OSO/ImpactStats.tsx | 88 ++++++++++--------- .../src/features/round/ViewProjectDetails.tsx | 4 +- 5 files changed, 56 insertions(+), 51 deletions(-) diff --git a/packages/grant-explorer/.env.example b/packages/grant-explorer/.env.example index 7db5325869..5b566c9f63 100644 --- a/packages/grant-explorer/.env.example +++ b/packages/grant-explorer/.env.example @@ -66,4 +66,6 @@ REACT_APP_EXPLORER_DISABLE_MATCHING_ESTIMATES=false REACT_APP_PASSPORT_API_KEY="test-key" REACT_APP_PASSPORT_AVALANCHE_API_KEY="test-key" REACT_APP_PASSPORT_API_COMMUNITY_ID="0000" -REACT_APP_PASSPORT_API_COMMUNITY_ID_AVALANCHE="0000" \ No newline at end of file +REACT_APP_PASSPORT_API_COMMUNITY_ID_AVALANCHE="0000" + +REACT_APP_OSO_API_KEY= \ No newline at end of file diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index d96281b837..b6f5cfaded 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -2,8 +2,6 @@ import { useState } from "react"; import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; -import internal from "stream"; -import { date } from "zod"; const osoApiKey = process.env.REACT_APP_OSO_API_KEY; const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; @@ -89,8 +87,6 @@ export function useOSO(projectGithub?: string) { const [stats, setStats] = useState(emptyReturn); const getStatsFor = async (projectRegistryGithub: string) => { - if (!osoUrl) throw new Error("Open Source Observer url not set."); - const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id @@ -127,14 +123,12 @@ export function useOSO(projectGithub?: string) { }` const items: IOSOStats = await graphQLClient.request(queryStats) - console.log(items); + if (!Array.isArray(items.code_metrics_by_project)) { setStats(emptyReturn); return; } - console.log(items.events_monthly_to_project); - if (items.events_monthly_to_project.length == 6) { const parsedItems : IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], diff --git a/packages/grant-explorer/src/features/round/KarmaGrant/GrantList.tsx b/packages/grant-explorer/src/features/round/KarmaGrant/GrantList.tsx index 65e888a674..954c14d33c 100644 --- a/packages/grant-explorer/src/features/round/KarmaGrant/GrantList.tsx +++ b/packages/grant-explorer/src/features/round/KarmaGrant/GrantList.tsx @@ -10,6 +10,7 @@ interface GrantListProps { export const GrantList: React.FC = ({ grants }) => { return ( +

Project milestones

{grants.length > 0 ? ( <> Total grants ({grants.length}) @@ -20,7 +21,7 @@ export const GrantList: React.FC = ({ grants }) => { url={getGapProjectUrl(grant.projectUID, grant.uid)} /> ))} - + Data provided by Karma via{" "} diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index 8bd7d4d9d8..70ae168427 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -1,45 +1,53 @@ import React from "react"; -//import { GrantItem } from "./GrantItem"; import { IOSOStats } from "../../api/oso"; import { Flex, Link, Text } from "@chakra-ui/react"; import { Stat } from "../ViewProjectDetails"; - export const StatList = ({ stats }: { stats: IOSOStats }) => { return ( stats.code_metrics_by_project.contributors > 0 ? ( - -
- - Project age - -
-
- - Unique code contributors -
-
- - Velocity -
-
- +

Impact stats

+ +
+
+ Project age + +
+
+
+ + Unique code contributors + +
+
+ + Velocity + +
+
+ Data provided by {" "} @@ -47,12 +55,12 @@ export const StatList = ({ stats }: { stats: IOSOStats }) => { -
+ ) : (
-
- )); + ) + ); }; function formatTimeAgo(dateString : number) { @@ -75,12 +83,12 @@ function projectVelocity(stats : IOSOStats){ const olderCommits = stats.events_monthly_to_project[3].amount + stats.events_monthly_to_project[4].amount + stats.events_monthly_to_project[5].amount; if (recentCommits == 0 && olderCommits == 0) { - return 'Unknown'; + return 'unknown'; } else if (recentCommits >= (1.5 * olderCommits)){ - return 'Increasing'; + return 'increasing'; } else if (recentCommits <= 0.5 * olderCommits){ - return 'Decreasing'; + return 'decreasing'; } else { - return 'Steady'; + return 'steady'; } } \ No newline at end of file diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index 617ac2f970..36d3153eb3 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -208,8 +208,8 @@ export default function ViewProjectDetails() { name: "Impact Measurement", content: ( - - + + ), }, From 57b9ba4d43ebbdaccdb9542f149b54e3829d1d0b Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Wed, 24 Apr 2024 23:06:26 -0400 Subject: [PATCH 05/24] linter fixes --- packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index 70ae168427..756ca68420 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -82,7 +82,7 @@ function projectVelocity(stats : IOSOStats){ const recentCommits = stats.events_monthly_to_project[0].amount + stats.events_monthly_to_project[1].amount + stats.events_monthly_to_project[2].amount; const olderCommits = stats.events_monthly_to_project[3].amount + stats.events_monthly_to_project[4].amount + stats.events_monthly_to_project[5].amount; - if (recentCommits == 0 && olderCommits == 0) { + if (recentCommits === 0 && olderCommits === 0) { return 'unknown'; } else if (recentCommits >= (1.5 * olderCommits)){ return 'increasing'; From 915b5697612c909e39d89c1f27faf2d0d1d6c42c Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Wed, 24 Apr 2024 23:16:56 -0400 Subject: [PATCH 06/24] linter fix --- packages/grant-explorer/src/features/api/oso.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index b6f5cfaded..e63b51eb45 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -129,7 +129,7 @@ export function useOSO(projectGithub?: string) { return; } - if (items.events_monthly_to_project.length == 6) { + if (items.events_monthly_to_project.length === 6) { const parsedItems : IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], events_monthly_to_project: items.events_monthly_to_project From 5e4add537b02bf2426e3e11035ed2ea329bf7634 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Thu, 25 Apr 2024 11:45:18 -0400 Subject: [PATCH 07/24] code cleaning from pr feedback --- package.json | 2 - packages/grant-explorer/.env.example | 1 + packages/grant-explorer/package.json | 2 + .../src/features/common/utils/utils.ts | 15 ++++ .../src/features/round/OSO/ImpactStats.tsx | 26 ++----- pnpm-lock.yaml | 75 ++++++------------- 6 files changed, 44 insertions(+), 77 deletions(-) diff --git a/package.json b/package.json index cf356447ba..796c968903 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,6 @@ }, "dependencies": { "concurrently": "^8.2.2", - "graphql": "^16.8.1", - "graphql-request": "^6.1.0", "prettier": "^3.0.3" }, "pnpm": { diff --git a/packages/grant-explorer/.env.example b/packages/grant-explorer/.env.example index 5b566c9f63..2656058d7c 100644 --- a/packages/grant-explorer/.env.example +++ b/packages/grant-explorer/.env.example @@ -68,4 +68,5 @@ REACT_APP_PASSPORT_AVALANCHE_API_KEY="test-key" REACT_APP_PASSPORT_API_COMMUNITY_ID="0000" REACT_APP_PASSPORT_API_COMMUNITY_ID_AVALANCHE="0000" +# create key following https://www.opensource.observer/docs/get-started/ REACT_APP_OSO_API_KEY= \ No newline at end of file diff --git a/packages/grant-explorer/package.json b/packages/grant-explorer/package.json index 983d45619b..b8443f7cad 100644 --- a/packages/grant-explorer/package.json +++ b/packages/grant-explorer/package.json @@ -76,6 +76,8 @@ "ethereum-blockies": "^0.1.1", "ethers": "^5.7.2", "framer-motion": "^10.15.0", + "graphql": "^16.8.1", + "graphql-request": "^6.1.0", "history": "^5.3.0", "html-react-parser": "^3.0.7", "https-browserify": "^1.0.0", diff --git a/packages/grant-explorer/src/features/common/utils/utils.ts b/packages/grant-explorer/src/features/common/utils/utils.ts index fe83dda364..9b034853c9 100644 --- a/packages/grant-explorer/src/features/common/utils/utils.ts +++ b/packages/grant-explorer/src/features/common/utils/utils.ts @@ -13,3 +13,18 @@ export const getFormattedRoundId = (roundId?: string | number): string => { return roundId; } }; + +export function formatTimeAgo(dateString : number) { + const date = new Date(dateString); + const now = new Date(); + const diffTime = Math.abs(now.getTime() - date.getTime()); // Difference in milliseconds + const diffMonths = Math.round(diffTime / (1000 * 60 * 60 * 24 * 30)); // Convert to months + + if (diffMonths === 0) { + return 'This month'; + } else if (diffMonths === 1) { + return 'Last month'; + } else { + return `${diffMonths} months`; + } +} diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index 756ca68420..db3f41126a 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -2,6 +2,7 @@ import React from "react"; import { IOSOStats } from "../../api/oso"; import { Flex, Link, Text } from "@chakra-ui/react"; import { Stat } from "../ViewProjectDetails"; +import { formatTimeAgo } from "../../common/utils/utils"; export const StatList = ({ stats }: { stats: IOSOStats }) => { return ( @@ -63,30 +64,13 @@ export const StatList = ({ stats }: { stats: IOSOStats }) => { ); }; -function formatTimeAgo(dateString : number) { - const date = new Date(dateString); - const now = new Date(); - const diffTime = Math.abs(now.getTime() - date.getTime()); // Difference in milliseconds - const diffMonths = Math.round(diffTime / (1000 * 60 * 60 * 24 * 30)); // Convert to months - - if (diffMonths === 0) { - return 'This month'; - } else if (diffMonths === 1) { - return 'Last month'; - } else { - return `${diffMonths} months`; - } -} - -function projectVelocity(stats : IOSOStats){ +function projectVelocity(stats : IOSOStats) { const recentCommits = stats.events_monthly_to_project[0].amount + stats.events_monthly_to_project[1].amount + stats.events_monthly_to_project[2].amount; const olderCommits = stats.events_monthly_to_project[3].amount + stats.events_monthly_to_project[4].amount + stats.events_monthly_to_project[5].amount; - if (recentCommits === 0 && olderCommits === 0) { - return 'unknown'; - } else if (recentCommits >= (1.5 * olderCommits)){ - return 'increasing'; - } else if (recentCommits <= 0.5 * olderCommits){ + if (recentCommits === 0 && olderCommits === 0) return 'unknown'; + if (recentCommits >= (1.5 * olderCommits)) return 'increasing'; + if (recentCommits <= 0.5 * olderCommits){ return 'decreasing'; } else { return 'steady'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d9fc355d2a..ca7bdd3285 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,12 +14,6 @@ importers: concurrently: specifier: ^8.2.2 version: 8.2.2 - graphql: - specifier: ^16.8.1 - version: 16.8.1 - graphql-request: - specifier: ^6.1.0 - version: 6.1.0(graphql@16.8.1) prettier: specifier: ^3.0.3 version: 3.0.3 @@ -487,7 +481,7 @@ importers: version: 3.3.0 graphql-request: specifier: ^6.1.0 - version: 6.1.0(graphql@16.8.0) + version: 6.1.0(graphql@16.8.1) knuth-shuffle-seeded: specifier: ^1.0.6 version: 1.0.6 @@ -735,6 +729,12 @@ importers: framer-motion: specifier: ^10.15.0 version: 10.16.4(react-dom@18.2.0)(react@18.2.0) + graphql: + specifier: ^16.8.1 + version: 16.8.1 + graphql-request: + specifier: ^6.1.0 + version: 6.1.0(graphql@16.8.1) history: specifier: ^5.3.0 version: 5.3.0 @@ -4267,7 +4267,6 @@ packages: - '@types/node' - postcss - typescript - dev: false /@craco/craco@7.1.0(@types/node@17.0.45)(postcss@8.4.29)(react-scripts@5.0.1)(typescript@5.3.3): resolution: {integrity: sha512-oRAcPIKYrfPXp9rSzlsDNeOaVtDiKhoyqSXUoqiK24jCkHr4T8m/a2f74yXIzCbIheoUWDOIfWZyRgFgT+cpqA==} @@ -4313,6 +4312,7 @@ packages: - '@types/node' - postcss - typescript + dev: false /@cspotcode/source-map-support@0.8.1: resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} @@ -5442,14 +5442,6 @@ packages: /@gitcoinco/passport-sdk-types@0.2.0: resolution: {integrity: sha512-qS7P4atgeAEfI6VlGcoXr10E6SsKAlHiPNfSyr25HJpnNomi7J0Yy6krscUPiPsn1eCKOFQeC8uDqTdiXXMGLw==} - /@graphql-typed-document-node/core@3.2.0(graphql@16.8.0): - resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} - peerDependencies: - graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - dependencies: - graphql: 16.8.0 - dev: false - /@graphql-typed-document-node/core@3.2.0(graphql@16.8.1): resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} peerDependencies: @@ -8228,7 +8220,6 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: false /@svgr/core@8.1.0(typescript@5.3.3): resolution: {integrity: sha512-8QqtOQT5ACVlmsvKOJNEaWmRPmcojMOzCz4Hs2BGG/toAp/K38LcsMRyLp349glq5AzJbCEeimEoxaX6v/fLrA==} @@ -8275,7 +8266,7 @@ packages: dependencies: '@babel/core': 7.22.15 '@svgr/babel-preset': 8.1.0(@babel/core@7.22.15) - '@svgr/core': 8.1.0(typescript@5.3.3) + '@svgr/core': 8.1.0(typescript@5.2.2) '@svgr/hast-util-to-babel-ast': 8.0.0 svg-parser: 2.0.4 transitivePeerDependencies: @@ -9261,7 +9252,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0)(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} @@ -9387,7 +9377,6 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: false /@typescript-eslint/experimental-utils@5.62.0(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} @@ -9400,6 +9389,7 @@ packages: transitivePeerDependencies: - supports-color - typescript + dev: false /@typescript-eslint/experimental-utils@5.62.0(eslint@8.50.0)(typescript@5.3.3): resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} @@ -9432,7 +9422,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/parser@5.62.0(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} @@ -9555,7 +9544,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/type-utils@5.62.0(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} @@ -9668,7 +9656,6 @@ packages: typescript: 5.2.2 transitivePeerDependencies: - supports-color - dev: false /@typescript-eslint/typescript-estree@5.62.0(typescript@5.3.3): resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} @@ -9772,7 +9759,6 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: false /@typescript-eslint/utils@5.62.0(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} @@ -13405,7 +13391,6 @@ packages: transitivePeerDependencies: - '@swc/core' - '@swc/wasm' - dev: false /cosmiconfig-typescript-loader@1.0.9(@types/node@17.0.45)(cosmiconfig@7.1.0)(typescript@5.3.3): resolution: {integrity: sha512-tRuMRhxN4m1Y8hP9SNYfz7jRwt8lZdWxdjg/ohg5esKmsndJIn4yT96oJVcf5x0eA11taXl+sIp+ielu529k6g==} @@ -13439,6 +13424,7 @@ packages: transitivePeerDependencies: - '@swc/core' - '@swc/wasm' + dev: false /cosmiconfig-typescript-loader@4.4.0(@types/node@20.4.7)(cosmiconfig@8.3.4)(ts-node@10.9.1)(typescript@5.4.5): resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} @@ -13489,7 +13475,6 @@ packages: parse-json: 5.2.0 path-type: 4.0.0 typescript: 5.2.2 - dev: false /cosmiconfig@8.3.4(typescript@5.3.3): resolution: {integrity: sha512-SF+2P8+o/PTV05rgsAjDzL4OFdVXAulSfC/L19VaeVT7+tpOOSscCt2QLxDZ+CLxF2WOiq6y1K5asvs8qUJT/Q==} @@ -13528,10 +13513,10 @@ packages: '@craco/craco': ^6.0.0 || ^7.0.0 || ^7.0.0-alpha react-scripts: ^5.0.0 dependencies: - '@craco/craco': 7.1.0(@types/node@18.17.14)(postcss@8.4.29)(react-scripts@5.0.1)(typescript@5.3.3) + '@craco/craco': 7.1.0(@types/node@17.0.45)(postcss@8.4.29)(react-scripts@5.0.1)(typescript@5.2.2) esbuild-jest: 0.5.0(esbuild@0.18.20) esbuild-loader: 2.21.0(webpack@5.88.2) - react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(esbuild@0.18.20)(eslint@8.48.0)(react@18.2.0)(ts-node@10.9.1)(typescript@5.3.3) + react-scripts: 5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(esbuild@0.18.20)(eslint@8.48.0)(react@18.2.0)(ts-node@10.9.1)(typescript@5.2.2) transitivePeerDependencies: - esbuild - supports-color @@ -15163,7 +15148,6 @@ packages: - eslint-import-resolver-webpack - jest - supports-color - dev: false /eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(eslint@8.48.0)(jest@27.5.1)(typescript@5.3.3): resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} @@ -15198,6 +15182,7 @@ packages: - eslint-import-resolver-webpack - jest - supports-color + dev: false /eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(eslint@8.50.0)(jest@27.5.1)(typescript@5.3.3): resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} @@ -15491,7 +15476,6 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: false /eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.48.0)(jest@27.5.1)(typescript@5.3.3): resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} @@ -15513,6 +15497,7 @@ packages: transitivePeerDependencies: - supports-color - typescript + dev: false /eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0)(eslint@8.50.0)(jest@27.5.1)(typescript@5.3.3): resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} @@ -15700,7 +15685,6 @@ packages: transitivePeerDependencies: - supports-color - typescript - dev: false /eslint-plugin-testing-library@5.11.1(eslint@8.48.0)(typescript@5.3.3): resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} @@ -15713,6 +15697,7 @@ packages: transitivePeerDependencies: - supports-color - typescript + dev: false /eslint-plugin-testing-library@5.11.1(eslint@8.50.0)(typescript@5.3.3): resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} @@ -16711,7 +16696,6 @@ packages: tapable: 1.1.3 typescript: 5.2.2 webpack: 5.88.2(esbuild@0.18.20) - dev: false /fork-ts-checker-webpack-plugin@6.5.3(eslint@8.48.0)(typescript@5.3.3)(webpack@5.88.2): resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} @@ -16743,6 +16727,7 @@ packages: tapable: 1.1.3 typescript: 5.3.3 webpack: 5.88.2(esbuild@0.18.20) + dev: false /fork-ts-checker-webpack-plugin@6.5.3(eslint@8.50.0)(typescript@5.3.3)(webpack@5.88.2): resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} @@ -17347,18 +17332,6 @@ packages: /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - /graphql-request@6.1.0(graphql@16.8.0): - resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} - peerDependencies: - graphql: 14 - 16 - dependencies: - '@graphql-typed-document-node/core': 3.2.0(graphql@16.8.0) - cross-fetch: 3.1.8 - graphql: 16.8.0 - transitivePeerDependencies: - - encoding - dev: false - /graphql-request@6.1.0(graphql@16.8.1): resolution: {integrity: sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==} peerDependencies: @@ -17371,14 +17344,9 @@ packages: - encoding dev: false - /graphql@16.8.0: - resolution: {integrity: sha512-0oKGaR+y3qcS5mCu1vb7KG+a89vjn06C7Ihq/dDl3jA+A8B3TKomvi3CiEcVLJQGalbu8F52LxkOym7U5sSfbg==} - engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - /graphql@16.8.1: resolution: {integrity: sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - dev: false /gzip-size@6.0.0: resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} @@ -21547,7 +21515,7 @@ packages: chalk: 4.1.1 chokidar: 3.5.3 cookie: 0.4.2 - graphql: 16.8.0 + graphql: 16.8.1 headers-polyfill: 3.2.3 inquirer: 8.2.6 is-node-process: 1.2.0 @@ -23942,7 +23910,6 @@ packages: - eslint - supports-color - vue-template-compiler - dev: false /react-dev-utils@12.0.1(eslint@8.48.0)(typescript@5.3.3)(webpack@5.88.2): resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} @@ -23984,6 +23951,7 @@ packages: - eslint - supports-color - vue-template-compiler + dev: false /react-dev-utils@12.0.1(eslint@8.50.0)(typescript@5.3.3)(webpack@5.88.2): resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} @@ -24358,7 +24326,6 @@ packages: - webpack-cli - webpack-hot-middleware - webpack-plugin-serve - dev: false /react-scripts@5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(esbuild@0.18.20)(eslint@8.48.0)(react@18.2.0)(ts-node@10.9.1)(typescript@5.3.3): resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} @@ -24455,6 +24422,7 @@ packages: - webpack-cli - webpack-hot-middleware - webpack-plugin-serve + dev: false /react-scripts@5.0.1(@babel/plugin-syntax-flow@7.22.5)(@babel/plugin-transform-react-jsx@7.22.15)(esbuild@0.18.20)(eslint@8.50.0)(react@18.2.0)(ts-node@10.9.1)(typescript@5.3.3): resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} @@ -26731,7 +26699,6 @@ packages: typescript: 5.2.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - dev: false /ts-node@10.9.1(@types/node@17.0.45)(typescript@5.3.3): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} @@ -26793,6 +26760,7 @@ packages: typescript: 5.3.3 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 + dev: false /ts-node@10.9.1(@types/node@20.4.7)(typescript@5.4.5): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} @@ -26883,7 +26851,6 @@ packages: dependencies: tslib: 1.14.1 typescript: 5.2.2 - dev: false /tsutils@3.21.0(typescript@5.3.3): resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} From 241e16afffac56579d6ecd0ed8c4c531e2fef667 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Fri, 26 Apr 2024 11:01:17 -0400 Subject: [PATCH 08/24] tweaked if styling --- .../grant-explorer/src/features/round/OSO/ImpactStats.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index db3f41126a..dc11a6be73 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -70,9 +70,6 @@ function projectVelocity(stats : IOSOStats) { if (recentCommits === 0 && olderCommits === 0) return 'unknown'; if (recentCommits >= (1.5 * olderCommits)) return 'increasing'; - if (recentCommits <= 0.5 * olderCommits){ - return 'decreasing'; - } else { - return 'steady'; - } + if (recentCommits <= 0.5 * olderCommits) return 'decreasing'; + return 'steady'; } \ No newline at end of file From 37f2d2a0080161e72168151a71c57f67b2ca99aa Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Sat, 27 Apr 2024 09:29:56 +0800 Subject: [PATCH 09/24] hotfix: normalize depth for sentry --- packages/grant-explorer/src/sentry.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/grant-explorer/src/sentry.ts b/packages/grant-explorer/src/sentry.ts index 6926c70f60..b30caf2caf 100644 --- a/packages/grant-explorer/src/sentry.ts +++ b/packages/grant-explorer/src/sentry.ts @@ -18,6 +18,7 @@ export const initSentry = () => { new Sentry.Replay(), new ExtraErrorData({ depth: 10 }), ], + normalizeDepth: 11, // This sets the sample rate to be 10%. You may want this to be 100% while // in development and sample at a lower rate in production replaysSessionSampleRate: 0.1, From 51b89fc7f69ed2772a6e18610f534be658167359 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Mon, 29 Apr 2024 07:06:46 +0200 Subject: [PATCH 10/24] add static ipfs collections (#3351) * add static ipfs collections * useMemo before condition * render collections only if !== undefined * adds more collections --------- Co-authored-by: Owocki Co-authored-by: Aditya Anand M C --- packages/common/src/icons/Discord.tsx | 2 +- packages/common/src/icons/Gitbook.tsx | 2 +- packages/common/src/icons/Github.tsx | 4 +- .../features/collections/CollectionCard.tsx | 17 +++--- .../features/collections/CollectionsGrid.tsx | 6 +- .../features/collections/community/index.ts | 60 +++++++++++++++++++ .../collections/hooks/useCollections.ts | 29 ++------- .../src/features/discovery/CardBanner.tsx | 48 ++++++++++----- .../src/features/discovery/LandingPage.tsx | 11 ++++ .../src/features/discovery/LandingTabs.tsx | 4 +- 10 files changed, 129 insertions(+), 54 deletions(-) create mode 100644 packages/grant-explorer/src/features/collections/community/index.ts diff --git a/packages/common/src/icons/Discord.tsx b/packages/common/src/icons/Discord.tsx index ac73e940e2..bfbc4d7e31 100644 --- a/packages/common/src/icons/Discord.tsx +++ b/packages/common/src/icons/Discord.tsx @@ -7,7 +7,7 @@ function Discord() { fill="none" xmlns="http://www.w3.org/2000/svg" > - + - + diff --git a/packages/grant-explorer/src/features/collections/CollectionCard.tsx b/packages/grant-explorer/src/features/collections/CollectionCard.tsx index 89addd5076..5d31887c9e 100644 --- a/packages/grant-explorer/src/features/collections/CollectionCard.tsx +++ b/packages/grant-explorer/src/features/collections/CollectionCard.tsx @@ -1,37 +1,38 @@ -import { Collection } from "data-layer"; +import { CommunityCollection } from "./community"; import { Link } from "react-router-dom"; import { Badge, BasicCard, CardHeader } from "../common/styles"; import { CollectionBanner } from "../discovery/CardBanner"; +import { collectionPath } from "common/src/routes/explorer"; export type CollectionCardProps = { - collection: Collection; + collection: CommunityCollection; size: "big" | "small"; }; const CollectionCard = ({ collection, size }: CollectionCardProps) => { - const { id, author, name, applicationRefs, images } = collection; + const { cid, author, name, numberOfProjects } = collection; return ( - - +
{name}
- {applicationRefs.length} projects + {numberOfProjects} projects
by {author}
- +
); }; diff --git a/packages/grant-explorer/src/features/collections/CollectionsGrid.tsx b/packages/grant-explorer/src/features/collections/CollectionsGrid.tsx index 69a332a7b7..bd19f6acbf 100644 --- a/packages/grant-explorer/src/features/collections/CollectionsGrid.tsx +++ b/packages/grant-explorer/src/features/collections/CollectionsGrid.tsx @@ -1,5 +1,5 @@ import { useMemo } from "react"; -import { Collection } from "data-layer"; +import { CommunityCollection } from "./community"; import CollectionCard from "./CollectionCard"; // Index position of the big cards @@ -7,7 +7,7 @@ const collectionGridLayout = [0, 5, 6, 11]; const DISPLAY_COUNT = 12; -export function CollectionsGrid({ data }: { data: Collection[] }) { +export function CollectionsGrid({ data }: { data: CommunityCollection[] }) { // Shuffle the collections const shuffled = useMemo(() => shuffle(data), [data]); @@ -17,7 +17,7 @@ export function CollectionsGrid({ data }: { data: Collection[] }) { const size = collectionGridLayout.includes(i) ? "big" : "small"; return (
diff --git a/packages/grant-explorer/src/features/collections/community/index.ts b/packages/grant-explorer/src/features/collections/community/index.ts new file mode 100644 index 0000000000..813e661ba8 --- /dev/null +++ b/packages/grant-explorer/src/features/collections/community/index.ts @@ -0,0 +1,60 @@ +export type CommunityCollection = { + cid: string; + author: string; + name: string; + numberOfProjects: number; + description: string; +}; + +const collections: CommunityCollection[] = [ + { + cid: "bafkreidobkgrbrw7mex556jnku4xlony6jvyhepc6yqpzzymasupnuvdi4", + author: "BitcoinLouie", + name: "Solo Staking", + numberOfProjects: 9, + description: + "This collection showcases BitcoinLouie's Solo Staking Collection", + }, + { + cid: "bafkreibp2yzwyj6m2fcgjqp7k6fikj3rr7ew3ceytrnr2zgi6dql2oiiry", + author: "Kevin Weaver", + name: "Regen Builders", + numberOfProjects: 20, + description: + "Kevin's bento assortment of public goods spanning apps, web3 infra, dev tools I use daily and climate initiatives that pair well.", + }, + { + cid: "bafkreifk3ejfp3j6eanuvvoqmp2bgyieuq67eh4kqpuxebegshaqaghu5e", + author: "ThankArb", + name: "Bring ARB Home ", + numberOfProjects: 22, + description: + "Think ARB is cool, but never felt like it would really work for you? Take a look at these rounds on Abriturum that you can use to impact your community close to home.", + }, + { + cid: "bafkreicneb6yinsk3zwcntohxklo3gcztosj5a2g72sr2dpqlawlcyvpli", + author: "buidlbox", + name: "buidl & shill sesh ", + numberOfProjects: 13, + description: + "We've rounded up all the projects from our recent buidl & shill spaces for #GG20 in a collection", + }, + { + cid: "bafkreihmuhsrdh62kjor5472dsgahhea3ltj33tffhr2cnc5bxae3qetou", + author: "Benjamin Life", + name: "Regen Civics", + numberOfProjects: 25, + description: + "Regen Civics is my curation of civic innovators in the @climate_program round on @gitcoin.", + }, + { + cid: "bafkreiffs6li5kwipwf6m4dgwbul3lf5mg766fujks72vm4crdebgybrme", + author: "Coleen Chase", + name: "Climate Projects Making Real-World Impact in Rural Africa", + numberOfProjects: 25, + description: + "Check out my collection of Climate Projects making real-world impact in rural Africa including 2 projects for dMRV.", + }, +]; + +export default collections; diff --git a/packages/grant-explorer/src/features/collections/hooks/useCollections.ts b/packages/grant-explorer/src/features/collections/hooks/useCollections.ts index 6ca8df6d66..33876949ab 100644 --- a/packages/grant-explorer/src/features/collections/hooks/useCollections.ts +++ b/packages/grant-explorer/src/features/collections/hooks/useCollections.ts @@ -1,33 +1,16 @@ import useSWR, { SWRResponse } from "swr"; -import { useDataLayer, Collection } from "data-layer"; +import { Collection } from "data-layer"; +import { useDataLayer } from "data-layer"; +import { CommunityCollection } from "../community"; import { CollectionV1, parseCollection } from "../collections"; import { getConfig } from "common/src/config"; +import communityCollections from "../community"; const config = getConfig(); -export const useCollections = (): SWRResponse => { - const dataLayer = useDataLayer(); - +export const useCollections = (): SWRResponse => { return useSWR(["collections"], async () => { - const collections = await dataLayer.getProjectCollections(); - return collections; - }); -}; - -export const useCollection = ( - id: string | null -): SWRResponse => { - const dataLayer = useDataLayer(); - return useSWR(id === null ? null : ["collections", id], async () => { - if (id === null) { - // The first argument to useSRW will ensure that this function never gets - // called if options is `null`. If it's still called, we fail early and - // clearly. - throw new Error("Bug"); - } - - const collection = await dataLayer.getProjectCollectionById(id); - return collection === null ? undefined : collection; + return communityCollections; }); }; diff --git a/packages/grant-explorer/src/features/discovery/CardBanner.tsx b/packages/grant-explorer/src/features/discovery/CardBanner.tsx index 4a40ed022b..348221710c 100644 --- a/packages/grant-explorer/src/features/discovery/CardBanner.tsx +++ b/packages/grant-explorer/src/features/discovery/CardBanner.tsx @@ -1,3 +1,4 @@ +import { useState } from "react"; import Stock1 from "../../assets/landing/stock1.jpg"; import Stock10 from "../../assets/landing/stock10.jpg"; import Stock11 from "../../assets/landing/stock11.jpg"; @@ -87,21 +88,40 @@ export function RoundBanner(props: { roundId: string }) { ); } -export function CollectionBanner({ images }: { images: string[] }) { +const gradients = [ + ["F68561", "FFD9CD"], + ["47A095", "ADEDE5"], + ["FFEFBE", "FBC624"], + ["D3EDFE", "15B8DC"], + ["FFD9CD", "5F94BC"], + ["FFD9CD", "ADEDE5"], + ["FFEFBE", "ADEDE5"], + ["DBF0DB", "5F94BC"], + ["FFE5F8", "FFEFBE"], + ["73E2E2", "FF9776"], + ["D9D6FF", "645AD8"], + ["B3DE9F", "DBF0DB"], + ["6935FF", "D3EDFE"], + ["FBC624", "FF7043"], + ["FF00B8", "FF9776"], + ["D3EDFE", "25BDCE"], + ["FF7043", "FFC2EE"], +]; + +function getRandomGradient() { + const r = Math.floor(Math.random() * gradients.length); + return gradients[r]; +} + +export function CollectionBanner() { + const [gradient] = useState(getRandomGradient()); return ( -
- {images.map((image, i) => { - return ( -
- ); - })} -
+
); } diff --git a/packages/grant-explorer/src/features/discovery/LandingPage.tsx b/packages/grant-explorer/src/features/discovery/LandingPage.tsx index 27fb89a041..6439f30411 100644 --- a/packages/grant-explorer/src/features/discovery/LandingPage.tsx +++ b/packages/grant-explorer/src/features/discovery/LandingPage.tsx @@ -15,6 +15,8 @@ import { RoundsGrid } from "./RoundsGrid"; import LandingHero from "./LandingHero"; import { LandingSection, ViewAllLink } from "./LandingSection"; import { toQueryString } from "./RoundsFilter"; +import { useCollections } from "../collections/hooks/useCollections"; +import { CollectionsGrid } from "../collections/CollectionsGrid"; const LandingPage = () => { const activeRounds = useFilterRounds( @@ -37,9 +39,18 @@ const LandingPage = () => { ); }, [roundsEndingSoon.data]); + const collections = useCollections(); + return ( + + + {collections.data !== undefined && ( + + )} + + - {tabs.map((tab) => { + {tabs.map((tab, i) => { const isActive = tab.activeRegExp.test(pathname); // Set the data-track-event attribute when the tab is active const tabProps = isActive ? { "data-track-event": tab.tabName } : {}; return ( Date: Mon, 29 Apr 2024 14:28:17 +0800 Subject: [PATCH 11/24] Ensure cart data is fresh (#3394) * ensure cart data is fresh * ensure we're not loading rejected applications * restore pnpm lock * update comment * fix linter * add comment * fix comment --- packages/data-layer/src/data-layer.ts | 21 +++++--- packages/data-layer/src/queries.ts | 12 ++++- packages/grant-explorer/src/checkoutStore.ts | 48 ++---------------- .../discovery/ExploreProjectsPage.tsx | 2 +- .../discovery/hooks/useApplications.ts | 7 +-- .../features/projects/hooks/useApplication.ts | 4 +- .../features/round/ViewCartPage/Summary.tsx | 1 - .../round/ViewCartPage/SummaryContainer.tsx | 7 ++- .../round/ViewCartPage/ViewCartPage.tsx | 49 ++++++++++++++++++- packages/grant-explorer/src/store.ts | 8 +++ 10 files changed, 92 insertions(+), 67 deletions(-) diff --git a/packages/data-layer/src/data-layer.ts b/packages/data-layer/src/data-layer.ts index 157ef8bb94..522b5259c3 100644 --- a/packages/data-layer/src/data-layer.ts +++ b/packages/data-layer/src/data-layer.ts @@ -32,7 +32,7 @@ import { SearchResult, } from "./openapi-search-client/index"; import { - getApplication, + getApprovedApplication, getApplicationsByProjectIds, getApplicationsByRoundIdAndProjectIds, getApplicationsForManager, @@ -347,7 +347,7 @@ export class DataLayer { * Returns a single application as identified by its id, round name and chain name * @param projectId */ - async getApplication({ + async getApprovedApplication({ roundId, chainId, applicationId, @@ -362,13 +362,17 @@ export class DataLayer { applicationId, }; - const response: { application: Application } = await request( + const response: { applications: Application[] } = await request( this.gsIndexerEndpoint, - getApplication, + getApprovedApplication, requestVariables, ); - return response.application ?? null; + if (response.applications.length === 0) { + return null; + } + + return response.applications[0]; } async getApplicationsForExplorer({ @@ -396,7 +400,7 @@ export class DataLayer { * Returns a list of applications identified by their chainId, roundId, and id. * @param expandedRefs */ - async getApplicationsByExpandedRefs( + async getApprovedApplicationsByExpandedRefs( expandedRefs: Array, ): Promise { if (expandedRefs.length === 0) { @@ -422,8 +426,9 @@ export class DataLayer { applications( first: 100 filter: { - or: [ - ${filters} + and: [ + { status: { equalTo: APPROVED } }, + { or: [ ${filters} ] } ] } ) { diff --git a/packages/data-layer/src/queries.ts b/packages/data-layer/src/queries.ts index a02f9a8b3b..14517ecb8f 100644 --- a/packages/data-layer/src/queries.ts +++ b/packages/data-layer/src/queries.ts @@ -246,13 +246,21 @@ export const getApplicationStatusByRoundIdAndCID = gql` } `; -export const getApplication = gql` +export const getApprovedApplication = gql` query Application( $chainId: Int! $applicationId: String! $roundId: String! ) { - application(chainId: $chainId, id: $applicationId, roundId: $roundId) { + applications( + first: 1 + condition: { + status: APPROVED + chainId: $chainId + id: $applicationId + roundId: $roundId + } + ) { id chainId roundId diff --git a/packages/grant-explorer/src/checkoutStore.ts b/packages/grant-explorer/src/checkoutStore.ts index 96e1b9a771..907e2680b8 100644 --- a/packages/grant-explorer/src/checkoutStore.ts +++ b/packages/grant-explorer/src/checkoutStore.ts @@ -101,8 +101,7 @@ export const useCheckoutStore = create()( checkout: async ( chainsToCheckout: { chainId: ChainId; permitDeadline: number }[], walletClient: WalletClient, - allo: Allo, - dataLayer: DataLayer + allo: Allo ) => { const chainIdsToCheckOut = chainsToCheckout.map((chain) => chain.chainId); get().setChainsToCheckout( @@ -238,50 +237,9 @@ export const useCheckoutStore = create()( const groupedEncodedVotes: Record = {}; for (const roundId in groupedDonations) { - const allProjectIds = groupedDonations[roundId].map( - (d) => d.projectRegistryId - ); - const response = - await dataLayer.getApplicationsByRoundIdAndProjectIds({ - chainId, - roundId, - projectIds: allProjectIds, - }); - - const roundDonations: { - roundId: string; - chainId: number; - amount: string; - recipient: string; - projectRegistryId: string; - applicationIndex: number; - anchorAddress: string; - }[] = []; - - groupedDonations[roundId].map((d) => { - const app = response.find( - (r) => r.projectId === d.projectRegistryId - ); - - if (!app) { - throw new Error( - `Application not found for projectRegistryId ${d.projectRegistryId} in round ${roundId} on chain ${chainId}` - ); - } - roundDonations.push({ - roundId: d.roundId, - chainId: d.chainId, - amount: d.amount, - recipient: d.recipient, - projectRegistryId: d.projectRegistryId, - applicationIndex: Number(app.id), - anchorAddress: app.anchorAddress, - }); - }); - groupedEncodedVotes[roundId] = isV2 - ? encodedQFAllocation(token, roundDonations) - : encodeQFVotes(token, roundDonations); + ? encodedQFAllocation(token, groupedDonations[roundId]) + : encodeQFVotes(token, groupedDonations[roundId]); } const groupedAmounts: Record = {}; diff --git a/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx b/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx index 9f7d5db191..5030e01d05 100644 --- a/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx +++ b/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx @@ -31,7 +31,7 @@ const FILTER_OPTIONS: FilterDropdownOption[] = [ }, ]; -function createCartProjectFromApplication( +export function createCartProjectFromApplication( application: ApplicationSummary ): CartProject { return { diff --git a/packages/grant-explorer/src/features/discovery/hooks/useApplications.ts b/packages/grant-explorer/src/features/discovery/hooks/useApplications.ts index a99cba2db8..c2083502b4 100644 --- a/packages/grant-explorer/src/features/discovery/hooks/useApplications.ts +++ b/packages/grant-explorer/src/features/discovery/hooks/useApplications.ts @@ -77,9 +77,10 @@ export function useApplications(options: ApplicationFetchOptions | null) { } case "applications-collection": { if (options.filter?.type === "expanded-refs") { - const applications = await dataLayer.getApplicationsByExpandedRefs( - options.filter?.refs ?? [] - ); + const applications = + await dataLayer.getApprovedApplicationsByExpandedRefs( + options.filter?.refs ?? [] + ); const v2Applications = applications.filter( (a) => a.tags?.includes("allo-v2") diff --git a/packages/grant-explorer/src/features/projects/hooks/useApplication.ts b/packages/grant-explorer/src/features/projects/hooks/useApplication.ts index aebb51b6b4..0c76a609b2 100644 --- a/packages/grant-explorer/src/features/projects/hooks/useApplication.ts +++ b/packages/grant-explorer/src/features/projects/hooks/useApplication.ts @@ -15,7 +15,9 @@ export function useApplication(params: Params, dataLayer: DataLayer) { applicationId: params.applicationId as string, roundId: params.roundId as string, }; - return (await dataLayer.getApplication(validatedParams)) ?? undefined; + return ( + (await dataLayer.getApprovedApplication(validatedParams)) ?? undefined + ); }); } diff --git a/packages/grant-explorer/src/features/round/ViewCartPage/Summary.tsx b/packages/grant-explorer/src/features/round/ViewCartPage/Summary.tsx index e7bff82e5e..dd3853f485 100644 --- a/packages/grant-explorer/src/features/round/ViewCartPage/Summary.tsx +++ b/packages/grant-explorer/src/features/round/ViewCartPage/Summary.tsx @@ -1,5 +1,4 @@ import { ChainId, useTokenPrice, VotingToken } from "common"; -import React from "react"; import { CHAINS } from "../../api/utils"; import { formatUnits, zeroAddress } from "viem"; import { useAccount, useBalance } from "wagmi"; diff --git a/packages/grant-explorer/src/features/round/ViewCartPage/SummaryContainer.tsx b/packages/grant-explorer/src/features/round/ViewCartPage/SummaryContainer.tsx index caadcd49a2..27d00633eb 100644 --- a/packages/grant-explorer/src/features/round/ViewCartPage/SummaryContainer.tsx +++ b/packages/grant-explorer/src/features/round/ViewCartPage/SummaryContainer.tsx @@ -1,3 +1,4 @@ +/* eslint-disable no-unexpected-multiline */ import { ChainId, getTokenPrice, NATIVE, submitPassportLite } from "common"; import { useCartStorage } from "../../../store"; import { useEffect, useMemo, useState } from "react"; @@ -183,10 +184,8 @@ export function SummaryContainer() { const currentPermitDeadline = rounds && rounds.length > 0 ? [...rounds] - .sort( - (a, b) => a.roundEndTime.getTime() - b.roundEndTime.getTime() - )[rounds.length - 1] - .roundEndTime.getTime() + .sort((a, b) => a.roundEndTime.getTime() - b.roundEndTime.getTime()) + [rounds.length - 1].roundEndTime.getTime() : 0; const [emptyInput, setEmptyInput] = useState(false); diff --git a/packages/grant-explorer/src/features/round/ViewCartPage/ViewCartPage.tsx b/packages/grant-explorer/src/features/round/ViewCartPage/ViewCartPage.tsx index 594a69e908..03ad550998 100644 --- a/packages/grant-explorer/src/features/round/ViewCartPage/ViewCartPage.tsx +++ b/packages/grant-explorer/src/features/round/ViewCartPage/ViewCartPage.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useEffect } from "react"; import { ChainId } from "common"; import { groupProjectsInCart } from "../../api/utils"; import Footer from "common/src/components/Footer"; @@ -9,11 +9,56 @@ import { Header } from "./Header"; import { useCartStorage } from "../../../store"; import { CartWithProjects } from "./CartWithProjects"; import { SummaryContainer } from "./SummaryContainer"; +import { useDataLayer } from "data-layer"; +import { createCartProjectFromApplication } from "../../discovery/ExploreProjectsPage"; export default function ViewCart() { - const { projects } = useCartStorage(); + const { projects, setCart } = useCartStorage(); + const dataLayer = useDataLayer(); const groupedCartProjects = groupProjectsInCart(projects); + // ensure cart data is up to date on mount + useEffect(() => { + const applicationRefs = projects.map((project) => { + return { + chainId: project.chainId, + roundId: project.roundId, + id: project.applicationIndex.toString(), + }; + }); + + // only update cart if fetching applications is successful + dataLayer + .getApprovedApplicationsByExpandedRefs(applicationRefs) + .then((applications) => { + const updatedProjects = applications.flatMap((application) => { + const existingProject = projects.find((project) => { + return applications.some( + (application) => + application.chainId === project.chainId && + application.roundId === project.roundId && + application.roundApplicationId === + project.applicationIndex.toString() + ); + }); + + const newProject = createCartProjectFromApplication(application); + + // update all application data, but preserve the selected amount + return { ...newProject, amount: existingProject?.amount ?? "" }; + }); + + // replace whole cart + setCart(updatedProjects); + }) + .catch((error) => { + console.error("error fetching applications in cart", error); + }); + + // we only want to run this once on mount + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + const breadCrumbs: BreadcrumbItem[] = [ { name: "Explorer Home", diff --git a/packages/grant-explorer/src/store.ts b/packages/grant-explorer/src/store.ts index bae0ae7c9d..f2d702e027 100644 --- a/packages/grant-explorer/src/store.ts +++ b/packages/grant-explorer/src/store.ts @@ -17,6 +17,7 @@ interface CartState { grantApplicationId: string, amount: string ) => void; + setCart: (projects: CartProject[]) => void; chainToVotingToken: Record; getVotingTokenForChain: (chainId: ChainId) => VotingToken; setVotingTokenForChain: (chainId: ChainId, votingToken: VotingToken) => void; @@ -91,6 +92,13 @@ export const useCartStorage = create()( persist( (set, get) => ({ projects: [], + + setCart: (projects: CartProject[]) => { + set({ + projects, + }); + }, + add: (newProject: CartProject) => { const currentProjects = get().projects; From 288e3b97a2a64ed0d84d9de086ac1715de7f00a6 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 30 Apr 2024 00:37:23 +0800 Subject: [PATCH 12/24] disable community colections on v (#3398) --- .../src/features/discovery/LandingPage.tsx | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/packages/grant-explorer/src/features/discovery/LandingPage.tsx b/packages/grant-explorer/src/features/discovery/LandingPage.tsx index 6439f30411..396c658ead 100644 --- a/packages/grant-explorer/src/features/discovery/LandingPage.tsx +++ b/packages/grant-explorer/src/features/discovery/LandingPage.tsx @@ -17,6 +17,7 @@ import { LandingSection, ViewAllLink } from "./LandingSection"; import { toQueryString } from "./RoundsFilter"; import { useCollections } from "../collections/hooks/useCollections"; import { CollectionsGrid } from "../collections/CollectionsGrid"; +import { getAlloVersion } from "common/src/config"; const LandingPage = () => { const activeRounds = useFilterRounds( @@ -45,11 +46,13 @@ const LandingPage = () => { - - {collections.data !== undefined && ( - - )} - + {getAlloVersion() === "allo-v2" && ( + + {collections.data !== undefined && ( + + )} + + )} Date: Tue, 30 Apr 2024 09:55:42 -0400 Subject: [PATCH 13/24] fetch OSO stats on pageload --- .../grant-explorer/src/features/api/oso.ts | 29 ++++++++++++------- .../src/features/round/OSO/ImpactStats.tsx | 4 ++- .../src/features/round/ViewProjectDetails.tsx | 3 +- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index e63b51eb45..043e77cca6 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,13 +3,15 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; + const osoApiKey = process.env.REACT_APP_OSO_API_KEY; const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; const graphQLClient = new GraphQLClient(osoUrl, { headers: { authorization: `Bearer ${osoApiKey}`, }, -}) +}); +let hasFetched = false; interface IOSOId { artifacts_by_project: { @@ -84,19 +86,21 @@ export function useOSO(projectGithub?: string) { } ] }; - const [stats, setStats] = useState(emptyReturn); + const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { + if (!osoApiKey) throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id ) { project_id } - }` + }`; try { - const idData: IOSOId = await graphQLClient.request(queryId) + hasFetched = true; + const idData: IOSOId = await graphQLClient.request(queryId); if (!Array.isArray(idData.artifacts_by_project)) { setStats(emptyReturn); @@ -120,9 +124,9 @@ export function useOSO(projectGithub?: string) { bucket_month amount } - }` + }`; - const items: IOSOStats = await graphQLClient.request(queryStats) + const items: IOSOStats = await graphQLClient.request(queryStats); if (!Array.isArray(items.code_metrics_by_project)) { setStats(emptyReturn); @@ -133,13 +137,13 @@ export function useOSO(projectGithub?: string) { const parsedItems : IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], events_monthly_to_project: items.events_monthly_to_project - } + }; setStats(parsedItems); } else { const parsedItems : IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], events_monthly_to_project: emptyReturn.events_monthly_to_project - } + }; setStats(parsedItems); } @@ -150,22 +154,25 @@ export function useOSO(projectGithub?: string) { } }; - const { isLoading } = useSWR(osoUrl, { + const { isLoading } = useSWR(osoUrl, + { fetcher: async () => projectGithub && getStatsFor(projectGithub), + revalidateOnMount: true, } ); + if ( stats === null && !hasFetched) projectGithub && getStatsFor(projectGithub); return { /** * Fetch OSO for stats on a project - * @param projectRegistryTitle projectTitle + * @param projectRegistryGithub projectGithub */ getStatsFor, /** * Stats for a project (loaded from OSO) */ stats, - isGapLoading: isLoading, + isStatsLoading: isLoading, }; } diff --git a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx index dc11a6be73..ace1300fd8 100644 --- a/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx +++ b/packages/grant-explorer/src/features/round/OSO/ImpactStats.tsx @@ -4,7 +4,9 @@ import { Flex, Link, Text } from "@chakra-ui/react"; import { Stat } from "../ViewProjectDetails"; import { formatTimeAgo } from "../../common/utils/utils"; -export const StatList = ({ stats }: { stats: IOSOStats }) => { + +export const StatList = ({ stats }: { stats: IOSOStats | null }) => { + if (stats === null) return; return ( stats.code_metrics_by_project.contributors > 0 ? ( diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index 882c4edd9f..acab5b3610 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -122,7 +122,7 @@ export default function ViewProjectDetails() { round?.roundMetadata?.quadraticFundingConfig?.sybilDefense === true; const { grants } = useGap(projectToRender?.projectRegistryId as string); - const { stats } = useOSO(projectToRender?.projectMetadata.projectGithub?.toString() as string); + const { stats } = useOSO(projectToRender?.projectMetadata.projectGithub as string); const currentTime = new Date(); const isAfterRoundEndDate = @@ -181,7 +181,6 @@ export default function ViewProjectDetails() { const { projectMetadata: { title, description = "", bannerImg }, } = projectToRender ?? { projectMetadata: {} }; - const projectDetailsTabs = useMemo( () => [ { From f24404a6ae813bb13509c41ce92e0eabc37c67e3 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Tue, 30 Apr 2024 16:22:53 -0400 Subject: [PATCH 14/24] checking env vars safer --- packages/grant-explorer/src/features/api/gap.ts | 4 ++-- packages/grant-explorer/src/features/api/oso.ts | 13 ++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/grant-explorer/src/features/api/gap.ts b/packages/grant-explorer/src/features/api/gap.ts index 8b505ad84d..b5ca3260c0 100644 --- a/packages/grant-explorer/src/features/api/gap.ts +++ b/packages/grant-explorer/src/features/api/gap.ts @@ -2,7 +2,7 @@ import { useState } from "react"; import useSWR from "swr"; import { Hex } from "viem"; -const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL; +const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL as string; export interface IGrantStatus { uid: Hex; @@ -33,7 +33,7 @@ export function useGap(projectId?: string) { const [grants, setGrants] = useState([]); const getGrantsFor = async (projectRegistryId: string) => { - if (!indexerUrl) throw new Error("GAP Indexer url not set."); + if (indexerUrl === "") throw new Error("GAP Indexer url not set."); try { const items: IGapGrant[] = await fetch( `${indexerUrl}/grants/external-id/${projectRegistryId}` diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index 043e77cca6..70ed2907d6 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,9 +3,8 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; - const osoApiKey = process.env.REACT_APP_OSO_API_KEY; -const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; +const osoUrl = "https://opensource-observer.hasura.app/v1/graphql" as string; const graphQLClient = new GraphQLClient(osoUrl, { headers: { authorization: `Bearer ${osoApiKey}`, @@ -16,14 +15,14 @@ let hasFetched = false; interface IOSOId { artifacts_by_project: { project_id : Hex; - } + }; } export interface IOSOStats { code_metrics_by_project: { contributors : number; first_commit_date : number; - } + }; events_monthly_to_project: [ { bucket_month: number; @@ -48,8 +47,8 @@ export interface IOSOStats { { bucket_month: number; amount: number; - } - ] + }, + ]; } export function useOSO(projectGithub?: string) { @@ -89,7 +88,7 @@ export function useOSO(projectGithub?: string) { const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { - if (!osoApiKey) throw new Error("OpenSourceObserver API key not set."); + if (osoApiKey === "") throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id From c354e053ee64724eb1a55c72a0992dbf578124ef Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Tue, 30 Apr 2024 16:45:48 -0400 Subject: [PATCH 15/24] further env var safe checks --- packages/grant-explorer/src/features/api/gap.ts | 2 +- packages/grant-explorer/src/features/api/oso.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/grant-explorer/src/features/api/gap.ts b/packages/grant-explorer/src/features/api/gap.ts index b5ca3260c0..672526fdb5 100644 --- a/packages/grant-explorer/src/features/api/gap.ts +++ b/packages/grant-explorer/src/features/api/gap.ts @@ -33,7 +33,7 @@ export function useGap(projectId?: string) { const [grants, setGrants] = useState([]); const getGrantsFor = async (projectRegistryId: string) => { - if (indexerUrl === "") throw new Error("GAP Indexer url not set."); + if (indexerUrl === undefined) throw new Error("GAP Indexer url not set."); try { const items: IGapGrant[] = await fetch( `${indexerUrl}/grants/external-id/${projectRegistryId}` diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index 70ed2907d6..22c009c6f0 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,8 +3,8 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; -const osoApiKey = process.env.REACT_APP_OSO_API_KEY; -const osoUrl = "https://opensource-observer.hasura.app/v1/graphql" as string; +const osoApiKey = process.env.REACT_APP_OSO_API_KEY as string; +const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; const graphQLClient = new GraphQLClient(osoUrl, { headers: { authorization: `Bearer ${osoApiKey}`, @@ -88,7 +88,7 @@ export function useOSO(projectGithub?: string) { const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { - if (osoApiKey === "") throw new Error("OpenSourceObserver API key not set."); + if (osoApiKey === undefined) throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id From 0c5b06586831ca2bfd8f604dcf93ac87c0465da0 Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Tue, 30 Apr 2024 17:03:53 -0400 Subject: [PATCH 16/24] further env var tweaks --- packages/grant-explorer/src/features/api/gap.ts | 4 ++-- packages/grant-explorer/src/features/api/oso.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/grant-explorer/src/features/api/gap.ts b/packages/grant-explorer/src/features/api/gap.ts index 672526fdb5..fbabac3026 100644 --- a/packages/grant-explorer/src/features/api/gap.ts +++ b/packages/grant-explorer/src/features/api/gap.ts @@ -2,7 +2,7 @@ import { useState } from "react"; import useSWR from "swr"; import { Hex } from "viem"; -const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL as string; +const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL as string || ""; export interface IGrantStatus { uid: Hex; @@ -33,7 +33,7 @@ export function useGap(projectId?: string) { const [grants, setGrants] = useState([]); const getGrantsFor = async (projectRegistryId: string) => { - if (indexerUrl === undefined) throw new Error("GAP Indexer url not set."); + if (indexerUrl === "") throw new Error("GAP Indexer url not set."); try { const items: IGapGrant[] = await fetch( `${indexerUrl}/grants/external-id/${projectRegistryId}` diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index 22c009c6f0..5e4fc6962d 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,7 +3,7 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; -const osoApiKey = process.env.REACT_APP_OSO_API_KEY as string; +const osoApiKey = process.env.REACT_APP_OSO_API_KEY as string || ""; const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; const graphQLClient = new GraphQLClient(osoUrl, { headers: { @@ -88,7 +88,7 @@ export function useOSO(projectGithub?: string) { const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { - if (osoApiKey === undefined) throw new Error("OpenSourceObserver API key not set."); + if (osoApiKey === "") throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id From 683836751acf53247afad2a45ab7ccfa66b81d6b Mon Sep 17 00:00:00 2001 From: Henry Wilson Date: Tue, 30 Apr 2024 17:21:13 -0400 Subject: [PATCH 17/24] return to previous env check --- packages/grant-explorer/src/features/api/gap.ts | 4 ++-- packages/grant-explorer/src/features/api/oso.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/grant-explorer/src/features/api/gap.ts b/packages/grant-explorer/src/features/api/gap.ts index fbabac3026..8b505ad84d 100644 --- a/packages/grant-explorer/src/features/api/gap.ts +++ b/packages/grant-explorer/src/features/api/gap.ts @@ -2,7 +2,7 @@ import { useState } from "react"; import useSWR from "swr"; import { Hex } from "viem"; -const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL as string || ""; +const indexerUrl = process.env.REACT_APP_KARMA_GAP_INDEXER_URL; export interface IGrantStatus { uid: Hex; @@ -33,7 +33,7 @@ export function useGap(projectId?: string) { const [grants, setGrants] = useState([]); const getGrantsFor = async (projectRegistryId: string) => { - if (indexerUrl === "") throw new Error("GAP Indexer url not set."); + if (!indexerUrl) throw new Error("GAP Indexer url not set."); try { const items: IGapGrant[] = await fetch( `${indexerUrl}/grants/external-id/${projectRegistryId}` diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index 5e4fc6962d..c80393bfc2 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,7 +3,7 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; -const osoApiKey = process.env.REACT_APP_OSO_API_KEY as string || ""; +const osoApiKey = process.env.REACT_APP_OSO_API_KEY; const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; const graphQLClient = new GraphQLClient(osoUrl, { headers: { @@ -88,7 +88,7 @@ export function useOSO(projectGithub?: string) { const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { - if (osoApiKey === "") throw new Error("OpenSourceObserver API key not set."); + if (!osoApiKey) throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id From b60de9ac39fb8620aac2d9c93229126cfadc7d57 Mon Sep 17 00:00:00 2001 From: Jaxcoder Date: Tue, 30 Apr 2024 18:23:38 -0400 Subject: [PATCH 18/24] update type/check --- .../grant-explorer/src/features/api/oso.ts | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/packages/grant-explorer/src/features/api/oso.ts b/packages/grant-explorer/src/features/api/oso.ts index c80393bfc2..48e405abd2 100644 --- a/packages/grant-explorer/src/features/api/oso.ts +++ b/packages/grant-explorer/src/features/api/oso.ts @@ -3,7 +3,7 @@ import useSWR from "swr"; import { Hex } from "viem"; import { gql, GraphQLClient } from "graphql-request"; -const osoApiKey = process.env.REACT_APP_OSO_API_KEY; +const osoApiKey = process.env.REACT_APP_OSO_API_KEY as string; const osoUrl = "https://opensource-observer.hasura.app/v1/graphql"; const graphQLClient = new GraphQLClient(osoUrl, { headers: { @@ -14,14 +14,14 @@ let hasFetched = false; interface IOSOId { artifacts_by_project: { - project_id : Hex; + project_id: Hex; }; } export interface IOSOStats { code_metrics_by_project: { - contributors : number; - first_commit_date : number; + contributors: number; + first_commit_date: number; }; events_monthly_to_project: [ { @@ -52,43 +52,43 @@ export interface IOSOStats { } export function useOSO(projectGithub?: string) { - const emptyReturn : IOSOStats = { - code_metrics_by_project: + const emptyReturn: IOSOStats = { + code_metrics_by_project: { + contributors: 0, + first_commit_date: 0, + }, + events_monthly_to_project: [ { - contributors : 0, - first_commit_date : 0 + bucket_month: 0, + amount: 0, }, - events_monthly_to_project: [ - { - bucket_month: 0, - amount: 0, - }, - { - bucket_month: 0, - amount: 0, - }, - { - bucket_month: 0, - amount: 0, - }, - { - bucket_month: 0, - amount: 0, - }, - { - bucket_month: 0, - amount: 0, - }, - { - bucket_month: 0, - amount: 0, - } - ] + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + { + bucket_month: 0, + amount: 0, + }, + ], }; const [stats, setStats] = useState(null); const getStatsFor = async (projectRegistryGithub: string) => { - if (!osoApiKey) throw new Error("OpenSourceObserver API key not set."); + if (osoApiKey === "") + throw new Error("OpenSourceObserver API key not set."); const queryId = gql`{ artifacts_by_project(where: {artifact_name: {_ilike: "%${projectRegistryGithub}/%"}} distinct_on: project_id @@ -106,8 +106,8 @@ export function useOSO(projectGithub?: string) { return; } - const parsedId : IOSOId = { - artifacts_by_project: idData.artifacts_by_project[0] + const parsedId: IOSOId = { + artifacts_by_project: idData.artifacts_by_project[0], }; const queryStats = gql`{ @@ -125,7 +125,8 @@ export function useOSO(projectGithub?: string) { } }`; - const items: IOSOStats = await graphQLClient.request(queryStats); + const items: IOSOStats = + await graphQLClient.request(queryStats); if (!Array.isArray(items.code_metrics_by_project)) { setStats(emptyReturn); @@ -133,19 +134,18 @@ export function useOSO(projectGithub?: string) { } if (items.events_monthly_to_project.length === 6) { - const parsedItems : IOSOStats = { + const parsedItems: IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], - events_monthly_to_project: items.events_monthly_to_project + events_monthly_to_project: items.events_monthly_to_project, }; setStats(parsedItems); - } else { - const parsedItems : IOSOStats = { + } else { + const parsedItems: IOSOStats = { code_metrics_by_project: items.code_metrics_by_project[0], - events_monthly_to_project: emptyReturn.events_monthly_to_project + events_monthly_to_project: emptyReturn.events_monthly_to_project, }; setStats(parsedItems); } - } catch (e) { console.error(`No stats found for project: ${projectGithub}`); console.error(e); @@ -153,14 +153,13 @@ export function useOSO(projectGithub?: string) { } }; - const { isLoading } = useSWR(osoUrl, - { - fetcher: async () => projectGithub && getStatsFor(projectGithub), - revalidateOnMount: true, - } - ); + const { isLoading } = useSWR(osoUrl, { + fetcher: async () => projectGithub && getStatsFor(projectGithub), + revalidateOnMount: true, + }); - if ( stats === null && !hasFetched) projectGithub && getStatsFor(projectGithub); + if (stats === null && !hasFetched) + projectGithub && getStatsFor(projectGithub); return { /** * Fetch OSO for stats on a project @@ -174,4 +173,3 @@ export function useOSO(projectGithub?: string) { isStatsLoading: isLoading, }; } - From f9b50719515288615982485c60e728d175394e28 Mon Sep 17 00:00:00 2001 From: jaxcoder / Date: Wed, 1 May 2024 12:24:38 -0400 Subject: [PATCH 19/24] fix explorer navabar typo/lint (#3401) --- packages/common/src/index.ts | 2 +- .../grant-explorer/src/features/collections/CollectionCard.tsx | 1 - .../src/features/collections/hooks/useCollections.ts | 2 -- packages/grant-explorer/src/features/common/Navbar.tsx | 2 +- .../grant-explorer/src/features/round/ViewProjectDetails.tsx | 2 +- 5 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 01ef8a2d15..bf77f0860c 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -430,7 +430,7 @@ const passportLiteRounds = [ { roundId: "23", chainId: 42161 }, // Hackathon Alumni { roundId: "24", chainId: 42161 }, // ENS { roundId: "25", chainId: 42161 }, // dApps & Apps - { roundId: "26", chainId: 42161 }, // WEB3 Infrastructurre + { roundId: "26", chainId: 42161 }, // WEB3 Infrastructure { roundId: "27", chainId: 42161 }, // Developer Tooling { roundId: "28", chainId: 42161 }, // Hypercerts Ecosystem { roundId: "29", chainId: 42161 }, // Climate Solutions diff --git a/packages/grant-explorer/src/features/collections/CollectionCard.tsx b/packages/grant-explorer/src/features/collections/CollectionCard.tsx index 5d31887c9e..5123cea4b1 100644 --- a/packages/grant-explorer/src/features/collections/CollectionCard.tsx +++ b/packages/grant-explorer/src/features/collections/CollectionCard.tsx @@ -1,5 +1,4 @@ import { CommunityCollection } from "./community"; -import { Link } from "react-router-dom"; import { Badge, BasicCard, CardHeader } from "../common/styles"; import { CollectionBanner } from "../discovery/CardBanner"; import { collectionPath } from "common/src/routes/explorer"; diff --git a/packages/grant-explorer/src/features/collections/hooks/useCollections.ts b/packages/grant-explorer/src/features/collections/hooks/useCollections.ts index 33876949ab..0dc6538365 100644 --- a/packages/grant-explorer/src/features/collections/hooks/useCollections.ts +++ b/packages/grant-explorer/src/features/collections/hooks/useCollections.ts @@ -1,6 +1,4 @@ import useSWR, { SWRResponse } from "swr"; -import { Collection } from "data-layer"; -import { useDataLayer } from "data-layer"; import { CommunityCollection } from "../community"; import { CollectionV1, parseCollection } from "../collections"; import { getConfig } from "common/src/config"; diff --git a/packages/grant-explorer/src/features/common/Navbar.tsx b/packages/grant-explorer/src/features/common/Navbar.tsx index 63ab2f89b5..3e1e891219 100644 --- a/packages/grant-explorer/src/features/common/Navbar.tsx +++ b/packages/grant-explorer/src/features/common/Navbar.tsx @@ -46,7 +46,7 @@ export default function Navbar(props: NavbarProps) { { chainId: 42161, roundId: "26", - name: "WEB3 Infrastructurre", + name: "WEB3 Infrastructure", link: "/round/42161/26", }, { diff --git a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx index ab9cebcb46..8301393278 100644 --- a/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx +++ b/packages/grant-explorer/src/features/round/ViewProjectDetails.tsx @@ -667,7 +667,7 @@ async function isVerified(args: { project: Project | undefined; dataLayer: DataLayer; }) { - const { verifiableCredential, provider, project, dataLayer } = args; + const { verifiableCredential, provider, project } = args; const passportVerifier = new PassportVerifierWithExpiration(); const vcHasValidProof = await passportVerifier.verifyCredential(verifiableCredential); From 0a4edee8d90fdf5ff23ee688c76e2fdb39ec42c9 Mon Sep 17 00:00:00 2001 From: Kevin Owocki Date: Wed, 1 May 2024 21:40:21 -0600 Subject: [PATCH 20/24] adds more collections as they roll in from the community (#3403) * more collections * updates --- .../features/collections/community/index.ts | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/packages/grant-explorer/src/features/collections/community/index.ts b/packages/grant-explorer/src/features/collections/community/index.ts index 813e661ba8..b5fc8a8e75 100644 --- a/packages/grant-explorer/src/features/collections/community/index.ts +++ b/packages/grant-explorer/src/features/collections/community/index.ts @@ -55,6 +55,30 @@ const collections: CommunityCollection[] = [ description: "Check out my collection of Climate Projects making real-world impact in rural Africa including 2 projects for dMRV.", }, + { + cid: "bafkreibmhp2c2wc7ppbdb3rlgql2xkaxuevfmbdjze2p5svoinrpfb4jim", + author: "Carl Cervone", + name: "Carl Cervone's high impact projects", + numberOfProjects: 100, + description: + "Carl Cervone's favorite OSS and non-OSS projects.", + }, + { + cid: "bafkreia7eablt2gbn4afqmo5z5p4gjiiymn3yhpwlmkkhiaotwqwfuidmq", + author: "Trent Van Epps", + name: "Trent Van Epps favorite projects", + numberOfProjects: 17, + description: + "Trents favorite ecosystem projects.", + }, + { + cid: "bafkreibmljr4sgcbopmj7z62pj55a4e2krc5hfrjyynj6urqugbhzyyrm4", + author: "Jon Ellison", + name: "ReFi DAO & Local Nodes", + numberOfProjects: 17, + description: + "List of ReFi DAO & Local Nodes.", + }, ]; export default collections; From b30ffab90ed76e275b04a89c4acfca1697b9be59 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Fri, 3 May 2024 01:42:21 +0800 Subject: [PATCH 21/24] add grant scan (#3408) --- .../discovery/ExploreProjectsPage.tsx | 39 ++++++++++++++++++- .../src/features/discovery/LandingSection.tsx | 16 ++++++-- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx b/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx index 5030e01d05..0d8568d4a6 100644 --- a/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx +++ b/packages/grant-explorer/src/features/discovery/ExploreProjectsPage.tsx @@ -193,6 +193,43 @@ export function ExploreProjectsPage(): JSX.Element { )} + + + + + + GrantScan + +
+ } title={ collection ? "" @@ -202,7 +239,7 @@ export function ExploreProjectsPage(): JSX.Element { } action={ collection && ( -
+
) { +}: { + left?: ReactNode; + action?: ReactNode; + title: string; +} & ComponentProps<"div">) { return (
-

- {title} -

+ {left} + {title && ( +

+ {title} +

+ )}
{action}
{children}
From 02ed7a3964d80cbdd41d9dfa9b5373bcc08983c1 Mon Sep 17 00:00:00 2001 From: jaxcoder / Date: Fri, 3 May 2024 00:23:44 -0400 Subject: [PATCH 22/24] update posthog with new account (#3406) * wip/update posthog with new account * update env name * remove doxxing info/wallet * lint --- packages/grant-explorer/.env.example | 6 +- packages/grant-explorer/package.json | 2 +- .../src/features/common/ProjectCard.tsx | 18 +- .../discovery/PaginatedProjectsList.tsx | 17 +- packages/grant-explorer/src/index.tsx | 122 +++++------ packages/grant-explorer/src/posthog.ts | 13 +- pnpm-lock.yaml | 194 ++++++++++++++---- 7 files changed, 269 insertions(+), 103 deletions(-) diff --git a/packages/grant-explorer/.env.example b/packages/grant-explorer/.env.example index 2656058d7c..21850a1c9b 100644 --- a/packages/grant-explorer/.env.example +++ b/packages/grant-explorer/.env.example @@ -69,4 +69,8 @@ REACT_APP_PASSPORT_API_COMMUNITY_ID="0000" REACT_APP_PASSPORT_API_COMMUNITY_ID_AVALANCHE="0000" # create key following https://www.opensource.observer/docs/get-started/ -REACT_APP_OSO_API_KEY= \ No newline at end of file +REACT_APP_OSO_API_KEY= + +# https://posthog.com/docs/libraries/react +REACT_APP_POSTHOG_KEY="" +REACT_APP_POSTHOG_HOST="" \ No newline at end of file diff --git a/packages/grant-explorer/package.json b/packages/grant-explorer/package.json index c9b87a0a34..277eb799ea 100644 --- a/packages/grant-explorer/package.json +++ b/packages/grant-explorer/package.json @@ -92,7 +92,7 @@ "moment": "^2.29.3", "node-fetch": "^3.3.1", "os-browserify": "^0.3.0", - "posthog-js": "^1.89.0", + "posthog-js": "^1.90.0", "process": "^0.11.10", "react": "^18.1.0", "react-datetime": "^3.1.1", diff --git a/packages/grant-explorer/src/features/common/ProjectCard.tsx b/packages/grant-explorer/src/features/common/ProjectCard.tsx index b258d65d0d..c5a7a15a89 100644 --- a/packages/grant-explorer/src/features/common/ProjectCard.tsx +++ b/packages/grant-explorer/src/features/common/ProjectCard.tsx @@ -14,6 +14,7 @@ import { applicationPath } from "common/src/routes/explorer"; import { ProjectBanner } from "./ProjectBanner"; import { createIpfsImageUrl } from "common/src/ipfs"; import { getConfig } from "common/src/config"; +import { usePostHog } from "posthog-js/react"; export function ProjectLogo(props: { className?: string; @@ -64,6 +65,7 @@ export function ProjectCard(props: { onRemoveFromCart: removeFromCart, } = props; + const posthog = usePostHog(); const roundId = application.roundId.toLowerCase(); return ( @@ -111,14 +113,26 @@ export function ProjectCard(props: { {inCart ? ( ) : ( diff --git a/packages/grant-explorer/src/features/discovery/PaginatedProjectsList.tsx b/packages/grant-explorer/src/features/discovery/PaginatedProjectsList.tsx index f678901887..8e46bbaddf 100644 --- a/packages/grant-explorer/src/features/discovery/PaginatedProjectsList.tsx +++ b/packages/grant-explorer/src/features/discovery/PaginatedProjectsList.tsx @@ -2,6 +2,7 @@ import PlusIcon from "@heroicons/react/20/solid/PlusIcon"; import { LoadingRing } from "../common/Spinner"; import { ProjectCard, ProjectCardSkeleton } from "../common/ProjectCard"; import { ApplicationSummary } from "data-layer"; +import { usePostHog } from "posthog-js/react"; interface PaginatedProjectsListProps { applications: ApplicationSummary[]; @@ -24,6 +25,8 @@ export function PaginatedProjectsList({ onRemoveApplicationFromCart, applicationExistsInCart, }: PaginatedProjectsListProps): JSX.Element { + const posthog = usePostHog(); + return ( <> {applications.map((application) => ( @@ -31,8 +34,18 @@ export function PaginatedProjectsList({ key={application.applicationRef} application={application} inCart={applicationExistsInCart(application)} - onAddToCart={() => onAddApplicationToCart(application)} - onRemoveFromCart={() => onRemoveApplicationFromCart(application)} + onAddToCart={() => { + posthog.capture("application_added_to_cart", { + applicationRef: application.applicationRef, + }); + onAddApplicationToCart(application); + }} + onRemoveFromCart={() => { + posthog.capture("application_removed_from_cart", { + applicationRef: application.applicationRef, + }); + onRemoveApplicationFromCart(application); + }} /> ))} {isLoadingMore && ( diff --git a/packages/grant-explorer/src/index.tsx b/packages/grant-explorer/src/index.tsx index 7bc4856e5a..ecde3d6fe0 100644 --- a/packages/grant-explorer/src/index.tsx +++ b/packages/grant-explorer/src/index.tsx @@ -32,11 +32,12 @@ import ViewProjectDetails from "./features/round/ViewProjectDetails"; import ViewRound from "./features/round/ViewRoundPage"; import AlloWrapper from "./features/api/AlloWrapper"; import { merge } from "lodash"; +import { PostHogProvider } from "posthog-js/react"; initSentry(); initDatadog(); initTagmanager(); -initPosthog(); +const posthog = initPosthog(); const root = ReactDOM.createRoot( document.getElementById("root") as HTMLElement @@ -71,63 +72,68 @@ const customRainbowKitTheme = merge(lightTheme(), { root.render( - - - - - - - - - {/* Protected Routes */} - } /> - - {/* Default Route */} - } /> - - } /> - } /> - - {/* Round Routes */} - } - /> - } - /> - - } /> - - } /> - - } - /> - - {/* Access Denied */} - } /> - } - /> - - {/* 404 */} - } /> - - - - - - - - + + + + + + + + + + {/* Protected Routes */} + } /> + + {/* Default Route */} + } /> + + } /> + } + /> + + {/* Round Routes */} + } + /> + } + /> + + } /> + + } /> + + } + /> + + {/* Access Denied */} + } /> + } + /> + + {/* 404 */} + } /> + + + + + + + + + ); diff --git a/packages/grant-explorer/src/posthog.ts b/packages/grant-explorer/src/posthog.ts index 09b8046d47..ca33e50622 100644 --- a/packages/grant-explorer/src/posthog.ts +++ b/packages/grant-explorer/src/posthog.ts @@ -1,12 +1,19 @@ import posthog from "posthog-js"; export const initPosthog = () => { - if (process.env.REACT_APP_POSTHOG_TOKEN) { - posthog.init(process.env.REACT_APP_POSTHOG_TOKEN, { - api_host: "https://grants-stack-ux-events.gitcoin.co", + console.log("Initializing Posthog"); + if (process.env.REACT_APP_POSTHOG_KEY && process.env.REACT_APP_POSTHOG_HOST) { + posthog.init(process.env.REACT_APP_POSTHOG_KEY, { + api_host: process.env.REACT_APP_POSTHOG_HOST, session_recording: { maskTextSelector: '[data-testid="rk-account-button"]', }, }); + + console.log("Posthog initialized"); + + return posthog; } + + console.log("Posthog not initialized"); }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22d140e988..513471c45a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,5 +1,9 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + overrides: webpack: ^5 @@ -434,7 +438,7 @@ importers: version: 1.10.7(typescript@5.4.3)(zod@3.22.4) wagmi: specifier: 0.12.19 - version: 0.12.19(@types/react@18.2.21)(ethers@5.7.2)(lokijs@1.5.12)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)(zod@3.22.4) + version: 0.12.19(@types/react@18.2.21)(ethers@5.7.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4) zod: specifier: ^3.22.4 version: 3.22.4 @@ -774,7 +778,7 @@ importers: specifier: ^0.3.0 version: 0.3.0 posthog-js: - specifier: ^1.89.0 + specifier: ^1.90.0 version: 1.90.0 process: specifier: ^0.11.10 @@ -4467,7 +4471,7 @@ packages: '@babel/preset-env': ^7.0.0 babel-loader: ^8.3 || ^9 cypress: '*' - webpack: ^4 || ^5 + webpack: ^5 dependencies: '@babel/core': 7.22.15 '@babel/preset-env': 7.22.15(@babel/core@7.22.15) @@ -4536,7 +4540,7 @@ packages: '@babel/core': ^7.0.1 '@babel/preset-env': ^7.0.0 babel-loader: ^8.3 || ^9 - webpack: ^4 || ^5 + webpack: ^5 dependencies: '@babel/core': 7.22.15 '@babel/preset-env': 7.22.15(@babel/core@7.22.15) @@ -6690,7 +6694,7 @@ packages: react-refresh: '>=0.10.0 <1.0.0' sockjs-client: ^1.4.0 type-fest: '>=0.17.0 <5.0.0' - webpack: '>=4.43.0 <6.0.0' + webpack: ^5 webpack-dev-server: 3.x || 4.x webpack-hot-middleware: 2.x webpack-plugin-serve: 0.x || 1.x @@ -6789,7 +6793,7 @@ packages: react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-remove-scroll: 2.5.4(@types/react@18.2.21)(react@18.2.0) - wagmi: 0.12.19(@types/react@18.2.21)(ethers@5.7.2)(lokijs@1.5.12)(react-dom@18.2.0)(react@18.2.0)(typescript@5.3.3)(zod@3.22.4) + wagmi: 0.12.19(@types/react@18.2.21)(ethers@5.7.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4) transitivePeerDependencies: - '@types/react' dev: false @@ -10153,6 +10157,17 @@ packages: typescript: 5.3.3 dev: false + /@wagmi/chains@0.2.22(typescript@5.4.3): + resolution: {integrity: sha512-TdiOzJT6TO1JrztRNjTA5Quz+UmQlbvWFG8N41u9tta0boHA1JCAzGGvU6KuIcOmJfRJkKOUIt67wlbopCpVHg==} + peerDependencies: + typescript: '>=4.9.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + typescript: 5.4.3 + dev: false + /@wagmi/chains@1.8.0(typescript@5.4.3): resolution: {integrity: sha512-UXo0GF0Cl0+neKC2KAmVAahv8L/5rACbFRRqkDvHMefzY6Fh7yzJd8F4GaGNNG3w4hj8eUB/E3+dEpaTYDN62w==} peerDependencies: @@ -10234,6 +10249,41 @@ packages: - zod dev: false + /@wagmi/connectors@0.3.24(@wagmi/core@0.10.17)(ethers@5.7.2)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4): + resolution: {integrity: sha512-1pI0G9HRblc651dCz9LXuEu/zWQk23XwOUYqJEINb/c2TTLtw5TnTRIcefxxK6RnxeJvcKfnmK0rdZp/4ujFAA==} + peerDependencies: + '@wagmi/core': '>=0.9.x' + ethers: '>=5.5.1 <6' + typescript: '>=4.9.4' + peerDependenciesMeta: + '@wagmi/core': + optional: true + typescript: + optional: true + dependencies: + '@coinbase/wallet-sdk': 3.7.1 + '@ledgerhq/connect-kit-loader': 1.1.2 + '@safe-global/safe-apps-provider': 0.15.2 + '@safe-global/safe-apps-sdk': 7.11.0 + '@wagmi/core': 0.10.17(@types/react@18.2.21)(ethers@5.7.2)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4) + '@walletconnect/ethereum-provider': 2.9.0(@walletconnect/modal@2.6.1)(lokijs@1.5.12) + '@walletconnect/legacy-provider': 2.0.0 + '@walletconnect/modal': 2.6.1(react@18.2.0) + abitype: 0.3.0(typescript@5.4.3)(zod@3.22.4) + ethers: 5.7.2 + eventemitter3: 4.0.7 + typescript: 5.4.3 + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - bufferutil + - encoding + - lokijs + - react + - supports-color + - utf-8-validate + - zod + dev: false + /@wagmi/connectors@3.1.1(react@18.2.0)(typescript@5.2.2)(viem@1.10.7)(zod@3.22.4): resolution: {integrity: sha512-ewOV40AlrXcX018qckU0V9OCsDgHhs+KZjQJZhlplqRtc2ijjS62B5kcypXkcTtfU5qXUBA9KEwPsSTxGdT4ag==} peerDependencies: @@ -10324,6 +10374,35 @@ packages: - zod dev: false + /@wagmi/core@0.10.17(@types/react@18.2.21)(ethers@5.7.2)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4): + resolution: {integrity: sha512-qud45y3IlHp7gYWzoFeyysmhyokRie59Xa5tcx5F1E/v4moD5BY0kzD26mZW/ZQ3WZuVK/lZwiiPRqpqWH52Gw==} + peerDependencies: + ethers: '>=5.5.1 <6' + typescript: '>=4.9.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@wagmi/chains': 0.2.22(typescript@5.4.3) + '@wagmi/connectors': 0.3.24(@wagmi/core@0.10.17)(ethers@5.7.2)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4) + abitype: 0.3.0(typescript@5.4.3)(zod@3.22.4) + ethers: 5.7.2 + eventemitter3: 4.0.7 + typescript: 5.4.3 + zustand: 4.4.1(@types/react@18.2.21)(react@18.2.0) + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - '@types/react' + - bufferutil + - encoding + - immer + - lokijs + - react + - supports-color + - utf-8-validate + - zod + dev: false + /@wagmi/core@1.4.1(@types/react@18.2.21)(react@18.2.0)(typescript@5.2.2)(viem@1.10.7)(zod@3.22.4): resolution: {integrity: sha512-b6LDFL0vZSCNcIHjnJzv++hakavTTt1/2WEQg2S5eEnaHTp7UoQlwfCyjKeiBhRih4yF34N06ea8cyEVjyjXrw==} peerDependencies: @@ -11288,6 +11367,20 @@ packages: zod: 3.22.4 dev: false + /abitype@0.3.0(typescript@5.4.3)(zod@3.22.4): + resolution: {integrity: sha512-0YokyAV4hKMcy97Pl+6QgZBlBdZJN2llslOs7kiFY+cu7kMlVXDBpxMExfv0krzBCQt2t7hNovpQ3y/zvEm18A==} + engines: {pnpm: '>=7'} + peerDependencies: + typescript: '>=4.9.4' + zod: '>=3.19.1' + peerDependenciesMeta: + zod: + optional: true + dependencies: + typescript: 5.4.3 + zod: 3.22.4 + dev: false + /abitype@0.8.7(typescript@5.2.2)(zod@3.22.4): resolution: {integrity: sha512-wQ7hV8Yg/yKmGyFpqrNZufCxbszDe5es4AZGYPBitocfSqXtjrTG9JMWFcc4N30ukl2ve48aBTwt7NJxVQdU3w==} peerDependencies: @@ -12027,7 +12120,7 @@ packages: engines: {node: '>= 8.9'} peerDependencies: '@babel/core': ^7.0.0 - webpack: '>=2' + webpack: ^5 dependencies: '@babel/core': 7.22.15 find-cache-dir: 3.3.2 @@ -13644,7 +13737,7 @@ packages: resolution: {integrity: sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==} engines: {node: '>= 12.13.0'} peerDependencies: - webpack: ^5.0.0 + webpack: ^5 dependencies: icss-utils: 5.1.0(postcss@8.4.35) postcss: 8.4.35 @@ -13664,7 +13757,7 @@ packages: clean-css: '*' csso: '*' esbuild: '*' - webpack: ^5.0.0 + webpack: ^5 peerDependenciesMeta: '@parcel/css': optional: true @@ -14929,7 +15022,7 @@ packages: /esbuild-loader@2.21.0(webpack@5.88.2): resolution: {integrity: sha512-k7ijTkCT43YBSZ6+fBCW1Gin7s46RrJ0VQaM8qA7lq7W+OLsGgtLyFV8470FzYi/4TeDexniTBTPTwZUnXXR5g==} peerDependencies: - webpack: ^4.40.0 || ^5.0.0 + webpack: ^5 dependencies: esbuild: 0.16.17 joycon: 3.1.1 @@ -15762,7 +15855,7 @@ packages: engines: {node: '>= 12.13.0'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 - webpack: ^5.0.0 + webpack: ^5 dependencies: '@types/eslint': 8.44.2 eslint: 8.48.0 @@ -15777,7 +15870,7 @@ packages: engines: {node: '>= 12.13.0'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 - webpack: ^5.0.0 + webpack: ^5 dependencies: '@types/eslint': 8.44.2 eslint: 8.50.0 @@ -16404,7 +16497,7 @@ packages: resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} engines: {node: '>= 10.13.0'} peerDependencies: - webpack: ^4.0.0 || ^5.0.0 + webpack: ^5 dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 @@ -16665,7 +16758,7 @@ packages: eslint: '>= 6' typescript: '>= 2.7' vue-template-compiler: '*' - webpack: '>= 4' + webpack: ^5 peerDependenciesMeta: eslint: optional: true @@ -16696,7 +16789,7 @@ packages: eslint: '>= 6' typescript: '>= 2.7' vue-template-compiler: '*' - webpack: '>= 4' + webpack: ^5 peerDependenciesMeta: eslint: optional: true @@ -16728,7 +16821,7 @@ packages: eslint: '>= 6' typescript: '>= 2.7' vue-template-compiler: '*' - webpack: '>= 4' + webpack: ^5 peerDependenciesMeta: eslint: optional: true @@ -17713,7 +17806,7 @@ packages: resolution: {integrity: sha512-q5oYdzjKUIPQVjOosjgvCHQOv9Ett9CYYHlgvJeXG0qQvdSojnBq4vAdQBwn1+yGveAwHCoe/rMR86ozX3+c2A==} engines: {node: '>=6.9'} peerDependencies: - webpack: ^4.0.0 || ^5.0.0 + webpack: ^5 dependencies: '@types/html-minifier-terser': 5.1.2 '@types/tapable': 1.0.12 @@ -17730,7 +17823,7 @@ packages: resolution: {integrity: sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==} engines: {node: '>=10.13.0'} peerDependencies: - webpack: ^5.20.0 + webpack: ^5 dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -21334,7 +21427,7 @@ packages: resolution: {integrity: sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==} engines: {node: '>= 12.13.0'} peerDependencies: - webpack: ^5.0.0 + webpack: ^5 dependencies: schema-utils: 4.2.0 webpack: 5.88.2(esbuild@0.18.20) @@ -22976,7 +23069,7 @@ packages: engines: {node: '>= 12.13.0'} peerDependencies: postcss: ^7.0.0 || ^8.0.1 - webpack: ^5.0.0 + webpack: ^5 dependencies: cosmiconfig: 7.1.0 klona: 2.0.6 @@ -23867,7 +23960,7 @@ packages: engines: {node: '>=14'} peerDependencies: typescript: '>=2.7' - webpack: '>=4' + webpack: ^5 peerDependenciesMeta: typescript: optional: true @@ -23908,7 +24001,7 @@ packages: engines: {node: '>=14'} peerDependencies: typescript: '>=2.7' - webpack: '>=4' + webpack: ^5 peerDependenciesMeta: typescript: optional: true @@ -23950,7 +24043,7 @@ packages: engines: {node: '>=14'} peerDependencies: typescript: '>=2.7' - webpack: '>=4' + webpack: ^5 peerDependenciesMeta: typescript: optional: true @@ -25118,7 +25211,7 @@ packages: node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 sass: ^1.3.0 sass-embedded: '*' - webpack: ^5.0.0 + webpack: ^5 peerDependenciesMeta: fibers: optional: true @@ -25562,7 +25655,7 @@ packages: resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} engines: {node: '>= 12.13.0'} peerDependencies: - webpack: ^5.0.0 + webpack: ^5 dependencies: abab: 2.0.6 iconv-lite: 0.6.3 @@ -25684,7 +25777,7 @@ packages: resolution: {integrity: sha512-AtVzD0bnIy2/B0fWqJpJgmhcrfWFhBlduzSo0uwplr/QvB33ZNZj2NEth3NONgdnZJqicK0W0mSxnLSbsVCDbw==} engines: {node: '>=6.0.0'} peerDependencies: - webpack: ^1 || ^2 || ^3 || ^4 || ^5 + webpack: ^5 dependencies: chalk: 4.1.2 webpack: 5.88.2(esbuild@0.18.20) @@ -26023,7 +26116,7 @@ packages: resolution: {integrity: sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==} engines: {node: '>= 12.13.0'} peerDependencies: - webpack: ^5.0.0 + webpack: ^5 dependencies: webpack: 5.88.2(esbuild@0.18.20) @@ -26291,7 +26384,7 @@ packages: '@swc/core': '*' esbuild: '*' uglify-js: '*' - webpack: ^5.1.0 + webpack: ^5 peerDependenciesMeta: '@swc/core': optional: true @@ -28015,6 +28108,39 @@ packages: - zod dev: false + /wagmi@0.12.19(@types/react@18.2.21)(ethers@5.7.2)(react-dom@18.2.0)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4): + resolution: {integrity: sha512-S/el9BDb/HNeQWh1v8TvntMPX/CgKLDAoJqDb8i7jifLfWPqFL7gor3vnI1Vs6ZlB8uh7m+K1Qyg+mKhbITuDQ==} + peerDependencies: + ethers: '>=5.5.1 <6' + react: '>=17.0.0' + typescript: '>=4.9.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@tanstack/query-sync-storage-persister': 4.35.0 + '@tanstack/react-query': 4.35.0(react-dom@18.2.0)(react@18.2.0) + '@tanstack/react-query-persist-client': 4.35.0(@tanstack/react-query@4.35.0) + '@wagmi/core': 0.10.17(@types/react@18.2.21)(ethers@5.7.2)(react@18.2.0)(typescript@5.4.3)(zod@3.22.4) + abitype: 0.3.0(typescript@5.4.3)(zod@3.22.4) + ethers: 5.7.2 + react: 18.2.0 + typescript: 5.4.3 + use-sync-external-store: 1.2.0(react@18.2.0) + transitivePeerDependencies: + - '@react-native-async-storage/async-storage' + - '@types/react' + - bufferutil + - encoding + - immer + - lokijs + - react-dom + - react-native + - supports-color + - utf-8-validate + - zod + dev: false + /wagmi@1.4.1(@types/react@18.2.21)(react-dom@18.2.0)(react@18.2.0)(typescript@5.2.2)(viem@1.10.7)(zod@3.22.4): resolution: {integrity: sha512-v3xd+uYZfLCAs1I4fLU7U9hg/gCw+Ud005J7kNR0mi20BcFAEU1EDN1LxHxpjUV0qKhOzSlMlrLjJyBCmSYhFA==} peerDependencies: @@ -28146,7 +28272,7 @@ packages: resolution: {integrity: sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==} engines: {node: '>= 12.13.0'} peerDependencies: - webpack: ^4.0.0 || ^5.0.0 + webpack: ^5 dependencies: colorette: 2.0.20 memfs: 3.5.3 @@ -28160,7 +28286,7 @@ packages: engines: {node: '>= 12.13.0'} hasBin: true peerDependencies: - webpack: ^4.37.0 || ^5.0.0 + webpack: ^5 webpack-cli: '*' peerDependenciesMeta: webpack: @@ -28209,7 +28335,7 @@ packages: resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} engines: {node: '>=12.22.0'} peerDependencies: - webpack: ^4.44.2 || ^5.47.0 + webpack: ^5 dependencies: tapable: 2.2.1 webpack: 5.88.2(esbuild@0.18.20) @@ -28560,7 +28686,7 @@ packages: resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} engines: {node: '>=10.0.0'} peerDependencies: - webpack: ^4.4.0 || ^5.9.0 + webpack: ^5 dependencies: fast-json-stable-stringify: 2.1.0 pretty-bytes: 5.6.0 @@ -28941,7 +29067,3 @@ packages: dependencies: '@types/node': 18.17.14 dev: false - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false From 92214ea11fade273532e5c1be1c267d2027bcaba Mon Sep 17 00:00:00 2001 From: Kevin Owocki Date: Fri, 3 May 2024 00:11:37 -0600 Subject: [PATCH 23/24] more projs (#3407) Co-authored-by: jaxcoder / --- .../features/collections/community/index.ts | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/packages/grant-explorer/src/features/collections/community/index.ts b/packages/grant-explorer/src/features/collections/community/index.ts index b5fc8a8e75..b92341a549 100644 --- a/packages/grant-explorer/src/features/collections/community/index.ts +++ b/packages/grant-explorer/src/features/collections/community/index.ts @@ -60,24 +60,44 @@ const collections: CommunityCollection[] = [ author: "Carl Cervone", name: "Carl Cervone's high impact projects", numberOfProjects: 100, - description: - "Carl Cervone's favorite OSS and non-OSS projects.", + description: "Carl Cervone's favorite OSS and non-OSS projects.", }, { cid: "bafkreia7eablt2gbn4afqmo5z5p4gjiiymn3yhpwlmkkhiaotwqwfuidmq", author: "Trent Van Epps", name: "Trent Van Epps favorite projects", numberOfProjects: 17, - description: - "Trents favorite ecosystem projects.", + description: "Trents favorite ecosystem projects.", }, { cid: "bafkreibmljr4sgcbopmj7z62pj55a4e2krc5hfrjyynj6urqugbhzyyrm4", author: "Jon Ellison", name: "ReFi DAO & Local Nodes", numberOfProjects: 17, + description: "List of ReFi DAO & Local Nodes.", + }, + { + cid: "bafkreic3it6ka4g6e3n2nplo2bmo34tn4nw2drrmkqmjifrespvwzg5ydu", + author: "David mortech ", + name: "Africa web3 Changemakers", + numberOfProjects: 29, + description: + "Africa web3 Changemakers in Gitcoin GG20 QF rounds take a look n support.", + }, + { + cid: "bafkreiaqclu2z3tlhhyux3mqgux3y5lfnmgi4end2a4itw25slm2fba4ba", + author: "Piraox", + name: "The Future", + numberOfProjects: 7, + description: "Projects I think are the future", + }, + { + cid: "bafkreifz2wakvsiw5o6dcinqn7vhgcun2t4wxl7rm22s5g2jsfznmwnnsi", + author: "Tarah Stafford", + name: "Women Founders", + numberOfProjects: 15, description: - "List of ReFi DAO & Local Nodes.", + "Womyn Founders GG20 - 15 impactful Climate/ReFi/Impact projects led and co-led by women #GG20", }, ]; From 1c827b0ccc081856280d1a79c8f3fa0300473052 Mon Sep 17 00:00:00 2001 From: jaxcoder / Date: Fri, 3 May 2024 14:59:14 -0400 Subject: [PATCH 24/24] fix: donations/when application is null (#3411) * fix: donations/when application is null * remove log --- packages/data-layer/src/data-layer.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/data-layer/src/data-layer.ts b/packages/data-layer/src/data-layer.ts index 522b5259c3..593c9b2fb2 100644 --- a/packages/data-layer/src/data-layer.ts +++ b/packages/data-layer/src/data-layer.ts @@ -683,7 +683,9 @@ export class DataLayer { ); return response.donations.filter((donation) => { - return donation.application.project !== null; + return ( + donation.application !== null && donation.application?.project !== null + ); }); }