Skip to content

Commit

Permalink
feat: top level projects in explore
Browse files Browse the repository at this point in the history
  • Loading branch information
awinogradov committed Apr 25, 2023
1 parent d4e56cf commit a5c5a38
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 3 deletions.
37 changes: 37 additions & 0 deletions graphql/resolvers/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,43 @@ export const query = (t: ObjectDefinitionBlock<'Query'>) => {
},
});

t.list.field('topProjects', {
type: Project,
resolve: async (_, __, { db, activity }) => {
if (!activity) return null;

const allProjects = await db.project.findMany({
orderBy: {
createdAt: 'asc',
},
include: {
activity: {
include: {
user: true,
ghost: true,
},
},
children: true,
parent: true,
_count: {
select: {
parent: true,
},
},
},
});

if (!allProjects.length) return [];

// FIX: it is hack!
const projects = allProjects.filter((p) => p._count.parent === 0);

if (!projects.length) return [];

return projects;
},
});

t.field('project', {
type: Project,
args: {
Expand Down
2 changes: 2 additions & 0 deletions graphql/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,7 @@ type Project {

type ProjectAggregation {
children: Int
parent: Int
participants: Int
stargizers: Int
watchers: Int
Expand Down Expand Up @@ -333,6 +334,7 @@ type Query {
projects: [Project]
settings: Settings
tagCompletion(query: String!, sortBy: SortOrder): [Tag]
topProjects: [Project]
userFilters: [Filter]
userGoals(data: UserGoalsInput!): UserGoalsOutput
users(sortBy: SortOrder): [User]
Expand Down
1 change: 1 addition & 0 deletions graphql/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ export const Project = objectType({
export const ProjectAggregation = objectType({
name: 'ProjectAggregation',
definition(t) {
t.int('parent');
t.int('children');
t.int('stargizers');
t.int('watchers');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"Goals": "Goals",
"Projects": "Projects",
"Explore": "Explore",
"See what the Taskany community is most excited about today": "See what the Taskany community is most excited about today"
"See what the Taskany community is most excited about today": "See what the Taskany community is most excited about today",
"Top": "Top"
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"Goals": "Цели",
"Projects": "Проекты",
"Explore": "Обзор",
"See what the Taskany community is most excited about today": "Смотри, чем пользователи Taskany интересуются сегодня"
"See what the Taskany community is most excited about today": "Смотри, чем пользователи Taskany интересуются сегодня",
"Top": "Топ"
}
1 change: 1 addition & 0 deletions src/components/ExplorePageLayout/ExplorePageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const ExplorePageLayout: React.FC<ExplorePageLayoutProps> = ({ children }
const router = useRouter();

const tabsMenuOptions: Array<[string, string]> = [
[tr('Top'), routes.exploreTopProjects()],
[tr('Projects'), routes.exploreProjects()],
// [tr('Goals'), routes.exploreGoals()],
];
Expand Down
2 changes: 1 addition & 1 deletion src/components/PageHeader/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const PageHeader: FC = () => {
// title: t('Boards'),
// },
{
href: routes.exploreProjects(),
href: routes.exploreTopProjects(),
title: tr('Explore'),
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "Taskany — Explore — Projects"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/* eslint-disable */
// Do not edit, use generator to update
import { i18n, fmt, I18nLangSet } from 'easy-typed-intl';
import getLang from '../../../../utils/getLang';

import ru from './ru.json';
import en from './en.json';

export type I18nKey = keyof typeof ru & keyof typeof en;
type I18nLang = 'ru' | 'en';

const keyset: I18nLangSet<I18nKey> = {};

keyset['ru'] = ru;
keyset['en'] = en;

export const tr = i18n<I18nLang, I18nKey>(keyset, fmt, getLang);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"title": "Taskany — Обзор — Проекты"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import useSWR from 'swr';
import { nullable } from '@taskany/bricks';

import { Project } from '../../../../graphql/@generated/genql';
import { createFetcher, refreshInterval } from '../../../utils/createFetcher';
import { declareSsrProps, ExternalPageProps } from '../../../utils/declareSsrProps';
import { routes } from '../../../hooks/router';
import { Page, PageContent } from '../../Page';
import { PageSep } from '../../PageSep';
import { ExplorePageLayout } from '../../ExplorePageLayout/ExplorePageLayout';
import { ProjectListItem } from '../../ProjectListItem';

import { tr } from './ExploreTopProjectsPage.i18n';

const fetcher = createFetcher(() => ({
topProjects: {
id: true,
title: true,
description: true,
createdAt: true,
activity: {
user: {
id: true,
name: true,
email: true,
image: true,
},
ghost: {
id: true,
email: true,
},
},
},
}));

export const getServerSideProps = declareSsrProps(
async ({ user }) => ({
fallback: {
'explore/projects': await fetcher(user),
},
}),
{
private: true,
},
);

export const ExploreTopProjectsPage = ({
user,
locale,
ssrTime,
fallback,
}: ExternalPageProps<Awaited<ReturnType<typeof fetcher>>>) => {
const { data } = useSWR('explore/projects', () => fetcher(user), {
fallback,
refreshInterval,
});
const projects = data?.topProjects;

return (
<Page user={user} locale={locale} ssrTime={ssrTime} title={tr('title')}>
<ExplorePageLayout>
<PageSep />

<PageContent>
{projects?.map((project: Project) =>
nullable(project, (p) => (
<ProjectListItem
key={p.id}
href={routes.project(p.id)}
createdAt={p.createdAt}
title={p.title}
description={p.description}
activity={p.activity}
/>
)),
)}
</PageContent>
</ExplorePageLayout>
</Page>
);
};
2 changes: 2 additions & 0 deletions src/hooks/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const routes = {
userSettings: () => '/users/settings',

exploreProjects: () => '/explore/projects',
exploreTopProjects: () => '/explore/top',
exploreGoals: () => '/explore/goals',

help: (locale: TLocale, slug: AvailableHelpPages) => `/help/${locale}/${slug}`,
Expand All @@ -38,6 +39,7 @@ export const useRouter = (): Record<keyof typeof routes, any> => {
userSettings: () => router.push(routes.userSettings()),

exploreProjects: () => router.push(routes.exploreProjects()),
exploreTopProjects: () => router.push(routes.exploreTopProjects()),
exploreGoals: () => router.push(routes.exploreGoals()),

help: (locale: TLocale, slug: AvailableHelpPages) => router.push(locale, slug),
Expand Down
5 changes: 5 additions & 0 deletions src/pages/explore/top.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { ExploreTopProjectsPage } from '../../components/pages/ExploreTopProjectsPage/ExploreTopProjectsPage';

export { getServerSideProps } from '../../components/pages/ExploreTopProjectsPage/ExploreTopProjectsPage';

export default ExploreTopProjectsPage;

0 comments on commit a5c5a38

Please sign in to comment.