Skip to content

Commit

Permalink
Enable viewby links
Browse files Browse the repository at this point in the history
  • Loading branch information
Jalaj committed Sep 6, 2020
1 parent 03a6c40 commit d720ce1
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 8 deletions.
2 changes: 1 addition & 1 deletion src/components/DesktopDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ class DesktopMenu extends React.Component {
Icon={PendingIcon}
/>
<DrawerItem
link="/todox/viewby/done"
link="/todox/viewby/completed"
text="Done"
Icon={CheckIcon}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/components/MobileDrawer.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ class MobileMenu extends React.Component {
<DrawerItem
className={this.props.classes.a}
handleDrawer={this.handleDrawerToggle}
link="/todox/viewby/done"
link="/todox/viewby/completed"
text="Done"
Icon={CheckIcon}
/>
Expand Down
10 changes: 8 additions & 2 deletions src/components/TodoItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ class TodoItem extends React.Component {
<div className={this.props.classes.root}>
<Accordion
expanded={this.state.isOpen}
className={this.task.starred ? this.props.classes.starred : ""}
className={this.task.done ? this.props.classes.done : this.task.starred ? this.props.classes.starred : ""}
>
<AccordionSummary
expandIcon={<ExpandMoreOutlined />}
Expand Down Expand Up @@ -219,15 +219,17 @@ class TodoItem extends React.Component {
<Divider />
<AccordionActions>
<Button
disabled={this.task.done}
startIcon={<DeleteOutlined />}
size="small"
onClick={this.handleDelete}
>
Delete
</Button>

<Link to={`/todox/edit/${this.task.id}`}>
<Link to={this.task.done ? "#" : `/todox/edit/${this.task.id}`}>
<Button
disabled={this.task.done}
startIcon={<EditOutlined />}
size="small"
color="secondary"
Expand All @@ -236,6 +238,7 @@ class TodoItem extends React.Component {
</Button>
</Link>
<Button
disabled={this.task.done}
startIcon={<CheckOutlined />}
size="small"
color="primary"
Expand Down Expand Up @@ -285,6 +288,9 @@ export default withStyles(theme => ({
starred: {
borderLeft: "3px solid yellow",
},
done: {
borderLeft: "3px solid #4caf50",
},
reminderTiming: {
minWidth: "fit-content",
},
Expand Down
2 changes: 2 additions & 0 deletions src/pages/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ let Lists = React.lazy(() => import("./lists"))
let Create = React.lazy(() => import("./create"))
let Starred = React.lazy(() => import("./starred"))
let Edit = React.lazy(() => import("./edit"))
let ViewBy = React.lazy(() => import("./viewby"))

const drawerWidth = 240

Expand Down Expand Up @@ -61,6 +62,7 @@ class Home extends React.Component {
<Route path="/todox/new/:id" component={Create} />
<Route path="/todox/starred" component={Starred} />
<Route path="/todox/edit/:id" component={Edit} />
<Route path="/todox/viewby/:id" component={ViewBy} />
</Switch>
</main>
</Suspense>
Expand Down
2 changes: 1 addition & 1 deletion src/pages/lists.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class List extends React.Component {

shouldComponentUpdate(nextProps, nextState) {
if (nextProps.match.params.id !== this.state.listname) {
this.updateListData(nextProps)
this.updateListData()
return false
} else {
if (this.state !== nextState) {
Expand Down
6 changes: 3 additions & 3 deletions src/pages/starred.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ let TodoList = props => {
)
}

class List extends React.Component {
class Starred extends React.Component {
/**
* This component is the actual 'list' where all the individual
* components are rendered.
Expand Down Expand Up @@ -114,7 +114,7 @@ class List extends React.Component {

shouldComponentUpdate(nextProps, nextState) {
if (nextProps.match.params.id !== this.state.listname) {
this.updateListData(nextProps)
this.updateListData()
return false
} else {
if (this.state !== nextState) {
Expand Down Expand Up @@ -230,4 +230,4 @@ export default withStyles(theme => ({
bottom: 25,
right: 25,
},
}))(List)
}))(Starred)
268 changes: 268 additions & 0 deletions src/pages/viewby.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
import React, { Suspense } from "react"
import { makeStyles, withStyles } from "@material-ui/core/styles"
import { Paper, Typography } from "@material-ui/core"
import { ErrorOutlineOutlined } from "@material-ui/icons"
import { Skeleton } from "@material-ui/lab"
import diff from "date-fns/differenceInMinutes"

/**
* Lazy load the TodoItem component becaus the list may be empty
* or it may even not exist
*/
let TodoItem = React.lazy(() => import("../components/TodoItem"))

/**
* This component provides a skeleton animation until
* the actual todos are being loaded
*/
let Loader = () => {
let classes = makeStyles(theme => ({
paper: {
width: "-webkit-fill-available",
alignItems: "center",
padding: 8,
marginTop: 8,
display: "block",
},
}))()
return (
<Paper className={classes.paper}>
<Skeleton width={0.5 * window.innerWidth} animation="wave" />
<Skeleton width={0.15 * window.innerWidth} animation="wave" />
</Paper>
)
}

/**
* This component renders the whole actual lis of todos
* for the given list. It i separate because it uses Suspense
* as the TodoItem component may not be loaded yet (Its being
* lazy loaded)
*
* @param {*} props
*/
let TodoList = props => {
return (
<Suspense fallback={<Loader />}>
{props.tasks.map(task => (
<TodoItem task={task} key={task.id} unMount={props.unMount} />
))}
</Suspense>
)
}

class Viewby extends React.Component {
/**
* This component is the actual 'list' where all the individual
* components are rendered.
*
* @param {*} props
*/
constructor(props) {
super(props)
let status
switch (this.props.match.params.id) {
case "completed":
status = 2
break
case "pending":
status = 0
break
case "missing":
status = 1
break
default:
status = 2
break
}
this.classes = this.props.classes
this.state = {
error: false,
loaded: false,
tasks: [],
statusText: this.props.match.params.id.capitalize(),
status,
}
this.updateListData = this.updateListData.bind(this)
}

updateListData(props) {
props = props || this.props
let status
switch (props.match.params.id) {
case "completed":
status = 2
break
case "pending":
status = 0
break
case "missing":
status = 1
break
default:
status = 2
break
}

let statusText = props.match.params.id.capitalize()

if (window.setTitle) window.setTitle(`${statusText} tasks`)
document.title = `${statusText} tasks`
//Get the tasks
window.database.getAllByIndex(
"tasks",
"status",
status
).onsuccess = evt => {
let tasks = evt.target.result
tasks.sort((a, b) => {
if (a.deadline) {
if (b.deadline) {
let d = diff(a.deadline, b.deadline)
return d > 0 ? 1 : d < 0 ? -1 : 0
} else {
let d = diff(a.deadline, b.timeStamp)
return d > 0 ? 1 : d < 0 ? -1 : 0
}
} else if (b.deadline) {
let d = diff(a.timeStamp, b.deadline)
return d > 0 ? 1 : d < 0 ? -1 : 0
} else {
let d = diff(a.timeStamp, b.timeStamp)
return d > 0 ? 1 : d < 0 ? -1 : 0
}
})
//Change the state
this.setState({
//Create an error if there are no tasks in the list
error: tasks.length === 0 ? "You have no tasks in this list yet" : null,
loaded: true,
tasks: tasks,
})
}
}

shouldComponentUpdate(nextProps, nextState) {
if (nextProps.match.params.id !== this.props.match.params.id) {
this.updateListData(nextProps)
return false
} else {
if (this.state !== nextState) {
return true
}
return false
}
}

componentDidUpdate(props, state) {
if (props.match.params.id !== this.props.match.params.id) {
let status
switch (this.props.match.params.id) {
case "completed":
status = 2
break
case "pending":
status = 0
break
case "missing":
status = 1
break
default:
status = 2
break
}
this.setState({
...this.state,
statusText: this.props.match.params.id.capitalize(),
status,
})
}
}

/**
* This function executes the tasks that we should do only
* once the component has been mounted, otherwise we won't
* be able to update the state.
*
* It accesses the database and searches for the tasks in this list
*/
componentDidMount() {
if (!window.database) {
import("../database").then(database => {
console.log("[indexedDB] Creating database instance")
new database.default().onsuccess = evt => {
window.database = evt.target.result
this.updateListData()
}
})
} else {
this.updateListData()
}
}

render() {
return (
<div className={this.classes.root}>
{
//Check whether data is available or not and show content likewise
this.state.loaded ? (
//Look for errors
this.state.error ? (
<div className={this.classes.error}>
<ErrorOutlineOutlined className={this.classes.icon} />
<Typography>{this.state.error}</Typography>
</div>
) : (
//Load the todos
<TodoList
tasks={this.state.tasks}
unMount={this.updateListData}
/>
)
) : (
//Show the loader
<Loader />
)
}
</div>
)
}
}

/**
* Get the list styled and export it.
*/
export default withStyles(theme => ({
root: {
display: "block",
maxHeight: "80vh",
},
grow: {
flexGrow: 1,
},
paper: {
width: "-webkit-fill-available",
display: "flex",
alignItems: "center",
padding: 8,
marginTop: 8,
},
icon: {
width: "60%",
height: "60%",
},
error: {
width: "-webkit-fill-available",
[theme.breakpoints.up("sm")]: {
width: "60%",
},
background: "transparent",
opacity: 0.7,
textAlign: "center",
},
fab: {
position: "fixed",
bottom: 25,
right: 25,
},
}))(Viewby)

0 comments on commit d720ce1

Please sign in to comment.