Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
6502495
build: add necessary form dependencies
hobbescodes Dec 31, 2024
32ca909
refactor(dashboard): enable new project cta
hobbescodes Dec 31, 2024
4071cad
feature(dashboard): set up base for new project dialog
hobbescodes Dec 31, 2024
d2141e1
feature(dashboard): set up base for new project dialog
hobbescodes Dec 31, 2024
37c43e6
refactor(new-project): add select component for organization selection
hobbescodes Dec 31, 2024
88a09c8
refactor(new-project): move select organization label to app.config
hobbescodes Dec 31, 2024
58acf91
feature(new-project): add necessary form inputs
hobbescodes Dec 31, 2024
e108762
feature(new-project): apply form field validation schema
hobbescodes Dec 31, 2024
7027e88
refactor(new-project): update schema validation for project slug
hobbescodes Dec 31, 2024
3ceafbe
Merge branch 'master' into feature/dashboard-mutations
hobbescodes Jan 2, 2025
d80e0e0
feature(graphql): add create project mutation
hobbescodes Jan 2, 2025
9c2dbc1
refactor(graphql): update organizations query
hobbescodes Jan 2, 2025
d57be4a
feature(dashboard): add proper mutation for creating a new project
hobbescodes Jan 2, 2025
52f45a2
refactor(new-project): add async validation for project slug
hobbescodes Jan 2, 2025
5e2ef46
Merge branch 'master' into feature/dashboard-mutations
hobbescodes Jan 2, 2025
d97eb01
fix(build): update queries to fix build errors due to merge conflicts
hobbescodes Jan 2, 2025
353a24e
refactor: update routing to use org and proj slugs
hobbescodes Jan 3, 2025
9fd9a82
fix(new-project): update create porject payload to include org slug
hobbescodes Jan 3, 2025
73c0f44
feature(dashboard): add dialog for creating a new organization
hobbescodes Jan 3, 2025
4f67fc5
feature(dashboard): add functionality for creating an organization
hobbescodes Jan 3, 2025
4e75558
refactor(dashboard): update responsive design pattern for pinned orgs
hobbescodes Jan 3, 2025
78e4e94
refactor(dashboard): adjust state management for CTAs when there are …
hobbescodes Jan 3, 2025
e6a97be
chore: format
hobbescodes Jan 3, 2025
806512a
refactor: adjust pattern for form submissions
hobbescodes Jan 3, 2025
34d3865
chore: format
hobbescodes Jan 3, 2025
12c2d95
refactor: adjust pattern for FormFieldError
hobbescodes Jan 3, 2025
9c49296
docs: add JSDoc to custom Link component
hobbescodes Jan 3, 2025
2870075
chore: format
hobbescodes Jan 3, 2025
87c4b72
Merge branch 'master' into feature/dashboard-mutations
hobbescodes Jan 4, 2025
410a046
fix: update field level validator for organization name
hobbescodes Jan 4, 2025
c43e78a
build: update to use JSONC formatted lockfile
hobbescodes Jan 4, 2025
5e60c7c
refactor: update auth flow to inject database rowId into the session …
hobbescodes Jan 5, 2025
3697681
chore: format
hobbescodes Jan 5, 2025
8d9c145
chore: add TODO comment regarding augmentation of session object
hobbescodes Jan 5, 2025
8545001
chore: update comment related to onChangeAsync validator
hobbescodes Jan 8, 2025
46a95c0
chore: update comment regarding onChangeAsync validator
hobbescodes Jan 8, 2025
063edcc
refactor(components): use custom link component throughout app
hobbescodes Jan 8, 2025
ec53be2
refactor(config): update placeholder text for form inputs
hobbescodes Jan 8, 2025
d14f964
fix(link): extend props to include html anchor element attributes
hobbescodes Jan 8, 2025
6209095
refactor(link): remove unnecessary children prop override
hobbescodes Jan 8, 2025
ee6a6af
refactor: update slug validations, use custom validation adapter
hobbescodes Jan 9, 2025
6207146
refactor: adjust comments and TODOs, remove web3 dependencies
hobbescodes Jan 10, 2025
7dd59dd
refactor: adjust naming convention for schema validator import, updat…
hobbescodes Jan 10, 2025
845a29a
refactor: adjust casing for schema validator import
hobbescodes Jan 10, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 3 additions & 5 deletions .env.local.template
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
WALLETCONNECT_PROJECT_ID=""

# auth
# Keycloak client secret, ask engineering team for this. It is required for local authentication
AUTH_KEYCLOAK_SECRET=""
# NB: an auth secret can be generated and injected automatically with `npx auth`, see https://cli.authjs.dev
AUTH_SECRET=""

# NB: mocked user ID from locally seeded database.
# TODO: remove once keycloak / hidra are synced with database (https://linear.app/omnidev/issue/OMNI-147/replace-mock-user-id-flow-with-hidra-integration)
NEXT_PUBLIC_MOCK_USER_ID=""
# NB: mocked user HIDRA ID from locally seeded database.
# TODO: remove once keycloak / hidra are synced with database and mock data is no longer needed (https://linear.app/omnidev/issue/OMNI-147/replace-mock-user-id-flow-with-hidra-integration)
NEXT_PUBLIC_MOCK_USER_HIDRA_ID=""
1,865 changes: 1,865 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

Binary file removed bun.lockb
Binary file not shown.
7 changes: 2 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"@graphql-codegen/typescript-operations": "^4.4.0",
"@graphql-codegen/typescript-react-query": "^6.1.0",
"@pandacss/dev": "^0.48.0",
"@types/lodash.merge": "^4.6.9",
"@types/node": "^20.11.19",
"@types/react": "^19.0.2",
"@types/react-dom": "^19.0.2",
Expand All @@ -36,14 +35,13 @@
"dependencies": {
"@ark-ui/react": "^4.4.3",
"@omnidev/sigil": "^0.12.2",
"@rainbow-me/rainbowkit": "^2.2.0",
"@tanstack/react-form": "^0.41.0",
"@tanstack/react-query": "^5.20.5",
"@tanstack/react-query-devtools": "^5.20.5",
"@theme-toggles/react": "^4.1.0",
"dayjs": "^1.11.10",
"graphql": "^16.10.0",
"graphql-request": "^7.1.2",
"lodash.merge": "^4.6.2",
"next": "^15.0.3",
"next-auth": "^5.0.0-beta.25",
"next-themes": "^0.4.3",
Expand All @@ -55,8 +53,7 @@
"recharts": "^2.13.3",
"ts-pattern": "^5.5.0",
"usehooks-ts": "^3.1.0",
"viem": "^2.7.9",
"wagmi": "^2.5.7"
"zod": "^3.24.1"
},
"trustedDependencies": [
"@biomejs/biome",
Expand Down
2 changes: 1 addition & 1 deletion src/app/not-found.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"use client";

import { Button, Text, VStack } from "@omnidev/sigil";
import Link from "next/link";

import { Link } from "components/core";
import { app } from "lib/config";

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@ import type { Metadata } from "next";
export const generateMetadata = async ({
params,
}: Props): Promise<Metadata> => {
const { organizationId } = await params;
const { organizationSlug } = await params;

const { organization } = await sdk.Organization({ rowId: organizationId });
const { organizationBySlug: organization } = await sdk.Organization({
slug: organizationSlug,
});

return {
title: `${organization?.name} | ${app.name}`,
Expand All @@ -24,18 +26,18 @@ export const generateMetadata = async ({

interface Props {
/** Organization page params. */
params: Promise<{ organizationId: string }>;
params: Promise<{ organizationSlug: string }>;
}

/**
* Organization overview page.
*/
const OrganizationPage = async ({ params }: Props) => {
const { organizationId } = await params;
const { organizationSlug } = await params;

const [session, { organization }] = await Promise.all([
const [session, { organizationBySlug: organization }] = await Promise.all([
getAuthSession(),
sdk.Organization({ rowId: organizationId }),
sdk.Organization({ slug: organizationSlug }),
]);

const breadcrumbs = [
Expand All @@ -44,7 +46,7 @@ const OrganizationPage = async ({ params }: Props) => {
href: "/organizations",
},
{
label: organization?.name ?? organizationId,
label: organization?.name ?? organizationSlug,
},
];

Expand All @@ -62,7 +64,7 @@ const OrganizationPage = async ({ params }: Props) => {
// TODO: get Sigil Icon component working and update accordingly. Context: https://github.com/omnidotdev/backfeed-app/pull/44#discussion_r1897974331
icon: <HiOutlineFolder />,
variant: "outline",
href: `/organizations/${organizationId}/projects`,
href: `/organizations/${organizationSlug}/projects`,
},
{
label: app.organizationPage.header.cta.newProject.label,
Expand All @@ -72,7 +74,10 @@ const OrganizationPage = async ({ params }: Props) => {
],
}}
>
<OrganizationOverview organizationId={organizationId} />
<OrganizationOverview
organizationId={organization?.rowId}
organizationSlug={organizationSlug}
/>
</Page>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const metadata = {
interface Props {
/** Feedback page params. */
params: Promise<{
organizationId: string;
projectId: string;
organizationSlug: string;
projectSlug: string;
feedbackId: string;
}>;
}
Expand All @@ -23,7 +23,7 @@ interface Props {
* Feedback overview page.
*/
const FeedbackPage = async ({ params }: Props) => {
const { organizationId, projectId, feedbackId } = await params;
const { organizationSlug, projectSlug, feedbackId } = await params;

const [session, { post: feedback }] = await Promise.all([
getAuthSession(),
Expand All @@ -36,16 +36,16 @@ const FeedbackPage = async ({ params }: Props) => {
href: "/organizations",
},
{
label: feedback?.project?.organization?.name ?? organizationId,
href: `/organizations/${organizationId}`,
label: feedback?.project?.organization?.name ?? organizationSlug,
href: `/organizations/${organizationSlug}`,
},
{
label: app.projectsPage.breadcrumb,
href: `/organizations/${organizationId}/projects`,
href: `/organizations/${organizationSlug}/projects`,
},
{
label: feedback?.project?.name ?? projectId,
href: `/organizations/${organizationId}/projects/${projectId}`,
label: feedback?.project?.name ?? projectSlug,
href: `/organizations/${organizationSlug}/projects/${projectSlug}`,
},
{
label: app.feedbackPage.breadcrumb,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { notFound } from "next/navigation";
import { LuSettings } from "react-icons/lu";
import { HiOutlineFolder } from "react-icons/hi2";
import { LuSettings } from "react-icons/lu";

import { ProjectOverview } from "components/project";
import { Page } from "components/layout";
import { ProjectOverview } from "components/project";
import { app } from "lib/config";
import { sdk } from "lib/graphql";
import { getAuthSession } from "lib/util";
Expand All @@ -13,9 +13,11 @@ import type { Metadata } from "next";
export const generateMetadata = async ({
params,
}: Props): Promise<Metadata> => {
const { projectId } = await params;
const { organizationSlug, projectSlug } = await params;

const { projects } = await sdk.Project({ projectSlug, organizationSlug });

const { project } = await sdk.Project({ rowId: projectId });
const project = projects?.nodes?.[0];

return {
title: `${project?.name} | ${app.name}`,
Expand All @@ -24,35 +26,37 @@ export const generateMetadata = async ({

interface Props {
/** Project page params. */
params: Promise<{ organizationId: string; projectId: string }>;
params: Promise<{ organizationSlug: string; projectSlug: string }>;
}

/**
* Project overview page.
*/
const ProjectPage = async ({ params }: Props) => {
const { organizationId, projectId } = await params;
const { organizationSlug, projectSlug } = await params;

const [session, { project }] = await Promise.all([
const [session, { projects }] = await Promise.all([
getAuthSession(),
sdk.Project({ rowId: projectId }),
sdk.Project({ projectSlug, organizationSlug }),
]);

const project = projects?.nodes?.[0];

const breadcrumbs = [
{
label: app.organizationsPage.breadcrumb,
href: "/organizations",
},
{
label: project?.organization?.name ?? organizationId,
href: `/organizations/${organizationId}`,
label: project?.organization?.name ?? organizationSlug,
href: `/organizations/${organizationSlug}`,
},
{
label: app.projectsPage.breadcrumb,
href: `/organizations/${organizationId}/projects`,
href: `/organizations/${organizationSlug}/projects`,
},
{
label: project?.name ?? projectId,
label: project?.name ?? projectSlug,
},
];

Expand All @@ -76,12 +80,12 @@ const ProjectPage = async ({ params }: Props) => {
// TODO: get Sigil Icon component working and update accordingly. Context: https://github.com/omnidotdev/backfeed-app/pull/44#discussion_r1897974331
icon: <HiOutlineFolder />,
variant: "outline",
href: `/organizations/${organizationId}/projects`,
href: `/organizations/${organizationSlug}/projects`,
},
],
}}
>
<ProjectOverview projectId={projectId} />
<ProjectOverview projectId={project?.rowId} />
</Page>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import type { Metadata } from "next";
export const generateMetadata = async ({
params,
}: Props): Promise<Metadata> => {
const { organizationId } = await params;
const { organizationSlug } = await params;

const { organization } = await sdk.Organization({ rowId: organizationId });
const { organizationBySlug: organization } = await sdk.Organization({
slug: organizationSlug,
});

return {
title: `${organization?.name} ${app.projectsPage.breadcrumb} | ${app.name}`,
Expand All @@ -23,18 +25,18 @@ export const generateMetadata = async ({

interface Props {
/** Projects page params. */
params: Promise<{ organizationId: string }>;
params: Promise<{ organizationSlug: string }>;
}

/**
* Projects overview page.
*/
const ProjectsPage = async ({ params }: Props) => {
const { organizationId } = await params;
const { organizationSlug } = await params;

const [session, { organization }] = await Promise.all([
const [session, { organizationBySlug: organization }] = await Promise.all([
getAuthSession(),
sdk.Organization({ rowId: organizationId }),
sdk.Organization({ slug: organizationSlug }),
]);

const breadcrumbs = [
Expand All @@ -43,8 +45,8 @@ const ProjectsPage = async ({ params }: Props) => {
href: "/organizations",
},
{
label: organization?.name ?? organizationId,
href: `/organizations/${organizationId}`,
label: organization?.name ?? organizationSlug,
href: `/organizations/${organizationSlug}`,
},
{
label: app.projectsPage.breadcrumb,
Expand Down
5 changes: 1 addition & 4 deletions src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client";

import {
BlockchainProvider,
QueryProvider,
SearchParamsProvider,
AuthProvider,
Expand All @@ -17,9 +16,7 @@ const Providers = ({ children }: { children: ReactNode }) => (
<AuthProvider>
<ThemeProvider>
<SearchParamsProvider>
<QueryProvider>
<BlockchainProvider>{children}</BlockchainProvider>
</QueryProvider>
<QueryProvider>{children}</QueryProvider>
</SearchParamsProvider>
</ThemeProvider>
</AuthProvider>
Expand Down
11 changes: 10 additions & 1 deletion src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import "next-auth/jwt";

import { token } from "generated/panda/tokens";

import { sdk } from "lib/graphql";
import type { User as NextAuthUser } from "next-auth";
import type { DefaultJWT } from "next-auth/jwt";
import { sdk } from "lib/graphql";

/**
* Augment the JWT interface with custom claims. See `callbacks` below, where the `jwt` callback is augmented.
Expand All @@ -28,6 +28,7 @@ declare module "next-auth/jwt" {
declare module "next-auth" {
interface Session {
user: {
rowId?: string;
hidraId?: string;
firstName?: string;
lastName?: string;
Expand Down Expand Up @@ -110,6 +111,14 @@ export const { handlers, auth } = NextAuth({
session.user.lastName = token.family_name;
session.user.username = token.preferred_username;

// retrieve user by HIDRA ID
const { userByHidraId } = await sdk.User({ hidraId: token.sub! });

if (userByHidraId) {
// TODO: discuss removing additional augmentation of the session object (i.e. user.rowId) and just overwriting the user.id field here. Currently, the user.id field is ovewritten within the `useAuth` hook to supply mock data, but when that is no longer required, we could simply overwrite that field here instead.
session.user.rowId = userByHidraId.rowId;
}

return session;
},
},
Expand Down
8 changes: 5 additions & 3 deletions src/components/core/Breadcrumb/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
"use client";

import { Flex, Icon, Text } from "@omnidev/sigil";
import { app } from "lib/config";
import Link from "next/link";
import { LuChevronRight } from "react-icons/lu";

import { Link } from "components/core";
import { app } from "lib/config";

export interface BreadcrumbRecord {
/** Label for the breadcrumb. */
label: string;
Expand Down Expand Up @@ -32,7 +33,8 @@ const Breadcrumb = ({ breadcrumbs }: Props) => (
const isLastItem = breadcrumbs.length - 1 === index;

return (
<Flex key={label} align="center">
// biome-ignore lint/suspicious/noArrayIndexKey: index used in the key in case an organization and project have the same label
<Flex key={`${label}-${index}`} align="center">
<Icon src={LuChevronRight} color="foreground.subtle" mx={2} />

{href ? (
Expand Down
Loading