add Article

This commit is contained in:
data 2019-07-04 04:06:59 -04:00
parent 364706b708
commit 7072045613
6 changed files with 275 additions and 3 deletions

View File

@ -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'

View 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

View File

@ -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'

View File

@ -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>

View 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')}>&laquo; 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

View 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}`)
}
}