diff --git a/.gitignore b/.gitignore
index ab35e71..a44e998 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ account/.eslintcache
admin/.eslintcache
frontend/.eslintcache
admin/.eslintcache
+data/*
diff --git a/README.md b/README.md
index 7b0d576..33b1f0a 100644
--- a/README.md
+++ b/README.md
@@ -111,6 +111,9 @@ You can then browser to:
- openmhz.test
- admin.openmhz.test
+*Interesting Note*: Safari 13+ does not like the **.test** TLD and doesn't seem to want to store cookies from the TLD. It seems to work fine in production when you are using a real TLD. I guess use Chrome for local testing or a different TLD for testing, like local.
+https://stackoverflow.com/questions/62023857/sharing-cookies-across-test-sub-domains-in-safari-13-not-possible
+
### Debugging React Apps using Hot Reloading
If you are trying to make changes to any of react frontends, it is a huge pain to have to compile to site and rebuild the container each time you make a change. Instead, simply run the react app in development mode. This will work for the frontends for the:
- admin frontend
diff --git a/account/public/android-chrome-192x192.png b/account/public/android-chrome-192x192.png
new file mode 100644
index 0000000..9ee745e
Binary files /dev/null and b/account/public/android-chrome-192x192.png differ
diff --git a/account/public/android-chrome-512x512.png b/account/public/android-chrome-512x512.png
new file mode 100644
index 0000000..9f72cfe
Binary files /dev/null and b/account/public/android-chrome-512x512.png differ
diff --git a/account/public/apple-touch-icon.png b/account/public/apple-touch-icon.png
new file mode 100644
index 0000000..2e9f065
Binary files /dev/null and b/account/public/apple-touch-icon.png differ
diff --git a/account/public/favicon-16x16.png b/account/public/favicon-16x16.png
new file mode 100644
index 0000000..77cbaab
Binary files /dev/null and b/account/public/favicon-16x16.png differ
diff --git a/account/public/favicon-32x32.png b/account/public/favicon-32x32.png
new file mode 100644
index 0000000..dcc8909
Binary files /dev/null and b/account/public/favicon-32x32.png differ
diff --git a/account/public/favicon.ico b/account/public/favicon.ico
index 354202a..a65d718 100644
Binary files a/account/public/favicon.ico and b/account/public/favicon.ico differ
diff --git a/account/public/index.html b/account/public/index.html
index 430b58f..fc897ee 100644
--- a/account/public/index.html
+++ b/account/public/index.html
@@ -6,15 +6,15 @@
-
+
-
+
-
React Redux App
+ %REACT_APP_SITE_NAME%
diff --git a/account/public/logo192.png b/account/public/logo192.png
deleted file mode 100644
index 3362410..0000000
Binary files a/account/public/logo192.png and /dev/null differ
diff --git a/account/public/logo512.png b/account/public/logo512.png
deleted file mode 100644
index b351622..0000000
Binary files a/account/public/logo512.png and /dev/null differ
diff --git a/account/public/manifest.json b/account/public/manifest.json
deleted file mode 100644
index 2f2be64..0000000
--- a/account/public/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "short_name": "React App",
- "name": "Create React App Sample",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff"
-}
diff --git a/account/public/site.webmanifest b/account/public/site.webmanifest
new file mode 100644
index 0000000..45dc8a2
--- /dev/null
+++ b/account/public/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/account/server/config/express.js b/account/server/config/express.js
index 38da07c..e040907 100644
--- a/account/server/config/express.js
+++ b/account/server/config/express.js
@@ -28,8 +28,8 @@ module.exports = function(app, passport) {
const sess = {
/*saveUninitialized: false,
resave: false,*/
- resave: true,
- saveUninitialized: true,
+ resave: false,
+ saveUninitialized: false,
secret: secrets.sessionSecret,
proxy: true,
name: "sessionId",
@@ -48,12 +48,12 @@ module.exports = function(app, passport) {
console.log('--------------------------');
console.log('===> 😊 Starting Server . . .');
console.log('===> Environment: ' + node_env);
- /*if(node_env === 'production') {
+ if(node_env === 'production') {
console.log('===> 🚦 Note: In order for authentication to work in production');
console.log('===> you will need a secure HTTPS connection');
sess.cookie.secure = true; // Serve secure cookies
sess.cookie.httpOnly = false;
- }*/
+ }
app.use(session(sess))
diff --git a/account/server/controllers/users.js b/account/server/controllers/users.js
index f4ff3ca..faeac7a 100644
--- a/account/server/controllers/users.js
+++ b/account/server/controllers/users.js
@@ -21,7 +21,7 @@ exports.isLoggedIn = function(req, res, next) {
exports.authenticated = function(req, res, next) {
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
- //console.log("account/server/controllers/users.js - exports.authenticated() Auth check for user: " + req.user + " is: " + req.isAuthenticated());
+ console.log("account/server/controllers/users.js - exports.authenticated() Auth check for user: " + req.user + " is: " + req.isAuthenticated());
if (req.isAuthenticated()) {
var clientUser = (({
firstName,
diff --git a/admin/public/android-chrome-192x192.png b/admin/public/android-chrome-192x192.png
new file mode 100644
index 0000000..9ee745e
Binary files /dev/null and b/admin/public/android-chrome-192x192.png differ
diff --git a/admin/public/android-chrome-512x512.png b/admin/public/android-chrome-512x512.png
new file mode 100644
index 0000000..9f72cfe
Binary files /dev/null and b/admin/public/android-chrome-512x512.png differ
diff --git a/admin/public/apple-touch-icon.png b/admin/public/apple-touch-icon.png
new file mode 100644
index 0000000..2e9f065
Binary files /dev/null and b/admin/public/apple-touch-icon.png differ
diff --git a/admin/public/favicon-16x16.png b/admin/public/favicon-16x16.png
new file mode 100644
index 0000000..77cbaab
Binary files /dev/null and b/admin/public/favicon-16x16.png differ
diff --git a/admin/public/favicon-32x32.png b/admin/public/favicon-32x32.png
new file mode 100644
index 0000000..dcc8909
Binary files /dev/null and b/admin/public/favicon-32x32.png differ
diff --git a/admin/public/favicon.ico b/admin/public/favicon.ico
index 354202a..a65d718 100644
Binary files a/admin/public/favicon.ico and b/admin/public/favicon.ico differ
diff --git a/admin/public/index.html b/admin/public/index.html
index 430b58f..fc897ee 100644
--- a/admin/public/index.html
+++ b/admin/public/index.html
@@ -6,15 +6,15 @@
-
+
-
+
- React Redux App
+ %REACT_APP_SITE_NAME%
diff --git a/admin/public/logo192.png b/admin/public/logo192.png
deleted file mode 100644
index 3362410..0000000
Binary files a/admin/public/logo192.png and /dev/null differ
diff --git a/admin/public/logo512.png b/admin/public/logo512.png
deleted file mode 100644
index b351622..0000000
Binary files a/admin/public/logo512.png and /dev/null differ
diff --git a/admin/public/manifest.json b/admin/public/manifest.json
deleted file mode 100644
index 2f2be64..0000000
--- a/admin/public/manifest.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "short_name": "React App",
- "name": "Create React App Sample",
- "icons": [
- {
- "src": "favicon.ico",
- "sizes": "64x64 32x32 24x24 16x16",
- "type": "image/x-icon"
- },
- {
- "src": "logo192.png",
- "type": "image/png",
- "sizes": "192x192"
- },
- {
- "src": "logo512.png",
- "type": "image/png",
- "sizes": "512x512"
- }
- ],
- "start_url": ".",
- "display": "standalone",
- "theme_color": "#000000",
- "background_color": "#ffffff"
-}
diff --git a/admin/public/site.webmanifest b/admin/public/site.webmanifest
new file mode 100644
index 0000000..45dc8a2
--- /dev/null
+++ b/admin/public/site.webmanifest
@@ -0,0 +1 @@
+{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
\ No newline at end of file
diff --git a/admin/server/config/express.js b/admin/server/config/express.js
index a3cd997..b54deef 100644
--- a/admin/server/config/express.js
+++ b/admin/server/config/express.js
@@ -26,8 +26,8 @@ module.exports = function(app, passport) {
app.use(express.static(path.join(process.cwd(), 'public')));
const sess = {
- resave: true,
- saveUninitialized: true,
+ resave: false,
+ saveUninitialized: false,
secret: secrets.sessionSecret,
proxy: true,
name: "sessionId",
@@ -46,12 +46,12 @@ module.exports = function(app, passport) {
console.log('--------------------------');
console.log('===> 😊 Starting Server . . .');
console.log('===> Environment: ' + node_env);
- /*
+
if(node_env === 'production') {
console.log('===> 🚦 Note: In order for authentication to work in production');
console.log('===> you will need a secure HTTPS connection');
sess.cookie.secure = true; // Serve secure cookies
- }*/
+ }
app.use(session(sess))
diff --git a/docker-compose.yml b/docker-compose.yml
index e393288..af9fce8 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -55,6 +55,7 @@ services:
pid: "host"
environment:
- MONGO_NODE_DRIVER_HOST=mongo
+ - NODE_ENV
- REACT_APP_BACKEND_SERVER
- REACT_APP_ADMIN_SERVER
- REACT_APP_FRONTEND_SERVER
@@ -98,6 +99,7 @@ services:
- REACT_APP_FRONTEND_SERVER
- REACT_APP_SITE_NAME
- MONGO_NODE_DRIVER_HOST=mongo
+ - NODE_ENV
depends_on:
- mongo
networks:
@@ -132,6 +134,7 @@ services:
- REACT_APP_SITE_NAME
- REACT_APP_ADMIN_EMAIL
- REACT_APP_COOKIE_DOMAIN
+ - NODE_ENV
depends_on:
- mongo
networks:
diff --git a/frontend/.eslintcache b/frontend/.eslintcache
index d4c212a..040af7d 100644
--- a/frontend/.eslintcache
+++ b/frontend/.eslintcache
@@ -1 +1 @@
-[{"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/ListCalls.js":"1","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-actions.js":"2","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystemsContainer.js":"3","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallPlayer.js":"4","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-constants.js":"5","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/SupportModal.js":"6","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/FilterModal.js":"7","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/query-string.js":"8","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModal.js":"9","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/configureStore.js":"10","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-actions.js":"11","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-reducer.js":"12","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/MediaPlayer.js":"13","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/GroupModal.js":"14","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-actions.js":"15","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js":"16","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js":"17","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModalContainer.js":"18","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js":"19","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-constants.js":"20","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallItem.js":"21","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js":"22","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-reducer.js":"23","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/MainContainer.js":"24","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-reducer.js":"25","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-constants.js":"26"},{"size":1638,"mtime":1613098982285,"results":"27","hashOfConfig":"28"},{"size":9179,"mtime":1609597700043,"results":"29","hashOfConfig":"28"},{"size":277,"mtime":1545362103911,"results":"30","hashOfConfig":"28"},{"size":18826,"mtime":1613099368034,"results":"31","hashOfConfig":"28"},{"size":151,"mtime":1545362103908,"results":"32","hashOfConfig":"28"},{"size":1313,"mtime":1610678127937,"results":"33","hashOfConfig":"28"},{"size":4455,"mtime":1612233941171,"results":"34","hashOfConfig":"28"},{"size":362,"mtime":1610678313030,"results":"35","hashOfConfig":"28"},{"size":1778,"mtime":1609597248589,"results":"36","hashOfConfig":"28"},{"size":854,"mtime":1611803272298,"results":"37","hashOfConfig":"28"},{"size":2433,"mtime":1609597717050,"results":"38","hashOfConfig":"28"},{"size":1395,"mtime":1545362103908,"results":"39","hashOfConfig":"28"},{"size":4252,"mtime":1612317546527,"results":"40","hashOfConfig":"28"},{"size":2023,"mtime":1612233431556,"results":"41","hashOfConfig":"28"},{"size":1747,"mtime":1609597708479,"results":"42","hashOfConfig":"28"},{"size":595,"mtime":1609596047661,"results":"43","hashOfConfig":"28"},{"size":2045,"mtime":1609520570000,"results":"44","hashOfConfig":"28"},{"size":763,"mtime":1545362103896,"results":"45","hashOfConfig":"28"},{"size":1547,"mtime":1609520315634,"results":"46","hashOfConfig":"28"},{"size":537,"mtime":1545362103916,"results":"47","hashOfConfig":"28"},{"size":2909,"mtime":1613011408389,"results":"48","hashOfConfig":"28"},{"size":1575,"mtime":1610678224214,"results":"49","hashOfConfig":"28"},{"size":1045,"mtime":1610678295131,"results":"50","hashOfConfig":"28"},{"size":264,"mtime":1545362103910,"results":"51","hashOfConfig":"28"},{"size":7019,"mtime":1560857753468,"results":"52","hashOfConfig":"28"},{"size":1109,"mtime":1560828045933,"results":"53","hashOfConfig":"28"},{"filePath":"54","messages":"55","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"1du4mf8",{"filePath":"56","messages":"57","errorCount":0,"warningCount":3,"fixableErrorCount":0,"fixableWarningCount":0,"source":"58","usedDeprecatedRules":"59"},{"filePath":"60","messages":"61","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"62"},{"filePath":"63","messages":"64","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"65","messages":"66","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"67"},{"filePath":"68","messages":"69","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"70","messages":"71","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"72","messages":"73","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"74","usedDeprecatedRules":"75"},{"filePath":"76","messages":"77","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"78"},{"filePath":"79","messages":"80","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"81","messages":"82","errorCount":0,"warningCount":7,"fixableErrorCount":0,"fixableWarningCount":0,"source":"83","usedDeprecatedRules":"59"},{"filePath":"84","messages":"85","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"86","messages":"87","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"88","messages":"89","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"90","messages":"91","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"92"},{"filePath":"93","messages":"94","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"96","messages":"97","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"98","messages":"99","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"100","messages":"101","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"102","messages":"103","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"62"},{"filePath":"104","messages":"105","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"106"},{"filePath":"107","messages":"108","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"67"},{"filePath":"109","messages":"110","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"95"},{"filePath":"111","messages":"112","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"113","messages":"114","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"115","usedDeprecatedRules":"95"},{"filePath":"116","messages":"117","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/ListCalls.js",["118"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-actions.js",["119","120","121"],"import axios from \"axios\";\n\nimport * as types from \"./call-constants\";\nimport { push } from 'connected-react-router';\n\nconst FETCH_SUCCESS_STATISTIC = \"FETCH_SUCCESS_STATISTIC\"\n\nfunction beginFetchCallInfo() {\n return { type: types.FETCH_CALL_INFO };\n}\n\nfunction fetchCallInfoSuccess(data) {\n return { type: types.FETCH_SUCCESS_CALL_INFO,\n data };\n}\n\nfunction fetchCallInfoError(data) {\n return { type: types.FETCH_ERROR_CALL_INFO,\n data };\n}\n\nfunction prependCall() {\n return { type: types.PREPEND_CALL };\n}\n\nfunction beginAddStar() {\n return { type: types.ADD_STAR };\n}\n\nfunction addStarSuccess(data) {\n return { type: types.ADD_STAR_SUCCESS, data };\n}\n\nfunction addStarError(data) {\n return { type: types.ADD_STAR_ERROR, data };\n}\n\nfunction beginFetchCall() {\n return { type: types.FETCH_CALL };\n}\n\nfunction fetchCallSuccess(data) {\n return { type: types.FETCH_SUCCESS_CALL,\n data };\n}\n\n\n\nfunction fetchOlderCallSuccess(data) {\n return { type: types.FETCH_SUCCESS_OLDER_CALL,\n data };\n}\n\nfunction fetchNewerCallSuccess(data) {\n return { type: types.FETCH_SUCCESS_NEWER_CALL,\n data };\n}\n\nfunction fetchCallError(data) {\n return { type: types.FETCH_ERROR_CALL,\n data };\n}\n\n\nexport function changeUrl(url) {\n return dispatch => {\n dispatch(push(url));\n };\n}\n\n// Example of an Async Action Creator\n// http://redux.js.org/docs/advanced/AsyncActions.html\n\nfunction shouldFetchCalls(state, subreddit) {\n return true;\n if ((!state.call.items) || (state.call.items.length <1)) {\n return true\n } else if (state.call.isWaiting) {\n return false\n } else {\n return false\n }\n}\n\n\n\n\nfunction buildUrlParams(a) {\n return Object.keys(a).map(function(k) {\n return encodeURIComponent(k) + '=' + encodeURIComponent(a[k])\n }).join('&')\n}\n\nfunction buildCallUrl(state, date, direction) {\n var params = {};\n var url = \"\";\n\n\n if ((typeof direction === 'string') && (typeof date === 'number')) {\n url = url + '/' + direction;\n params[\"time\"] = date;\n } else {\n if (state.call.filterDate){\n url = url + '/older'\n params[\"time\"] = state.call.filterDate;\n }\n }\n if (state.call.filterStarred) {\n params[\"filter-starred\"] = true;\n }\n switch(state.call.filterType) {\n case 1:\n params[\"filter-type\"] = \"group\";\n params[\"filter-code\"] = state.call.filterGroupId;\n break;\n case 2:\n params[\"filter-type\"] = \"talkgroup\";\n params[\"filter-code\"] = state.call.filterTalkgroups;\n break;\n default:\n case 0:\n }\n/*\n\n if (this.filterCode != \"\") {\n params[\"filter-code\"] = this.filterCode;\n }\n\n if (this.filterType == this.FilterType.Group) {\n params[\"filter-type\"] = \"group\";\n params[\"filter-name\"] = this.filterName;\n }\n\n if (this.filterType == this.FilterType.Talkgroup) {\n params[\"filter-type\"] = \"talkgroup\";\n }\n\n if (this.filterType == this.FilterType.Unit) {\n params[\"filter-type\"] = \"unit\";\n }\n\n*/\n // url = startUp.backend_server + \"/\" + startUp.shortName.toLowerCase() + \"/calls\" + url + '?' + buildUrlParams(params);\n url = process.env.REACT_APP_BACKEND_SERVER + \"/\" + state.call.shortName + \"/calls\" + url + '?' + buildUrlParams(params);\n console.log(\"Trying to fetch data from this url: \" + url);\n return url;\n}\n\nexport function fetchNewerCalls( timestamp) {\n return (dispatch, getState) => {\n const state = getState();\n if (shouldFetchCalls(state)) {\n dispatch(beginFetchCall());\n const url = buildCallUrl(state, timestamp, \"newer\")\n return axios\n .get(url)\n .then(response => {\n if ((response.data) && (response.data.calls.length >0)) {\n var data = {shortName: state.call.shortName, calls: response.data.calls}\n dispatch(fetchNewerCallSuccess(data));\n } else {\n dispatch(fetchCallError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n}\n\n\nexport function fetchOlderCalls( timestamp) {\n return (dispatch, getState) => {\n const state = getState();\n if (shouldFetchCalls(state)) {\n dispatch(beginFetchCall());\n const url = buildCallUrl(state, timestamp, \"older\")\n return axios\n .get(url)\n .then(response => {\n if (response.data) {\n var data = {shortName: state.call.shortName, calls: response.data.calls}\n dispatch(fetchOlderCallSuccess(data));\n } else {\n dispatch(fetchCallError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n}\n\n\nexport function addStar( callId) {\n return (dispatch, getState) => {\n const state = getState();\n dispatch(beginAddStar());\n\n const url = process.env.REACT_APP_BACKEND_SERVER + \"/\" + state.call.shortName.toLowerCase() + \"/star/\" + callId\n return axios\n .post(url,{}, {\n headers: {\n 'Content-Type': 'application/x-www-form-urlencoded'\n }\n }).then(response => {\n if (response.data.success) {\n dispatch(addStarSuccess(response.data.call));\n } else {\n dispatch(addStarError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n\n\n\nexport function fetchCallInfo( callId) {\n return (dispatch, getState) => {\n const state = getState();\n dispatch(beginFetchCallInfo());\n\n const url = process.env.REACT_APP_BACKEND_SERVER + \"/\" + state.call.shortName.toLowerCase() + \"/call/\" + callId\n return axios\n .get(url)\n .then(response => {\n if (response.data.success) {\n dispatch(fetchCallInfoSuccess(response.data.call));\n } else {\n dispatch(fetchCallInfoError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n\nexport function fetchCalls() {\n return (dispatch, getState) => {\n const state = getState();\n if (shouldFetchCalls(state)) {\n dispatch(beginFetchCall());\n const url=buildCallUrl(state);\n return axios\n .get(url)\n .then(response => {\n if (response.data) {\n // check to make sure you actually got some calls back.\n if (response.data.calls.length > 0) {\n var data = {shortName: state.call.shortName, calls: response.data.calls}\n dispatch(fetchCallSuccess(data));\n } else {\n dispatch(fetchCallError());\n }\n } else {\n dispatch(fetchCallError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n}\n\nexport function addCall(call) {\n return (dispatch, getState) => {\n dispatch({ type: types.UPSERT_CALL, data: call});\n };\n}\n\nexport function setStarred(starred) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_STARRED_FILTER, data: starred});\n };\n}\n\nexport function setLive(live) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_LIVE, data: live});\n };\n}\n\nexport function setCurrentCallId(callId) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_CURRENT_CALL_ID, data: callId});\n };\n}\n\n// should be as a unix timestamp\nexport function setDateFilter(date) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_DATE_FILTER, date: date});\n };\n}\n\nexport function setAllFilter() {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_ALL_FILTER});\n };\n}\n\nexport function setTalkgroupFilter(tgs) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_TALKGROUP_FILTER, talkgroups: tgs});\n };\n}\n\nexport function setGroupFilter(groupId) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_GROUP_FILTER, groupId: groupId});\n };\n}\n\nexport function setShortName(shortName) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_SHORT_NAME, data: shortName});\n };\n}\n\nexport function setFilter(filter) {\n return (dispatch, getState) => {\n dispatch({ type: types.SET_FILTER, data: filter});\n };\n}\n",["122","123"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystemsContainer.js",[],["124","125"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallPlayer.js",["126","127"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-constants.js",[],["128","129"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/SupportModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/FilterModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/query-string.js",["130"],"export default {\n parse: function parse(queryString) {\n var query = {};\n var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');\n for (var i = 0; i < pairs.length; i++) {\n var pair = pairs[i].split('=');\n query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');\n }\n return query;\n }\n}\n",["131","132"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModal.js",["133"],"import React, { Component } from \"react\";\nimport {\n Modal,\n Button,\n Icon,\n Header\n} from \"semantic-ui-react\";\nimport \"./CalendarModal.css\";\nimport DatePicker from 'react-datepicker';\nimport { subDays } from 'date-fns'\nimport 'react-datepicker/dist/react-datepicker.css';\n\nclass CalendarModal extends Component {\n constructor(props) {\n super(props)\n this.handleDateChange = this.handleDateChange.bind(this);\n this.handleDone = this.handleDone.bind(this);\n this.handleClose = this.handleClose.bind(this);\n\n this.state = {\n open: false,\n startDate: new Date()\n }\n}\n\nhandleDateChange = (date) => {\n this.setState({\n startDate: date\n });\n }\n\nhandleClose = () => this.props.onClose(false);\nhandleDone(event) {\n this.props.callActions.setDateFilter(this.state.startDate.getTime());\n this.props.onClose(true);\n}\n\n\n render() {\n \n return (\n\n \n Select a Date & Time\n \n \n \n \n \n \n \n \n \n\n )\n }\n}\n\nexport default CalendarModal;\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/configureStore.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-actions.js",["134","135","136","137","138","139","140"],"import axios from 'axios';\n//import { browserHistory } from \"react-router\"\nimport * as types from \"./talkgroup-constants\";\nimport { push } from 'connected-react-router';\n\n// \"Log In\" action creators\nfunction beginImportTalkgroup() {\n return { type: types.IMPORT_TALKGROUP };\n}\n\nfunction importTalkgroupSuccess(data) {\n return {\n type: types.IMPORT_SUCCESS_TALKGROUP,\n data\n };\n}\n\nfunction importTalkgroupError(data) {\n return {\n type: types.IMPORT_ERROR_TALKGROUP,\n data\n };\n}\n\nfunction beginExportTalkgroup() {\n return { type: types.EXPORT_TALKGROUP };\n}\n\nfunction exportTalkgroupSuccess() {\n return { type: types.EXPORT_SUCCESS_TALKGROUP };\n}\n\nfunction exportTalkgroupError() {\n return { type: types.EXPORT_ERROR_TALKGROUP };\n}\n\n\nfunction beginFetchTalkgroup() {\n return { type: types.FETCH_TALKGROUP };\n}\n\nfunction fetchTalkgroupSuccess(data) {\n return { type: types.FETCH_SUCCESS_TALKGROUP,\n data };\n}\n\nfunction fetchTalkgroupError(data) {\n return { type: types.FETCH_ERROR_TALKGROUP,\n data };\n}\n\n\nfunction makeUserRequest(method, data, api) {\n // returns a Promise\n return axios({\n method: method,\n url: api,\n data: data\n });\n}\n\nexport function changeUrl(url) {\n return dispatch => {\n dispatch(push(url));\n };\n}\n\n\n// https://stackoverflow.com/questions/41878838/how-do-i-set-multipart-in-axios-with-react\n\n\n\nfunction shouldFetchTalkgroups(state, shortName) {\n if (!state.talkgroup.items.hasOwnProperty(shortName)) {\n return true\n } else if (state.talkgroup.isWaiting) {\n return false\n } else {\n return false\n }\n}\n\nexport function fetchTalkgroups(shortName) {\n return (dispatch, getState) => {\n if (shouldFetchTalkgroups(getState(), shortName)) {\n dispatch(beginFetchTalkgroup());\n\n return axios\n .get(process.env.REACT_APP_BACKEND_SERVER + \"/\" + shortName + \"/talkgroups\")\n .then(response => {\n if (response.data) {\n var data = {shortName: shortName, talkgroups: response.data.talkgroups}\n dispatch(fetchTalkgroupSuccess( data));\n } else {\n dispatch(fetchTalkgroupError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n}\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-reducer.js",["141","142"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/MediaPlayer.js",["143","144"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/GroupModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-actions.js",[],["145","146"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js",[],["147","148"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModalContainer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-constants.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallItem.js",["149"],"\nimport React, { Component } from \"react\";\nimport {\n Table,\n Icon,\n Label\n} from \"semantic-ui-react\";\nimport { connect } from \"react-redux\"\nimport { bindActionCreators } from 'redux'\nimport * as callActionCreators from \"./call-actions\"\n\n\nfunction mapStateToProps(state, props) {\n return {\n shortName: props.shortName\n\n\t}\n}\n\nfunction mapDispatchToProps(dispatch) {\n return {\n callActions: bindActionCreators(callActionCreators, dispatch)\n }\n}\n\n\nclass CallItem extends Component {\nconstructor(props) {\n super(props);\n this.hideStar = this.hideStar.bind(this);\n this.showStar = this.showStar.bind(this);\n this.addStar = this.addStar.bind(this);\n this.state = {\n starVisible: false,\n starClicked: false\n }\n}\nsourceString(call) {\n var srcString = \"\";\n if (call.srcList) {\n for (var src in call.srcList) {\n /* srcNum = call.srcList[src].src;\n if (sources.hasOwnProperty(srcNum)) {\n srcString = srcString + sources[srcNum].codeName + \", \";\n }*/\n }\n }\n\n return srcString;\n}\n\ncomponentDidUpdate(){\n if (this.props.activeCall) {\n console.log(\"Active call mounted\")\n }\n}\naddStar(e) {\n e.preventDefault();\n e.stopPropagation();\n e.nativeEvent.stopImmediatePropagation();\n if (!this.state.starClicked) {\n \n this.props.callActions.addStar(this.props.call._id);\n this.setState({starClicked: true});\n }\n}\n\nhideStar() {\n this.setState({ starVisible: false })\n}\n\nshowStar() {\n this.setState({ starVisible: true })\n}\n\nrender() {\n const call = this.props.call;\n const time = new Date(call.time);\n var rowSelected={};\n let starButton;\n var starClickable = {};\n if (!this.state.starClicked) {\n starClickable = {link: true };\n }\n if (!call.star && this.state.starVisible) {\n starButton = \n }\n\n if (call.star) {\n starButton = \n }\n if (call.star && call.star > 1) {\n starButton = (\n \n \n )\n }\n\n if (this.props.activeCall) {\n rowSelected={positive: true}\n }\n var talkgroup;\n if ((typeof this.props.talkgroups == 'undefined') || (typeof this.props.talkgroups[call.talkgroupNum] == 'undefined')) {\n talkgroup = call.talkgroupNum;\n } else {\n talkgroup = this.props.talkgroups[call.talkgroupNum].description;\n }\n return (\n this.props.onClick({call: call}, e)} {...rowSelected}>\n {call.len} \n {talkgroup} \n {time.toLocaleTimeString()} \n {starButton}\n \n\n\n );\n}\n}\n\nexport default connect(\n\tmapStateToProps,\n\tmapDispatchToProps\n)(CallItem)\n\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-reducer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/MainContainer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-reducer.js",["150","151"],"import {\n FETCH_CALL_INFO,\n FETCH_SUCCESS_CALL_INFO,\n FETCH_ERROR_CALL_INFO,\n FETCH_CALL,\n PREPEND_CALL,\n UPSERT_CALL,\n FETCH_SUCCESS_CALL,\n FETCH_SUCCESS_OLDER_CALL,\n FETCH_SUCCESS_NEWER_CALL,\n FETCH_ERROR_CALL,\n SET_SHORT_NAME,\n SET_ALL_FILTER,\n SET_GROUP_FILTER,\n SET_TALKGROUP_FILTER,\n SET_DATE_FILTER,\n SET_STARRED_FILTER,\n SET_FILTER,\n SET_CURRENT_CALL_ID,\n SET_LIVE,\n ADD_STAR_SUCCESS\n} from \"./call-constants\";\n\nfunction updateObject(oldObject, newValues) {\n // Encapsulate the idea of passing a new object as the first parameter\n // to Object.assign to ensure we correctly copy data instead of mutating\n return Object.assign({}, oldObject, newValues);\n}\n\nfunction updateCallInItems(calls, action) {\nreturn calls.map( (item) => {\n if (item._id !== action.data._id) {\n // This isn't the item we care about - keep it as-is\n return item;\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...action.data\n };\n });\n}\n/*\nfunction updateObjectInArray(array, action) {\n return array.map((item, index) => {\n if (index !== action.index) {\n // This isn't the item we care about - keep it as-is\n return item\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...item,\n ...action.item\n }\n })\n}\n\nfunction updateObjectInArray(array, shortName, updatedItem) {\n return array.map( item => {\n if(item.shortName !== shortName) {\n // This isn't the item we care about - keep it as-is\n return item;\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...item,\n ...updatedItem\n };\n });\n}\n*/\nconst now = new Date();\nconst call = (\n state = {\n isWaiting: false,\n shortName: \"\",\n byId: {},\n allIds: [],\n oldestCallTime: now,\n newestCallTime: now,\n filterType: 0,\n filterTalkgroups: [],\n filterGroupId: false,\n filterDate: false,\n filterStarred: false,\n currentCallId: false,\n live: false\n },\n action\n) => {\n switch (action.type) {\n\n case SET_CURRENT_CALL_ID:\n return Object.assign({}, state, {currentCallId: action.data});\n \n case SET_FILTER:\n {\n var filter={};\n filter.live = !action.data.live ? state.live : action.data.live;\n filter.filterStarred = !action.data.filterStarred ? false : action.data.filterStarred;\n filter.filterType = !action.data.filterType ? 0 : action.data.filterType;\n filter.filterTalkgroups = !action.data.filterTalkgroups ? [] : action.data.filterTalkgroups;\n filter.filterGroupId = !action.data.filterGroupId ? false : action.data.filterGroupId;\n filter.filterDate = !action.data.filterDate ? 0 : action.data.filterDate;\n return Object.assign({}, state, {\n live: action.data.live,\n filterType: action.data.filterType,\n filterTalkgroups: action.data.filterTalkgroups,\n filterGroupId: action.data.filterGroupId,\n filterDate: action.data.filterDate,\n filterStarred: action.data.filterStarred\n });\n }\n\n case SET_LIVE:\n return Object.assign({}, state, {live: action.data});\n \n case SET_SHORT_NAME:\n return Object.assign({}, state, {shortName: action.data});\n\n case SET_DATE_FILTER:\n return Object.assign({}, state, {filterDate: action.date});\n\n case SET_STARRED_FILTER:\n return Object.assign({}, state, {filterStarred: action.data});\n\n case SET_ALL_FILTER:\n return Object.assign({}, state, {filterType: 0, filterTalkgroups:[], filterGroupId: false});\n\n case SET_GROUP_FILTER:\n return Object.assign({}, state, {filterType: 1, filterTalkgroups:[], filterGroupId: action.groupId});\n\n case SET_TALKGROUP_FILTER:\n return Object.assign({}, state, {filterType: 2, filterTalkgroups: action.talkgroups, filterGroupId: false});\n\n case FETCH_CALL_INFO:\n case FETCH_CALL:\n return Object.assign({}, state, { isWaiting: true});\n\n case FETCH_SUCCESS_CALL_INFO:\n return Object.assign({}, state, {\n byId: {...state.byId, [action.data._id]: action.data },\n isWaiting: false\n\n });\n\n case ADD_STAR_SUCCESS:\n return Object.assign({}, state,{\n byId: {...state.byId, [action.data._id]: action.data },\n isWaiting: false\n\n });\n // This will set the items to the rx data\n case FETCH_SUCCESS_CALL:\n {\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id);\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n newestCallTime: new Date(action.data.calls[0].time),\n oldestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: { ...byId},\n allIds: [...allIds]\n });\n }\n\n case UPSERT_CALL:\n if (typeof state.byId[action.data._id] !== \"undefined\") {\n return Object.assign({}, state, {\n byId: {...state.byId, [action.data._id]: action.data },\n });\n } else {\n return Object.assign({}, state, {\n newestCallTime: new Date(action.data.time),\n byId: {[action.data._id]: action.data, ...state.byId},\n allIds: [action.data._id, ...state.allIds]\n }); \n }\n\n case PREPEND_CALL:\n return Object.assign({}, state, {\n isWaiting: false,\n newestCallTime: new Date(action.data.time),\n byId: {[action.data._id]: action.data, ...state.byId},\n allIds: [action.data._id, ...state.allIds]\n });\n\n// This will add the array of Calls in the data to the beginning of the existing array of Calls\n case FETCH_SUCCESS_NEWER_CALL:\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id).reverse();\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n newestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: {...state.byId, ...byId},\n allIds: [...allIds, ...state.allIds]\n });\n\n// This will add the array of Calls in the data to the end of the existing array of Calls\n case FETCH_SUCCESS_OLDER_CALL:\n {\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id);\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n oldestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: {...state.byId, ...byId},\n allIds: [ ...state.allIds, ...allIds]\n });\n }\n case FETCH_ERROR_CALL_INFO:\n case FETCH_ERROR_CALL:\n return Object.assign({}, state, {\n isWaiting: false\n });\n\n default:\n return state;\n }\n};\n\nexport default call;\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-constants.js",[],{"ruleId":"152","severity":1,"message":"153","line":12,"column":3,"nodeType":"154","messageId":"155","endLine":16,"endColumn":4},{"ruleId":"156","severity":1,"message":"157","line":6,"column":7,"nodeType":"158","messageId":"159","endLine":6,"endColumn":30},{"ruleId":"156","severity":1,"message":"160","line":22,"column":10,"nodeType":"158","messageId":"159","endLine":22,"endColumn":21},{"ruleId":"161","severity":1,"message":"162","line":76,"column":3,"nodeType":"163","messageId":"164","endLine":82,"endColumn":4},{"ruleId":"165","replacedBy":"166"},{"ruleId":"167","replacedBy":"168"},{"ruleId":"165","replacedBy":"169"},{"ruleId":"167","replacedBy":"170"},{"ruleId":"156","severity":1,"message":"171","line":285,"column":15,"nodeType":"158","messageId":"159","endLine":285,"endColumn":19},{"ruleId":"172","severity":1,"message":"173","line":446,"column":27,"nodeType":"174","messageId":"175","endLine":446,"endColumn":29},{"ruleId":"165","replacedBy":"176"},{"ruleId":"167","replacedBy":"177"},{"ruleId":"178","severity":1,"message":"179","line":1,"column":1,"nodeType":"180","endLine":11,"endColumn":2},{"ruleId":"165","replacedBy":"181"},{"ruleId":"167","replacedBy":"182"},{"ruleId":"156","severity":1,"message":"183","line":6,"column":3,"nodeType":"158","messageId":"159","endLine":6,"endColumn":9},{"ruleId":"156","severity":1,"message":"184","line":7,"column":10,"nodeType":"158","messageId":"159","endLine":7,"endColumn":30},{"ruleId":"156","severity":1,"message":"185","line":11,"column":10,"nodeType":"158","messageId":"159","endLine":11,"endColumn":32},{"ruleId":"156","severity":1,"message":"186","line":18,"column":10,"nodeType":"158","messageId":"159","endLine":18,"endColumn":30},{"ruleId":"156","severity":1,"message":"187","line":25,"column":10,"nodeType":"158","messageId":"159","endLine":25,"endColumn":30},{"ruleId":"156","severity":1,"message":"188","line":29,"column":10,"nodeType":"158","messageId":"159","endLine":29,"endColumn":32},{"ruleId":"156","severity":1,"message":"189","line":33,"column":10,"nodeType":"158","messageId":"159","endLine":33,"endColumn":30},{"ruleId":"156","severity":1,"message":"190","line":53,"column":10,"nodeType":"158","messageId":"159","endLine":53,"endColumn":25},{"ruleId":"156","severity":1,"message":"191","line":7,"column":10,"nodeType":"158","messageId":"159","endLine":7,"endColumn":22},{"ruleId":"156","severity":1,"message":"192","line":13,"column":10,"nodeType":"158","messageId":"159","endLine":13,"endColumn":27},{"ruleId":"193","severity":1,"message":"194","line":77,"column":3,"nodeType":"154","messageId":"175","endLine":78,"endColumn":4},{"ruleId":"156","severity":1,"message":"195","line":89,"column":5,"nodeType":"158","messageId":"159","endLine":89,"endColumn":16},{"ruleId":"165","replacedBy":"196"},{"ruleId":"167","replacedBy":"197"},{"ruleId":"165","replacedBy":"198"},{"ruleId":"167","replacedBy":"199"},{"ruleId":"156","severity":1,"message":"200","line":41,"column":18,"nodeType":"158","messageId":"159","endLine":41,"endColumn":21},{"ruleId":"156","severity":1,"message":"191","line":24,"column":10,"nodeType":"158","messageId":"159","endLine":24,"endColumn":22},{"ruleId":"156","severity":1,"message":"201","line":30,"column":10,"nodeType":"158","messageId":"159","endLine":30,"endColumn":27},"no-useless-constructor","Useless constructor.","MethodDefinition","noUselessConstructor","no-unused-vars","'FETCH_SUCCESS_STATISTIC' is assigned a value but never used.","Identifier","unusedVar","'prependCall' is defined but never used.","no-unreachable","Unreachable code.","IfStatement","unreachableCode","no-native-reassign",["202"],"no-negated-in-lhs",["203"],["202"],["203"],"'refs' is assigned a value but never used.","eqeqeq","Expected '!==' and instead saw '!='.","BinaryExpression","unexpected",["202"],["203"],"import/no-anonymous-default-export","Assign object to a variable before exporting as module default","ExportDefaultDeclaration",["202"],["203"],"'Header' is defined but never used.","'beginImportTalkgroup' is defined but never used.","'importTalkgroupSuccess' is defined but never used.","'importTalkgroupError' is defined but never used.","'beginExportTalkgroup' is defined but never used.","'exportTalkgroupSuccess' is defined but never used.","'exportTalkgroupError' is defined but never used.","'makeUserRequest' is defined but never used.","'updateObject' is defined but never used.","'updateItemInArray' is defined but never used.","no-dupe-class-members","Duplicate name 'componentDidUpdate'.","'playEnabled' is assigned a value but never used.",["202"],["203"],["202"],["203"],"'src' is assigned a value but never used.","'updateCallInItems' is defined but never used.","no-global-assign","no-unsafe-negation"]
\ No newline at end of file
+[{"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/ListCalls.js":"1","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-actions.js":"2","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystemsContainer.js":"3","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallPlayer.js":"4","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-constants.js":"5","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/SupportModal.js":"6","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/FilterModal.js":"7","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/query-string.js":"8","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModal.js":"9","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/configureStore.js":"10","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-actions.js":"11","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-reducer.js":"12","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/MediaPlayer.js":"13","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/GroupModal.js":"14","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-actions.js":"15","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js":"16","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js":"17","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModalContainer.js":"18","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js":"19","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-constants.js":"20","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallItem.js":"21","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js":"22","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-reducer.js":"23","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/MainContainer.js":"24","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-reducer.js":"25","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-constants.js":"26","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js":"27"},{"size":1638,"mtime":1613617344583,"results":"28","hashOfConfig":"29"},{"size":9120,"mtime":1613445049756,"results":"30","hashOfConfig":"29"},{"size":277,"mtime":1545362103911,"results":"31","hashOfConfig":"29"},{"size":19377,"mtime":1613615960319,"results":"32","hashOfConfig":"29"},{"size":151,"mtime":1545362103908,"results":"33","hashOfConfig":"29"},{"size":1313,"mtime":1610678127937,"results":"34","hashOfConfig":"29"},{"size":4455,"mtime":1613445049753,"results":"35","hashOfConfig":"29"},{"size":362,"mtime":1610678313030,"results":"36","hashOfConfig":"29"},{"size":1778,"mtime":1609597248589,"results":"37","hashOfConfig":"29"},{"size":854,"mtime":1611803272298,"results":"38","hashOfConfig":"29"},{"size":2433,"mtime":1609597717050,"results":"39","hashOfConfig":"29"},{"size":1395,"mtime":1545362103908,"results":"40","hashOfConfig":"29"},{"size":4313,"mtime":1613615882987,"results":"41","hashOfConfig":"29"},{"size":2023,"mtime":1612233431556,"results":"42","hashOfConfig":"29"},{"size":1747,"mtime":1609597708479,"results":"43","hashOfConfig":"29"},{"size":595,"mtime":1609596047661,"results":"44","hashOfConfig":"29"},{"size":2045,"mtime":1609520570000,"results":"45","hashOfConfig":"29"},{"size":763,"mtime":1545362103896,"results":"46","hashOfConfig":"29"},{"size":1547,"mtime":1609520315634,"results":"47","hashOfConfig":"29"},{"size":537,"mtime":1545362103916,"results":"48","hashOfConfig":"29"},{"size":2982,"mtime":1613617462684,"results":"49","hashOfConfig":"29"},{"size":1575,"mtime":1610678224214,"results":"50","hashOfConfig":"29"},{"size":1045,"mtime":1610678295131,"results":"51","hashOfConfig":"29"},{"size":264,"mtime":1545362103910,"results":"52","hashOfConfig":"29"},{"size":7019,"mtime":1560857753468,"results":"53","hashOfConfig":"29"},{"size":1109,"mtime":1560828045933,"results":"54","hashOfConfig":"29"},{"size":1221,"mtime":1613445049764,"results":"55","hashOfConfig":"29"},{"filePath":"56","messages":"57","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"1du4mf8",{"filePath":"58","messages":"59","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"60","messages":"61","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"62"},{"filePath":"63","messages":"64","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"65","messages":"66","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"67"},{"filePath":"68","messages":"69","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"70","messages":"71","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"72","messages":"73","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"74","usedDeprecatedRules":"75"},{"filePath":"76","messages":"77","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":"78"},{"filePath":"79","messages":"80","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"81","messages":"82","errorCount":0,"warningCount":7,"fixableErrorCount":0,"fixableWarningCount":0,"source":"83","usedDeprecatedRules":"84"},{"filePath":"85","messages":"86","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"87","messages":"88","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"89","messages":"90","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"91","messages":"92","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"93"},{"filePath":"94","messages":"95","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"96"},{"filePath":"97","messages":"98","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"96"},{"filePath":"99","messages":"100","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"101","messages":"102","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"103","messages":"104","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"62"},{"filePath":"105","messages":"106","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"107","messages":"108","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"67"},{"filePath":"109","messages":"110","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"usedDeprecatedRules":"96"},{"filePath":"111","messages":"112","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"113","messages":"114","errorCount":0,"warningCount":2,"fixableErrorCount":0,"fixableWarningCount":0,"source":"115","usedDeprecatedRules":"96"},{"filePath":"116","messages":"117","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"118","messages":"119","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/ListCalls.js",["120"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-actions.js",["121","122"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystemsContainer.js",[],["123","124"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallPlayer.js",["125","126"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-constants.js",[],["127","128"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/SupportModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/FilterModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/query-string.js",["129"],"export default {\n parse: function parse(queryString) {\n var query = {};\n var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');\n for (var i = 0; i < pairs.length; i++) {\n var pair = pairs[i].split('=');\n query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');\n }\n return query;\n }\n}\n",["130","131"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModal.js",["132"],"import React, { Component } from \"react\";\nimport {\n Modal,\n Button,\n Icon,\n Header\n} from \"semantic-ui-react\";\nimport \"./CalendarModal.css\";\nimport DatePicker from 'react-datepicker';\nimport { subDays } from 'date-fns'\nimport 'react-datepicker/dist/react-datepicker.css';\n\nclass CalendarModal extends Component {\n constructor(props) {\n super(props)\n this.handleDateChange = this.handleDateChange.bind(this);\n this.handleDone = this.handleDone.bind(this);\n this.handleClose = this.handleClose.bind(this);\n\n this.state = {\n open: false,\n startDate: new Date()\n }\n}\n\nhandleDateChange = (date) => {\n this.setState({\n startDate: date\n });\n }\n\nhandleClose = () => this.props.onClose(false);\nhandleDone(event) {\n this.props.callActions.setDateFilter(this.state.startDate.getTime());\n this.props.onClose(true);\n}\n\n\n render() {\n \n return (\n\n \n Select a Date & Time\n \n \n \n \n \n \n \n \n \n\n )\n }\n}\n\nexport default CalendarModal;\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/configureStore.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-actions.js",["133","134","135","136","137","138","139"],"import axios from 'axios';\n//import { browserHistory } from \"react-router\"\nimport * as types from \"./talkgroup-constants\";\nimport { push } from 'connected-react-router';\n\n// \"Log In\" action creators\nfunction beginImportTalkgroup() {\n return { type: types.IMPORT_TALKGROUP };\n}\n\nfunction importTalkgroupSuccess(data) {\n return {\n type: types.IMPORT_SUCCESS_TALKGROUP,\n data\n };\n}\n\nfunction importTalkgroupError(data) {\n return {\n type: types.IMPORT_ERROR_TALKGROUP,\n data\n };\n}\n\nfunction beginExportTalkgroup() {\n return { type: types.EXPORT_TALKGROUP };\n}\n\nfunction exportTalkgroupSuccess() {\n return { type: types.EXPORT_SUCCESS_TALKGROUP };\n}\n\nfunction exportTalkgroupError() {\n return { type: types.EXPORT_ERROR_TALKGROUP };\n}\n\n\nfunction beginFetchTalkgroup() {\n return { type: types.FETCH_TALKGROUP };\n}\n\nfunction fetchTalkgroupSuccess(data) {\n return { type: types.FETCH_SUCCESS_TALKGROUP,\n data };\n}\n\nfunction fetchTalkgroupError(data) {\n return { type: types.FETCH_ERROR_TALKGROUP,\n data };\n}\n\n\nfunction makeUserRequest(method, data, api) {\n // returns a Promise\n return axios({\n method: method,\n url: api,\n data: data\n });\n}\n\nexport function changeUrl(url) {\n return dispatch => {\n dispatch(push(url));\n };\n}\n\n\n// https://stackoverflow.com/questions/41878838/how-do-i-set-multipart-in-axios-with-react\n\n\n\nfunction shouldFetchTalkgroups(state, shortName) {\n if (!state.talkgroup.items.hasOwnProperty(shortName)) {\n return true\n } else if (state.talkgroup.isWaiting) {\n return false\n } else {\n return false\n }\n}\n\nexport function fetchTalkgroups(shortName) {\n return (dispatch, getState) => {\n if (shouldFetchTalkgroups(getState(), shortName)) {\n dispatch(beginFetchTalkgroup());\n\n return axios\n .get(process.env.REACT_APP_BACKEND_SERVER + \"/\" + shortName + \"/talkgroups\")\n .then(response => {\n if (response.data) {\n var data = {shortName: shortName, talkgroups: response.data.talkgroups}\n dispatch(fetchTalkgroupSuccess( data));\n } else {\n dispatch(fetchTalkgroupError());\n let registerMessage = response.data.message;\n return registerMessage;\n }\n })\n .catch(response => {\n if (response instanceof Error) {\n // Something happened in setting up the request that triggered an Error\n console.log(\"Error\", response.message);\n }\n });\n };\n};\n}\n",["140","141"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-reducer.js",["142","143"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/MediaPlayer.js",["144","145"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/GroupModal.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Group/group-actions.js",[],["146","147"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/redux-router/reducers.js",[],["148","149"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/SystemCard.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CalendarModalContainer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/ListSystems.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-constants.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/CallItem.js",["150"],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/System/system-actions.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Talkgroups/talkgroup-reducer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Main/MainContainer.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-reducer.js",["151","152"],"import {\n FETCH_CALL_INFO,\n FETCH_SUCCESS_CALL_INFO,\n FETCH_ERROR_CALL_INFO,\n FETCH_CALL,\n PREPEND_CALL,\n UPSERT_CALL,\n FETCH_SUCCESS_CALL,\n FETCH_SUCCESS_OLDER_CALL,\n FETCH_SUCCESS_NEWER_CALL,\n FETCH_ERROR_CALL,\n SET_SHORT_NAME,\n SET_ALL_FILTER,\n SET_GROUP_FILTER,\n SET_TALKGROUP_FILTER,\n SET_DATE_FILTER,\n SET_STARRED_FILTER,\n SET_FILTER,\n SET_CURRENT_CALL_ID,\n SET_LIVE,\n ADD_STAR_SUCCESS\n} from \"./call-constants\";\n\nfunction updateObject(oldObject, newValues) {\n // Encapsulate the idea of passing a new object as the first parameter\n // to Object.assign to ensure we correctly copy data instead of mutating\n return Object.assign({}, oldObject, newValues);\n}\n\nfunction updateCallInItems(calls, action) {\nreturn calls.map( (item) => {\n if (item._id !== action.data._id) {\n // This isn't the item we care about - keep it as-is\n return item;\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...action.data\n };\n });\n}\n/*\nfunction updateObjectInArray(array, action) {\n return array.map((item, index) => {\n if (index !== action.index) {\n // This isn't the item we care about - keep it as-is\n return item\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...item,\n ...action.item\n }\n })\n}\n\nfunction updateObjectInArray(array, shortName, updatedItem) {\n return array.map( item => {\n if(item.shortName !== shortName) {\n // This isn't the item we care about - keep it as-is\n return item;\n }\n\n // Otherwise, this is the one we want - return an updated value\n return {\n ...item,\n ...updatedItem\n };\n });\n}\n*/\nconst now = new Date();\nconst call = (\n state = {\n isWaiting: false,\n shortName: \"\",\n byId: {},\n allIds: [],\n oldestCallTime: now,\n newestCallTime: now,\n filterType: 0,\n filterTalkgroups: [],\n filterGroupId: false,\n filterDate: false,\n filterStarred: false,\n currentCallId: false,\n live: false\n },\n action\n) => {\n switch (action.type) {\n\n case SET_CURRENT_CALL_ID:\n return Object.assign({}, state, {currentCallId: action.data});\n \n case SET_FILTER:\n {\n var filter={};\n filter.live = !action.data.live ? state.live : action.data.live;\n filter.filterStarred = !action.data.filterStarred ? false : action.data.filterStarred;\n filter.filterType = !action.data.filterType ? 0 : action.data.filterType;\n filter.filterTalkgroups = !action.data.filterTalkgroups ? [] : action.data.filterTalkgroups;\n filter.filterGroupId = !action.data.filterGroupId ? false : action.data.filterGroupId;\n filter.filterDate = !action.data.filterDate ? 0 : action.data.filterDate;\n return Object.assign({}, state, {\n live: action.data.live,\n filterType: action.data.filterType,\n filterTalkgroups: action.data.filterTalkgroups,\n filterGroupId: action.data.filterGroupId,\n filterDate: action.data.filterDate,\n filterStarred: action.data.filterStarred\n });\n }\n\n case SET_LIVE:\n return Object.assign({}, state, {live: action.data});\n \n case SET_SHORT_NAME:\n return Object.assign({}, state, {shortName: action.data});\n\n case SET_DATE_FILTER:\n return Object.assign({}, state, {filterDate: action.date});\n\n case SET_STARRED_FILTER:\n return Object.assign({}, state, {filterStarred: action.data});\n\n case SET_ALL_FILTER:\n return Object.assign({}, state, {filterType: 0, filterTalkgroups:[], filterGroupId: false});\n\n case SET_GROUP_FILTER:\n return Object.assign({}, state, {filterType: 1, filterTalkgroups:[], filterGroupId: action.groupId});\n\n case SET_TALKGROUP_FILTER:\n return Object.assign({}, state, {filterType: 2, filterTalkgroups: action.talkgroups, filterGroupId: false});\n\n case FETCH_CALL_INFO:\n case FETCH_CALL:\n return Object.assign({}, state, { isWaiting: true});\n\n case FETCH_SUCCESS_CALL_INFO:\n return Object.assign({}, state, {\n byId: {...state.byId, [action.data._id]: action.data },\n isWaiting: false\n\n });\n\n case ADD_STAR_SUCCESS:\n return Object.assign({}, state,{\n byId: {...state.byId, [action.data._id]: action.data },\n isWaiting: false\n\n });\n // This will set the items to the rx data\n case FETCH_SUCCESS_CALL:\n {\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id);\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n newestCallTime: new Date(action.data.calls[0].time),\n oldestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: { ...byId},\n allIds: [...allIds]\n });\n }\n\n case UPSERT_CALL:\n if (typeof state.byId[action.data._id] !== \"undefined\") {\n return Object.assign({}, state, {\n byId: {...state.byId, [action.data._id]: action.data },\n });\n } else {\n return Object.assign({}, state, {\n newestCallTime: new Date(action.data.time),\n byId: {[action.data._id]: action.data, ...state.byId},\n allIds: [action.data._id, ...state.allIds]\n }); \n }\n\n case PREPEND_CALL:\n return Object.assign({}, state, {\n isWaiting: false,\n newestCallTime: new Date(action.data.time),\n byId: {[action.data._id]: action.data, ...state.byId},\n allIds: [action.data._id, ...state.allIds]\n });\n\n// This will add the array of Calls in the data to the beginning of the existing array of Calls\n case FETCH_SUCCESS_NEWER_CALL:\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id).reverse();\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n newestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: {...state.byId, ...byId},\n allIds: [...allIds, ...state.allIds]\n });\n\n// This will add the array of Calls in the data to the end of the existing array of Calls\n case FETCH_SUCCESS_OLDER_CALL:\n {\n const byId = action.data.calls.reduce((acc, call) => ({ ...acc, [call._id]: call }), {});\n const allIds = action.data.calls.map(call => call._id);\n return Object.assign({}, state, {\n isWaiting: false,\n shortName: action.data.shortName,\n oldestCallTime: new Date(action.data.calls[action.data.calls.length-1].time),\n byId: {...state.byId, ...byId},\n allIds: [ ...state.allIds, ...allIds]\n });\n }\n case FETCH_ERROR_CALL_INFO:\n case FETCH_ERROR_CALL:\n return Object.assign({}, state, {\n isWaiting: false\n });\n\n default:\n return state;\n }\n};\n\nexport default call;\n","/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/Call/call-constants.js",[],"/Users/luke/Projects/OpenMHz/trunk-server-public/frontend/src/index.js",[],{"ruleId":"153","severity":1,"message":"154","line":12,"column":3,"nodeType":"155","messageId":"156","endLine":16,"endColumn":4},{"ruleId":"157","severity":1,"message":"158","line":20,"column":10,"nodeType":"159","messageId":"160","endLine":20,"endColumn":21},{"ruleId":"161","severity":1,"message":"162","line":74,"column":3,"nodeType":"163","messageId":"164","endLine":80,"endColumn":4},{"ruleId":"165","replacedBy":"166"},{"ruleId":"167","replacedBy":"168"},{"ruleId":"157","severity":1,"message":"169","line":288,"column":15,"nodeType":"159","messageId":"160","endLine":288,"endColumn":19},{"ruleId":"157","severity":1,"message":"170","line":340,"column":13,"nodeType":"159","messageId":"160","endLine":340,"endColumn":24},{"ruleId":"165","replacedBy":"171"},{"ruleId":"167","replacedBy":"172"},{"ruleId":"173","severity":1,"message":"174","line":1,"column":1,"nodeType":"175","endLine":11,"endColumn":2},{"ruleId":"165","replacedBy":"176"},{"ruleId":"167","replacedBy":"177"},{"ruleId":"157","severity":1,"message":"178","line":6,"column":3,"nodeType":"159","messageId":"160","endLine":6,"endColumn":9},{"ruleId":"157","severity":1,"message":"179","line":7,"column":10,"nodeType":"159","messageId":"160","endLine":7,"endColumn":30},{"ruleId":"157","severity":1,"message":"180","line":11,"column":10,"nodeType":"159","messageId":"160","endLine":11,"endColumn":32},{"ruleId":"157","severity":1,"message":"181","line":18,"column":10,"nodeType":"159","messageId":"160","endLine":18,"endColumn":30},{"ruleId":"157","severity":1,"message":"182","line":25,"column":10,"nodeType":"159","messageId":"160","endLine":25,"endColumn":30},{"ruleId":"157","severity":1,"message":"183","line":29,"column":10,"nodeType":"159","messageId":"160","endLine":29,"endColumn":32},{"ruleId":"157","severity":1,"message":"184","line":33,"column":10,"nodeType":"159","messageId":"160","endLine":33,"endColumn":30},{"ruleId":"157","severity":1,"message":"185","line":53,"column":10,"nodeType":"159","messageId":"160","endLine":53,"endColumn":25},{"ruleId":"165","replacedBy":"186"},{"ruleId":"167","replacedBy":"187"},{"ruleId":"157","severity":1,"message":"188","line":7,"column":10,"nodeType":"159","messageId":"160","endLine":7,"endColumn":22},{"ruleId":"157","severity":1,"message":"189","line":13,"column":10,"nodeType":"159","messageId":"160","endLine":13,"endColumn":27},{"ruleId":"190","severity":1,"message":"191","line":77,"column":3,"nodeType":"155","messageId":"192","endLine":78,"endColumn":4},{"ruleId":"157","severity":1,"message":"193","line":89,"column":5,"nodeType":"159","messageId":"160","endLine":89,"endColumn":16},{"ruleId":"165","replacedBy":"194"},{"ruleId":"167","replacedBy":"195"},{"ruleId":"165","replacedBy":"196"},{"ruleId":"167","replacedBy":"197"},{"ruleId":"157","severity":1,"message":"198","line":41,"column":18,"nodeType":"159","messageId":"160","endLine":41,"endColumn":21},{"ruleId":"157","severity":1,"message":"188","line":24,"column":10,"nodeType":"159","messageId":"160","endLine":24,"endColumn":22},{"ruleId":"157","severity":1,"message":"199","line":30,"column":10,"nodeType":"159","messageId":"160","endLine":30,"endColumn":27},"no-useless-constructor","Useless constructor.","MethodDefinition","noUselessConstructor","no-unused-vars","'prependCall' is defined but never used.","Identifier","unusedVar","no-unreachable","Unreachable code.","IfStatement","unreachableCode","no-native-reassign",["200"],"no-negated-in-lhs",["201"],"'refs' is assigned a value but never used.","'currentCall' is assigned a value but never used.",["200"],["201"],"import/no-anonymous-default-export","Assign object to a variable before exporting as module default","ExportDefaultDeclaration",["200"],["201"],"'Header' is defined but never used.","'beginImportTalkgroup' is defined but never used.","'importTalkgroupSuccess' is defined but never used.","'importTalkgroupError' is defined but never used.","'beginExportTalkgroup' is defined but never used.","'exportTalkgroupSuccess' is defined but never used.","'exportTalkgroupError' is defined but never used.","'makeUserRequest' is defined but never used.",["200"],["201"],"'updateObject' is defined but never used.","'updateItemInArray' is defined but never used.","no-dupe-class-members","Duplicate name 'componentDidUpdate'.","unexpected","'playEnabled' is assigned a value but never used.",["200"],["201"],["200"],["201"],"'src' is assigned a value but never used.","'updateCallInItems' is defined but never used.","no-global-assign","no-unsafe-negation"]
\ No newline at end of file
diff --git a/frontend/public/android-chrome-192x192.png b/frontend/public/android-chrome-192x192.png
new file mode 100644
index 0000000..9ee745e
Binary files /dev/null and b/frontend/public/android-chrome-192x192.png differ
diff --git a/frontend/public/android-chrome-512x512.png b/frontend/public/android-chrome-512x512.png
new file mode 100644
index 0000000..9f72cfe
Binary files /dev/null and b/frontend/public/android-chrome-512x512.png differ
diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png
new file mode 100644
index 0000000..2e9f065
Binary files /dev/null and b/frontend/public/apple-touch-icon.png differ
diff --git a/frontend/public/favicon-16x16.png b/frontend/public/favicon-16x16.png
new file mode 100644
index 0000000..77cbaab
Binary files /dev/null and b/frontend/public/favicon-16x16.png differ
diff --git a/frontend/public/favicon-32x32.png b/frontend/public/favicon-32x32.png
new file mode 100644
index 0000000..dcc8909
Binary files /dev/null and b/frontend/public/favicon-32x32.png differ
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
index 354202a..a65d718 100644
Binary files a/frontend/public/favicon.ico and b/frontend/public/favicon.ico differ
diff --git a/frontend/public/index.html b/frontend/public/index.html
index d0ae633..47ae8c7 100644
--- a/frontend/public/index.html
+++ b/frontend/public/index.html
@@ -6,15 +6,15 @@
-
+
-
+