diff --git a/apps/frontend/src/components/analytics/analytics.component.tsx b/apps/frontend/src/components/analytics/analytics.component.tsx
index 210c09f9..17e9435a 100644
--- a/apps/frontend/src/components/analytics/analytics.component.tsx
+++ b/apps/frontend/src/components/analytics/analytics.component.tsx
@@ -6,29 +6,14 @@ import { StarsTableComponent } from '@gitroom/frontend/components/analytics/star
import useSWR from 'swr';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { LoadingComponent } from '@gitroom/frontend/components/layout/loading';
-import clsx from 'clsx';
-import { useStateCallback } from '@gitroom/react/helpers/use.state.callback';
export const AnalyticsComponent: FC = () => {
const fetch = useFetch();
- const [page, setPage] = useStateCallback(1);
const load = useCallback(async (path: string) => {
return await (await fetch(path)).json();
}, []);
- const starsCallback = useCallback(
- async (path: string) => {
- return await (
- await fetch(path, {
- body: JSON.stringify({ page }),
- method: 'POST',
- })
- ).json();
- },
- [page]
- );
-
const { isLoading: isLoadingAnalytics, data: analytics } = useSWR(
'/analytics',
load
@@ -37,83 +22,16 @@ export const AnalyticsComponent: FC = () => {
'/analytics/trending',
load
);
- const {
- isLoading: isLoadingStars,
- data: stars,
- mutate,
- } = useSWR('/analytics/stars', starsCallback);
- const changePage = useCallback(
- (type: 'increase' | 'decrease') => () => {
- setPage(type === 'increase' ? page + 1 : page - 1, () => mutate());
- },
- [page, mutate]
- );
-
- if (isLoadingAnalytics || isLoadingTrending || isLoadingStars) {
+ if (isLoadingAnalytics || isLoadingTrending) {
return ;
}
return (
-
-
-
-
- {stars?.stars?.length ? (
-
- ) : (
-
- Load your GitHub repository from settings to see analytics
-
- )}
-
-
+
+
{/*
*/}
{/*
News Feed
*/}
diff --git a/apps/frontend/src/components/analytics/stars.and.forks.interface.ts b/apps/frontend/src/components/analytics/stars.and.forks.interface.ts
index ad380707..3360f3c9 100644
--- a/apps/frontend/src/components/analytics/stars.and.forks.interface.ts
+++ b/apps/frontend/src/components/analytics/stars.and.forks.interface.ts
@@ -19,5 +19,4 @@ export interface StarsAndForksInterface {
last: string;
predictions: string;
};
- stars: Stars[];
}
\ No newline at end of file
diff --git a/apps/frontend/src/components/analytics/stars.table.component.tsx b/apps/frontend/src/components/analytics/stars.table.component.tsx
index 36c5e23a..4af67f70 100644
--- a/apps/frontend/src/components/analytics/stars.table.component.tsx
+++ b/apps/frontend/src/components/analytics/stars.table.component.tsx
@@ -1,30 +1,231 @@
-import {FC} from "react";
-import {Stars} from "@gitroom/frontend/components/analytics/stars.and.forks.interface";
-import {UtcToLocalDateRender} from "../../../../../libraries/react-shared-libraries/src/helpers/utc.date.render";
+import { FC, useCallback, useEffect, useMemo } from 'react';
+import { UtcToLocalDateRender } from '@gitroom/react/helpers/utc.date.render';
+import { Button } from '@gitroom/react/form/button';
+import dayjs from 'dayjs';
+import Link from 'next/link';
+import { useRouter, useSearchParams } from 'next/navigation';
+import useSWR from 'swr';
+import clsx from 'clsx';
+import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
-export const StarsTableComponent: FC<{stars: Stars[]}> = (props) => {
- const {stars} = props;
- return (
-
+export const UpDown: FC<{ name: string; param: string }> = (props) => {
+ const { name, param } = props;
+ const router = useRouter();
+ const searchParams = useSearchParams();
+
+ const state = useMemo(() => {
+ const newName = searchParams.get('key');
+ const newState = searchParams.get('state');
+
+ if (newName != param) {
+ return 'none';
+ }
+
+ return newState as 'asc' | 'desc';
+ }, [searchParams, name, param]);
+
+ const changeStateUrl = useCallback(
+ (newState: string) => {
+ const query =
+ newState === 'none' ? `` : `?key=${param}&state=${newState}`;
+ router.replace(`/analytics${query}`);
+ },
+ [state, param]
+ );
+
+ const changeState = useCallback(() => {
+ changeStateUrl(
+ state === 'none' ? 'desc' : state === 'desc' ? 'asc' : 'none'
+ );
+ }, [state, param]);
+
+ return (
+
+
{name}
+
+ {['none', 'asc'].indexOf(state) > -1 && (
+
+ )}
+ {['none', 'desc'].indexOf(state) > -1 && (
+
+ )}
+
+
+ );
+};
+
+export const StarsTableComponent = () => {
+ const fetch = useFetch();
+ const router = useRouter();
+ const searchParams = useSearchParams();
+ const page = +(searchParams.get('page') || 1);
+
+ const starsCallback = useCallback(
+ async (path: string) => {
+ const key = searchParams.get('key');
+ const state = searchParams.get('state');
+ const page = +(searchParams.get('page') || 1);
+
+ return await (
+ await fetch(path, {
+ body: JSON.stringify({
+ page,
+ ...(key && state ? { key, state } : {}),
+ }),
+ method: 'POST',
+ })
+ ).json();
+ },
+ [searchParams]
+ );
+
+ const {
+ isLoading: isLoadingStars,
+ data: stars,
+ mutate,
+ } = useSWR('/analytics/stars', starsCallback, {
+ revalidateOnMount: false,
+ });
+
+ useEffect(() => {
+ mutate();
+ }, [searchParams]);
+
+ const renderMediaLink = useCallback((date: string) => {
+ const local = dayjs.utc(date).local();
+ const weekNumber = local.isoWeek();
+ const year = local.year();
+ return `/launches?week=${weekNumber}&year=${year}`;
+ }, []);
+
+ const changePage = useCallback(
+ (type: 'increase' | 'decrease') => () => {
+ const key = searchParams.get('key');
+ const state = searchParams.get('state');
+ const page = +(searchParams.get('page') || 1);
+
+ const newPage = type === 'increase' ? page + 1 : page - 1;
+ const keyAndState = key && state ? `&key=${key}&state=${state}` : '';
+ router.replace(`/analytics?page=${newPage}${keyAndState}`, {
+ forceOptimisticNavigation: false,
+ });
+ },
+ [searchParams]
+ );
+
+ return (
+
+
+
+ {stars?.stars?.length ? (
+
-
- | Repository |
- Date |
- Total |
- Stars |
+
+ |
+
+ |
+
+
+ |
+
+
+ |
+
+
+ |
Media |
-
+
- {stars.map(p => (
- | {p.login} |
- |
- {p.totalStars} |
- {p.stars} |
- Media |
+ {stars?.stars?.map((p: any) => (
+
+ | {p.login} |
+
+
+ |
+ {p.totalStars} |
+ {p.stars} |
+
+
+
+
+ |
- ))}
+ ))}
-
- )
-}
\ No newline at end of file
+
+ ) : (
+
+ Load your GitHub repository from settings to see analytics
+
+ )}
+
+
+ );
+};
diff --git a/apps/frontend/src/components/billing/no.billing.component.tsx b/apps/frontend/src/components/billing/no.billing.component.tsx
index 1aec28ea..3b055f0a 100644
--- a/apps/frontend/src/components/billing/no.billing.component.tsx
+++ b/apps/frontend/src/components/billing/no.billing.component.tsx
@@ -12,12 +12,10 @@ import ReactLoading from 'react-loading';
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
import { useToaster } from '@gitroom/react/toaster/toaster';
import dayjs from 'dayjs';
-import utc from 'dayjs/plugin/utc';
import clsx from 'clsx';
import { pricing } from '@gitroom/nestjs-libraries/database/prisma/subscriptions/pricing';
-import {useRouter} from "next/navigation";
-import {FAQComponent} from "@gitroom/frontend/components/billing/faq.component";
-dayjs.extend(utc);
+import { useRouter } from 'next/navigation';
+import { FAQComponent } from '@gitroom/frontend/components/billing/faq.component';
export interface Tiers {
month: Array<{
diff --git a/apps/frontend/src/components/launches/calendar.context.tsx b/apps/frontend/src/components/launches/calendar.context.tsx
index 019db9e3..d7f4dc0c 100644
--- a/apps/frontend/src/components/launches/calendar.context.tsx
+++ b/apps/frontend/src/components/launches/calendar.context.tsx
@@ -1,8 +1,5 @@
'use client';
import 'reflect-metadata';
-import weekOfYear from 'dayjs/plugin/weekOfYear';
-import isoWeek from 'dayjs/plugin/isoWeek';
-import utc from 'dayjs/plugin/utc';
import {
createContext,
@@ -18,10 +15,7 @@ import dayjs from 'dayjs';
import useSWR, { useSWRConfig } from 'swr';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
import { Post, Integration } from '@prisma/client';
-
-dayjs.extend(weekOfYear);
-dayjs.extend(isoWeek);
-dayjs.extend(utc);
+import {useRouter, useSearchParams} from 'next/navigation';
const CalendarContext = createContext({
currentWeek: dayjs().week(),
@@ -49,6 +43,8 @@ export const CalendarWeekProvider: FC<{
const [internalData, setInternalData] = useState([] as any[]);
const [trendings, setTrendings] = useState([]);
const { mutate } = useSWRConfig();
+ const searchParams = useSearchParams();
+ const router = useRouter();
useEffect(() => {
(async () => {
@@ -57,13 +53,16 @@ export const CalendarWeekProvider: FC<{
}, []);
const [filters, setFilters] = useState({
- currentWeek: dayjs().week(),
- currentYear: dayjs().year(),
+ currentWeek: +(searchParams.get('week') || dayjs().week()),
+ currentYear: +(searchParams.get('year') || dayjs().year()),
});
const setFiltersWrapper = useCallback(
(filters: { currentWeek: number; currentYear: number }) => {
setFilters(filters);
+ router.replace(`/launches?week=${filters.currentWeek}&year=${filters.currentYear}`, {
+ forceOptimisticNavigation: false,
+ })
setTimeout(() => {
mutate('/posts');
});
diff --git a/apps/frontend/src/components/launches/calendar.tsx b/apps/frontend/src/components/launches/calendar.tsx
index 4696bb2d..fbfe6d19 100644
--- a/apps/frontend/src/components/launches/calendar.tsx
+++ b/apps/frontend/src/components/launches/calendar.tsx
@@ -6,9 +6,6 @@ import {
useCalendar,
} from '@gitroom/frontend/components/launches/calendar.context';
import dayjs from 'dayjs';
-import isBetween from 'dayjs/plugin/isBetween';
-dayjs.extend(isBetween);
-
import { openModal, useModals } from '@mantine/modals';
import { AddEditModal } from '@gitroom/frontend/components/launches/add.edit.model';
import clsx from 'clsx';
diff --git a/apps/frontend/src/components/layout/layout.settings.tsx b/apps/frontend/src/components/layout/layout.settings.tsx
index e2dbcfa1..ea31a87b 100644
--- a/apps/frontend/src/components/layout/layout.settings.tsx
+++ b/apps/frontend/src/components/layout/layout.settings.tsx
@@ -16,6 +16,16 @@ import NotificationComponent from '@gitroom/frontend/components/notifications/no
import Link from 'next/link';
import useSWR from 'swr';
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
+import dayjs from "dayjs";
+import utc from "dayjs/plugin/utc";
+import weekOfYear from "dayjs/plugin/weekOfYear";
+import isoWeek from "dayjs/plugin/isoWeek";
+import isBetween from "dayjs/plugin/isBetween";
+
+dayjs.extend(utc);
+dayjs.extend(weekOfYear);
+dayjs.extend(isoWeek);
+dayjs.extend(isBetween);
export const LayoutSettings = ({ children }: { children: ReactNode }) => {
const fetch = useFetch();
diff --git a/libraries/nestjs-libraries/src/database/prisma/stars/stars.repository.ts b/libraries/nestjs-libraries/src/database/prisma/stars/stars.repository.ts
index 0563725b..d3e2bb8c 100644
--- a/libraries/nestjs-libraries/src/database/prisma/stars/stars.repository.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/stars/stars.repository.ts
@@ -130,7 +130,7 @@ export class StarsRepository {
getStarsFilter(githubs: string[], starsFilter: StarsListDto) {
return this._stars.model.star.findMany({
orderBy: {
- [starsFilter.sortBy || 'date']: 'desc'
+ [starsFilter.key || 'date']: starsFilter.state || 'desc'
},
where: {
login: {
diff --git a/libraries/nestjs-libraries/src/dtos/analytics/stars.list.dto.ts b/libraries/nestjs-libraries/src/dtos/analytics/stars.list.dto.ts
index 0cd39e73..cc435f11 100644
--- a/libraries/nestjs-libraries/src/dtos/analytics/stars.list.dto.ts
+++ b/libraries/nestjs-libraries/src/dtos/analytics/stars.list.dto.ts
@@ -6,6 +6,10 @@ export class StarsListDto {
page: number;
@IsOptional()
- @IsIn(['totalStars', 'stars', 'date'])
- sortBy: 'date' | 'stars' | 'totalStars';
+ @IsIn(['login', 'totalStars', 'stars', 'date'])
+ key: 'login' | 'date' | 'stars' | 'totalStars';
+
+ @IsOptional()
+ @IsIn(['desc', 'asc'])
+ state: 'desc' | 'asc';
}
\ No newline at end of file