Skip to content

Commit e980f2c

Browse files
committed
Show only group LinkedIn posts and add publication image viewer
1 parent 6730927 commit e980f2c

13 files changed

Lines changed: 139 additions & 34 deletions

‎web/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ The site reads only stored files during the build. Visits do not call GitHub or
4444

4545
The workflow updates GitHub data, people and LinkedIn, commits changed content with GITHUB_TOKEN, builds and deploys Pages. Shared concurrency prevents overlapping runs. Bot commits do not trigger another workflow; `[skip ci]` adds a second safeguard. Pushes to main deploy without collecting LinkedIn. Concurrent human changes are rebased without force-pushing; conflicts stop publication instead of overwriting work.
4646

47-
Apify uses actor `buIWk2uOUzTmcLsuB` for UFFeScience’s company page and Daniel de Oliveira’s profile. The initial archived history is preserved. Weekly tasks collect the last month (up to 100 posts per source), update existing records and merge new ones. A source/week journal in the named Apify Key-value Store and a task-run lookup resume an existing run after interruption. Manual updates in the same week do not start another extraction. Failed sources retain the last valid files; an empty result never clears history. A failed run is not restarted in the same week. If a run is still active, rerun manually to import its result.
47+
Apify uses actor `buIWk2uOUzTmcLsuB` only for UFFeScience’s company page. Daniel de Oliveira’s profile is no longer collected, and his archived posts are excluded from the catalogs. Historical detail URLs remain available. The initial archived history is preserved. Weekly tasks collect the last month (up to 100 posts per source), update existing records and merge new ones. A source/week journal in the named Apify Key-value Store and a task-run lookup resume an existing run after interruption. Manual updates in the same week do not start another extraction. Failed sources retain the last valid files; an empty result never clears history. A failed run is not restarted in the same week. If a run is still active, rerun manually to import its result.
4848

4949
Open Actions → **Update content and deploy Next.js to Pages** → **Run workflow** on main. Keep `refresh_content` checked to update stored data, or uncheck it for a deployment only. For local updates: `npm run sync:weekly` with APIFY_TOKEN and optionally GITHUB_TOKEN in `.env.local` or the process environment. `--force` on the publication importer bypasses the local shortcut, but never the source/week extraction guard.
5050

‎web/app/globals.css‎

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1693,3 +1693,51 @@ footer {
16931693
.paper-entry h3 {
16941694
overflow-wrap: anywhere;
16951695
}
1696+
1697+
.publication-image-open {
1698+
display: block;
1699+
width: 100%;
1700+
border: 0;
1701+
padding: 0;
1702+
background: transparent;
1703+
cursor: zoom-in;
1704+
}
1705+
.publication-image-open:focus-visible {
1706+
outline: 2px solid #167ab4;
1707+
outline-offset: 4px;
1708+
}
1709+
.publication-image-dialog {
1710+
max-width: 96vw;
1711+
max-height: 96vh;
1712+
padding: 48px 16px 16px;
1713+
border: 0;
1714+
border-radius: 6px;
1715+
background: #fff;
1716+
overscroll-behavior: contain;
1717+
}
1718+
.publication-image-dialog::backdrop {
1719+
background: rgb(8 22 35 / 85%);
1720+
}
1721+
.publication-image-dialog > img {
1722+
display: block;
1723+
max-width: 88vw;
1724+
max-height: 77vh;
1725+
object-fit: contain;
1726+
margin: auto;
1727+
}
1728+
.publication-image-dialog > a {
1729+
display: block;
1730+
text-align: center;
1731+
margin-top: 12px;
1732+
font-size: 13px;
1733+
}
1734+
.publication-image-close {
1735+
position: absolute;
1736+
right: 8px;
1737+
top: 8px;
1738+
display: flex;
1739+
padding: 6px;
1740+
background: white;
1741+
border: 0;
1742+
cursor: pointer;
1743+
}

‎web/app/linkedin-posts.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export default function LinkedinPosts({ news, listing = false }) {
3333
<div className="publication-shelf">
3434
<div className="publication-shelf-toolbar">
3535
<p>
36-
UFFeScience Research Group and Daniel de Oliveira · updated weekly
36+
UFFeScience Research Group · updated weekly
3737
{news.lastCollectedAt &&
3838
` · last collected on ${new Date(news.lastCollectedAt).toLocaleDateString('en-US')}`}
3939
</p>

‎web/app/papers.js‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,6 @@ export default function Papers({ papers, listing = false }) {
5757
</div>
5858
<p className="section-description">
5959
Peer-reviewed papers since 2013 · {filtered.length} papers
60-
{papers.lattesUpdatedAt &&
61-
` · from Daniel de Oliveira’s Lattes CV, updated on ${new Date(
62-
`${papers.lattesUpdatedAt}T12:00:00Z`,
63-
).toLocaleDateString('en-US')}`}
6460
</p>
6561
{listing ? (
6662
<label className="catalog-search">

‎web/app/publicacoes/[slug]/page.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { assetPath } from '../../../lib/site-path';
22
import Link from 'next/link';
33
import { notFound } from 'next/navigation';
44
import { ArrowLeft, ArrowUpRight } from 'lucide-react';
5-
import { readPublications } from '../../../lib/publication-store';
5+
import { readPublications, readGroupPublications } from '../../../lib/publication-store';
66
import SiteHeader from '../../site-header';
77
import PublicationImage from '../../publication-image';
88
export const dynamicParams = false;
@@ -23,8 +23,9 @@ export default async function PublicationPage({ params }) {
2323
const { posts } = await readPublications();
2424
const post = posts.find((item) => item.slug === slug || item.aliasSlugs?.includes(slug));
2525
if (!post) notFound();
26-
const index = posts.findIndex((item) => item.id === post.id),
27-
next = posts[index + 1];
26+
const { posts: groupPosts } = await readGroupPublications();
27+
const index = groupPosts.findIndex((item) => item.id === post.id),
28+
next = groupPosts[index + 1];
2829
return (
2930
<>
3031
<SiteHeader />
@@ -71,6 +72,7 @@ export default async function PublicationPage({ params }) {
7172
<PublicationImage
7273
src={post.cover}
7374
alt={`Publication image by ${post.author.name}`}
75+
zoomable
7476
className="publication-detail-cover"
7577
/>
7678
)}
@@ -86,6 +88,7 @@ export default async function PublicationPage({ params }) {
8688
key={image}
8789
src={image}
8890
alt={`Publication image ${i + 2}`}
91+
zoomable
8992
className="publication-gallery-image"
9093
/>
9194
))}

‎web/app/publicacoes/page.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import SiteHeader from '../site-header';
22
import LinkedinPosts from '../linkedin-posts';
3-
import { readPublications } from '../../lib/publication-store';
3+
import { readGroupPublications } from '../../lib/publication-store';
44
export const metadata = { title: 'All publications — UFFeScience' };
55
export default async function PublicationsPage() {
66
return (
@@ -13,7 +13,7 @@ export default async function PublicationsPage() {
1313
<h1>Publications</h1>
1414
</div>
1515
</div>
16-
<LinkedinPosts news={await readPublications()} listing />
16+
<LinkedinPosts news={await readGroupPublications()} listing />
1717
</main>
1818
</>
1919
);

‎web/app/publication-image.js‎

Lines changed: 48 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,60 @@
11
'use client';
22
import { assetPath } from '../lib/site-path';
3-
import { useState } from 'react';
4-
export default function PublicationImage({ src, alt, className = '' }) {
3+
import { useRef, useState } from 'react';
4+
import { X } from 'lucide-react';
5+
6+
export default function PublicationImage({ src, alt, className = '', zoomable = false }) {
57
const [failed, setFailed] = useState(false);
6-
return src && !failed ? (
8+
const dialog = useRef(null);
9+
if (!src || failed) {
10+
return (
11+
<div className={`publication-cover-placeholder ${className}`}>
12+
<img src={assetPath('/uffescience-logo.png')} alt="UFF eScience" />
13+
<span>Research and knowledge</span>
14+
</div>
15+
);
16+
}
17+
const image = (
718
<img
819
src={assetPath(src)}
920
alt={alt}
1021
className={className}
1122
loading="lazy"
1223
onError={() => setFailed(true)}
1324
/>
14-
) : (
15-
<div className={`publication-cover-placeholder ${className}`}>
16-
<img src={assetPath('/uffescience-logo.png')} alt="UFF eScience" />
17-
<span>Research and knowledge</span>
18-
</div>
25+
);
26+
if (!zoomable) return image;
27+
return (
28+
<>
29+
<button
30+
className="publication-image-open"
31+
onClick={() => dialog.current?.showModal()}
32+
aria-label={`Enlarge image: ${alt}`}
33+
>
34+
{image}
35+
</button>
36+
<dialog
37+
ref={dialog}
38+
className="publication-image-dialog"
39+
aria-label={alt}
40+
onClick={(event) => {
41+
if (event.target === event.currentTarget) dialog.current.close();
42+
}}
43+
>
44+
<button
45+
type="button"
46+
autoFocus
47+
className="publication-image-close"
48+
onClick={() => dialog.current.close()}
49+
aria-label="Close enlarged image"
50+
>
51+
<X size={24} />
52+
</button>
53+
<img src={assetPath(src)} alt={alt} />
54+
<a href={assetPath(src)} target="_blank" rel="noreferrer">
55+
Open original image
56+
</a>
57+
</dialog>
58+
</>
1959
);
2060
}

‎web/data/apify-config.json‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@
55
"id": "ApeMyM9MfdX6fpjPH",
66
"name": "uffescience-company",
77
"url": "https://www.linkedin.com/company/uffescience-research-group"
8-
},
9-
{
10-
"id": "w7sEIreYSimjaIOnL",
11-
"name": "daniel-de-oliveira",
12-
"url": "https://www.linkedin.com/in/daniel-de-oliveira-b258368/"
138
}
149
],
1510
"storeId": "tOJCj89elzSvIqNdg",

‎web/lib/data.js‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'server-only';
22
import fs from 'node:fs/promises';
33
import path from 'node:path';
4-
import { readPublications } from './publication-store';
4+
import { readGroupPublications } from './publication-store';
55

66
export async function getGithub() {
77
const store = JSON.parse(
@@ -10,5 +10,5 @@ export async function getGithub() {
1010
return store;
1111
}
1212
export async function getNews() {
13-
return readPublications();
13+
return readGroupPublications();
1414
}

‎web/lib/publication-model.js‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,6 @@ export const publicationSources = [
55
name: 'UFFeScience Research Group',
66
url: 'https://www.linkedin.com/company/uffescience-research-group',
77
},
8-
{
9-
id: 'daniel',
10-
name: 'Daniel de Oliveira',
11-
url: 'https://www.linkedin.com/in/daniel-de-oliveira-b258368/',
12-
},
138
];
149
export function slugify(text) {
1510
return text

0 commit comments

Comments
 (0)