diff --git a/.eslintrc.json b/.eslintrc.json index 1d91cd0903..20e6d27f80 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,6 @@ "rules": { "comma-dangle": "error", "quotes": "error", - "camelcase": "error", "jsx-quotes": "error", "semi": "error", "indent": ["error", 2] diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c717a8ac9..11a744b522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,69 @@ > All notable changes to this project will be documented in this file +## [1.36.0-beta.5](https://github.com/open-sauced/insights/compare/v1.36.0-beta.4...v1.36.0-beta.5) (2023-03-16) + + +### πŸ• Features + +* implement repo suggestions in create insight page ([#1011](https://github.com/open-sauced/insights/issues/1011)) ([8814289](https://github.com/open-sauced/insights/commit/8814289cc76ea9234f0ead05dd44078bc034dc66)) + +## [1.36.0-beta.4](https://github.com/open-sauced/insights/compare/v1.36.0-beta.3...v1.36.0-beta.4) (2023-03-16) + + +### πŸ• Features + +* add context to the Insights list page ([#1017](https://github.com/open-sauced/insights/issues/1017)) ([bd293d1](https://github.com/open-sauced/insights/commit/bd293d1a7e3d5912b6ae30378158d8ed1d1131de)) + +## [1.36.0-beta.3](https://github.com/open-sauced/insights/compare/v1.36.0-beta.2...v1.36.0-beta.3) (2023-03-15) + + +### πŸ› Bug Fixes + +* thumbnail topic images ([#1010](https://github.com/open-sauced/insights/issues/1010)) ([3f64f6d](https://github.com/open-sauced/insights/commit/3f64f6d3657abec66b227c04cd229df671c10689)) + + +### πŸ• Features + +* connect pull requests to API ([#1015](https://github.com/open-sauced/insights/issues/1015)) ([4e06a6f](https://github.com/open-sauced/insights/commit/4e06a6f09096dd57db45fc2f02174c6b4116c895)) + +## [1.36.0-beta.2](https://github.com/open-sauced/insights/compare/v1.36.0-beta.1...v1.36.0-beta.2) (2023-03-15) + + +### πŸ”₯ Performance Improvements + +* load balance test, primarily for the backend ([2dcce75](https://github.com/open-sauced/insights/commit/2dcce75a6518dcaf49db1082c05c108c740d553f)) + +## [1.36.0-beta.1](https://github.com/open-sauced/insights/compare/v1.35.0...v1.36.0-beta.1) (2023-03-15) + + +### 🎨 Styles + +* log netlify env variables ([245b625](https://github.com/open-sauced/insights/commit/245b6255af96e1a76028812b4b88ebffcb9e5a15)) + + +### πŸ§‘β€πŸ’» Code Refactoring + +* correct some missing hook dependencies ([4868b5f](https://github.com/open-sauced/insights/commit/4868b5f49c222a0b17377f6cdea8c09711dbc618)) +* correct user insight repos search results ([9503d17](https://github.com/open-sauced/insights/commit/9503d17eff3d14f5b1af1f1fad120f393b47db08)) +* correctly await router transitions ([8fa63c0](https://github.com/open-sauced/insights/commit/8fa63c040bd7980657024b3bd60c1ce5781ec815)) + + +### πŸ› Bug Fixes + +* correct database repo types and import loops ([d70f067](https://github.com/open-sauced/insights/commit/d70f06720f4b22b3fc92ab2aaeaeb45240e8a8f7)) +* enable displaying/editing of insight page repos from API ([f4cc62f](https://github.com/open-sauced/insights/commit/f4cc62f5e6f39b96ec76041998b3664ab8068f8b)) +* formatting ([065ede0](https://github.com/open-sauced/insights/commit/065ede07e9218568f363e66cbb997d0c88597310)) + + +### πŸ• Features + +* add support for repo full name for onboarding/insight repos ([#861](https://github.com/open-sauced/insights/issues/861)) ([d075f90](https://github.com/open-sauced/insights/commit/d075f90a6b287fd52e31ec96cd8a2256f147b74f)) +* connect contributors to public API ([0eb73e9](https://github.com/open-sauced/insights/commit/0eb73e9b081477567be8762689ff3ff964b5869e)) +* connect pull requests to search API ([5904102](https://github.com/open-sauced/insights/commit/5904102337a875e17ff8aeef5cdfe793d0c7dc06)) +* get pull requests for dashboard from API ([ec31c42](https://github.com/open-sauced/insights/commit/ec31c4207f321dccb9b8281b6171cd41235e3b3c)) +* implement linked data with JSON-LD ([#888](https://github.com/open-sauced/insights/issues/888)) ([e8bda0e](https://github.com/open-sauced/insights/commit/e8bda0ec892750ad2d91acccd51624ed669a9542)), closes [#814](https://github.com/open-sauced/insights/issues/814) + ## [1.35.0](https://github.com/open-sauced/insights/compare/v1.34.0...v1.35.0) (2023-03-14) diff --git a/components/atoms/LanguagePill/LanguagePill.tsx b/components/atoms/LanguagePill/LanguagePill.tsx index 59cbf1ddda..5609fb7270 100644 --- a/components/atoms/LanguagePill/LanguagePill.tsx +++ b/components/atoms/LanguagePill/LanguagePill.tsx @@ -1,22 +1,25 @@ import React from "react"; import Image, { StaticImageData } from "next/image"; -import JavascriptIcon from "img/topic-thumbnails/javascript.svg"; -import ReactIcon from "/img/topic-thumbnails/react.svg"; -import PythonIcon from "/img/topic-thumbnails/python.svg"; -import AIIcon from "/img/topic-thumbnails/ai.svg"; -import MLIcon from "/img/topic-thumbnails/machine-learning.svg"; -import RustIcon from "/img/topic-thumbnails/rust.svg"; -import PhpIcon from "/img/topic-thumbnails/php.svg"; -import CsharpIcon from "/img/topic-thumbnails/c-sharp.svg"; -import CIcon from "/img/topic-thumbnails/c.svg"; -import CppIcon from "/img/topic-thumbnails/c-plus.svg"; -import TypeScriptIcon from "/img/topic-thumbnails/typescript.svg"; -import RubyIcon from "/img/topic-thumbnails/ruby.svg"; -import JavaIcon from "/img/topic-thumbnails/java.svg"; -import GolangIcon from "/img/topic-thumbnails/golang.svg"; + +import JavascriptIcon from "img/icons/interests/javascript.svg"; +import ReactIcon from "/img/icons/interests/react.svg"; +import PythonIcon from "/img/icons/interests/python.svg"; +import AIIcon from "/img/icons/interests/ai.svg"; +import MLIcon from "/img/icons//interests/machine-learning.svg"; +import RustIcon from "/img/icons/interests/rust.svg"; +import PhpIcon from "/img/icons/interests/php.svg"; +import CsharpIcon from "/img/icons/interests/c-sharp.svg"; +import CIcon from "/img/icons/interests/c.svg"; +import CppIcon from "/img/icons/interests/c-plus.svg"; +import TypeScriptIcon from "/img/icons/interests/typescript.svg"; +import RubyIcon from "/img/icons/interests/ruby.svg"; +import JavaIcon from "/img/icons/interests/java.svg"; +import GolangIcon from "img/icons/interests/golang.svg"; + import topicNameFormatting from "lib/utils/topic-name-formatting"; + interface LanguagePillProps { topic: | "react" diff --git a/components/molecules/FilterHeader/filter-header.tsx b/components/molecules/FilterHeader/filter-header.tsx index 5cd198821c..cf2c68d46a 100644 --- a/components/molecules/FilterHeader/filter-header.tsx +++ b/components/molecules/FilterHeader/filter-header.tsx @@ -23,11 +23,11 @@ const HeaderFilter = () => { const { filterName, toolName, selectedFilter } = router.query; const filterBtnRouting = (filter: string) => { captureAnayltics("Filters", "toolsFilter", `${filter} applied`); - router.push(`/${filterName}/${toolName}/filter/${filter.toLocaleLowerCase()}`); + return router.push(`/${filterName}/${toolName}/filter/${filter.toLocaleLowerCase()}`); }; const cancelFilterRouting = () => { - router.push(`/${filterName}/${toolName}`); + return router.push(`/${filterName}/${toolName}`); }; const topicRouting = (topic: string) => { diff --git a/components/molecules/LatestPrTableRow/latest-pr-table-row.tsx b/components/molecules/LatestPrTableRow/latest-pr-table-row.tsx index ed83e5cdad..11fefa37b7 100644 --- a/components/molecules/LatestPrTableRow/latest-pr-table-row.tsx +++ b/components/molecules/LatestPrTableRow/latest-pr-table-row.tsx @@ -17,8 +17,7 @@ interface LatestPrTableRowProps { noOfFilesChanged: number; noOfLinesChanged: number; isHoverCard?: boolean; - repoName: string; - repoOwner: string; + repoFullName: string; prNumber: number; prUpdatedTime: string; } @@ -31,8 +30,7 @@ const LatestPrTableRow = ({ noOfLinesChanged, merged, isHoverCard, - repoName, - repoOwner, + repoFullName, prNumber, prUpdatedTime }: LatestPrTableRowProps) => { @@ -58,18 +56,18 @@ const LatestPrTableRow = ({ )} - {calcDistanceFromToday(new Date(parseInt(prUpdatedTime, 10)))} + {calcDistanceFromToday(new Date(prUpdatedTime))} - + {prName}
- {calcDistanceFromToday(new Date(parseInt(prIssuedTime, 10)))} + {calcDistanceFromToday(new Date(prIssuedTime))}
- {merged ? calcDistanceFromToday(new Date(parseInt(prMergedTime, 10))) : "-"} + {merged ? calcDistanceFromToday(new Date(prMergedTime)) : "-"}
{noOfFilesChanged >= 1000 ? humanizeNumber(noOfFilesChanged, "abbreviation") : noOfFilesChanged} diff --git a/components/molecules/PullRequestTable/pull-request-table.tsx b/components/molecules/PullRequestTable/pull-request-table.tsx index 288500cfcc..eef5b1ee2d 100644 --- a/components/molecules/PullRequestTable/pull-request-table.tsx +++ b/components/molecules/PullRequestTable/pull-request-table.tsx @@ -1,4 +1,4 @@ -import { useTopicContributorPRs } from "lib/hooks/useTopicContributorPRs"; +import useContributorPullRequests from "lib/hooks/api/useContributorPullRequests"; import SkeletonWrapper from "components/atoms/SkeletonLoader/skeleton-wrapper"; import LatestPrTableHeader from "../LatestPrTableHeader/latest-pr-table-header"; @@ -22,7 +22,7 @@ interface CardTableProps { } const PullRequestTable = ({ contributor, topic, repositories, limit, isHoverCard }: CardTableProps): JSX.Element => { - const { data, isLoading } = useTopicContributorPRs(contributor, topic, repositories, limit); + const { data, isLoading } = useContributorPullRequests(contributor, topic, repositories, limit); return data.length > 0 ? ( <> @@ -37,11 +37,11 @@ const PullRequestTable = ({ contributor, topic, repositories, limit, isHoverCard merged, merged_at: prMergedTime, created_at: prIssuedTime, - filesCount: noOfFilesChanged, - linesCount: noOfLinesChanged, + changed_files: noOfFilesChanged, + additions, + deletions, number: prNumber, - repo_name: repoName, - repo_owner: repoOwner, + full_name: fullName, updated_at: prUpdatedTime }, index @@ -53,9 +53,8 @@ const PullRequestTable = ({ contributor, topic, repositories, limit, isHoverCard prStatus, merged, noOfFilesChanged, - noOfLinesChanged, - repoName, - repoOwner, + noOfLinesChanged: Math.abs(additions - deletions), + repoFullName: fullName, prNumber, prUpdatedTime }; diff --git a/components/molecules/RepoCardProfile/repo-card-profile.tsx b/components/molecules/RepoCardProfile/repo-card-profile.tsx index 33c83643b1..afb463a9f8 100644 --- a/components/molecules/RepoCardProfile/repo-card-profile.tsx +++ b/components/molecules/RepoCardProfile/repo-card-profile.tsx @@ -6,8 +6,8 @@ import { VscIssues } from "react-icons/vsc"; export interface RepoCardProfileProps { avatar?: string | StaticImageData; - orgName?: string; - repoName?: string; + orgName: string; + repoName: string; prCount?: number; issueCount?: number; className?: string; diff --git a/components/molecules/SuggestedRepo/suggested-repo.tsx b/components/molecules/SuggestedRepo/suggested-repo.tsx index 44b0a5f4b5..ce5e8c3f8b 100644 --- a/components/molecules/SuggestedRepo/suggested-repo.tsx +++ b/components/molecules/SuggestedRepo/suggested-repo.tsx @@ -7,14 +7,16 @@ import Avatar from "components/atoms/Avatar/avatar"; import RepoCardProfile, { RepoCardProfileProps } from "../RepoCardProfile/repo-card-profile"; interface SuggestedRopsitoryProps { - data?: RepoCardProfileProps; + data: RepoCardProfileProps; + onAddRepo?: (repo: string) => void; } -const SuggestedRepository = ({ data }: SuggestedRopsitoryProps) => { - // Utilizing static data for testing purpose until real data is available +const SuggestedRepository = ({ data, onAddRepo }: SuggestedRopsitoryProps) => { return (
-
diff --git a/components/organisms/Dashboard/dashboard.tsx b/components/organisms/Dashboard/dashboard.tsx index dc2881e485..8fe50a14fc 100644 --- a/components/organisms/Dashboard/dashboard.tsx +++ b/components/organisms/Dashboard/dashboard.tsx @@ -9,10 +9,10 @@ import { ScatterChartDataItems } from "components/molecules/NivoScatterChart/niv import humanizeNumber from "lib/utils/humanizeNumber"; import { useMediaQuery } from "lib/hooks/useMediaQuery"; import { getInsights, useInsights } from "lib/hooks/useInsights"; -import { useTopicPRs } from "lib/hooks/useTopicPRs"; import { calcDaysFromToday } from "lib/utils/date-utils"; import roundedImage from "lib/utils/roundedImages"; import { useTopicContributions } from "lib/hooks/useTopicContributions"; +import usePullRequests from "lib/hooks/api/usePullRequests"; type ContributorPrMap = { [contributor: string]: DbRepoPR }; export type PrStatusFilter = "open" | "closed" | "all"; @@ -23,7 +23,7 @@ interface DashboardProps { export const Dashboard = ({ repositories }: DashboardProps): JSX.Element => { const { data: insightsData, isLoading } = useInsights(repositories); - const { data: prData, isError: prError } = useTopicPRs(undefined, repositories); + const { data: prData, isError: prError } = usePullRequests(undefined, repositories); const { data: contributorData } = useTopicContributions(10, repositories); const [showBots, setShowBots] = useState(false); const isMobile = useMediaQuery("(max-width:720px)"); @@ -44,10 +44,10 @@ export const Dashboard = ({ repositories }: DashboardProps): JSX.Element => { if (curr.state !== prStateFilter && prStateFilter !== "all") return prs; if (prs[curr.author_login]) { - prs[curr.author_login].linesCount += curr.linesCount; + prs[curr.author_login].linesCount += Math.abs(curr.additions - curr.deletions); } else { prs[curr.author_login] = { ...curr }; - prs[curr.author_login].linesCount = curr.linesCount; + prs[curr.author_login].linesCount = Math.abs(curr.additions - curr.deletions); } return prs; @@ -70,7 +70,7 @@ export const Dashboard = ({ repositories }: DashboardProps): JSX.Element => { const author_image = author_login.includes("[bot]") ? "octocat" : author_login; const data = { - x: calcDaysFromToday(new Date(parseInt(updated_at, 10))), + x: calcDaysFromToday(new Date(updated_at)), y: linesCount, contributor: author_login, image: roundedImage(`https://www.github.com/${author_image}.png?size=60`, process.env.NEXT_PUBLIC_CLOUD_NAME) diff --git a/components/organisms/InsightPage/InsightPage.tsx b/components/organisms/InsightPage/InsightPage.tsx index 4123962424..66d913a18d 100644 --- a/components/organisms/InsightPage/InsightPage.tsx +++ b/components/organisms/InsightPage/InsightPage.tsx @@ -18,6 +18,8 @@ import useStore from "lib/store"; import Error from "components/atoms/Error/Error"; import Search from "components/atoms/Search/search"; import { useDebounce } from "rooks"; +import SuggestedRepositoriesList from "../SuggestedRepoList/suggested-repo-list"; +import { RepoCardProfileProps } from "components/molecules/RepoCardProfile/repo-card-profile"; enum RepoLookupError { Initial = 0, @@ -105,7 +107,7 @@ const InsightPage = ({ edit, insight, pageRepos }: InsightPageProps) => { }, body: JSON.stringify({ name, - ids: repos.map((repo) => repo.id), + repos: repos.map((repo) => ({ id: repo.host_id, fullName: repo.full_name })), // eslint-disable-next-line is_public: isPublic }) @@ -129,7 +131,7 @@ const InsightPage = ({ edit, insight, pageRepos }: InsightPageProps) => { }, body: JSON.stringify({ name, - ids: repos.map((repo) => repo.id), + repos: repos.map((repo) => ({ id: repo.host_id, fullName: repo.full_name })), // eslint-disable-next-line is_public: isPublic }) @@ -261,6 +263,11 @@ const InsightPage = ({ edit, insight, pageRepos }: InsightPageProps) => { updateSuggestionsDebounced(); }, [repoSearchTerm]); + const staticSuggestedRepos: RepoCardProfileProps[] = [ + { avatar: "https://avatars.githubusercontent.com/u/57568598?s=200&v=4", prCount: 8, repoName: "insights", issueCount: 87, orgName: "open-sauced" }, + { avatar: "https://avatars.githubusercontent.com/u/59704711?s=200&v=4", prCount: 26, repoName: "cli", issueCount: 398, orgName: "cli" }, + { avatar: "https://avatars.githubusercontent.com/u/42048915?s=200&v=4", prCount: 100, repoName: "deno", issueCount: 1200, orgName: "denoland" } + ]; return (
@@ -299,6 +306,9 @@ const InsightPage = ({ edit, insight, pageRepos }: InsightPageProps) => { Add Repository
+ + {loadAndAddRepo(repo);}} />
diff --git a/components/organisms/Repositories/repositories.tsx b/components/organisms/Repositories/repositories.tsx index fd4c14523c..27e0e6ccea 100644 --- a/components/organisms/Repositories/repositories.tsx +++ b/components/organisms/Repositories/repositories.tsx @@ -73,9 +73,9 @@ const Repositories = ({ repositories }: RepositoriesProps): JSX.Element => { const handleOnSearch = (search?: string) => { if (search && /^[a-zA-Z0-9\-\.]+\/[a-zA-Z0-9\-\.]+$/.test(search)) { - router.push(`/${topic}/${toolName}/filter/${search}`); + return router.push(`/${topic}/${toolName}/filter/${search}`); } else { - router.push(`/${topic}/${toolName}`); + return router.push(`/${topic}/${toolName}`); } }; diff --git a/components/organisms/SuggestedRepoList/suggested-repo-list.tsx b/components/organisms/SuggestedRepoList/suggested-repo-list.tsx index 44defe8422..04e1f00b95 100644 --- a/components/organisms/SuggestedRepoList/suggested-repo-list.tsx +++ b/components/organisms/SuggestedRepoList/suggested-repo-list.tsx @@ -1,10 +1,15 @@ import Title from "components/atoms/Typography/title"; +import { RepoCardProfileProps } from "components/molecules/RepoCardProfile/repo-card-profile"; import SuggestedRepository from "components/molecules/SuggestedRepo/suggested-repo"; import React from "react"; -const SuggestedRepositoriesList = () => { - // Random array to be replaced with real repositories data - const randomSuggestions = Array.apply(null, Array(3)); +interface SuggestedRepositoriesListProps { + reposData: RepoCardProfileProps[]; + onAddRepo?: (repo: string) => void; +} + +const SuggestedRepositoriesList = ({ reposData, onAddRepo }: SuggestedRepositoriesListProps) => { + return (
@@ -12,10 +17,11 @@ const SuggestedRepositoriesList = () => {
- {randomSuggestions.map((item, index) => ( + {reposData.map((item, index) => ( ))}
diff --git a/components/organisms/TopNav/top-nav.tsx b/components/organisms/TopNav/top-nav.tsx index fdfd4cd74f..784644c09b 100644 --- a/components/organisms/TopNav/top-nav.tsx +++ b/components/organisms/TopNav/top-nav.tsx @@ -25,7 +25,7 @@ const TopNav: React.FC = () => { {!!user && onboarded ? ( <> - Insights Hub + Insights Explore diff --git a/img/icons/interests/ai.svg b/img/icons/interests/ai.svg new file mode 100644 index 0000000000..50568cda3a --- /dev/null +++ b/img/icons/interests/ai.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/c-plus.svg b/img/icons/interests/c-plus.svg new file mode 100644 index 0000000000..7b29067e83 --- /dev/null +++ b/img/icons/interests/c-plus.svg @@ -0,0 +1,110 @@ + + + + \ No newline at end of file diff --git a/img/icons/interests/c-sharp.svg b/img/icons/interests/c-sharp.svg new file mode 100644 index 0000000000..33e9c62354 --- /dev/null +++ b/img/icons/interests/c-sharp.svg @@ -0,0 +1,6 @@ + + + +piano + + \ No newline at end of file diff --git a/img/icons/interests/c.svg b/img/icons/interests/c.svg new file mode 100644 index 0000000000..5b742ece67 --- /dev/null +++ b/img/icons/interests/c.svg @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/icons/interests/golang.svg b/img/icons/interests/golang.svg new file mode 100644 index 0000000000..cce1995aba --- /dev/null +++ b/img/icons/interests/golang.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/java.svg b/img/icons/interests/java.svg new file mode 100644 index 0000000000..ce848bc231 --- /dev/null +++ b/img/icons/interests/java.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/javascript.svg b/img/icons/interests/javascript.svg new file mode 100644 index 0000000000..878d6d95e1 --- /dev/null +++ b/img/icons/interests/javascript.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/icons/interests/machine-learning.svg b/img/icons/interests/machine-learning.svg new file mode 100644 index 0000000000..a3e74010ca --- /dev/null +++ b/img/icons/interests/machine-learning.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/php.svg b/img/icons/interests/php.svg new file mode 100644 index 0000000000..74796ad95a --- /dev/null +++ b/img/icons/interests/php.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/img/icons/interests/python.svg b/img/icons/interests/python.svg new file mode 100644 index 0000000000..e206c22de7 --- /dev/null +++ b/img/icons/interests/python.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/react.svg b/img/icons/interests/react.svg new file mode 100644 index 0000000000..ade105a8a4 --- /dev/null +++ b/img/icons/interests/react.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/ruby.svg b/img/icons/interests/ruby.svg new file mode 100644 index 0000000000..5e5deebc8e --- /dev/null +++ b/img/icons/interests/ruby.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/img/icons/interests/rust-lang-icon.svg b/img/icons/interests/rust-lang-icon.svg new file mode 100644 index 0000000000..f62525ee8c --- /dev/null +++ b/img/icons/interests/rust-lang-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/icons/interests/rust.svg b/img/icons/interests/rust.svg new file mode 100644 index 0000000000..34ebb806bc --- /dev/null +++ b/img/icons/interests/rust.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/icons/interests/typescript.svg b/img/icons/interests/typescript.svg new file mode 100644 index 0000000000..65c078d5d3 --- /dev/null +++ b/img/icons/interests/typescript.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/img/topic-thumbnails/Go-Logo_Black.svg b/img/topic-thumbnails/Go-Logo_Black.svg new file mode 100644 index 0000000000..666408bf64 --- /dev/null +++ b/img/topic-thumbnails/Go-Logo_Black.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/topic-thumbnails/ai.svg b/img/topic-thumbnails/ai.svg index 50568cda3a..78f14c56c2 100644 --- a/img/topic-thumbnails/ai.svg +++ b/img/topic-thumbnails/ai.svg @@ -1,9 +1,4 @@ - - - - - - - - + + + diff --git a/img/topic-thumbnails/c.svg b/img/topic-thumbnails/c.svg index 5b742ece67..93303fdd95 100644 --- a/img/topic-thumbnails/c.svg +++ b/img/topic-thumbnails/c.svg @@ -1,110 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + diff --git a/img/topic-thumbnails/cpp.svg b/img/topic-thumbnails/cpp.svg new file mode 100644 index 0000000000..77a6dc2fd8 --- /dev/null +++ b/img/topic-thumbnails/cpp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/topic-thumbnails/csharp.svg b/img/topic-thumbnails/csharp.svg new file mode 100644 index 0000000000..72ea62b69c --- /dev/null +++ b/img/topic-thumbnails/csharp.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/img/topic-thumbnails/go.svg b/img/topic-thumbnails/go.svg new file mode 100644 index 0000000000..64e9620777 --- /dev/null +++ b/img/topic-thumbnails/go.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/img/topic-thumbnails/java.svg b/img/topic-thumbnails/java.svg index ce848bc231..40b5695aeb 100644 --- a/img/topic-thumbnails/java.svg +++ b/img/topic-thumbnails/java.svg @@ -1,9 +1,3 @@ - - - - - - - - - + + + diff --git a/img/topic-thumbnails/javascript.svg b/img/topic-thumbnails/javascript.svg index 878d6d95e1..9c50946380 100644 --- a/img/topic-thumbnails/javascript.svg +++ b/img/topic-thumbnails/javascript.svg @@ -1,36 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/img/topic-thumbnails/machine-learning.svg b/img/topic-thumbnails/machine-learning.svg index a3e74010ca..17c9b0d837 100644 --- a/img/topic-thumbnails/machine-learning.svg +++ b/img/topic-thumbnails/machine-learning.svg @@ -1,9 +1,4 @@ - - - - - - - - + + + diff --git a/img/topic-thumbnails/ml.svg b/img/topic-thumbnails/ml.svg new file mode 100644 index 0000000000..c7ec84c8b1 --- /dev/null +++ b/img/topic-thumbnails/ml.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/img/topic-thumbnails/php.svg b/img/topic-thumbnails/php.svg index 74796ad95a..24b228c7c5 100644 --- a/img/topic-thumbnails/php.svg +++ b/img/topic-thumbnails/php.svg @@ -1,14 +1,3 @@ - - - - - - - - - - - \ No newline at end of file + + + diff --git a/img/topic-thumbnails/python.svg b/img/topic-thumbnails/python.svg index e206c22de7..89f555ed36 100644 --- a/img/topic-thumbnails/python.svg +++ b/img/topic-thumbnails/python.svg @@ -1,9 +1,3 @@ - - - - - - - - - + + + diff --git a/img/topic-thumbnails/react.svg b/img/topic-thumbnails/react.svg index ade105a8a4..57540f8aee 100644 --- a/img/topic-thumbnails/react.svg +++ b/img/topic-thumbnails/react.svg @@ -1,9 +1,3 @@ - - - - - - - - - + + + diff --git a/img/topic-thumbnails/ruby.svg b/img/topic-thumbnails/ruby.svg index 5e5deebc8e..71009741a6 100644 --- a/img/topic-thumbnails/ruby.svg +++ b/img/topic-thumbnails/ruby.svg @@ -1,2 +1,3 @@ - - \ No newline at end of file + + + diff --git a/img/topic-thumbnails/rust.svg b/img/topic-thumbnails/rust.svg index 34ebb806bc..f62525ee8c 100644 --- a/img/topic-thumbnails/rust.svg +++ b/img/topic-thumbnails/rust.svg @@ -1,9 +1 @@ - - - - - - - - - + \ No newline at end of file diff --git a/img/topic-thumbnails/typescript.svg b/img/topic-thumbnails/typescript.svg index 65c078d5d3..805a94e43f 100644 --- a/img/topic-thumbnails/typescript.svg +++ b/img/topic-thumbnails/typescript.svg @@ -1,31 +1,3 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + diff --git a/interfaces/global-state-types.ts b/interfaces/global-state-types.ts index 110c5d1172..e649a5f4a5 100644 --- a/interfaces/global-state-types.ts +++ b/interfaces/global-state-types.ts @@ -1,4 +1,4 @@ -import { User } from "@supabase/gotrue-js/src/lib/types"; +import { User } from "@supabase/supabase-js"; export interface GlobalStateInterface { user?: User | null; diff --git a/layouts/hub-page.tsx b/layouts/hub-page.tsx index f641b130c7..4ea89f3067 100644 --- a/layouts/hub-page.tsx +++ b/layouts/hub-page.tsx @@ -21,7 +21,7 @@ const HubPageLayout = ({ children }: { children: React.ReactNode }) => { const { toolList, selectedTool, selectedFilter, userOrg } = useNav(repositories); - let isOwner = userId && insight && `${userId}` === `${insight.user_id}` ? true : false; + let isOwner = !!(userId && insight && `${userId}` === `${insight.user_id}`); return ( <> diff --git a/lib/hooks/api/useContributorPullRequests.ts b/lib/hooks/api/useContributorPullRequests.ts new file mode 100644 index 0000000000..8f34507b4e --- /dev/null +++ b/lib/hooks/api/useContributorPullRequests.ts @@ -0,0 +1,47 @@ +import useSWR, { Fetcher } from "swr"; +import { useRouter } from "next/router"; + +import publicApiFetcher from "lib/utils/public-api-fetcher"; +import getFilterQuery from "lib/utils/get-filter-query"; + +interface PaginatedResponse { + readonly data: DbRepoPR[]; + readonly meta: Meta; +} + +const useContributorPullRequests = (contributor: string, topic: string, repoIds: number[] = [], limit = 8) => { + const router = useRouter(); + const { selectedFilter } = router.query; + const filterQuery = getFilterQuery(selectedFilter); + const query = new URLSearchParams(filterQuery); + + if (Number.isNaN(Number(topic)) && topic !== "*") { + query.set("topic", topic); + } + + if (limit) { + query.set("limit", `${limit}`); + } + + if (repoIds?.length > 0) { + query.set("repoIds", repoIds.join(",")); + } + + const baseEndpoint = `users/${contributor}/prs`; + const endpointString = `${baseEndpoint}?${query.toString()}`; + + const { data, error, mutate } = useSWR( + contributor ? endpointString : null, + publicApiFetcher as Fetcher + ); + + return { + data: data?.data ?? [], + meta: data?.meta ?? { itemCount: 0, limit: 0, page: 0, hasNextPage: false, hasPreviousPage: false, pageCount: 0 }, + isLoading: !error && !data, + isError: !!error, + mutate + }; +}; + +export default useContributorPullRequests; diff --git a/lib/hooks/api/useContributors.ts b/lib/hooks/api/useContributors.ts new file mode 100644 index 0000000000..694ed25bcc --- /dev/null +++ b/lib/hooks/api/useContributors.ts @@ -0,0 +1,43 @@ +import { useState } from "react"; +import useSWR, { Fetcher } from "swr"; +import publicApiFetcher from "lib/utils/public-api-fetcher"; + +interface PaginatedResponse { + readonly data: GhUser[]; + readonly meta: Meta; +} + +const useContributors = () => { + const [page, setPage] = useState(1); + const [limit, setLimit] = useState(10); + const query = new URLSearchParams(); + + if (page) { + query.set("page", `${page}`); + } + + if (limit) { + query.set("limit", `${limit}`); + } + + const baseEndpoint = "users/list"; + const endpointString = `${baseEndpoint}?${query}`; + + const { data, error, mutate } = useSWR( + endpointString, + publicApiFetcher as Fetcher + ); + + return { + data: data?.data ?? [], + meta: data?.meta ?? { itemCount: 0, limit: 0, page: 0, hasNextPage: false, hasPreviousPage: false, pageCount: 0 }, + isLoading: !error && !data, + isError: !!error, + mutate, + page, + setPage, + setLimit + }; +}; + +export default useContributors; diff --git a/lib/hooks/api/usePullRequests.ts b/lib/hooks/api/usePullRequests.ts new file mode 100644 index 0000000000..30a4f008bd --- /dev/null +++ b/lib/hooks/api/usePullRequests.ts @@ -0,0 +1,56 @@ +import { useState } from "react"; +import useSWR, { Fetcher } from "swr"; +import { useRouter } from "next/router"; + +import publicApiFetcher from "lib/utils/public-api-fetcher"; +import getFilterQuery from "lib/utils/get-filter-query"; + +interface PaginatedResponse { + readonly data: DbRepoPR[]; + readonly meta: Meta; +} + +const usePullRequests = (limit = 1000, repoIds: number[] = []) => { + const router = useRouter(); + const [page, setPage] = useState(1); + const { filterName, selectedFilter } = router.query; + const topic = filterName as string; + const filterQuery = getFilterQuery(selectedFilter); + const query = new URLSearchParams(filterQuery); + + if (Number.isNaN(Number(topic))) { + query.set("topic", topic); + } + + if (page) { + query.set("page", `${page}`); + } + + if (limit) { + query.set("limit", `${limit}`); + } + + if (repoIds?.length > 0) { + query.set("repoIds", repoIds.join(",")); + } + + const baseEndpoint = "prs/search"; + const endpointString = `${baseEndpoint}?${query.toString()}`; + + const { data, error, mutate } = useSWR( + endpointString, + publicApiFetcher as Fetcher + ); + + return { + data: data?.data ?? [], + meta: data?.meta ?? { itemCount: 0, limit: 0, page: 0, hasNextPage: false, hasPreviousPage: false, pageCount: 0 }, + isLoading: !error && !data, + isError: !!error, + mutate, + page, + setPage + }; +}; + +export default usePullRequests; diff --git a/lib/utils/get-filter-query.ts b/lib/utils/get-filter-query.ts index 72fefabfe9..d5597ec4a9 100644 --- a/lib/utils/get-filter-query.ts +++ b/lib/utils/get-filter-query.ts @@ -1,9 +1,13 @@ const getFilterQuery = (filter: string | string[] | undefined): string => { + const query = new URLSearchParams(); + if (Array.isArray(filter) && filter.length === 2) { - return `&repo=${encodeURIComponent(filter.join("/"))}`; + query.set("repo", filter.join("/")); + } else if (filter) { + query.set("filter", Array.isArray(filter) ? filter[0] : filter); } - return filter ? `&filter=${Array.isArray(filter) ? filter[0] : filter}` : ""; + return `${query}` ? `&${query}` : ""; }; export default getFilterQuery; \ No newline at end of file diff --git a/lib/utils/getTopicThumbnail.ts b/lib/utils/getTopicThumbnail.ts index 132e3e9b11..50a52d27ed 100644 --- a/lib/utils/getTopicThumbnail.ts +++ b/lib/utils/getTopicThumbnail.ts @@ -2,16 +2,17 @@ import javaScript from "img/topic-thumbnails/javascript.svg"; import python from "img/topic-thumbnails/python.svg"; import typeScript from "img/topic-thumbnails/typescript.svg"; import java from "img/topic-thumbnails/java.svg"; -import cSharp from "img/topic-thumbnails/c-sharp.svg"; -import cpp from "img/topic-thumbnails/c-plus.svg"; +import cSharp from "img/topic-thumbnails/csharp.svg"; +import cpp from "img/topic-thumbnails/cpp.svg"; import php from "img/topic-thumbnails/php.svg"; import c from "img/topic-thumbnails/c.svg"; import ruby from "img/topic-thumbnails/ruby.svg"; import ai from "img/topic-thumbnails/ai.svg"; +import go from "img/topic-thumbnails/go.svg"; import ml from "img/topic-thumbnails/machine-learning.svg"; import react from "img/topic-thumbnails/react.svg"; -import golang from "img/topic-thumbnails/golang.svg"; import rust from "img/topic-thumbnails/rust.svg"; + import contextThumbnailImage from "../../img/open-sourced-with-bg-icon.png"; import { interestsType } from "./getInterestOptions"; @@ -29,7 +30,7 @@ const topicThumbnails: Record = { ai: ai, react: react, ml: ml, - golang: golang, + golang: go, rust: rust }; diff --git a/next-types.d.ts b/next-types.d.ts index 798b81e07f..aaa9f6c85f 100644 --- a/next-types.d.ts +++ b/next-types.d.ts @@ -2,9 +2,12 @@ interface DbRepo { readonly id: string; + readonly host_id: string; readonly size: number; readonly stars: number; + readonly issues: number; readonly name: string; + readonly full_name: string; readonly owner: string; readonly prActiveCount: number; readonly openPrsCount?: number; @@ -30,9 +33,11 @@ interface DbRepoPR { readonly filesCount: number; linesCount: number; readonly merged: boolean; - readonly repo_owner: string; - readonly repo_name: string; + readonly full_name: string; readonly number: number; + readonly additions: number; + readonly deletions: number; + readonly changed_files: number; } interface DbRepoCommit { @@ -106,7 +111,8 @@ interface DbUserInsightRepo { readonly id: number; readonly insight_id: number; readonly repo_id: number; - readonly created_at: string; + readonly full_name: string; + readonly created_at?: string; } interface DbUser { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 2f973e4f6e..64d59986d6 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,12 +1,12 @@ { "name": "@open-sauced/insights", - "version": "1.35.0", + "version": "1.36.0-beta.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@open-sauced/insights", - "version": "1.35.0", + "version": "1.36.0-beta.5", "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -48,8 +48,10 @@ "react-hot-toast": "^2.4.0", "react-icons": "^4.7.1", "react-loading-skeleton": "^3.1.0", + "react-schemaorg": "^2.0.0", "react-spring": "^9.6.1", "rooks": "^7.4.4", + "schema-dts": "^1.1.0", "stripe": "^11.8.0", "swr": "^2.0.3", "tailwindcss-radix": "^2.7.0", @@ -29746,6 +29748,19 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" }, + "node_modules/react-schemaorg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/react-schemaorg/-/react-schemaorg-2.0.0.tgz", + "integrity": "sha512-UqciFKA203ewNjn0zC09uYKuJSvMD8L75L1s/cW4rc7cS64w8l7vaI3SYkuoI/nwCBkJRmOkSJedWDUZBlYZwg==", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "react": ">=16.3.0", + "schema-dts": ">=0.7.4", + "typescript": ">=3.1.6" + } + }, "node_modules/react-sizeme": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/react-sizeme/-/react-sizeme-3.0.2.tgz", @@ -31000,6 +31015,14 @@ "loose-envify": "^1.1.0" } }, + "node_modules/schema-dts": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/schema-dts/-/schema-dts-1.1.2.tgz", + "integrity": "sha512-MpNwH0dZJHinVxk9bT8XUdjKTxMYrA5bLtrrGmFA6PTLwlOKnhi67XoRd6/ty+Djt6ZC0slR57qFhZDNMI6DhQ==", + "peerDependencies": { + "typescript": ">=4.1.0" + } + }, "node_modules/schema-utils": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", diff --git a/package.json b/package.json index 75134b6858..b13e06616a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "@open-sauced/insights", "description": "πŸ•The dashboard for open source discovery.", "keywords": [], - "version": "1.35.0", + "version": "1.36.0-beta.5", "author": "TED Vortex ", "private": true, "license": "MIT", @@ -82,7 +82,9 @@ "react-hot-toast": "^2.4.0", "react-icons": "^4.7.1", "react-loading-skeleton": "^3.1.0", + "react-schemaorg": "^2.0.0", "react-spring": "^9.6.1", + "schema-dts": "^1.1.0", "rooks": "^7.4.4", "stripe": "^11.8.0", "swr": "^2.0.3", diff --git a/pages/[filterName]/index.tsx b/pages/[filterName]/index.tsx index 1645f09fb9..90659cf14c 100644 --- a/pages/[filterName]/index.tsx +++ b/pages/[filterName]/index.tsx @@ -4,12 +4,12 @@ import Loader from "components/templates/Loader/loader"; const Filter: React.FC = () => { const router = useRouter(); - + const { filterName: topic } = router.query; useEffect(() => { if (topic) { - router.push(`${topic}/dashboard/filter/recent`); + router.push(`${topic}/dashboard/filter/recent`).then(() => {}); } }, [router, topic]); @@ -18,4 +18,4 @@ const Filter: React.FC = () => { ); }; -export default Filter; \ No newline at end of file +export default Filter; diff --git a/pages/[filterName]/insights/index.tsx b/pages/[filterName]/insights/index.tsx index dfbcb799e2..07ededf64d 100644 --- a/pages/[filterName]/insights/index.tsx +++ b/pages/[filterName]/insights/index.tsx @@ -16,6 +16,7 @@ import useUserInsights from "lib/hooks/useUserInsights"; import useSupabaseAuth from "lib/hooks/useSupabaseAuth"; import { supabase } from "lib/utils/supabase"; import useSession from "lib/hooks/useSession"; +import Text from "components/atoms/Typography/text"; const InsightsHub: WithPageLayout = () => { const { data: insightsData, meta: insightsMeta, isError, isLoading, page, setPage } = useUserInsights(); @@ -29,23 +30,30 @@ const InsightsHub: WithPageLayout = () => { const currentUser = await supabase.auth.getSession(); if (!currentUser?.data?.session || onboarded === false) { - router.push("/"); + await router.push("/"); } } catch (e: unknown) { router.push("/"); } } - getUser(); + getUser() + .catch(console.error) + .then(() => {}); }, [router, onboarded]); return user && onboarded ? (
-
- - Your Pages - -
+
+
+ + Insights + + + Welcome to your Insights Hub! Here, you can set up pages to view all of your insights or other open source insights in one place. + +
+
{/* Search box temporarily hidden */}
@@ -74,14 +82,12 @@ const InsightsHub: WithPageLayout = () => { Create a new Insight Page -
- +
+ { } const userId = session?.user?.user_metadata.sub as string; - const isOwner = userId && insight && `${userId}` === `${insight.user_id}` ? true : false; + const isOwner = !!(userId && insight && `${userId}` === `${insight.user_id}`); if (insight && !insight.is_public && !isOwner) { return { diff --git a/pages/user/[username]/index.tsx b/pages/user/[username]/index.tsx index fb5d56af69..8c8af769eb 100644 --- a/pages/user/[username]/index.tsx +++ b/pages/user/[username]/index.tsx @@ -7,8 +7,11 @@ import { ContributorsProfileType } from "components/molecules/ContributorHoverCa import ProfileLayout from "layouts/profile"; import { useFetchUser } from "lib/hooks/useFetchUser"; +import Head from "next/head"; import { WithPageLayout } from "interfaces/with-page-layout"; import { useEffect } from "react"; +import { Person } from "schema-dts"; +import { jsonLdScriptProps } from "react-schemaorg"; const Contributor: WithPageLayout = () => { const router = useRouter(); @@ -37,23 +40,39 @@ const Contributor: WithPageLayout = () => { }, [contributorLogin, user?.bio, profile.githubAvatar]); return ( -
- -
+ <> + + {user &&