mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
feat: add approvals workflow and unified member invitation management across projects, workspaces, and videos
This commit is contained in:
@@ -18,15 +18,17 @@ interface DashboardClientProps {
|
||||
serializedProjects: SerializedProject[];
|
||||
workspaces: { id: string; name: string }[];
|
||||
totalPages: number;
|
||||
canCreateProjects: boolean;
|
||||
}
|
||||
|
||||
export function DashboardClient({ serializedProjects, workspaces, totalPages }: DashboardClientProps) {
|
||||
export function DashboardClient({ serializedProjects, workspaces, totalPages, canCreateProjects }: DashboardClientProps) {
|
||||
return (
|
||||
<div className="px-6 lg:px-8 py-8 w-full">
|
||||
<ProjectFilter
|
||||
projects={serializedProjects}
|
||||
workspaces={workspaces}
|
||||
totalPages={totalPages}
|
||||
canCreateProjects={canCreateProjects}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -49,6 +49,16 @@ export default async function DashboardPage({
|
||||
distinct: ['workspaceId']
|
||||
});
|
||||
|
||||
const creatableWorkspaces = await db.workspace.count({
|
||||
where: {
|
||||
OR: [
|
||||
{ ownerId: session.user.id },
|
||||
{ members: { some: { userId: session.user.id, role: 'ADMIN' } } },
|
||||
],
|
||||
},
|
||||
});
|
||||
const canCreateProjects = creatableWorkspaces > 0;
|
||||
|
||||
const workspaceMap = new Map<string, string>();
|
||||
for (const project of accessibleProjects) {
|
||||
if (project.workspace) {
|
||||
@@ -105,6 +115,7 @@ export default async function DashboardPage({
|
||||
serializedProjects={serializedProjects}
|
||||
workspaces={workspaces}
|
||||
totalPages={totalPages}
|
||||
canCreateProjects={canCreateProjects}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ interface ProjectFilterProps {
|
||||
projects: SerializedProject[];
|
||||
workspaces: { id: string; name: string }[];
|
||||
totalPages: number;
|
||||
canCreateProjects: boolean;
|
||||
}
|
||||
|
||||
function formatRelativeTime(dateStr: string): string {
|
||||
@@ -61,7 +62,7 @@ function VisibilityIcon({ visibility }: { visibility: string }) {
|
||||
|
||||
type SortOrder = 'desc' | 'asc';
|
||||
|
||||
export function ProjectFilter({ projects, workspaces, totalPages }: ProjectFilterProps) {
|
||||
export function ProjectFilter({ projects, workspaces, totalPages, canCreateProjects }: ProjectFilterProps) {
|
||||
const router = useRouter();
|
||||
const pathname = usePathname();
|
||||
const searchParams = useSearchParams();
|
||||
@@ -138,12 +139,14 @@ export function ProjectFilter({ projects, workspaces, totalPages }: ProjectFilte
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
<Button asChild>
|
||||
<Link href="/projects/new">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
New Project
|
||||
</Link>
|
||||
</Button>
|
||||
{canCreateProjects && (
|
||||
<Button asChild>
|
||||
<Link href="/projects/new">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
New Project
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -205,12 +208,14 @@ export function ProjectFilter({ projects, workspaces, totalPages }: ProjectFilte
|
||||
? 'Create your first project to start collecting video feedback'
|
||||
: 'Create a project in this workspace to get started'}
|
||||
</p>
|
||||
<Button asChild>
|
||||
<Link href="/projects/new">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Create Project
|
||||
</Link>
|
||||
</Button>
|
||||
{canCreateProjects && (
|
||||
<Button asChild>
|
||||
<Link href="/projects/new">
|
||||
<Plus className="h-4 w-4 mr-2" />
|
||||
Create Project
|
||||
</Link>
|
||||
</Button>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user