Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"presets": [
"es2015",
"react"
]
}
132 changes: 132 additions & 0 deletions Brian Task List.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
[] Unit Test with Mocha in order of importance
[] Components
[x] ModalConfirm
[] Reducers
[] Selectors
[] Action Creators
[] JS DOM
[] REST API
[x] Research Mockgoose. It looks like it requires MongoDB to be installed locally.
[] Configure an ENV variable within Unit Test and adapt REST service.
[] Since MongoDB is in Cloud, setup another "testDB" where the default data script can be loaded each time.
[] Modify the "defaultData" method to insert addtional "flags" within the array on each "site" document.
[] Microservices: Configure a consumer contract and Pact broker

[] Integrate application with Web Components or React Components for the "Date Pickers"
[x] Finish wiring up the DELETE actions and update the server through a POST.
[x] Make sure that the reducers clear out any array indexes after the server responds because the positions may have changed.

[x] Create a generic a <ModalConfirm/> component that can be used for "Delete Flag".
[x] Find out why the JSX List is not matching to the Filtered array (by date).... weird, weird, weird.
[x] Reset the Edit/New form on the state after a successful update.
[x] The Edit functionality is not selecting the default option in the list.
[x] Need to solve a bug dealing with "skipped records". Currently the SiteDetails will print a message if there are no Flags in the database for the given site. However it's possible that the <FlagRowContainer> component will return NULL if the EndDate exists in the past.
[x] Create a dummy FlagRow component that will wire back the click events for EDIT/DELETE
[x] Create a FlagRowContainer that will take care of rendering the Dummy Flag row, and also any EDIT functionality.
[] Sort the results from the SiteList rest call. Mongo is putting the most recently saved document to the bottom.
[] When selecting a Site, make sure to clear out any "hasErrorSaving" flag. Otherwise an error message could be hanging around from the last attempt
[x] Solve MongoDB error when trying to update the Site Object: 'Modifiers operate on fields but we found type string instead. For example: {$mod: {<field>: ...}} not {$set: "{"flags":[{"flagType":"Retailer - Location Priority","startDate":"8/25/18","endDate":""}]}"}',
[x] Wire up the REST call for creating a new Flag from within the AddFlagContainer component.
[] Solve error on REST service: Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
[x] Just change the PUT route to a POST for now.
[x] Find out why JSON body is not showing up on the server through req.body.
[x] Install the Body Parser middle-ware for Express.
[x] Find out why FETCH is doing a pre-flight request (i.e. OPTIONS whenever ApplicationType JSON is put in the headers)
[x] Figure out a way to use BodyParser with "text/plain" or write a custom middleware to chunk the req.body.

[x] Add form validation to the AddOrEditFlag dumb component.
[] Clean up all of the state properties on the individual Sites array when the SiteDetailList is closed within the Reducer (likely by brute force). For example, if the Add Flag form is open on a view, then it appears open when re-visiting the same site details page.
[x] Fix weird warning that happens when canceling the AddFlag Form: "Form submission canceled because the form is not connected"
[] Find out why HotReloading doesn't work within a Route (on the Site Details page).
[x] Solve error from AddFlagContainerComponent: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components)
[x] Solve infinite loop that started happening after clicking into a SiteDetails with an AddEditRow component.
[x] Abstract the Form for Add/Edit flag so that it can be re-used for both types (like a New/Edit registration page).
[x] Ensure that all Components have PropTypes configured.
[x] Design process for processing the Flag objects in an array on the Site Details page.
[x] Create <FlagRowContainer> objects which accept a SiteID and a FlagIndex as a prop. That way there's no need to pass forward/back callbacks and pollute the SiteDetailsContainer.

[x] Come up with a way to un-select the current site by routing <Link>ing back to the main page.
[] Refactor the Reducer for SELECT_SITE. It doesn't need to send a flag in the payload now because another action will be used for un-selecting.
[x] Find out why Selector for getSelectedSiteIsLoaded is returning stale data from the state.
[x] Solve error connecting to MongoDB. Just happened out of the blue: "Topology was destroyed"
[x] Solve problem of Selected SiteID not updating from change to Router parameters.
[] Currently the SitesList is going to re-render for every change to a child component. Consider making the SiteList just an array of SiteID,Name within a new selector to keep the component stable.
[x] Find out with the SiteDetailsContainer is not re-rendering after a change to the State.
[] Refactor codebase to get rid of inconsistent use of "siteList..." versus "sitesList".
[x] Store the selected Site ID on the State after a Route change so that the Site Details can be memoized in various selectors.
[x] Move the info about the SiteList, such as error, inProgress, etc. into its own Key on the state and combine reducers.

[x] Refactor the dispatch calls for "isLoading(false)" on SiteDeails Load/Save. The Reducers can infer when the action for the Response or Error is given.
[] Find out why the ES7 "rest" operators is reporting a syntax error in the browser. Chrome works with the same syntax natively. Maybe it's an ESlint thing?
[] Confirm that WebPack will strip out console.log() statements in production.
[x] Solve Double-load problem on SiteListContainer component.
[x] Figure out why MapStateToProps is not reflecting the state returned from the reducer in the Container method.
[x] Explain why there seems to be 2 separate Redux stores.
[x] Find out why the entry page (/app/js/app.js) is executed twice.

[x] Add CORS support for the REST service.
[x] Fix error that started showing up: Module not found: Error: Can't resolve 'whatwg-fetch' in ...
[x] I had to take out the Pollyfill I created for "fetch" in the WebPack config. Maybe I need to import another library like Axios or manually pollyfill?

[x] Create a Container component for the SiteList that will take care of loading the data from the API if the state is empty.
[] Setup Decorators to validate function inputs, like TypeScript.
[x] Stub out actions with basic Thunk workflow.
[x] Decide on convention for Action types. SFA
[x] How to deal with Errors on PUT "SiteData" which has a SiteID associated with the Payload.
[x] Create Thunk Aysnc Actions for GetSiteList, GetSiteData(SiteID), SaveSiteData(siteId)

[x] Decide on a process for loading data from the server and saving mutations.
[x] Design shape of reducers
[] Find a way to keep the "key" entries unique on <flag> components within Site Details view.
[] Figure out how to use Nomalizr with "flag" entries. They don't have unique ID's on their own.
[] Create REST API
[x] Store DB credentials within an ENV variable or maybe a flat file, just to demonstrate a consideration for security.
[] Get DB Access working with Promises.
[x] Populate MongoDB with a temp script.
[x] Figure out why I can't perform a "findOne()" by _id.
[x] Create a GET route for /sites
[x] Create a GET route for /sites/:id which returns a single Site document.
[x] Create a PUT route for /sites/:id which updates the single Site document.
[x] Verify that the document exists first, no upserting.
[x] Validate contents of the Site document.
[] Setup Mongoose to validate the Site Update route.

[x] Configure server-side framework
[x] Install Express
[x] Install Mongo
[x] Sign up for a MongoDB provider in the cloud.
[x] Verify connection to Mongo server on startup of Express app.

[] Configure client-side framework
[x] Install WebPack DevServer
[x] Install Babel and configure .babelrc
[x] Install React and React-DOM
[x] Create test file for /app/js/app.js
[x] Make sure that running "webpack" (global) will output to DIST.
[x] Install file-loader.
[x] Solve WebPack error: ERROR in Entry module not found: Error: Can't resolve 'file' in '\Projects\full-stack-coding-exercise/app'
[x] Solve issue with "Multiple assets emit to the same filename"
[x] Install html-webpack-plugin instead of using file-loader.
[] Find out why WebPack 2 doesn't use a "root" for module dependencies. How important is this over using relative paths?
[X] Install ESLint... Use AirBnB's rules: https://github.com/airbnb/javascript/tree/master/packages/eslint-config-airbnb
[x] Install React Hot Reloader
[x] Fix error after insalling Hot Reloader to WebPack: 'import' and 'export' may only appear at the top level (3:0)
[x] Install React-Router
[x] Create 2 basic routes for the SiteList and SiteDetail/:slug:
[x] Install Redux
[] Install Normalizr
[] Install Immutable.js
[] Install CSS framework
[x] Install React-Thunk
[] Install React-Promises
[x] Pollyfill the "fetch" and "promise" using WebPack, doesn't look like Babel does this.
[] Verify that Pollyfill worked, even if WebPack compiled OK.
[x] Install "prop-types"

[x] Research CSS Solution. CSS Modules ... Styled Components???
[x] Get JSX / Babel Package for SublimeText
[] Figure out why Sublime Text is not honoring the .editorconfig IDE settings.
[] Figure out why .sublime_project is not allowing Tabbed spaces.

[x] Setup local repo with a Fork and GitFlow
[x] Go through Readme and clarify any ambiguity. exercise
11 changes: 11 additions & 0 deletions app/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<title>GSTV Full Stack Coding Exercise</title>
<meta charset="utf-8">
</head>
<body>
<div id="app"></div>
<script src="app.js"></script>
</body>
</html>
60 changes: 60 additions & 0 deletions app/js/actions/actionObjects.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as actionTypes from './actionTypes.js'


export function confirmDeleteShow(siteId, flagIndex) {
return {
type: actionTypes.CONFIRM_DELETE_FLAG,
payload: { siteId, flagIndex, show:true }
}
}

export function confirmDeleteHide(siteId, flagIndex) {
return {
type: actionTypes.CONFIRM_DELETE_FLAG,
payload: { siteId, flagIndex, show:false }
}
}

export function selectSite(siteId) {
return {
type: actionTypes.SELECT_SITE,
payload: { siteId, show:true }
}
}

export function unselectActiveSite() {
return {
type: actionTypes.UNSELECT_ACTIVE_SITE,
payload: { }
}
}

export function editFlag(siteId, flagIndex) {
return {
type: actionTypes.EDIT_FLAG,
payload: { siteId, flagIndex, show:true }
}
}

export function editFlagCancel(siteId, flagIndex) {
return {
type: actionTypes.EDIT_FLAG,
payload: { siteId, flagIndex, show:false }
}
}

export function addFlag(siteId) {
return {
type: actionTypes.ADD_FLAG,
payload: { siteId, show:true }
}
}

export function addFlagCancel(siteId) {
return {
type: actionTypes.ADD_FLAG,
payload: { siteId, show:false }
}
}


18 changes: 18 additions & 0 deletions app/js/actions/actionTypes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const EDIT_FLAG = 'EDIT_FLAG'

export const ADD_FLAG = 'ADD_FLAG'

export const CONFIRM_DELETE_FLAG = 'CONFIRM_DELETE_FLAG'

export const SITE_DATA_LOADING = 'SITE_DATA_LOADING'
export const SITE_DATA_RESPONSE = 'SITE_DATA_RESPONSE'

export const SITE_DATA_SAVE_SENDING = 'SITE_DATA_SAVE_SENDING'
export const SITE_DATA_SAVE_RESPONSE = 'SITE_DATA_SAVE_RESPONSE'

export const SITES_LIST_LOADING = 'SITES_LIST_LOADING'
export const SITES_LIST_RESPONSE = 'SITES_LIST_RESPONSE'

export const SELECT_SITE = 'SELECT_SITE'
export const UNSELECT_ACTIVE_SITE = 'UNSELECT_ACTIVE_SITE'

Loading