Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
98 changes: 82 additions & 16 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,25 +58,91 @@ jobs:

jq --arg version "$NEXT_VERSION" '.Website = $version' .release-please-manifest.json > temp.json && mv temp.json .release-please-manifest.json

echo "## [$NEXT_VERSION] - $(date +'%Y-%m-%d')" > temp_changelog.md
echo "" >> temp_changelog.md
echo "### Changed" >> temp_changelog.md
# Generate enhanced changelog
cat > generate_changelog.js << 'EOF'
const { execSync } = require('child_process');

function generateChangelog(lastTag, nextVersion, repo) {
let commits = [];
try {
const output = execSync(`git log ${lastTag}..HEAD --pretty=format:"%h|%s"`).toString();
commits = output.split('\n').filter(line => line.trim()).map(line => {
const [hash, message] = line.split('|');
return { hash, message };
});
} catch (error) {
console.log('No commits found or error getting commits');
return `## [${nextVersion}] - ${new Date().toISOString().split('T')[0]}\n\n### Changed\n- Manual release\n\n`;
}

const categories = {
'Features': [],
'Bug Fixes': [],
'Performance Improvements': [],
'UI/UX Improvements': [],
'Code Refactoring': [],
'Other Changes': []
};

commits.forEach(commit => {
const { hash, message } = commit;
const link = `([${hash}](https://github.com/${repo}/commit/${hash}))`;
let cleanMessage = message;

// Clean up common prefixes
cleanMessage = cleanMessage.replace(/^(feat|feature):\s*/i, '');
cleanMessage = cleanMessage.replace(/^(fix|bugfix):\s*/i, '');
cleanMessage = cleanMessage.replace(/^(perf|performance):\s*/i, '');
cleanMessage = cleanMessage.replace(/^(style|ui|ux):\s*/i, '');
cleanMessage = cleanMessage.replace(/^(refactor|refact):\s*/i, '');
cleanMessage = cleanMessage.replace(/^chore:\s*/i, '');

// Categorize commits
if (message.match(/^feat|feature|add|implement|new/i) || message.includes('PBI')) {
categories['Features'].push(`* ${cleanMessage} ${link}`);
} else if (message.match(/^fix|bug|resolve|correct/i)) {
categories['Bug Fixes'].push(`* ${cleanMessage} ${link}`);
} else if (message.match(/perf|performance|optim|speed|fast/i)) {
categories['Performance Improvements'].push(`* ${cleanMessage} ${link}`);
} else if (message.match(/ui|ux|style|design|visual|appearance/i)) {
categories['UI/UX Improvements'].push(`* ${cleanMessage} ${link}`);
} else if (message.match(/refactor|restructure|reorganize|clean/i)) {
categories['Code Refactoring'].push(`* ${cleanMessage} ${link}`);
} else if (!message.match(/^merge|^chore\(release\)/i)) {
categories['Other Changes'].push(`* ${cleanMessage} ${link}`);
}
});

let changelog = `## [${nextVersion}] - ${new Date().toISOString().split('T')[0]}\n\n`;

Object.entries(categories).forEach(([category, items]) => {
if (items.length > 0) {
changelog += `### ${category}\n\n`;
items.forEach(item => {
changelog += `${item}\n`;
});
changelog += '\n';
}
});

// If no categorized items, add a simple changed section
if (Object.values(categories).every(cat => cat.length === 0)) {
changelog += `### Changed\n\n* Manual ${nextVersion.includes('major') ? 'major' : nextVersion.includes('minor') ? 'minor' : 'patch'} release\n\n`;
}

return changelog;
}

const lastTag = process.argv[2];
const nextVersion = process.argv[3];
const repo = process.argv[4];
console.log(generateChangelog(lastTag, nextVersion, repo));
EOF

LAST_TAG="website-v$CURRENT_VERSION"
git fetch --tags
if git rev-parse "$LAST_TAG" >/dev/null 2>&1; then
echo "- Changes since $CURRENT_VERSION:" >> temp_changelog.md
COMMITS=$(git log "$LAST_TAG"..HEAD --pretty=format:"- %s")
if [ -n "$COMMITS" ]; then
echo "$COMMITS" >> temp_changelog.md
else
echo "- No new commits since last version" >> temp_changelog.md
fi
else
echo "- Manual ${{ github.event.inputs.release_type }} release" >> temp_changelog.md
echo "- (No previous tag $LAST_TAG found to compare commits)" >> temp_changelog.md
fi
echo "" >> temp_changelog.md

node generate_changelog.js "$LAST_TAG" "$NEXT_VERSION" "${{ github.repository }}" > temp_changelog.md

if [ -f "Website/CHANGELOG.md" ]; then
cat temp_changelog.md Website/CHANGELOG.md > temp_full_changelog.md
Expand Down
94 changes: 85 additions & 9 deletions Website/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { createSession } from "@/lib/session";
import { useRouter } from "next/navigation";
import { FormEvent } from "react";
import { FormEvent, useState, useEffect } from "react";
import { Eye, EyeOff } from "lucide-react";
import { LastSynched } from "@/generated/Data";

export default function LoginPage() {
const router = useRouter();
const [showPassword, setShowPassword] = useState(false);
const [version, setVersion] = useState<string | null>(null);

useEffect(() => {
fetch('/api/version')
.then((res) => res.json())
.then((data) => setVersion(data.version))
.catch(() => setVersion('Unknown'))
}, []);

async function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
Expand All @@ -25,7 +35,6 @@ export default function LoginPage() {
});

if (response.ok) {

await createSession(password?.valueOf() as string);
router.push("/");
} else {
Expand All @@ -34,12 +43,79 @@ export default function LoginPage() {
}

return (
<div className="flex items-center justify-center h-screen w-full">
<form onSubmit={handleSubmit} className="flex flex-col gap-5 p-5 border border-gray-300 rounded-lg">
<Label htmlFor="password">Password</Label>
<Input id="password" type="text" name="password" />
<Button type="submit">Login</Button>
</form>
<div className="min-h-screen bg-gradient-to-br from-indigo-50 to-sky-200 flex items-center justify-center p-4">
<div className="w-full max-w-md">

{/* Logo and Header */}
<div className="text-center mb-8">
<div className="flex justify-center mb-6">
<img
src="/DMVLOGOHORZ.svg"
alt="Data Model Viewer Logo"
className="h-16 sm:h-20 object-contain"
/>
</div>
</div>

{/* Login Form */}
<div className="bg-white shadow-xl rounded-2xl p-8 border border-gray-100">

<h1 className="text-md text-gray-400 text">Enter model password</h1>
<h1 className="text-2xl font-semibold text-gray-700 mb-8 text mt-0">Welcome back</h1>


<form onSubmit={handleSubmit} className="space-y-6">
<div>
<div className="relative">
<Input
id="password"
name="password"
type={showPassword ? "text" : "password"}
required
className="pr-12 h-12 border-gray-300 focus:border-blue-500 focus:ring-blue-500"
placeholder="Enter your password"
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword)}
className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500 hover:text-gray-700 transition-colors"
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? (
<EyeOff className="h-5 w-5" />
) : (
<Eye className="h-5 w-5" />
)}
</button>
</div>
</div>

<Button
type="submit"
className="w-full bg-blue-400 hover:bg-blue-500 text-white font-medium rounded-lg transition-colors"
>
Sign In
</Button>
</form>
</div>

{/* Footer Information */}
<div className="mt-6 text-center space-y-1 text-gray-700 text-xs">
<div className="">
Last Synched: <b>{LastSynched ? LastSynched.toLocaleString(undefined, {
timeZoneName: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
}) : '...'}</b>
</div>
<div className="">
Version: <b>{version ?? '...'}</b>
</div>
</div>
</div>
</div>
);
}
Loading