diff --git a/package-lock.json b/package-lock.json
index 59009eb8..7fe81c2f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -2126,6 +2126,11 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "@types/lodash": {
+ "version": "4.14.170",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.170.tgz",
+ "integrity": "sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q=="
+ },
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@@ -5484,23 +5489,23 @@
"integrity": "sha512-q2PeCP2PQXSYadDo9uNY+uHXjdB9PcsUpCVoGlY8TZOPHGlXdevlqW9PkKeqCxn2QBkGB8b6AcMO++gh8X82bA=="
},
"elliptic": {
- "version": "6.5.3",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.3.tgz",
- "integrity": "sha512-IMqzv5wNQf+E6aHeIqATs0tOLeOTwj1QKbRcS3jBbYkl5oLAserA8yJTT7/VyHUYG91PRmPyeQDObKLPpeS4dw==",
+ "version": "6.5.4",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz",
+ "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==",
"requires": {
- "bn.js": "^4.4.0",
- "brorand": "^1.0.1",
+ "bn.js": "^4.11.9",
+ "brorand": "^1.1.0",
"hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.0"
+ "hmac-drbg": "^1.0.1",
+ "inherits": "^2.0.4",
+ "minimalistic-assert": "^1.0.1",
+ "minimalistic-crypto-utils": "^1.0.1"
},
"dependencies": {
"bn.js": {
- "version": "4.11.9",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.9.tgz",
- "integrity": "sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw=="
+ "version": "4.12.0",
+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
+ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA=="
}
}
},
@@ -6778,11 +6783,6 @@
"readable-stream": "^2.3.6"
}
},
- "fn-name": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fn-name/-/fn-name-2.0.1.tgz",
- "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc="
- },
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
@@ -7336,9 +7336,9 @@
}
},
"hosted-git-info": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
- "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg=="
+ "version": "2.8.9",
+ "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
+ "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="
},
"hpack.js": {
"version": "2.1.6",
@@ -7655,9 +7655,9 @@
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"ini": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz",
- "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw=="
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"inquirer": {
"version": "7.2.0",
@@ -10011,9 +10011,9 @@
}
},
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
"lodash-es": {
"version": "4.17.15",
@@ -10548,6 +10548,11 @@
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz",
"integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw=="
},
+ "nanoclone": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
+ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
+ },
"nanomatch": {
"version": "1.2.13",
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
@@ -10607,11 +10612,6 @@
"tslib": "^1.10.0"
}
},
- "node-forge": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz",
- "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ=="
- },
"node-gyp": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
@@ -12538,9 +12538,9 @@
}
},
"property-expr": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-1.5.1.tgz",
- "integrity": "sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g=="
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
+ "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg=="
},
"proxy-addr": {
"version": "2.0.6",
@@ -12756,9 +12756,9 @@
},
"dependencies": {
"lodash": {
- "version": "4.17.20",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
- "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}
}
},
@@ -14112,11 +14112,18 @@
"integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo="
},
"selfsigned": {
- "version": "1.10.7",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz",
- "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==",
+ "version": "1.10.11",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
+ "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
"requires": {
- "node-forge": "0.9.0"
+ "node-forge": "^0.10.0"
+ },
+ "dependencies": {
+ "node-forge": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
+ "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA=="
+ }
}
},
"semver": {
@@ -14732,9 +14739,9 @@
}
},
"ssri": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz",
- "integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.1.tgz",
+ "integrity": "sha512-w+daCzXN89PseTL99MkA+fxJEcU3wfaE/ah0i0lnOlpG1CYLJ2ZjzEry68YBKfLs4JfoTShrTEsJkAZuNZ/stw==",
"requires": {
"figgy-pudding": "^3.5.1",
"minipass": "^3.1.1"
@@ -15103,11 +15110,6 @@
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="
},
- "synchronous-promise": {
- "version": "2.0.13",
- "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.13.tgz",
- "integrity": "sha512-R9N6uDkVsghHePKh1TEqbnLddO2IY25OcsksyFp/qBe7XYd0PVbKEWxhcdMhpLzE1I6skj5l4aEZ3CRxcbArlA=="
- },
"table": {
"version": "5.4.6",
"resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
@@ -15776,9 +15778,9 @@
}
},
"url-parse": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
- "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
+ "integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
"requires": {
"querystringify": "^2.1.1",
"requires-port": "^1.0.0"
@@ -17354,9 +17356,9 @@
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
},
"y18n": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
- "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
},
"yallist": {
"version": "2.1.2",
@@ -17440,16 +17442,27 @@
}
},
"yup": {
- "version": "0.27.0",
- "resolved": "https://registry.npmjs.org/yup/-/yup-0.27.0.tgz",
- "integrity": "sha512-v1yFnE4+u9za42gG/b/081E7uNW9mUj3qtkmelLbW5YPROZzSH/KUUyJu9Wt8vxFJcT9otL/eZopS0YK1L5yPQ==",
- "requires": {
- "@babel/runtime": "^7.0.0",
- "fn-name": "~2.0.1",
- "lodash": "^4.17.11",
- "property-expr": "^1.5.0",
- "synchronous-promise": "^2.0.6",
+ "version": "0.32.9",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.9.tgz",
+ "integrity": "sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==",
+ "requires": {
+ "@babel/runtime": "^7.10.5",
+ "@types/lodash": "^4.14.165",
+ "lodash": "^4.17.20",
+ "lodash-es": "^4.17.15",
+ "nanoclone": "^0.2.1",
+ "property-expr": "^2.0.4",
"toposort": "^2.0.2"
+ },
+ "dependencies": {
+ "@babel/runtime": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.0.tgz",
+ "integrity": "sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==",
+ "requires": {
+ "regenerator-runtime": "^0.13.4"
+ }
+ }
}
},
"zen-observable": {
diff --git a/package.json b/package.json
index cd6809a7..8634e011 100644
--- a/package.json
+++ b/package.json
@@ -30,7 +30,7 @@
"redux": "^4.0.5",
"slugify": "^1.3.6",
"styled-components": "^5.2.1",
- "yup": "^0.27.0"
+ "yup": "^0.32.9"
},
"scripts": {
"start": "react-scripts start",
diff --git a/src/example/StartHere.js b/src/example/StartHere.js
new file mode 100644
index 00000000..14585969
--- /dev/null
+++ b/src/example/StartHere.js
@@ -0,0 +1,27 @@
+/// ____ _____ _ ____ _____ _ _ _____ ____ _____
+/// / ___|_ _|/ \ | _ \_ _| | | | | ____| _ \| ____|
+/// \___ \ | | / _ \ | |_) || | | |_| | _| | |_) | _|
+/// ___) || |/ ___ \| _ < | | | _ | |___| _ <| |___
+/// |____/ |_/_/ \_\_| \_\|_| |_| |_|_____|_| \_\_____|
+///
+/// We will be using the Model-View-Controller (MVC) architecture pattern for the
+/// CLEANEST codebase ever (knock on wood). This guide will take you through
+/// each segment of example implementation to give you a better
+/// understanding of how the M, V, and C work cohesively.
+///
+/// There is a number on the screen and the user presses a button that
+/// increments it, this is what happens behind the scenes:
+/// 1. The View's Button tells the Controller that the button has been pressed.
+/// 2. The Controller increments the number that is contained in the Model.
+/// 3. The Controller tells the View that the number in the Model has changed.
+/// 4. The View then shows the incremented number.
+///
+/// Visually, it looks like this:
+/// View <--> Presenter <--> Model
+///
+/// The MVC is best used for classed based programming but here we can see the pattern for functional programming
+/// by breaking down the component and abstratcing the logic from the view from the model.
+///
+/// To start please head to TimerController.js!
+
+/// SO to Adin for writing this, tweaked it a bit from the mobile BizTech app
\ No newline at end of file
diff --git a/src/example/TimerController.js b/src/example/TimerController.js
new file mode 100644
index 00000000..58485374
--- /dev/null
+++ b/src/example/TimerController.js
@@ -0,0 +1,67 @@
+/// This is a TimerController example!
+/// To see this in action, please initialize a new react app with this component along with the associated files
+/// Here we see that the TimerController model does not see anything within what the controller is doing, it just contains the data
+
+import { useState } from 'react'
+import TimerView from './TimerView'
+
+/// TIMERCONTROLLER MODEL START ---------------------------------------------------------------------------------------------------------------------------------------------
+
+const TimerController = () => {
+ // Timer Controller: does not see anything in the controller - completely separate
+ const [time, setTime] = useState(new Date(0))
+ const [timerInterval, setTimerInterval] = useState(null)
+
+ /// TIMERCONTROLLER MODEL END ---------------------------------------------------------------------------------------------------------------------------------------------
+
+ /// Here, the controller contains all the logic for the component, it decides what to change in the model and in the view
+ /// note that the model does not know anything going on in the controller and we will see this likewise with the view and the controlller
+
+ /// TIMERCONTROLLER CONTROLLER START ---------------------------------------------------------------------------------------------------------------------------------------------
+
+ // Timer Controller: contains all the functions that relates to the model and the view
+ function startClicked () {
+ const step = 10
+ if (!timerInterval) {
+ setTimerInterval(setInterval(() => {
+ setTime((oldState) => {
+ const newMs = oldState.getTime() + step
+ return new Date(newMs)
+ })
+ }, step))
+ }
+ }
+
+ function pauseClicked () {
+ clearInterval(timerInterval)
+ setTimerInterval(null)
+ }
+
+ function resetClicked () {
+ setTime(new Date(0))
+ }
+
+ /// TIMERCONTROLLER CONTROLLER END ---------------------------------------------------------------------------------------------------------------------------------------------
+
+ /// Here we have the View and note that the view does not know anything of the model, the controller tells what the view should be and the view's job is to just
+ /// display the time
+ /// There is a helper for the View in TimerView.js file
+
+ /// TIMERCONTROLLER VIEW START ---------------------------------------------------------------------------------------------------------------------------------------------
+ // Timer View
+ return (
+ // eslint-disable-next-line react/react-in-jsx-scope
+