naslovnica: isti izvajalec vsaj 5 mest narazen namesto premikanja clankov v drugo rubriko
This commit is contained in:
@@ -0,0 +1,161 @@
|
|||||||
|
// Samodejno iz /opt/folx-shared/artists.json (29. 8. 2026). Ne urejaj rocno.
|
||||||
|
export const ARTISTS: string[] = [
|
||||||
|
"Zillertaler Haderlumpen",
|
||||||
|
"Die Jungen Klostertaler",
|
||||||
|
"Die Jungen Zillertaler",
|
||||||
|
"Anna-Carina Woitschack",
|
||||||
|
"Engelbert Humperdinck",
|
||||||
|
"Kastelruther Spatzen",
|
||||||
|
"Die 4 von der Koralm",
|
||||||
|
"Florian Silbereisen",
|
||||||
|
"Oesch's die Dritten",
|
||||||
|
"Melissa Naschenweng",
|
||||||
|
"Die Schlagerpiloten",
|
||||||
|
"Gioiello Sabbatelli",
|
||||||
|
"Maximilian Sedlmayr",
|
||||||
|
"Wildecker Herzbuben",
|
||||||
|
"Michelle\" Schlager",
|
||||||
|
"Marianne Rosenberg",
|
||||||
|
"Esteriore Brothers",
|
||||||
|
"Alexandra Hofmann",
|
||||||
|
"Fantasy\" Schlager",
|
||||||
|
"Alpen Oberkrainer",
|
||||||
|
"Sigrid und Marina",
|
||||||
|
"Giovanni Zarrella",
|
||||||
|
"Paolo Santa Maria",
|
||||||
|
"Vanessa Siziliano",
|
||||||
|
"Hansi Hinterseer",
|
||||||
|
"Andreas Gabalier",
|
||||||
|
"Daniela Alfinito",
|
||||||
|
"Olaf der Flipper",
|
||||||
|
"Nockalm Quintett",
|
||||||
|
"Damiano Maiolini",
|
||||||
|
"Stefanie Hertel",
|
||||||
|
"Die Draufgänger",
|
||||||
|
"Die Zillertaler",
|
||||||
|
"Ybbstal Express",
|
||||||
|
"Die Pagger Buam",
|
||||||
|
"Die Grubertaler",
|
||||||
|
"Michael Wendler",
|
||||||
|
"Die Cappuccinos",
|
||||||
|
"Alexander Fuchs",
|
||||||
|
"Gerrit Grünberg",
|
||||||
|
"Helene Fischer",
|
||||||
|
"Wolfgang Petry",
|
||||||
|
"Christin Stark",
|
||||||
|
"Oswald Sattler",
|
||||||
|
"Lucas Cordalis",
|
||||||
|
"Die Stoakogler",
|
||||||
|
"Die Mayrhofner",
|
||||||
|
"Francine Jordi",
|
||||||
|
"Bernhard Brink",
|
||||||
|
"Alexander Rier",
|
||||||
|
"Nino de Angelo",
|
||||||
|
"Costa Cordalis",
|
||||||
|
"Matthias Reim",
|
||||||
|
"Beatrice Egli",
|
||||||
|
"Roland Kaiser",
|
||||||
|
"Anita Hofmann",
|
||||||
|
"Vincent Gross",
|
||||||
|
"Ramon Roselly",
|
||||||
|
"Sonia Liebing",
|
||||||
|
"Melanie Payer",
|
||||||
|
"Joelina Drews",
|
||||||
|
"Ursprung Buam",
|
||||||
|
"Steirergreens",
|
||||||
|
"Zellberg Buam",
|
||||||
|
"Melanie Oesch",
|
||||||
|
"Monika Martin",
|
||||||
|
"Eric Philippi",
|
||||||
|
"Rosanna Rocci",
|
||||||
|
"Andrea Kiewel",
|
||||||
|
"Pietro Basile",
|
||||||
|
"Nevio Passero",
|
||||||
|
"Laterndl Trio",
|
||||||
|
"Stefan Mross",
|
||||||
|
"Semino Rossi",
|
||||||
|
"Norbert Rier",
|
||||||
|
"Angela Wiedl",
|
||||||
|
"Peter Maffay",
|
||||||
|
"Saso Avsenik",
|
||||||
|
"Jürgen Drews",
|
||||||
|
"Die Flippers",
|
||||||
|
"Klostertaler",
|
||||||
|
"Lechner Buam",
|
||||||
|
"Die Paldauer",
|
||||||
|
"Marc Pircher",
|
||||||
|
"Hansi Berger",
|
||||||
|
"Ella Endlich",
|
||||||
|
"Oliver Haidt",
|
||||||
|
"Ralph Siegel",
|
||||||
|
"Johnny Logan",
|
||||||
|
"Bonnie Tyler",
|
||||||
|
"Sašo Avsenik",
|
||||||
|
"Mark Medlock",
|
||||||
|
"Laura Müller",
|
||||||
|
"Andrea Berg",
|
||||||
|
"Achim Petry",
|
||||||
|
"Maite Kelly",
|
||||||
|
"Vanessa Mai",
|
||||||
|
"Ross Antony",
|
||||||
|
"Ireen Sheer",
|
||||||
|
"Kerstin Ott",
|
||||||
|
"Die Edlseer",
|
||||||
|
"Die Fetzign",
|
||||||
|
"Die Ladiner",
|
||||||
|
"Jörg Bausch",
|
||||||
|
"Stefan Roos",
|
||||||
|
"Julian Reim",
|
||||||
|
"Linda Hesse",
|
||||||
|
"Anna Heesch",
|
||||||
|
"Rod Stewart",
|
||||||
|
"Luca Stangl",
|
||||||
|
"Hein Simons",
|
||||||
|
"Grubertaler",
|
||||||
|
"Marie Reim",
|
||||||
|
"Die Amigos",
|
||||||
|
"Ben Zucker",
|
||||||
|
"Luca Hänni",
|
||||||
|
"Die Lauser",
|
||||||
|
"Ralph Sieg",
|
||||||
|
"Anni Perka",
|
||||||
|
"Andy Borg",
|
||||||
|
"Stereoact",
|
||||||
|
"Calimeros",
|
||||||
|
"Feuerherz",
|
||||||
|
"Mary Roos",
|
||||||
|
"Voxxclub",
|
||||||
|
"Die Seer",
|
||||||
|
"Michelle",
|
||||||
|
"voXXclub",
|
||||||
|
"DJ Ötzi",
|
||||||
|
"Ragazzi",
|
||||||
|
"Fantasy",
|
||||||
|
"Nik P.",
|
||||||
|
"Nockis",
|
||||||
|
"Nicole",
|
||||||
|
"Amigos",
|
||||||
|
"Andita",
|
||||||
|
"Belsy",
|
||||||
|
"Harpo",
|
||||||
|
];
|
||||||
|
|
||||||
|
const norm = (s: string) =>
|
||||||
|
s.toLowerCase().replace(/[-\u2010-\u2015\u00ad]/g, " ").replace(/\s+/g, " ");
|
||||||
|
|
||||||
|
const NORMED = ARTISTS.map((a) => [a, norm(a)] as const);
|
||||||
|
|
||||||
|
/** Ime izvajalca iz naslova; prazen niz, ce ga ni na seznamu. */
|
||||||
|
export function artistKey(title: string): string {
|
||||||
|
const t = norm(title || "");
|
||||||
|
let best = "";
|
||||||
|
let bestPos = Infinity;
|
||||||
|
for (const [orig, n] of NORMED) {
|
||||||
|
const p = t.indexOf(n);
|
||||||
|
if (p >= 0 && (p < bestPos || (p === bestPos && orig.length > best.length))) {
|
||||||
|
best = orig;
|
||||||
|
bestPos = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best ? norm(best) : "";
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
|
import { artistKey } from "@/lib/artists";
|
||||||
import { Link } from "wouter";
|
import { Link } from "wouter";
|
||||||
import { type Article } from "@shared/schema";
|
import { type Article } from "@shared/schema";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
@@ -772,6 +773,27 @@ export default function Home() {
|
|||||||
return [...head, ...tail];
|
return [...head, ...tail];
|
||||||
}, [articles]);
|
}, [articles]);
|
||||||
|
|
||||||
|
// Na naslovnici isti izvajalec ne sme stati drug ob drugem: med dvema clankoma
|
||||||
|
// istega izvajalca mora biti vsaj 5 mest. Clanek ostane v rubriki News in v indeksu.
|
||||||
|
const RAZMIK = 5;
|
||||||
|
const spaced = useMemo(() => {
|
||||||
|
const rest = [...shuffled];
|
||||||
|
const out: Article[] = [];
|
||||||
|
const recent: string[] = [];
|
||||||
|
while (rest.length) {
|
||||||
|
let idx = rest.findIndex((a) => {
|
||||||
|
const k = artistKey(a.title || "");
|
||||||
|
return !k || !recent.includes(k);
|
||||||
|
});
|
||||||
|
if (idx < 0) idx = 0;
|
||||||
|
const a = rest.splice(idx, 1)[0];
|
||||||
|
out.push(a);
|
||||||
|
recent.push(artistKey(a.title || ""));
|
||||||
|
if (recent.length >= RAZMIK) recent.shift();
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}, [shuffled]);
|
||||||
|
|
||||||
const widgets = useMemo(() => [
|
const widgets = useMemo(() => [
|
||||||
{ id: "horoscope", el: <HoroscopeWidget key="horoscope" /> },
|
{ id: "horoscope", el: <HoroscopeWidget key="horoscope" /> },
|
||||||
{ id: "news", el: <div key="news" className="flex flex-col gap-4"><NewsWidget /></div> },
|
{ id: "news", el: <div key="news" className="flex flex-col gap-4"><NewsWidget /></div> },
|
||||||
@@ -794,19 +816,19 @@ export default function Home() {
|
|||||||
for (let r = 0; r < widgetRows; r++) {
|
for (let r = 0; r < widgetRows; r++) {
|
||||||
if (wi < widgets.length) items.push({ type: "widget", key: `w-${widgets[wi].id}`, widget: widgets[wi++] });
|
if (wi < widgets.length) items.push({ type: "widget", key: `w-${widgets[wi].id}`, widget: widgets[wi++] });
|
||||||
if (wi < widgets.length) items.push({ type: "widget", key: `w-${widgets[wi].id}`, widget: widgets[wi++] });
|
if (wi < widgets.length) items.push({ type: "widget", key: `w-${widgets[wi].id}`, widget: widgets[wi++] });
|
||||||
if (ai < shuffled.length) items.push({ type: "article", key: `a-${shuffled[ai].id}`, article: shuffled[ai++] });
|
if (ai < spaced.length) items.push({ type: "article", key: `a-${spaced[ai].id}`, article: spaced[ai++] });
|
||||||
if (ai < shuffled.length) items.push({ type: "article", key: `a-${shuffled[ai].id}`, article: shuffled[ai++] });
|
if (ai < spaced.length) items.push({ type: "article", key: `a-${spaced[ai].id}`, article: spaced[ai++] });
|
||||||
}
|
}
|
||||||
|
|
||||||
while (ai < shuffled.length) {
|
while (ai < spaced.length) {
|
||||||
items.push({ type: "article", key: `a-${shuffled[ai].id}`, article: shuffled[ai++] });
|
items.push({ type: "article", key: `a-${spaced[ai].id}`, article: spaced[ai++] });
|
||||||
}
|
}
|
||||||
|
|
||||||
const remainder = items.length % 4;
|
const remainder = items.length % 4;
|
||||||
if (remainder > 0 && shuffled.length > 0) {
|
if (remainder > 0 && spaced.length > 0) {
|
||||||
let fill = 0;
|
let fill = 0;
|
||||||
while (items.length % 4 !== 0) {
|
while (items.length % 4 !== 0) {
|
||||||
const art = shuffled[fill % shuffled.length];
|
const art = spaced[fill % spaced.length];
|
||||||
items.push({ type: "article", key: `fill-${fill}`, article: art });
|
items.push({ type: "article", key: `fill-${fill}`, article: art });
|
||||||
fill++;
|
fill++;
|
||||||
}
|
}
|
||||||
@@ -824,7 +846,7 @@ export default function Home() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return items;
|
return items;
|
||||||
}, [shuffled, widgets]);
|
}, [spaced, widgets]);
|
||||||
|
|
||||||
const gridRows: (typeof gridItems)[] = useMemo(() => {
|
const gridRows: (typeof gridItems)[] = useMemo(() => {
|
||||||
const rows: (typeof gridItems)[] = [];
|
const rows: (typeof gridItems)[] = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user