Skip to content

Commit

Permalink
Add loading state and refactor props
Browse files Browse the repository at this point in the history
campb303 committed Mar 1, 2021
1 parent abf98df commit f144667
Showing 6 changed files with 66 additions and 59 deletions.
95 changes: 47 additions & 48 deletions src/components/ItemBodyView/ItemBodyView.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import React from "react";
import PropTypes from "prop-types";
import { Timeline, TimelineItem, TimelineSeparator, TimelineConnector, TimelineContent, TimelineDot, Skeleton } from '@material-ui/lab';
import { Timeline, TimelineItem, TimelineSeparator, TimelineConnector, TimelineContent, TimelineDot } from '@material-ui/lab';
import { makeStyles } from "@material-ui/core";
import DirectoryInformation from "../DirectoryInformation/";
import Assignment from "../Assignment/";
import TimelineActionCard from "../TimelineActionCard/";
import MessageView from "../MessageView/";
import ParseError from "../ParseError/";
import { objectIsEmpty } from "../../utilities";
import TimelineSkeleton from "../TimelineSkeleton/";

export default function ItemBodyView({ item }) {
export default function ItemBodyView({ sections, loading }) {

const useStyles = makeStyles(() => ({
"Timeline-root": {
@@ -30,6 +30,11 @@ export default function ItemBodyView({ item }) {
}));
const classes = useStyles();

/**
* Returns a section type specific timeline item.
* @param {Object} section The
* @returns {Node} A section type specific timeline item.
*/
const generateTimelineItem = (section) => {
switch (section.type) {
case "directory_information":
@@ -41,66 +46,60 @@ export default function ItemBodyView({ item }) {
case "status":
return <TimelineActionCard {...section} />
case "assignment":
return <Assignment {...section} />
return <Assignment {...section} />
case "reply_to_user":
return <TimelineActionCard {...section} />
case "reply_from_user":
return <MessageView {...section} />
return <MessageView {...section} />
case "parse_error":
return <ParseError {...section} />
default:
return `No match found for type: ${section.type}`;
};
};

const testing = true;
const TimelineItemTemplate = ({ children }) => (
<TimelineItem classes={{ missingOppositeContent: classes["TimelineItem-missingOppositeContent"] }} >
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent classes={{ root: classes["TimelineContent-root"] }} >
{children}
</TimelineContent>
</TimelineItem>
);

return (
<Timeline align="left" classes={{ root: classes["Timeline-root"] }}>
{/* Below is the original ternary operation for the map fucntion for future reference */}
{/* {objectIsEmpty(item) ? "" : item.content.map((section) */}

{testing ? Object.keys(item).map((section) => (
<TimelineItem
classes={{
missingOppositeContent: classes["TimelineItem-missingOppositeContent"],
}}
>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent
classes={{ root: classes["TimelineContent-root"] }}
>
<Skeleton />
</TimelineContent>
</TimelineItem>
))
: item.content.map((section) => (
<TimelineItem
classes={{
missingOppositeContent: classes["TimelineItem-missingOppositeContent"],
}}
>
<TimelineSeparator>
<TimelineDot />
<TimelineConnector />
</TimelineSeparator>
<TimelineContent
classes={{ root: classes["TimelineContent-root"] }}
>{item === undefined
? <Skeleton />
: generateTimelineItem(section)
}
</TimelineContent>
</TimelineItem>
))}
{ loading
? ( // Generate 3 placeholders.
[...Array(3).keys()].map( (_, index) => (
<TimelineItemTemplate key={index.toString()}>
<TimelineSkeleton />
</TimelineItemTemplate>
))
)
: ( // Generate timeline.
sections.map((section) => (
<TimelineItemTemplate>
{generateTimelineItem(section)}
</TimelineItemTemplate>
))
)
}
</Timeline>
);
};

ItemBodyView.propTypes = {
/** The item to diplay. */
"item": PropTypes.object.isRequired
};
/** Section of an item to display. */
"sections": PropTypes.array,
/** If true, shows loading placeholder. */
"loading": PropTypes.bool
};

ItemBodyView.defaultProps = {
"sections": [],
"loading": false
}
15 changes: 8 additions & 7 deletions src/components/ItemBodyView/ItemBodyView.md
Original file line number Diff line number Diff line change
@@ -8,15 +8,16 @@ The ItemBodyView displays the seven actions possible in an item:
- **Reply To User:** a message sent from an ECN employee to a user.
- **Reply To ECN:** a message sent from the user to ECN that has been merged into an existing item.

```jsx
import ItemBodyView from "./ItemBodyView";
## Default View
![ItemBodyView_Loaded](/ItemBodyView_Loaded.png)

const demoItem = {"queue": "ce", "number": 100, "lastUpdated": "09-28-20 01:26 PM", "headers": [{"type": "Merged-Time", "content": "Tue, 23 Jun 2020 13:31:53 -0400"}, {"type": "Merged-By", "content": "campb303"}, {"type": "QTime", "content": "1"}, {"type": "QTime-Updated-Time", "content": "Tue, 23 Jun 2020 13:28:50 EDT"}, {"type": "QTime-Updated-By", "content": "campb303"}, {"type": "Time", "content": "1"}, {"type": "Time-Updated-Time", "content": "Tue, 23 Jun 2020 13:28:50 EDT"}, {"type": "Time-Updated-By", "content": "campb303"}, {"type": "Replied-Time", "content": "Tue, 23 Jun 2020 13:28:48 -0400"}, {"type": "Replied-By", "content": "campb303"}, {"type": "Edited-Time", "content": "Tue, 23 Jun 2020 13:27:56 -0400"}, {"type": "Edited-By", "content": "campb303"}, {"type": "QAssigned-To", "content": "campb303"}, {"type": "QAssigned-To-Updated-Time", "content": "Tue, 23 Jun 2020 13:27:00 EDT"}, {"type": "QAssigned-To-Updated-By", "content": "campb303"}, {"type": "Assigned-To", "content": "campb303"}, {"type": "Assigned-To-Updated-Time", "content": "Tue, 23 Jun 2020 13:27:00 EDT"}, {"type": "Assigned-To-Updated-By", "content": "campb303"}, {"type": "QStatus", "content": "Dont Delete"}, {"type": "QStatus-Updated-Time", "content": "Tue, 23 Jun 2020 13:26:55 EDT"}, {"type": "QStatus-Updated-By", "content": "campb303"}, {"type": "Status", "content": "Dont Delete"}, {"type": "Status-Updated-Time", "content": "Tue, 23 Jun 2020 13:26:55 EDT"}, {"type": "Status-Updated-By", "content": "campb303"}, {"type": "Date", "content": "Tue, 23 Jun 2020 13:25:51 -0400"}, {"type": "From", "content": "Justin Campbell <campb303@purdue.edu>"}, {"type": "Message-ID", "content": "<911CE050-3240-4980-91DD-9C3EBB8DBCF8@purdue.edu>"}, {"type": "Subject", "content": "Beepboop"}, {"type": "To", "content": "cesite@ecn.purdue.edu"}, {"type": "Content-Type", "content": "text/plain; charset=\"utf-8\""}, {"type": "X-ECN-Queue-Original-Path", "content": "/home/pier/e/queue/Attachments/inbox/2020-06-23/208-original.txt"}, {"type": "X-ECN-Queue-Original-URL", "content": "https://engineering.purdue.edu/webqueue/Attachments/inbox/2020-06-23/208-original.txt"}], "content": [{"type": "directory_information", "Name": "Heyi Feng", "Login": "feng293", "Computer": "civil4147pc2.ecn", "Location": "HAMP 4147", "Email": "feng293@purdue.edu", "Phone": "5039154835", "Office": "", "UNIX Dir": "None", "Zero Dir": "U=\\\\myhome.itap.purdue.edu\\myhome\\%username%", "User ECNDB": "http://eng.purdue.edu/jump/2e29495", "Host ECNDB": "http://eng.purdue.edu/jump/2eccc3f", "Subject": "Upgrade system and Abaqus"}, {"type": "assignment", "datetime": "2020-06-23T13:27:00-0400", "by": "campb303", "to": "campb303"}, {"type": "initial_message", "datetime": "2020-06-23T13:25:51-0400", "from_name": "Justin Campbell", "user_email": "campb303@purdue.edu", "to": [{"name": "", "email": "cesite@ecn.purdue.edu"}], "cc": [], "content": ["Testtest\n"]}, {"type": "status", "datetime": "2020-06-23T13:26:55", "by": "campb303", "content": ["Dont Delete\n"]}, {"type": "edit", "datetime": "2020-06-23T13:27:56", "by": "campb303", "content": ["This be an edit my boy\n"]}, {"type": "reply_to_user", "datetime": "2020-06-23T13:28:18", "by": "campb303", "content": ["This be a reply my son\n", "\n", "Justin\n", "ECN\n"]}, {"type": "reply_from_user", "datetime": "2020-06-23T13:30:45-0400", "from_name": "Justin Campbell", "from_email": "campb303@purdue.edu", "cc": [], "content": ["X-ECN-Queue-Original-Path: /home/pier/e/queue/Attachments/inbox/2020-06-23/212-original.txt\n", "X-ECN-Queue-Original-URL: https://engineering.purdue.edu/webqueue/Attachments/inbox/2020-06-23/212-original.txt\n", "\n", "Huzzah!\n"]}], "isLocked": "ce 100 is locked by knewell using qvi", "userEmail": "campb303@purdue.edu", "userName": "Justin Campbell", "userAlias": "campb303", "assignedTo": "campb303", "subject": "Beepboop", "status": "Dont Delete", "priority": "", "department": "", "building": "", "dateReceived": "2020-06-23T13:25:51-0400"};
<div style={{backgroundColor: "white", padding: "1em"}}>
<ItemBodyView item={demoItem} />
</div>
```jsx static
<ItemBodyView sections={sections} />
```

## Loading View
![ItemBodyView_Loaded](/ItemBodyView_Loading.gif)

```jsx static
<ItemBodyView item={demoItem} />
<ItemBodyView sections={sections} loading={true} />
```
10 changes: 7 additions & 3 deletions src/components/ItemView/ItemView.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from "prop-types";
import { Paper, AppBar, Tab, makeStyles, useTheme } from '@material-ui/core';
// Import these tab components from @material-ui/lab instead of @material-ui/core for automatic a11y props
@@ -7,14 +7,16 @@ import { TabContext, TabList, TabPanel } from '@material-ui/lab';
import ItemMetadataView from "../ItemMetadataView"
import ItemBodyView from "../ItemBodyView";
import ItemHeaderView from "../ItemHeaderView";
import { useItem } from "../ItemProvider";
import { useItem, useItemSetter } from "../ItemProvider";

export default function ItemView(){
// Set stateful variables
const [activeTab, setActiveTab] = useState('Conversation');
const [isLoading, setIsLoading] = useState(false);

// Set contextual variables
const activeItem = useItem();
const setActiveItem = useItemSetter();

const theme = useTheme();
const useStyles = makeStyles({
@@ -44,9 +46,11 @@ export default function ItemView(){
<Tab label="Headers" value="Headers" />
</TabList>
</AppBar>

<TabPanel value="Conversation" classes={{ root: classes.tabPanelPadding }}>
<ItemBodyView item={activeItem} />
<ItemBodyView sections={activeItem.content} loading={isLoading} />
</TabPanel>

<TabPanel value="Headers" classes={{ root: classes.tabPanelPadding }}>
<ItemHeaderView data={activeItem.headers} />
</TabPanel>
5 changes: 4 additions & 1 deletion src/components/TimelineSkeleton/TimelineSkeleton.js
Original file line number Diff line number Diff line change
@@ -24,7 +24,10 @@ export default function TimelineSkeleton(){
</Typography>
</div>
<div className={classes.padding}>
{[...Array(2).keys()].map( _ => <Skeleton /> )}
{
// Generate 2 placeholders.
[...Array(2).keys()].map( (_, index) => <Skeleton key={index.toString()} /> )
}
</div>
</Paper>
);
Binary file added styleguidist/assetsDir/ItemBodyView_Loaded.png

Unable to render rich display

Invalid image source.

Binary file added styleguidist/assetsDir/ItemBodyView_Loading.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit f144667

Please sign in to comment.