worker-1: completed task task-entry-display [failed]
This commit is contained in:
parent
6f67ad651f
commit
cca0461b43
@ -16,6 +16,7 @@ description: |
|
||||
- Navigation between entries
|
||||
- Responsive layout for entries
|
||||
assigned_to: worker-1
|
||||
status: in_progress
|
||||
status: failed
|
||||
result: 'qwen: agent loop: agent exceeded max steps (20)'
|
||||
created_at: 2026-04-08T00:01:49.285216405Z
|
||||
updated_at: 2026-04-08T00:11:56.093348849Z
|
||||
updated_at: 2026-04-08T00:14:14.753366487Z
|
||||
|
||||
55
src/components/EntryDetailCard.css
Normal file
55
src/components/EntryDetailCard.css
Normal file
@ -0,0 +1,55 @@
|
||||
.entry-detail-card {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.entry-header {
|
||||
margin-bottom: 20px;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.entry-title {
|
||||
margin: 0 0 8px 0;
|
||||
color: #212529;
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.entry-category {
|
||||
font-size: 1rem;
|
||||
color: #6c757d;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.entry-content {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.entry-definition {
|
||||
font-size: 1.1rem;
|
||||
color: #495057;
|
||||
margin: 0 0 20px 0;
|
||||
padding: 16px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 6px;
|
||||
border-left: 4px solid #28a745;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.entry-detail-card {
|
||||
margin: 10px;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.entry-title {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.entry-definition {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
37
src/components/EntryDetailCard.js
Normal file
37
src/components/EntryDetailCard.js
Normal file
@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import EntryMetadata from './EntryMetadata';
|
||||
import RelatedEntries from './RelatedEntries';
|
||||
import './EntryDetailCard.css';
|
||||
|
||||
const EntryDetailCard = ({ entry }) => {
|
||||
return (
|
||||
<div className="entry-detail-card">
|
||||
<div className="entry-header">
|
||||
<h1 className="entry-title">{entry.term}</h1>
|
||||
<div className="entry-category">{entry.category}</div>
|
||||
</div>
|
||||
|
||||
<div className="entry-content">
|
||||
<p className="entry-definition">{entry.definition}</p>
|
||||
|
||||
<EntryMetadata entry={entry} />
|
||||
|
||||
{entry.relatedTerms && entry.relatedTerms.length > 0 && (
|
||||
<RelatedEntries
|
||||
relatedEntries={entry.relatedTerms}
|
||||
title="Related Terms"
|
||||
/>
|
||||
)}
|
||||
|
||||
{entry.relatedEntries && entry.relatedEntries.length > 0 && (
|
||||
<RelatedEntries
|
||||
relatedEntries={entry.relatedEntries}
|
||||
title="Related Entries"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EntryDetailCard;
|
||||
23
src/components/EntryMetadata.css
Normal file
23
src/components/EntryMetadata.css
Normal file
@ -0,0 +1,23 @@
|
||||
.entry-metadata {
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
margin: 20px 0;
|
||||
border-left: 4px solid #007bff;
|
||||
}
|
||||
|
||||
.metadata-item {
|
||||
display: flex;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.metadata-label {
|
||||
font-weight: bold;
|
||||
margin-right: 8px;
|
||||
min-width: 80px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.metadata-value {
|
||||
color: #212529;
|
||||
}
|
||||
25
src/components/EntryMetadata.js
Normal file
25
src/components/EntryMetadata.js
Normal file
@ -0,0 +1,25 @@
|
||||
import React from 'react';
|
||||
import './EntryMetadata.css';
|
||||
|
||||
const EntryMetadata = ({ entry }) => {
|
||||
return (
|
||||
<div className="entry-metadata">
|
||||
<div className="metadata-item">
|
||||
<span className="metadata-label">Category:</span>
|
||||
<span className="metadata-value">{entry.category}</span>
|
||||
</div>
|
||||
<div className="metadata-item">
|
||||
<span className="metadata-label">Added:</span>
|
||||
<span className="metadata-value">{entry.dateAdded}</span>
|
||||
</div>
|
||||
{entry.author && (
|
||||
<div className="metadata-item">
|
||||
<span className="metadata-label">Author:</span>
|
||||
<span className="metadata-value">{entry.author}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EntryMetadata;
|
||||
47
src/components/EntryNavigation.css
Normal file
47
src/components/EntryNavigation.css
Normal file
@ -0,0 +1,47 @@
|
||||
.entry-navigation {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 20px 0;
|
||||
padding: 16px 0;
|
||||
border-top: 1px solid #e9ecef;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
padding: 10px 20px;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.prev-button {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.prev-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.next-button {
|
||||
background-color: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.next-button:hover {
|
||||
background-color: #1e7e34;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.entry-navigation {
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
width: 80%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
31
src/components/EntryNavigation.js
Normal file
31
src/components/EntryNavigation.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './EntryNavigation.css';
|
||||
|
||||
const EntryNavigation = ({ entry, allEntries }) => {
|
||||
if (!allEntries || allEntries.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentIndex = allEntries.findIndex(e => e.id === entry.id);
|
||||
const prevEntry = currentIndex > 0 ? allEntries[currentIndex - 1] : null;
|
||||
const nextEntry = currentIndex < allEntries.length - 1 ? allEntries[currentIndex + 1] : null;
|
||||
|
||||
return (
|
||||
<div className="entry-navigation">
|
||||
{prevEntry && (
|
||||
<Link to={`/entry/${prevEntry.id}`} className="nav-button prev-button">
|
||||
← {prevEntry.term}
|
||||
</Link>
|
||||
)}
|
||||
|
||||
{nextEntry && (
|
||||
<Link to={`/entry/${nextEntry.id}`} className="nav-button next-button">
|
||||
{nextEntry.term} →
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EntryNavigation;
|
||||
32
src/components/RelatedEntries.css
Normal file
32
src/components/RelatedEntries.css
Normal file
@ -0,0 +1,32 @@
|
||||
.related-entries {
|
||||
margin: 20px 0;
|
||||
padding: 16px;
|
||||
background-color: #e9ecef;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.related-entries-title {
|
||||
margin-top: 0;
|
||||
margin-bottom: 12px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.related-entries-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.related-entry-link {
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
text-decoration: none;
|
||||
font-size: 0.9em;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.related-entry-link:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
28
src/components/RelatedEntries.js
Normal file
28
src/components/RelatedEntries.js
Normal file
@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import './RelatedEntries.css';
|
||||
|
||||
const RelatedEntries = ({ relatedEntries, title = "Related Terms" }) => {
|
||||
if (!relatedEntries || relatedEntries.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="related-entries">
|
||||
<h4 className="related-entries-title">{title}</h4>
|
||||
<div className="related-entries-list">
|
||||
{relatedEntries.map((entry, index) => (
|
||||
<Link
|
||||
key={index}
|
||||
to={typeof entry === 'string' ? `/search?q=${entry}` : `/entry/${entry.id}`}
|
||||
className="related-entry-link"
|
||||
>
|
||||
{typeof entry === 'string' ? entry : entry.term}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default RelatedEntries;
|
||||
18
src/components/ResponsiveEntryLayout.css
Normal file
18
src/components/ResponsiveEntryLayout.css
Normal file
@ -0,0 +1,18 @@
|
||||
.responsive-entry-layout {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.responsive-entry-layout {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.responsive-entry-layout {
|
||||
padding: 0 5px;
|
||||
}
|
||||
}
|
||||
12
src/components/ResponsiveEntryLayout.js
Normal file
12
src/components/ResponsiveEntryLayout.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react';
|
||||
import './ResponsiveEntryLayout.css';
|
||||
|
||||
const ResponsiveEntryLayout = ({ children, className = "" }) => {
|
||||
return (
|
||||
<div className={`responsive-entry-layout ${className}`}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ResponsiveEntryLayout;
|
||||
11
src/pages/EntryDetail.css
Normal file
11
src/pages/EntryDetail.css
Normal file
@ -0,0 +1,11 @@
|
||||
.entry-detail {
|
||||
padding: 20px 0;
|
||||
min-height: calc(100vh - 160px);
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.entry-detail {
|
||||
padding: 10px 0;
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,14 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import EntryDetailCard from '../components/EntryDetailCard';
|
||||
import EntryNavigation from '../components/EntryNavigation';
|
||||
import './EntryDetail.css';
|
||||
|
||||
const EntryDetail = () => {
|
||||
const { id } = useParams();
|
||||
const [entry, setEntry] = useState(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
// In a real app, this would fetch from an API or data file
|
||||
@ -16,7 +20,12 @@ const EntryDetail = () => {
|
||||
definition: "A person who enjoys exploring the details of programmable systems and how to stretch their capabilities.",
|
||||
category: "Core Terms",
|
||||
relatedTerms: ["Cracker", "Security Researcher"],
|
||||
dateAdded: "2026-04-08"
|
||||
relatedEntries: [
|
||||
{ id: 2, term: "Guru" },
|
||||
{ id: 3, term: "Foo" }
|
||||
],
|
||||
dateAdded: "2026-04-08",
|
||||
author: "Tech Contributor"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
@ -24,7 +33,12 @@ const EntryDetail = () => {
|
||||
definition: "A person who has achieved a high level of skill in a particular field or domain.",
|
||||
category: "Core Terms",
|
||||
relatedTerms: ["Expert", "Master"],
|
||||
dateAdded: "2026-04-08"
|
||||
relatedEntries: [
|
||||
{ id: 1, term: "Hacker" },
|
||||
{ id: 3, term: "Foo" }
|
||||
],
|
||||
dateAdded: "2026-04-08",
|
||||
author: "Tech Contributor"
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
@ -32,14 +46,41 @@ const EntryDetail = () => {
|
||||
definition: "A generic term used as a placeholder in examples and documentation.",
|
||||
category: "Technical Terms",
|
||||
relatedTerms: ["Bar", "Baz"],
|
||||
dateAdded: "2026-04-08"
|
||||
relatedEntries: [
|
||||
{ id: 1, term: "Hacker" },
|
||||
{ id: 2, term: "Guru" }
|
||||
],
|
||||
dateAdded: "2026-04-08",
|
||||
author: "Tech Contributor"
|
||||
}
|
||||
];
|
||||
|
||||
const foundEntry = mockEntries.find(e => e.id === parseInt(id));
|
||||
|
||||
if (foundEntry) {
|
||||
setEntry(foundEntry);
|
||||
} else {
|
||||
setError('Entry not found');
|
||||
}
|
||||
setLoading(false);
|
||||
}, [id]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="entry-detail">
|
||||
<p>Loading entry...</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<div className="entry-detail">
|
||||
<p>{error}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
return (
|
||||
<div className="entry-detail">
|
||||
@ -50,28 +91,12 @@ const EntryDetail = () => {
|
||||
|
||||
return (
|
||||
<div className="entry-detail">
|
||||
<div className="entry-header">
|
||||
<h1>{entry.term}</h1>
|
||||
<span className="entry-category">{entry.category}</span>
|
||||
</div>
|
||||
<div className="entry-content">
|
||||
<p className="entry-definition">{entry.definition}</p>
|
||||
{entry.relatedTerms && entry.relatedTerms.length > 0 && (
|
||||
<div className="related-terms">
|
||||
<h4>Related Terms</h4>
|
||||
<div className="related-terms-list">
|
||||
{entry.relatedTerms.map((term, index) => (
|
||||
<span key={index} className="related-term">
|
||||
{term}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="entry-meta">
|
||||
<p>Added: {entry.dateAdded}</p>
|
||||
</div>
|
||||
</div>
|
||||
<EntryDetailCard entry={entry} />
|
||||
<EntryNavigation entry={entry} allEntries={[
|
||||
{ id: 1, term: "Hacker" },
|
||||
{ id: 2, term: "Guru" },
|
||||
{ id: 3, term: "Foo" }
|
||||
]} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user