From add5abd24aeb749e669ec0d14eb5b487586d3691 Mon Sep 17 00:00:00 2001 From: Zakaria Mansouri Date: Sat, 18 Jan 2025 18:38:36 +0100 Subject: [PATCH 1/2] remove milestone-related types, actions, and components from the codebase --- api/src/app/endpoints.ts | 4 -- api/src/app/index.ts | 2 - api/src/github/service.ts | 16 ----- api/src/github/types.ts | 22 ------ api/src/milestone/controller.ts | 60 ---------------- api/src/milestone/types.ts | 6 -- packages/models/src/milestone/index.ts | 13 ---- web/src/components/locale/dictionary.ts | 8 --- web/src/pages/landing/index.tsx | 91 ------------------------- web/src/redux/actions/milestones.ts | 18 ----- web/src/redux/slices/landing-page.ts | 21 ------ web/src/redux/store.tsx | 2 - 12 files changed, 263 deletions(-) delete mode 100644 api/src/milestone/controller.ts delete mode 100644 api/src/milestone/types.ts delete mode 100644 packages/models/src/milestone/index.ts delete mode 100644 web/src/redux/actions/milestones.ts delete mode 100644 web/src/redux/slices/landing-page.ts diff --git a/api/src/app/endpoints.ts b/api/src/app/endpoints.ts index efe0b530a..8838fbe9e 100644 --- a/api/src/app/endpoints.ts +++ b/api/src/app/endpoints.ts @@ -10,7 +10,6 @@ import { GetContributorsForSitemapResponse, GetContributorsResponse, } from "src/contributor/types"; -import { GetMilestonesResponse } from "src/milestone/types"; import { GetProjectNameResponse, GetProjectResponse, @@ -63,9 +62,6 @@ export interface Endpoints { response: GetContributorNameResponse; params: { id: string }; }; - "api:milestones/dzcode": { - response: GetMilestonesResponse; - }; "api:search": { response: SearchResponse; query: [["query", string], ["limit", number]]; diff --git a/api/src/app/index.ts b/api/src/app/index.ts index e603ed32b..b3c1da8e2 100644 --- a/api/src/app/index.ts +++ b/api/src/app/index.ts @@ -14,7 +14,6 @@ import { DigestCron } from "src/digest/cron"; import { GithubController } from "src/github/controller"; import { LoggerMiddleware } from "./middlewares/logger"; import { LoggerService } from "src/logger/service"; -import { MilestoneController } from "src/milestone/controller"; import { PostgresService } from "src/postgres/service"; import { ProjectController } from "src/project/controller"; import { RobotsController } from "./middlewares/robots"; @@ -46,7 +45,6 @@ useContainer(Container); // eslint-disable-line react-hooks/rules-of-hooks controllers: [ ContributionController, GithubController, - MilestoneController, ProjectController, ContributorController, RobotsController, diff --git a/api/src/github/service.ts b/api/src/github/service.ts index 04d9ce900..59fb6f8e9 100644 --- a/api/src/github/service.ts +++ b/api/src/github/service.ts @@ -8,8 +8,6 @@ import { GetRepositoryIssuesResponse, GetRepositoryResponse, GetUserInput, - GitHubListRepositoryMilestonesInput, - GithubMilestone, GitHubRateLimitApiResponse, GitHubUserApiResponse, ListRepositoryContributorsResponse, @@ -88,20 +86,6 @@ export class GithubService { }; }; - public listRepositoryMilestones = async ({ - owner, - repository, - }: GitHubListRepositoryMilestonesInput): Promise => { - const milestones = await this.fetchService.get( - `${this.apiURL}/repos/${owner}/${repository}/milestones`, - { - headers: this.githubToken ? { Authorization: `Token ${this.githubToken}` } : {}, - params: { state: "all", per_page: 100 }, - }, - ); - return milestones; - }; - private githubToken = this.configService.env().GITHUB_TOKEN; private apiURL = "https://api.github.com"; } diff --git a/api/src/github/types.ts b/api/src/github/types.ts index 8548718ff..bd88c484e 100644 --- a/api/src/github/types.ts +++ b/api/src/github/types.ts @@ -30,28 +30,6 @@ export interface GetRepositoryInput { owner: string; repo: string; } - -interface GitHubListRepositoryIssuesInput { - owner: string; - repository: string; -} - -export type GitHubListRepositoryMilestonesInput = GitHubListRepositoryIssuesInput; - -export interface GithubMilestone { - html_url: string; - number: number; - title: string; - description: string; - state: "closed" | "open"; - open_issues: number; - closed_issues: number; - created_at: string; - updated_at: string; - closed_at: string | null; - due_on: string | null; -} - export interface GitHubRateLimitApiResponse { resources: { core: { diff --git a/api/src/milestone/controller.ts b/api/src/milestone/controller.ts deleted file mode 100644 index fa1bd1c6c..000000000 --- a/api/src/milestone/controller.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { Controller, Get } from "routing-controllers"; -import { GithubService } from "src/github/service"; -import { Service } from "typedi"; - -import { GetMilestonesResponse } from "./types"; - -@Service() -@Controller("/milestones") -export class MilestoneController { - constructor(private readonly githubService: GithubService) {} - - @Get("/dzcode") - public async getMilestones(): Promise { - const githubMilestones = await this.githubService.listRepositoryMilestones({ - owner: "dzcode-io", - repository: "dzcode.io", - }); - return { - milestones: githubMilestones - .sort((a, b) => { - if (b.state !== a.state) { - return b.state === "closed" ? 1 : -1; - } - if (a.state === "closed") { - return ( - new Date(a.due_on || a.closed_at || "").getTime() - - new Date(b.due_on || b.closed_at || "").getTime() - ); - } - if (a.state === "open") { - return ( - new Date(a.due_on || a.created_at || "").getTime() - - new Date(b.due_on || b.closed_at || "").getTime() - ); - } - return 0; - }) - .map((githubMilestone, githubMilestoneIndex) => ({ - id: `${githubMilestone.number}`, - title: githubMilestone.title, - description: githubMilestone.description, - url: githubMilestone.html_url, - status: - (!githubMilestones[githubMilestoneIndex - 1] || - githubMilestones[githubMilestoneIndex - 1].state === "closed") && - githubMilestone.state === "open" - ? "in-progress" - : githubMilestone.state, - closedIssuesCount: githubMilestone.closed_issues, - openIssuesCount: githubMilestone.open_issues, - createdAt: githubMilestone.created_at, - closedAt: - (githubMilestone.state === "closed" && githubMilestone.due_on) || - githubMilestone.closed_at || - undefined, - dueAt: githubMilestone.due_on || undefined, - })), - }; - } -} diff --git a/api/src/milestone/types.ts b/api/src/milestone/types.ts deleted file mode 100644 index 919ba7699..000000000 --- a/api/src/milestone/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { MilestoneEntity } from "@dzcode.io/models/dist/milestone"; -import { GeneralResponse } from "src/app/types"; - -export interface GetMilestonesResponse extends GeneralResponse { - milestones: MilestoneEntity[]; -} diff --git a/packages/models/src/milestone/index.ts b/packages/models/src/milestone/index.ts deleted file mode 100644 index 8878a3b72..000000000 --- a/packages/models/src/milestone/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// TODO-ZM: digest this to database later (then extends BaseEntity) -export interface MilestoneEntity { - id: string; - title: string; - description: string; - url: string; - openIssuesCount: number; - closedIssuesCount: number; - status: "open" | "closed" | "in-progress"; - createdAt: string; - dueAt?: string; - closedAt?: string; -} diff --git a/web/src/components/locale/dictionary.ts b/web/src/components/locale/dictionary.ts index e52f732f5..24707b9c9 100644 --- a/web/src/components/locale/dictionary.ts +++ b/web/src/components/locale/dictionary.ts @@ -175,14 +175,6 @@ Besides the open tasks on [/contribute](/contribute) page, you can also contribu en: "Make a Contribution", ar: "قدم مساهمة", }, - "landing-milestones-title": { - en: "Project roadmap", - ar: "خارطة طريق المشروع", - }, - "landing-milestones-subtitle": { - en: "See how and when new features are released and share your ideas and feedback to help us better shape dzcode roadmap", - ar: "تعرف على كيفية ووقت إصدار الميزات الجديدة وشارك بأفكارك وملاحظاتك لمساعدتنا في تشكيل خارطة طريق dzcode بشكل أفضل", - }, "team-title": { en: "Meet the team! | DzCode i/o", ar: "تعرّف على الفريق! | DzCode i / o", diff --git a/web/src/pages/landing/index.tsx b/web/src/pages/landing/index.tsx index 02cfad03e..9c699c95b 100644 --- a/web/src/pages/landing/index.tsx +++ b/web/src/pages/landing/index.tsx @@ -1,23 +1,11 @@ -import { useEffect } from "react"; import { Helmet } from "react-helmet-async"; import { Link } from "src/components/link"; -import { Loading } from "src/components/loading"; import { Locale, useLocale } from "src/components/locale"; -import { Markdown } from "src/components/markdown"; -import { TryAgain } from "src/components/try-again"; -import { fetchMilestonesListAction } from "src/redux/actions/milestones"; -import { useAppDispatch, useAppSelector } from "src/redux/store"; import React from "react"; // ts-prune-ignore-next export default function Page(): JSX.Element { const { localize } = useLocale(); - const { milestones } = useAppSelector((state) => state.landingPage); - const dispatch = useAppDispatch(); - - useEffect(() => { - dispatch(fetchMilestonesListAction()); - }, [dispatch]); return (
@@ -45,85 +33,6 @@ export default function Page(): JSX.Element { - -
-

- -

-

- -

- -
- {milestones === "ERROR" ? ( - { - dispatch(fetchMilestonesListAction()); - }} - /> - ) : milestones === null ? ( - - ) : ( -
-
    - {milestones.map((milestone, milestoneIndex) => { - const isEven = milestoneIndex % 2 === 0; - - return ( -
  • -
    -
    -

    {milestone.title}

    -

    - -

    -
    -
    - {milestone.closedAt ? ( - - - - ) : ( - - - - )} -
    -
    -
  • - ); - })} -
-
- )} -
-
); } diff --git a/web/src/redux/actions/milestones.ts b/web/src/redux/actions/milestones.ts deleted file mode 100644 index 09d9d0c32..000000000 --- a/web/src/redux/actions/milestones.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { Action, ThunkAction } from "@reduxjs/toolkit"; -import { captureException } from "@sentry/react"; -import { landingPageSlice } from "src/redux/slices/landing-page"; -import { AppState } from "src/redux/store"; -import { fetchV2 } from "src/utils/fetch"; - -export const fetchMilestonesListAction = - (): ThunkAction => async (dispatch, getState) => { - try { - if (getState().landingPage.milestones === "ERROR") - dispatch(landingPageSlice.actions.set({ milestones: null })); - const { milestones } = await fetchV2("api:milestones/dzcode", {}); - dispatch(landingPageSlice.actions.set({ milestones })); - } catch (error) { - dispatch(landingPageSlice.actions.set({ milestones: "ERROR" })); - captureException(error, { tags: { type: "WEB_FETCH" } }); - } - }; diff --git a/web/src/redux/slices/landing-page.ts b/web/src/redux/slices/landing-page.ts deleted file mode 100644 index 066c7e340..000000000 --- a/web/src/redux/slices/landing-page.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { GetMilestonesResponse } from "@dzcode.io/api/dist/milestone/types"; -import { createSlice } from "@reduxjs/toolkit"; -import { setReducerFactory } from "src/redux/utils"; -import { Loadable } from "src/utils/loadable"; - -// ts-prune-ignore-next -export interface LandingPageState { - milestones: Loadable; -} - -const initialState: LandingPageState = { - milestones: null, -}; - -export const landingPageSlice = createSlice({ - name: "landing-page", - initialState, - reducers: { - set: setReducerFactory(), - }, -}); diff --git a/web/src/redux/store.tsx b/web/src/redux/store.tsx index 0fd35902a..87a7e930e 100644 --- a/web/src/redux/store.tsx +++ b/web/src/redux/store.tsx @@ -6,7 +6,6 @@ import { Provider as ReduxProvider, useDispatch, useSelector } from "react-redux import { contributionsPageSlice } from "./slices/contributions-page"; import { contributionPageSlice } from "./slices/contribution-page"; import { contributorsPageSlice } from "./slices/contributors-page"; -import { landingPageSlice } from "./slices/landing-page"; import { projectsPageSlice } from "./slices/projects-page"; import { settingsSlice } from "./slices/settings"; import { projectPageSlice } from "./slices/project-page"; @@ -22,7 +21,6 @@ const makeAppStore = () => { contributorPage: contributorPageSlice.reducer, contributionsPage: contributionsPageSlice.reducer, contributionPage: contributionPageSlice.reducer, - landingPage: landingPageSlice.reducer, }, }); }; From efe9a0ca1172937c88b1f836a9f8d19a86991433 Mon Sep 17 00:00:00 2001 From: Zakaria Mansouri Date: Sat, 18 Jan 2025 19:07:10 +0100 Subject: [PATCH 2/2] add whitespace-nowrap class to tab elements in TopBar component --- web/src/components/top-bar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/components/top-bar.tsx b/web/src/components/top-bar.tsx index cccaabce2..3d295686c 100644 --- a/web/src/components/top-bar.tsx +++ b/web/src/components/top-bar.tsx @@ -152,7 +152,7 @@ export function TopBar({ version, links }: TopBarProps): JSX.Element { href={href} key={index} role="tab" - className={`tab ${activeIndex === index ? "tab-active" : ""}`} + className={`whitespace-nowrap tab ${activeIndex === index ? "tab-active" : ""}`} data-testid={`top-bar-to:${href}`} >