forked from git.gladyson/openmonetis
chore: remove implementação do changelog
- Remove página /changelog e seus arquivos - Remove componentes ChangelogLink e ChangelogList - Remove referência do header-dashboard
This commit is contained in:
@@ -1,23 +0,0 @@
|
|||||||
import PageDescription from "@/components/page-description";
|
|
||||||
import { RiGitCommitLine } from "@remixicon/react";
|
|
||||||
|
|
||||||
export const metadata = {
|
|
||||||
title: "Changelog | Opensheets",
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function RootLayout({
|
|
||||||
children,
|
|
||||||
}: {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}) {
|
|
||||||
return (
|
|
||||||
<section className="space-y-6 px-6">
|
|
||||||
<PageDescription
|
|
||||||
icon={<RiGitCommitLine />}
|
|
||||||
title="Changelog"
|
|
||||||
subtitle="Histórico completo de alterações e atualizações do projeto."
|
|
||||||
/>
|
|
||||||
{children}
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
|
||||||
|
|
||||||
export default function Loading() {
|
|
||||||
return (
|
|
||||||
<main className="container mx-auto px-4 py-8 max-w-4xl">
|
|
||||||
<div className="mb-8">
|
|
||||||
<Skeleton className="h-9 w-48 mb-2" />
|
|
||||||
<Skeleton className="h-5 w-96" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="space-y-4">
|
|
||||||
{[...Array(5)].map((_, i) => (
|
|
||||||
<Card key={i}>
|
|
||||||
<CardHeader className="pb-3">
|
|
||||||
<Skeleton className="h-6 w-3/4 mb-2" />
|
|
||||||
<div className="flex gap-3">
|
|
||||||
<Skeleton className="h-4 w-20" />
|
|
||||||
<Skeleton className="h-4 w-32" />
|
|
||||||
<Skeleton className="h-4 w-24" />
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="pt-0">
|
|
||||||
<Skeleton className="h-4 w-32" />
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
import { ChangelogList } from "@/components/changelog/changelog-list";
|
|
||||||
import { execSync } from "child_process";
|
|
||||||
|
|
||||||
type GitCommit = {
|
|
||||||
hash: string;
|
|
||||||
shortHash: string;
|
|
||||||
author: string;
|
|
||||||
date: string;
|
|
||||||
message: string;
|
|
||||||
body: string;
|
|
||||||
filesChanged: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
function getGitRemoteUrl(): string | null {
|
|
||||||
try {
|
|
||||||
const remoteUrl = execSync("git config --get remote.origin.url", {
|
|
||||||
encoding: "utf-8",
|
|
||||||
cwd: process.cwd(),
|
|
||||||
}).trim();
|
|
||||||
|
|
||||||
// Converter SSH para HTTPS se necessário
|
|
||||||
if (remoteUrl.startsWith("git@")) {
|
|
||||||
return remoteUrl
|
|
||||||
.replace("git@github.com:", "https://github.com/")
|
|
||||||
.replace("git@gitlab.com:", "https://gitlab.com/")
|
|
||||||
.replace(".git", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
return remoteUrl.replace(".git", "");
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching git remote URL:", error);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getGitCommits(): GitCommit[] {
|
|
||||||
try {
|
|
||||||
// Buscar os últimos 50 commits
|
|
||||||
const commits = execSync(
|
|
||||||
'git log -50 --pretty=format:"%H|%h|%an|%ad|%s|%b" --date=iso --name-only',
|
|
||||||
{
|
|
||||||
encoding: "utf-8",
|
|
||||||
cwd: process.cwd(),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.trim()
|
|
||||||
.split("\n\n");
|
|
||||||
|
|
||||||
return commits
|
|
||||||
.map((commitBlock) => {
|
|
||||||
const lines = commitBlock.split("\n");
|
|
||||||
const [hash, shortHash, author, date, message, ...rest] =
|
|
||||||
lines[0].split("|");
|
|
||||||
|
|
||||||
// Separar body e arquivos
|
|
||||||
const bodyLines: string[] = [];
|
|
||||||
const filesChanged: string[] = [];
|
|
||||||
let isBody = true;
|
|
||||||
|
|
||||||
rest.forEach((line) => {
|
|
||||||
if (line && !line.includes("/") && !line.includes(".")) {
|
|
||||||
bodyLines.push(line);
|
|
||||||
} else {
|
|
||||||
isBody = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
lines.slice(1).forEach((line) => {
|
|
||||||
if (line.trim()) {
|
|
||||||
filesChanged.push(line.trim());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
hash,
|
|
||||||
shortHash,
|
|
||||||
author,
|
|
||||||
date,
|
|
||||||
message,
|
|
||||||
body: bodyLines.join("\n").trim(),
|
|
||||||
filesChanged: filesChanged.filter(
|
|
||||||
(f) => f && !f.startsWith("git log")
|
|
||||||
),
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.filter((commit) => commit.hash && commit.message);
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching git commits:", error);
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default async function ChangelogPage() {
|
|
||||||
const commits = getGitCommits();
|
|
||||||
const repoUrl = getGitRemoteUrl();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<main>
|
|
||||||
<ChangelogList commits={commits} repoUrl={repoUrl} />
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
|
||||||
import {
|
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from "@/components/ui/tooltip";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { RiGitCommitLine } from "@remixicon/react";
|
|
||||||
import Link from "next/link";
|
|
||||||
|
|
||||||
export function ChangelogLink() {
|
|
||||||
return (
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<Link
|
|
||||||
href="/changelog"
|
|
||||||
className={cn(
|
|
||||||
buttonVariants({ variant: "ghost", size: "icon-sm" }),
|
|
||||||
"group relative text-muted-foreground transition-all duration-200",
|
|
||||||
"hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40 border",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<RiGitCommitLine className="size-4" />
|
|
||||||
<span className="sr-only">Changelog</span>
|
|
||||||
</Link>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent side="bottom" sideOffset={8}>
|
|
||||||
Changelog
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,200 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "@/components/ui/accordion";
|
|
||||||
import { formatDistanceToNow } from "date-fns";
|
|
||||||
import { ptBR } from "date-fns/locale";
|
|
||||||
import {
|
|
||||||
RiGitCommitLine,
|
|
||||||
RiUserLine,
|
|
||||||
RiCalendarLine,
|
|
||||||
RiFileList2Line,
|
|
||||||
} from "@remixicon/react";
|
|
||||||
|
|
||||||
type GitCommit = {
|
|
||||||
hash: string;
|
|
||||||
shortHash: string;
|
|
||||||
author: string;
|
|
||||||
date: string;
|
|
||||||
message: string;
|
|
||||||
body: string;
|
|
||||||
filesChanged: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type ChangelogListProps = {
|
|
||||||
commits: GitCommit[];
|
|
||||||
repoUrl: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
type CommitType = {
|
|
||||||
type: string;
|
|
||||||
scope?: string;
|
|
||||||
description: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
function parseCommitMessage(message: string): CommitType {
|
|
||||||
const conventionalPattern = /^(\w+)(?:$$([^)]+)$$)?:\s*(.+)$/;
|
|
||||||
const match = message.match(conventionalPattern);
|
|
||||||
|
|
||||||
if (match) {
|
|
||||||
return {
|
|
||||||
type: match[1],
|
|
||||||
scope: match[2],
|
|
||||||
description: match[3],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: "chore",
|
|
||||||
description: message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCommitTypeColor(type: string): string {
|
|
||||||
const colors: Record<string, string> = {
|
|
||||||
feat: "bg-emerald-500/10 text-emerald-700 dark:text-emerald-400 border-emerald-500/20",
|
|
||||||
fix: "bg-red-500/10 text-red-700 dark:text-red-400 border-red-500/20",
|
|
||||||
docs: "bg-blue-500/10 text-blue-700 dark:text-blue-400 border-blue-500/20",
|
|
||||||
style:
|
|
||||||
"bg-purple-500/10 text-purple-700 dark:text-purple-400 border-purple-500/20",
|
|
||||||
refactor:
|
|
||||||
"bg-orange-500/10 text-orange-700 dark:text-orange-400 border-orange-500/20",
|
|
||||||
perf: "bg-yellow-500/10 text-yellow-700 dark:text-yellow-400 border-yellow-500/20",
|
|
||||||
test: "bg-pink-500/10 text-pink-700 dark:text-pink-400 border-pink-500/20",
|
|
||||||
chore: "bg-gray-500/10 text-gray-700 dark:text-gray-400 border-gray-500/20",
|
|
||||||
};
|
|
||||||
|
|
||||||
return colors[type] || colors.chore;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ChangelogList({ commits, repoUrl }: ChangelogListProps) {
|
|
||||||
if (!commits || commits.length === 0) {
|
|
||||||
return (
|
|
||||||
<div className="text-center py-12">
|
|
||||||
<p className="text-muted-foreground">
|
|
||||||
Nenhum commit encontrado no repositório
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="space-y-2">
|
|
||||||
{commits.map((commit) => (
|
|
||||||
<CommitCard key={commit.hash} commit={commit} repoUrl={repoUrl} />
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function CommitCard({
|
|
||||||
commit,
|
|
||||||
repoUrl,
|
|
||||||
}: {
|
|
||||||
commit: GitCommit;
|
|
||||||
repoUrl: string | null;
|
|
||||||
}) {
|
|
||||||
const commitDate = new Date(commit.date);
|
|
||||||
const relativeTime = formatDistanceToNow(commitDate, {
|
|
||||||
addSuffix: true,
|
|
||||||
locale: ptBR,
|
|
||||||
});
|
|
||||||
|
|
||||||
const commitUrl = repoUrl ? `${repoUrl}/commit/${commit.hash}` : null;
|
|
||||||
const parsed = parseCommitMessage(commit.message);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Card className="hover:shadow-sm transition-shadow">
|
|
||||||
<CardHeader>
|
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className={`${getCommitTypeColor(parsed.type)} py-1`}
|
|
||||||
>
|
|
||||||
{parsed.type}
|
|
||||||
</Badge>
|
|
||||||
{parsed.scope && (
|
|
||||||
<Badge
|
|
||||||
variant="outline"
|
|
||||||
className="text-muted-foreground border-muted-foreground/30 text-xs py-0"
|
|
||||||
>
|
|
||||||
{parsed.scope}
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
<span className="font-bold text-lg flex-1 min-w-0 first-letter:uppercase">
|
|
||||||
{parsed.description}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-4 flex-wrap text-xs text-muted-foreground">
|
|
||||||
{commitUrl ? (
|
|
||||||
<a
|
|
||||||
href={commitUrl}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="hover:text-foreground underline transition-colors font-mono flex items-center gap-1"
|
|
||||||
>
|
|
||||||
<RiGitCommitLine className="size-4" />
|
|
||||||
{commit.shortHash}
|
|
||||||
</a>
|
|
||||||
) : (
|
|
||||||
<span className="font-mono flex items-center gap-1">
|
|
||||||
<RiGitCommitLine className="size-3" />
|
|
||||||
{commit.shortHash}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
<span className="flex items-center gap-1">
|
|
||||||
<RiUserLine className="size-3" />
|
|
||||||
{commit.author}
|
|
||||||
</span>
|
|
||||||
<span className="flex items-center gap-1">
|
|
||||||
<RiCalendarLine className="size-3" />
|
|
||||||
{relativeTime}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</CardHeader>
|
|
||||||
|
|
||||||
{commit.body && (
|
|
||||||
<CardContent className="text-muted-foreground leading-relaxed">
|
|
||||||
{commit.body}
|
|
||||||
</CardContent>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{commit.filesChanged.length > 0 && (
|
|
||||||
<CardContent>
|
|
||||||
<Accordion type="single" collapsible className="w-full">
|
|
||||||
<AccordionItem value="files-changed" className="border-0">
|
|
||||||
<AccordionTrigger className="py-0 text-xs text-muted-foreground hover:text-foreground hover:no-underline">
|
|
||||||
<div className="flex items-center gap-1.5">
|
|
||||||
<RiFileList2Line className="size-3.5" />
|
|
||||||
<span>
|
|
||||||
{commit.filesChanged.length} arquivo
|
|
||||||
{commit.filesChanged.length !== 1 ? "s" : ""}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</AccordionTrigger>
|
|
||||||
<AccordionContent className="pt-2 pb-0">
|
|
||||||
<ul className="space-y-1 max-h-48 overflow-y-auto">
|
|
||||||
{commit.filesChanged.map((file, index) => (
|
|
||||||
<li
|
|
||||||
key={index}
|
|
||||||
className="text-xs font-mono bg-muted rounded px-2 py-1 text-muted-foreground break-all"
|
|
||||||
>
|
|
||||||
{file}
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</AccordionContent>
|
|
||||||
</AccordionItem>
|
|
||||||
</Accordion>
|
|
||||||
</CardContent>
|
|
||||||
)}
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { ChangelogLink } from "@/components/changelog/changelog-link";
|
|
||||||
import { FeedbackDialog } from "@/components/feedback/feedback-dialog";
|
import { FeedbackDialog } from "@/components/feedback/feedback-dialog";
|
||||||
import { NotificationBell } from "@/components/notificacoes/notification-bell";
|
import { NotificationBell } from "@/components/notificacoes/notification-bell";
|
||||||
import { SidebarTrigger } from "@/components/ui/sidebar";
|
import { SidebarTrigger } from "@/components/ui/sidebar";
|
||||||
@@ -29,7 +28,6 @@ export async function SiteHeader({ notificationsSnapshot }: SiteHeaderProps) {
|
|||||||
<PrivacyModeToggle />
|
<PrivacyModeToggle />
|
||||||
<AnimatedThemeToggler />
|
<AnimatedThemeToggler />
|
||||||
<span className="text-muted-foreground">|</span>
|
<span className="text-muted-foreground">|</span>
|
||||||
<ChangelogLink />
|
|
||||||
<FeedbackDialog />
|
<FeedbackDialog />
|
||||||
<LogoutButton />
|
<LogoutButton />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user