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
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"root": true,
"extends": ["next/core-web-vitals", "next/typescript"],
"ignorePatterns": ["out/", ".next/", "node_modules/", "coverage/"]
}
16 changes: 11 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
name: CI
name: CI/CD Pipeline

env:
GITHUB_PAGES: "true"
NEXT_PUBLIC_BASE_PATH: "/OpenDQM"
NEXT_PUBLIC_BASE_PATH: "/${{ github.event.repository.name }}"
NEXT_PUBLIC_INTERVIEW_ENDPOINT: ${{ vars.NEXT_PUBLIC_INTERVIEW_ENDPOINT }}
NEXT_PUBLIC_INTERVIEW_EMAIL_ENDPOINT: ${{ vars.NEXT_PUBLIC_INTERVIEW_EMAIL_ENDPOINT }}
NEXT_PUBLIC_INTERVIEW_APPS_SCRIPT_URL: ${{ vars.NEXT_PUBLIC_INTERVIEW_APPS_SCRIPT_URL }}

on:
push:
Expand All @@ -17,7 +20,7 @@ permissions:

jobs:
validate:
name: Lint, Test, and Build
name: Test, Build & Upload
runs-on: ubuntu-latest

steps:
Expand All @@ -31,20 +34,23 @@ jobs:
cache: npm

- name: Install dependencies
run: npm install
run: npm ci

- name: Lint
run: npm run lint

- name: Typecheck
run: npm run typecheck

- name: Prettier
run: npm run format:check

- name: Test
run: npm run test

- name: Security audit
run: npm audit --omit=dev --audit-level=moderate

- name: Build
run: npm run build

Expand Down
12 changes: 5 additions & 7 deletions app/about/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,17 @@ export default function AboutPage() {
<section className="section about-intro">
<div className="container about-intro-grid">
<Reveal>
<GradientHeading
lead="What is OpenDQM?"
emphasis=" "
/>
<GradientHeading lead="What is OpenDQM?" emphasis=" " />
</Reveal>
<Reveal className="about-intro-copy">
<p>
A community-driven effort that connects people exploring how quality can work across organizations, tools, and locations/
A community-driven effort that connects people exploring how quality can work across
organizations, tools, and locations/
</p>
<p>
How can information move without requiring every participant to use the same system?

How can open participation be supported while preserving accountability, learning, and trust?
How can open participation be supported while preserving accountability, learning, and
trust?
</p>
</Reveal>
</div>
Expand Down
21 changes: 6 additions & 15 deletions app/contact/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Metadata } from "next";
import { PageHeader } from "@/components/PageHeader";
import { ContactChoices } from "@/components/ContactChoices";
import "@/app/interview.css";

export const metadata: Metadata = {
title: "Contact",
Expand All @@ -12,22 +14,11 @@ export default function ContactPage() {
return (
<>
<PageHeader
eyebrow="Contact"
title="Help shape distributed quality management."
description="OpenDQM is developing shared infrastructure and community practices for an open, trusted, interoperable quality ecosystem."
eyebrow="Get involved"
title="Help shape distributed quality management"
description="Whether you'd like to ask a question or participate in the research, we'd like to hear from you."
/>
<section className="section">
<div className="container contact-panel">
<article className="info-card">
<span className="card-kicker">Contact</span>
<h2>Contact information coming soon.</h2>
<p>
OpenDQM is formalizing contact details, community calls, and workshop logistics. More
ways to connect will be shared here as they become available.
</p>
</article>
</div>
</section>
<ContactChoices />
</>
);
}
4 changes: 2 additions & 2 deletions app/events/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Metadata } from "next";
import { EventCollections } from "@/components/EventCollections";
import { PageHeader } from "@/components/PageHeader";
import { SurveyCta } from "@/components/SurveyCta";
import { InterviewCta } from "@/components/InterviewCta";

export const metadata: Metadata = {
title: "Events",
Expand All @@ -22,7 +22,7 @@ export default function EventsPage() {
<EventCollections />
</div>
</section>
<SurveyCta compact />
<InterviewCta compact />
</>
);
}
3 changes: 1 addition & 2 deletions app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -3247,7 +3247,6 @@ footer .brand span:last-child {
}
}


.horizontal-story-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
Expand Down Expand Up @@ -3275,4 +3274,4 @@ footer .brand span:last-child {
.footer-funding span {
font-size: 0.9rem;
line-height: 1.4;
}
}
215 changes: 215 additions & 0 deletions app/interview.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
#schedule-interview {
scroll-margin-top: 120px;
}

.interview-panel {
max-width: 940px;
padding: clamp(24px, 5vw, 56px);
background: #faf9ff;
border: 1px solid #c8c3e2;
border-radius: var(--radius);
box-shadow: var(--shadow-soft);
}

.interview-form {
display: grid;
gap: 24px;
margin-top: 32px;
}

.form-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 24px;
}

.interview-form label {
display: grid;
gap: 8px;
color: var(--night);
font-size: 0.95rem;
min-width: 0;
}

.interview-form label > span {
color: var(--muted);
}

.interview-form input,
.interview-form textarea {
width: 100%;
min-width: 0;
padding: 12px 14px;
border: 1px solid #827a9e;
border-radius: 10px;
background: #fff;
color: var(--ink);
font: inherit;
}

.interview-form textarea {
resize: vertical;
}

.form-help {
font-size: 0.85rem;
color: var(--muted);
}

.interview-form .consent {
display: flex;
align-items: flex-start;
gap: 12px;
font-size: 0.85rem;
}

.interview-form .consent input {
width: 20px;
height: 20px;
flex-shrink: 0;
margin-top: 4px;
accent-color: var(--grape);
}

.form-trap {
position: absolute;
left: -10000px;
width: 1px;
height: 1px;
overflow: hidden;
}

.form-errors {
color: #842236;
background: #fff0f2;
padding: 20px 20px 20px 40px;
border-radius: 12px;
}

.form-success {
padding: 24px;
background: #eceafa;
border-radius: var(--radius-sm);
}

.interview-form button[type="submit"] {
justify-self: start;
}

button:disabled {
opacity: 0.65;
cursor: not-allowed;
}

.contact-choices {
background: linear-gradient(180deg, #f7f6fc, #e5e8f2);
}

.contact-choices h2 {
margin: 0 0 12px;
font-size: clamp(1.8rem, 3vw, 2.6rem);
color: var(--night);
}

.connect-intro {
color: var(--muted);
margin-bottom: 32px;
}

.brand-icon {
flex-shrink: 0;
vertical-align: middle;
}

.contact-flow {
background: linear-gradient(180deg, #f7f6fc, #e5e8f2);
}

.contact-flow > section {
background: transparent;
}

.contact-flow .interview-section {
background: transparent;
}

.contact-paths {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: clamp(32px, 6vw, 80px);
margin-top: 40px;
}

.contact-path {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: 16px;
}

.contact-path-icon {
display: grid;
place-items: center;
width: 48px;
height: 48px;
border-radius: 50%;
background: #e7e2f6;
color: var(--grape);
}

.contact-path h3 {
margin: 0;
font-size: clamp(1.4rem, 2.3vw, 1.8rem);
color: var(--night);
}

.contact-path p {
margin: 0;
color: var(--muted);
}

.contact-path .contact-email {
color: var(--grape);
text-decoration: underline;
text-underline-offset: 4px;
}

.contact-path .button {
margin-top: auto;
}

.interview-section {
padding-top: 32px;
background: #f7f6fc;
}

.availability-fields {
padding: 24px;
background: #eeebfa;
border-radius: var(--radius-sm);
}

.timezone-field {
max-width: 370px;
margin-top: 24px;
}

.interview-form input:focus-visible,
.interview-form textarea:focus-visible,
.contact-flow button:focus-visible,
.contact-flow [tabindex="-1"]:focus-visible {
outline: 3px solid #49369a;
outline-offset: 4px;
}
.contact-flow [hidden] {
display: none !important;
}
@media (max-width: 767px) {
.form-grid,
.contact-paths {
grid-template-columns: 1fr;
}
.availability-fields {
padding: 16px;
}
}
10 changes: 3 additions & 7 deletions app/resources/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Metadata } from "next";
import { PageHeader } from "@/components/PageHeader";
// import { resources } from "@/data/resources";
import { SurveyCta } from "@/components/SurveyCta";
import { InterviewCta } from "@/components/InterviewCta";

export const metadata: Metadata = {
title: "Resources",
Expand All @@ -12,12 +12,8 @@ export const metadata: Metadata = {
export default function ResourcesPage() {
return (
<>
<PageHeader
eyebrow=" "
title="Explore OpenDQM."
description=""
/>
<SurveyCta />;
<PageHeader eyebrow=" " title="Explore OpenDQM." description="" />
<InterviewCta />;
{/* <section className="section resources-page">
<div className="container resource-groups">
<section className="resource-group" aria-labelledby="participate-heading">
Expand Down
Loading
Loading