change the npm to yarn and update the json
This commit is contained in:
parent
78738c9282
commit
effd1d38d0
19 changed files with 4111 additions and 6 deletions
|
@ -88,9 +88,9 @@ There are mainly 2 ways of installing Perplexica - With Docker, Without Docker.
|
|||
1. Install SearXNG and allow `JSON` format in the SearXNG settings.
|
||||
2. Clone the repository and rename the `sample.config.toml` file to `config.toml` in the root directory. Ensure you complete all required fields in this file.
|
||||
3. Rename the `.env.example` file to `.env` in the `ui` folder and fill in all necessary fields.
|
||||
4. After populating the configuration and environment files, run `npm i` in both the `ui` folder and the root directory.
|
||||
5. Install the dependencies and then execute `npm run build` in both the `ui` folder and the root directory.
|
||||
6. Finally, start both the frontend and the backend by running `npm run start` in both the `ui` folder and the root directory.
|
||||
4. After populating the configuration and environment files, run `yarn install` in both the `ui` folder and the root directory.
|
||||
5. Install the dependencies and then execute `yarn build` in both the `ui` folder and the root directory.
|
||||
6. Finally, start both the frontend and the backend by running `yarn start` in both the `ui` folder and the root directory.
|
||||
|
||||
**Note**: Using Docker is recommended as it simplifies the setup process, especially for managing environment variables and dependencies.
|
||||
|
||||
|
|
622
public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json
Normal file
622
public/data/1fa9b398-080f-54de-9a4f-3ba386acce11.json
Normal file
File diff suppressed because one or more lines are too long
427
public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json
Normal file
427
public/data/73090b7b-a04e-5c50-ae84-c77f1d7d03a8.json
Normal file
File diff suppressed because one or more lines are too long
546
public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json
Normal file
546
public/data/869d933c-e186-51b0-a225-edc2d338b6fa.json
Normal file
File diff suppressed because one or more lines are too long
1316
public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json
Normal file
1316
public/data/b84c7962-2971-53de-a99b-3c9e45492c79.json
Normal file
File diff suppressed because one or more lines are too long
387
public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json
Normal file
387
public/data/ed701716-e443-5804-aaa9-99e7e04c33e2.json
Normal file
File diff suppressed because one or more lines are too long
549
public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json
Normal file
549
public/data/fd20973f-54b2-5b15-bf7b-79b5e5515b5c.json
Normal file
File diff suppressed because one or more lines are too long
32
public/data/index.json
Normal file
32
public/data/index.json
Normal file
|
@ -0,0 +1,32 @@
|
|||
[
|
||||
{
|
||||
"id": "ed701716-e443-5804-aaa9-99e7e04c33e2",
|
||||
"title": "胖东来食品安全事件:迅速回应与整改措施",
|
||||
"summary": "一位顾客在抖音平台曝光了新乡胖东来餐饮部的卫生问题,引发广泛关注。胖东来商贸集团迅速回应,发布调查报告并采取补偿措施,包括现金奖励和退款。公司还对相关责任人进行了处理,并制定了整改措施以提升食品安全标准。尽管事件对品牌形象造成影响,但透明处理赢得了消费者的信任和支持。"
|
||||
},
|
||||
{
|
||||
"id": "869d933c-e186-51b0-a225-edc2d338b6fa",
|
||||
"title": "姜萍:从中专生到数学竞赛决赛的传奇",
|
||||
"summary": "来自江苏涟水中等专业学校的17岁女生姜萍,以其卓越的数学才能和不懈的努力,成功闯入2024年阿里巴巴全球数学竞赛决赛,取得第12名的优异成绩。她的成就不仅打破了对中专生和女性在数学领域的刻板印象,还引发了关于教育公平的广泛讨论。尽管面临质疑,姜萍的故事激励了无数人,展示了知识改变命运的力量。"
|
||||
},
|
||||
{
|
||||
"id": "73090b7b-a04e-5c50-ae84-c77f1d7d03a8",
|
||||
"title": "梅州洪灾:紧急救援与重建希望",
|
||||
"summary": "近日,梅州遭遇罕见洪灾,暴雨引发的洪水和山体滑坡导致多个乡镇严重受灾,造成重大人员伤亡和经济损失。政府和社会各界迅速展开紧急救援行动,社区成员齐心协力,积极投身于家园重建工作。同时,卫生部门展开大规模防疫行动,确保灾后安全。受灾居民展现出惊人的坚韧与希望,共同努力恢复正常生活。"
|
||||
},
|
||||
{
|
||||
"id": "1fa9b398-080f-54de-9a4f-3ba386acce11",
|
||||
"title": "东方甄选主播顿顿直播间公开表达不满引发热议",
|
||||
"summary": "在一次直播中,东方甄选主播顿顿对公司管理表达了强烈不满,指出沟通不畅和公关反应迟缓等问题。这一言论迅速引发广泛关注,不仅影响了公司股价,还引起了粉丝的热烈讨论。市场对公司管理的担忧加剧,凸显了内部管理亟需改进的迫切性。"
|
||||
},
|
||||
{
|
||||
"id": "fd20973f-54b2-5b15-bf7b-79b5e5515b5c",
|
||||
"title": "鸿蒙智行销量创新高,智能科技引领豪华车新潮流",
|
||||
"summary": "鸿蒙智行在2024年上半年实现了近20万辆的交付量,成为中国新势力品牌的销量冠军。其关键车型如问界M9和新M7表现尤为突出,凭借卓越的产品质量和技术创新,鸿蒙智行不仅提升了用户的驾驶体验,还重新定义了豪华车的标准。未来,鸿蒙智行将继续推动行业变革,推出更多创新车型和技术,巩固其市场领导地位。"
|
||||
},
|
||||
{
|
||||
"id": "b84c7962-2971-53de-a99b-3c9e45492c79",
|
||||
"title": "Apple Secures Observer Role on OpenAI Board",
|
||||
"summary": "Apple has taken a significant step in enhancing its AI capabilities by obtaining an observer position on OpenAI's board. This move, highlighted by the appointment of Phil Schiller, aims to deepen Apple's understanding of AI advancements. The integration of ChatGPT into Apple's ecosystem promises to revolutionize user experiences, positioning Apple at the forefront of AI innovation and consumer technology."
|
||||
}
|
||||
]
|
12
ui/app/news/[id]/layout.tsx
Normal file
12
ui/app/news/[id]/layout.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import Link from "next/link";
|
||||
|
||||
export default function NewsLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto p-4">
|
||||
<Link href="/" className="text-blue-500 hover:underline mb-4 inline-block">
|
||||
← Back to News List
|
||||
</Link>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
13
ui/app/news/[id]/page.tsx
Normal file
13
ui/app/news/[id]/page.tsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { fetchNewsData } from "../../../lib/fetchNewsData";
|
||||
import NewsDetail from "../../../components/NewsDetail";
|
||||
|
||||
|
||||
export default async function NewsPage({ params }: { params: { id: string } }) {
|
||||
const newsData = await fetchNewsData(params.id);
|
||||
|
||||
if (!newsData) {
|
||||
return <div>News not found</div>;
|
||||
}
|
||||
|
||||
return <NewsDetail news={newsData} />;
|
||||
}
|
12
ui/app/news/layout.tsx
Normal file
12
ui/app/news/layout.tsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Metadata } from "next";
|
||||
import React from "react";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "News - Perplexica",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <div>{children}</div>;
|
||||
};
|
||||
|
||||
export default Layout;
|
5
ui/app/news/page.tsx
Normal file
5
ui/app/news/page.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import NewsPage from "@/components/NewsPage";
|
||||
|
||||
export default function Page() {
|
||||
return <NewsPage />;
|
||||
}
|
42
ui/components/ContextItem.tsx
Normal file
42
ui/components/ContextItem.tsx
Normal file
|
@ -0,0 +1,42 @@
|
|||
import React from "react";
|
||||
import Image from "next/image";
|
||||
|
||||
interface ContextItemProps {
|
||||
item: {
|
||||
name: string;
|
||||
url: string;
|
||||
description: string;
|
||||
provider: { name: string; image?: { thumbnail: { contentUrl: string } } }[];
|
||||
datePublished: string;
|
||||
image?: {
|
||||
contentUrl: string;
|
||||
thumbnail: { contentUrl: string; width: number; height: number };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const ContextItem: React.FC<ContextItemProps> = ({ item }) => {
|
||||
return (
|
||||
<div className="border p-4 rounded-lg mb-4">
|
||||
<h4 className="font-bold">{item.name}</h4>
|
||||
{item.image && (
|
||||
<Image
|
||||
src={item.image.contentUrl}
|
||||
alt={item.name}
|
||||
width={item.image.thumbnail.width}
|
||||
height={item.image.thumbnail.height}
|
||||
className="my-2 rounded"
|
||||
/>
|
||||
)}
|
||||
<p>{item.description}</p>
|
||||
<div className="text-sm text-gray-500 mt-2">
|
||||
{item.provider[0].name} | {new Date(item.datePublished).toLocaleDateString()}
|
||||
</div>
|
||||
<a href={item.url} target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline">
|
||||
Read more
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ContextItem;
|
|
@ -4,6 +4,7 @@ const Attach = () => {
|
|||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Attach a file"
|
||||
className="p-2 text-black/50 dark:text-white/50 rounded-xl hover:bg-light-secondary dark:hover:bg-dark-secondary transition duration-200 hover:text-black dark:hover:text-white"
|
||||
>
|
||||
<CopyPlus />
|
||||
|
|
35
ui/components/NewsDetail.tsx
Normal file
35
ui/components/NewsDetail.tsx
Normal file
|
@ -0,0 +1,35 @@
|
|||
import React from "react";
|
||||
import ContextItem from "./ContextItem";
|
||||
|
||||
interface NewsDetailProps {
|
||||
news: {
|
||||
title: string;
|
||||
sections: {
|
||||
title: string;
|
||||
content: string;
|
||||
context: any[];
|
||||
}[];
|
||||
};
|
||||
}
|
||||
|
||||
const NewsDetail: React.FC<NewsDetailProps> = ({ news }) => {
|
||||
return (
|
||||
<article className="prose lg:prose-xl">
|
||||
<h1>{news.title}</h1>
|
||||
{news.sections.map((section, index) => (
|
||||
<section key={index}>
|
||||
<h2>{section.title}</h2>
|
||||
<p>{section.content}</p>
|
||||
<div className="mt-4">
|
||||
<h3>Related Context:</h3>
|
||||
{section.context.map((item, i) => (
|
||||
<ContextItem key={i} item={item} />
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
))}
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewsDetail;
|
85
ui/components/NewsPage.tsx
Normal file
85
ui/components/NewsPage.tsx
Normal file
|
@ -0,0 +1,85 @@
|
|||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import { Newspaper } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
|
||||
interface NewsItem {
|
||||
id: string;
|
||||
title: string;
|
||||
summary: string;
|
||||
}
|
||||
|
||||
const NewsPage = () => {
|
||||
const [news, setNews] = useState<NewsItem[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchNews = async () => {
|
||||
try {
|
||||
console.log("Fetching news...");
|
||||
const response = await fetch(
|
||||
"https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/index.json",
|
||||
);
|
||||
console.log("Response status:", response.status);
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const data = await response.json();
|
||||
console.log("Fetched data:", data);
|
||||
setNews(data);
|
||||
} catch (error) {
|
||||
console.error("Error fetching news:", error);
|
||||
setError(`Failed to load news. Error: ${error instanceof Error ? error.message : String(error)}`);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchNews();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="fixed z-40 top-0 left-0 right-0 lg:pl-[104px] lg:pr-6 lg:px-8 px-4 py-4 lg:py-6 border-b border-light-200 dark:border-dark-200">
|
||||
<div className="flex flex-row items-center space-x-2 max-w-screen-lg lg:mx-auto">
|
||||
<Newspaper />
|
||||
<h2 className="text-black dark:text-white lg:text-3xl lg:font-medium">News</h2>
|
||||
</div>
|
||||
</div>
|
||||
{loading ? (
|
||||
<div className="flex flex-row items-center justify-center min-h-screen">
|
||||
<p className="text-black/70 dark:text-white/70 text-sm">Loading news...</p>
|
||||
</div>
|
||||
) : error ? (
|
||||
<div className="flex flex-col items-center justify-center min-h-screen">
|
||||
<p className="text-red-500 text-sm mb-2">Failed to load news.</p>
|
||||
<p className="text-red-500 text-xs">{error}</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col pt-16 lg:pt-24">
|
||||
{news.length === 0 ? (
|
||||
<p className="text-black/70 dark:text-white/70 text-sm text-center">No news available.</p>
|
||||
) : (
|
||||
news.map(item => (
|
||||
<div
|
||||
key={item.id}
|
||||
className="flex flex-col space-y-4 border-b border-white-200 dark:border-dark-200 py-6 lg:mx-4"
|
||||
>
|
||||
<Link href={`/news/${item.id}`}>
|
||||
<h3 className="text-black dark:text-white lg:text-xl font-medium hover:underline cursor-pointer">
|
||||
{item.title}
|
||||
</h3>
|
||||
</Link>
|
||||
<p className="text-black/70 dark:text-white/70 text-sm">{item.summary}</p>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NewsPage;
|
|
@ -1,7 +1,7 @@
|
|||
"use client";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { BookOpenText, Home, Search, SquarePen, Settings } from "lucide-react";
|
||||
import { BookOpenText, Home, Search, SquarePen, Settings, Newspaper } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
import { useSelectedLayoutSegments } from "next/navigation";
|
||||
import React, { useState, type ReactNode } from "react";
|
||||
|
@ -36,6 +36,12 @@ const Sidebar = ({ children }: { children: React.ReactNode }) => {
|
|||
active: segments.includes("library"),
|
||||
label: "Library",
|
||||
},
|
||||
{
|
||||
icon: Newspaper,
|
||||
href: "/news",
|
||||
active: segments.includes("news"),
|
||||
label: "News",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
|
|
9
ui/lib/fetchNewsData.ts
Normal file
9
ui/lib/fetchNewsData.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
export async function fetchNewsData(id: string) {
|
||||
const response = await fetch(
|
||||
`https://raw.githubusercontent.com/newspedia-crew/newspedia-web/intern-change/public/data/${id}.json`,
|
||||
);
|
||||
if (!response.ok) {
|
||||
return null;
|
||||
}
|
||||
return response.json();
|
||||
}
|
|
@ -2,14 +2,20 @@
|
|||
// eslint-disable-next-line no-undef, @typescript-eslint/no-var-requires
|
||||
const webpack = require("webpack");
|
||||
|
||||
/** @type {import('next').NextConfig} */
|
||||
/** @type {import("next").NextConfig} */
|
||||
const nextConfig = {
|
||||
images: {
|
||||
remotePatterns: [
|
||||
{
|
||||
hostname: "s2.googleusercontent.com",
|
||||
protocol: "https",
|
||||
hostname: "**",
|
||||
},
|
||||
{
|
||||
protocol: "http",
|
||||
hostname: "**",
|
||||
},
|
||||
],
|
||||
domains: ["raw.githubusercontent.com"],
|
||||
},
|
||||
|
||||
webpack: (config, { isServer }) => {
|
||||
|
|
Loading…
Add table
Reference in a new issue