add Article
This commit is contained in:
parent
364706b708
commit
7072045613
52
src/App.js
52
src/App.js
@ -1,6 +1,13 @@
|
||||
import React from 'react'
|
||||
import axios from 'axios'
|
||||
|
||||
import {
|
||||
createArticle,
|
||||
updateArticle,
|
||||
deleteArticle,
|
||||
selectArticle,
|
||||
} from './controllers/articles'
|
||||
|
||||
import {
|
||||
createTask,
|
||||
updateTask,
|
||||
@ -20,6 +27,8 @@ import { updateProfile } from './controllers/profile'
|
||||
|
||||
import {
|
||||
About,
|
||||
Articles,
|
||||
UpdateArticle,
|
||||
Tasks,
|
||||
UpdateTask,
|
||||
Profile,
|
||||
@ -39,6 +48,7 @@ const defaultState = {
|
||||
component: 'projects',
|
||||
// TODO try to get rid of:
|
||||
search: '',
|
||||
newArticle: '',
|
||||
newTask: '',
|
||||
newProject: '',
|
||||
project: {},
|
||||
@ -52,6 +62,10 @@ class App extends React.Component {
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
this.handleSubmit = this.handleSubmit.bind(this)
|
||||
|
||||
this.createArticle = createArticle.bind(this)
|
||||
this.updateArticle = updateArticle.bind(this)
|
||||
this.deleteArticle = deleteArticle.bind(this)
|
||||
|
||||
this.createTask = createTask.bind(this)
|
||||
this.updateTask = updateTask.bind(this)
|
||||
this.deleteTask = deleteTask.bind(this)
|
||||
@ -62,10 +76,21 @@ class App extends React.Component {
|
||||
|
||||
this.updateProfile = updateProfile.bind(this)
|
||||
|
||||
this.selectArticle = selectArticle.bind(this)
|
||||
this.selectTask = selectTask.bind(this)
|
||||
this.selectProject = selectProject.bind(this)
|
||||
}
|
||||
|
||||
async fetchArticles() {
|
||||
try {
|
||||
const { data } = await axios.get(API + '/api/articles')
|
||||
return data
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
this.setState({ error })
|
||||
}
|
||||
}
|
||||
|
||||
async fetchTasks() {
|
||||
try {
|
||||
const { data } = await axios.get(API + '/api/tasks')
|
||||
@ -87,9 +112,10 @@ class App extends React.Component {
|
||||
}
|
||||
|
||||
async fetchData() {
|
||||
const articles = await this.fetchArticles()
|
||||
const tasks = await this.fetchTasks()
|
||||
const projects = await this.fetchProjects()
|
||||
await this.setState({ loading: false, tasks, projects })
|
||||
await this.setState({ loading: false, articles, tasks, projects })
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@ -139,6 +165,26 @@ class App extends React.Component {
|
||||
/>
|
||||
)
|
||||
}
|
||||
renderArticles() {
|
||||
return (<Articles
|
||||
navigate={this.navigate}
|
||||
handleChange={this.handleChange}
|
||||
createArticle={this.createArticle}
|
||||
selectArticle={this.selectArticle}
|
||||
deleteArticle={this.deleteArticle}
|
||||
{...this.state}
|
||||
/>
|
||||
)
|
||||
}
|
||||
renderUpdateArticle() {
|
||||
return (<UpdateArticle
|
||||
handleChange={this.handleChange}
|
||||
updateArticle={this.updateArticle}
|
||||
navigate={this.navigate}
|
||||
{...this.state}
|
||||
/>
|
||||
)
|
||||
}
|
||||
renderProjects() {
|
||||
return (
|
||||
<Projects
|
||||
@ -217,6 +263,10 @@ class App extends React.Component {
|
||||
? this.renderLoading()
|
||||
: this.state.error
|
||||
? this.renderError()
|
||||
: this.state.component === 'articles'
|
||||
? this.renderArticles()
|
||||
: this.state.component === 'article'
|
||||
? this.renderUpdateArticle()
|
||||
: this.state.component === 'tasks'
|
||||
? this.renderTasks(filtered, completed)
|
||||
: this.state.component === 'task'
|
||||
|
49
src/components/articles.js
Normal file
49
src/components/articles.js
Normal file
@ -0,0 +1,49 @@
|
||||
import React from 'react'
|
||||
|
||||
function Articles(props) {
|
||||
return (
|
||||
<div>
|
||||
<h3 className="mt-4">Articles</h3>
|
||||
<ul className="list-group">
|
||||
{props.articles &&
|
||||
props.articles.map(article => (
|
||||
<li className="list-group-item" key={article.id}>
|
||||
<button
|
||||
className="btn btn-outline-danger mr-1"
|
||||
onClick={() => props.deleteArticle(article.id)}
|
||||
>
|
||||
X
|
||||
</button>
|
||||
<button
|
||||
className="btn ml-1"
|
||||
onClick={() => props.selectArticle(article.id)}
|
||||
>
|
||||
{article.title}{' '}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
|
||||
<li className="list-group-item">
|
||||
<form className="form-group row" onSubmit={props.createArticle}>
|
||||
<input
|
||||
className="form-control col input-sm"
|
||||
placeholder="Create Article"
|
||||
name="newArticle"
|
||||
value={props.newArticle}
|
||||
onChange={props.handleChange}
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
className="form-control col col-sm-2 ml-1 btn btn-primary"
|
||||
onClick={props.createArticle}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Articles
|
@ -1,5 +1,7 @@
|
||||
export { default as Navbar } from './navbar'
|
||||
export { default as About } from './about'
|
||||
export { default as Articles } from './articles'
|
||||
export { default as UpdateArticle } from './update-article'
|
||||
export { default as Tasks } from './tasks'
|
||||
export { default as UpdateTask } from './update-task'
|
||||
export { default as Profile } from './profile'
|
||||
|
@ -23,13 +23,23 @@ function Navbar(props) {
|
||||
</button>
|
||||
<div className="collapse navbar-collapse" id="navbarText">
|
||||
<ul className="navbar-nav mr-auto">
|
||||
<li
|
||||
className={`nav-item ${
|
||||
props.component === 'about' ? 'active' : ''
|
||||
}`}
|
||||
onClick={() => props.navigate('articles')}
|
||||
>
|
||||
<a className="nav-link" href="#articles">
|
||||
Articles
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
className={`nav-item ${
|
||||
props.component === 'project' ? 'active' : ''
|
||||
}`}
|
||||
onClick={() => props.navigate('project')}
|
||||
onClick={() => props.navigate('projects')}
|
||||
>
|
||||
<a className="nav-link" href="#project">
|
||||
<a className="nav-link" href="#projects">
|
||||
Projects
|
||||
</a>
|
||||
</li>
|
||||
|
76
src/components/update-article.js
Normal file
76
src/components/update-article.js
Normal file
@ -0,0 +1,76 @@
|
||||
import React from 'react'
|
||||
|
||||
class UpdateArticle extends React.Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
const article = props.articles.find(t => t.id === props.selectedArticleId)
|
||||
this.state = article
|
||||
this.handleChange = this.handleChange.bind(this)
|
||||
|
||||
if (!props.selectedArticleId) {
|
||||
props.navigate('articles')
|
||||
}
|
||||
}
|
||||
|
||||
handleChange(e) {
|
||||
this.setState({ [e.target.name]: e.target.value })
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div>
|
||||
<span onClick={() => this.props.navigate('articles')}>« back</span>
|
||||
<form>
|
||||
<h2 className="form-group row">Article {this.state.id}</h2>
|
||||
<div className="form-group row">
|
||||
<input
|
||||
type="text"
|
||||
className="form-control mb-1"
|
||||
name="title"
|
||||
value={this.state.title}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-group row">
|
||||
<textarea
|
||||
type="text"
|
||||
className="form-control"
|
||||
name="text"
|
||||
rows="25"
|
||||
value={this.state.text || ""}
|
||||
onChange={this.handleChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="form-group row">
|
||||
<label htmlFor="createdAt" className="col-sm-2 col-form-label">
|
||||
Created:
|
||||
</label>
|
||||
<div className="col-sm-10">
|
||||
<input
|
||||
className="form-control"
|
||||
name="createdAt"
|
||||
value={this.state.createdAt}
|
||||
readOnly
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="form-group row">
|
||||
<div className="col-sm-10">
|
||||
<button
|
||||
type="submit"
|
||||
className="btn btn-primary"
|
||||
onClick={e => this.props.updateArticle(e, this.state)}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
export default UpdateArticle
|
85
src/controllers/articles.js
Normal file
85
src/controllers/articles.js
Normal file
@ -0,0 +1,85 @@
|
||||
import axios from 'axios'
|
||||
const API = process.env.REACT_APP_API || 'http://localhost:1337'
|
||||
|
||||
export async function createArticle(e) {
|
||||
e.preventDefault()
|
||||
if (this.state.newArticle === '') {
|
||||
alert('You forgot the title.')
|
||||
return
|
||||
}
|
||||
const article = { title: this.state.newArticle }
|
||||
try {
|
||||
const { data, error } = await axios.post(API + '/api/articles', article)
|
||||
if (error) {
|
||||
alert(`Received error when creating article ${article.name}: ${error}`)
|
||||
} else if (data.id) {
|
||||
this.setState({
|
||||
articles: this.state.articles.concat(data),
|
||||
newArticle: '',
|
||||
})
|
||||
console.log(`Added article: `, data)
|
||||
} else {
|
||||
alert(`Failed to add article '${article}'.`)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Failed to add article '${this.state.newArticle}'.`)
|
||||
}
|
||||
}
|
||||
|
||||
export function selectArticle(selectedArticleId) {
|
||||
this.setState({ selectedArticleId })
|
||||
this.navigate('article')
|
||||
}
|
||||
|
||||
export async function updateArticle(e, updatedArticle) {
|
||||
e.preventDefault()
|
||||
const oldArticle = this.state.articles.find(t => t.id === updatedArticle.id)
|
||||
if (JSON.stringify(oldArticle) === JSON.stringify(updatedArticle)) {
|
||||
this.navigate('articles')
|
||||
return
|
||||
}
|
||||
try {
|
||||
const { data, error } = await axios.put(
|
||||
API + `/api/articles/${oldArticle.id}`,
|
||||
updatedArticle,
|
||||
)
|
||||
if (error) {
|
||||
alert('Received error when updating article: ', error)
|
||||
} else if (data.title) {
|
||||
const oldArticles = this.state.articles.filter(t => t.id !== updatedArticle.id)
|
||||
this.setState({ articles: oldArticles.concat(updatedArticle) })
|
||||
console.log('Successfully updated article:', data)
|
||||
this.navigate('articles')
|
||||
} else {
|
||||
console.log('Received malformed data when updating article: ', data)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Updating article failed: ${e}`)
|
||||
}
|
||||
}
|
||||
|
||||
export async function deleteArticle(id) {
|
||||
const article = this.state.articles.find(p => p.id === id)
|
||||
if (!article.id) {
|
||||
alert(`Could not find article with id ${id}.`)
|
||||
return
|
||||
}
|
||||
try {
|
||||
const { data, error } = await axios.post(
|
||||
API + `/api/articles/${article.id}/delete`,
|
||||
)
|
||||
if (error) {
|
||||
alert(`Received error when deleting article ${article.title}: ${error}`)
|
||||
} else if (data.title) {
|
||||
console.log('Deleted article:', data)
|
||||
this.setState({
|
||||
articles: this.state.articles.filter(p => p.id !== article.id),
|
||||
})
|
||||
this.navigate('articles')
|
||||
} else {
|
||||
alert(`Failed to delete article '${article.title}'.`)
|
||||
}
|
||||
} catch (e) {
|
||||
alert(`Failed to delete article '${article.title}': ${e}`)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user