merge with base

This commit is contained in:
Hunter Miller 2021-08-19 15:51:52 -05:00
commit eec41ab2f0
16 changed files with 323 additions and 439 deletions

View File

@ -30,6 +30,7 @@ module.exports = {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error'],
'no-use-before-define': 'off',
'no-param-reassign': ['error', { props: true, ignorePropertyModificationsFor: ['draft'] }],
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-empty-function': 'off',
'react/jsx-filename-extension': ['warn', { extensions: ['.tsx'] }],

View File

@ -17,13 +17,13 @@
"clipboard-copy": "^4.0.1",
"color2k": "^1.2.4",
"fuzzy": "^0.1.3",
"immer": "^9.0.5",
"lodash-es": "^4.17.21",
"mousetrap": "^1.6.5",
"postcss-import": "^14.0.2",
"query-string": "^7.0.1",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-query": "^3.19.2",
"react-router-dom": "^5.2.0",
"slugify": "^1.6.0",
"zustand": "^3.5.7"
@ -1568,7 +1568,8 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/base64-js": {
"version": "1.5.1",
@ -1589,14 +1590,6 @@
}
]
},
"node_modules/big-integer": {
"version": "1.6.48",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@ -1610,6 +1603,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -1627,21 +1621,6 @@
"node": ">=8"
}
},
"node_modules/broadcast-channel": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
"integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
"dependencies": {
"@babel/runtime": "^7.7.2",
"detect-node": "^2.1.0",
"js-sha3": "0.8.0",
"microseconds": "0.2.0",
"nano-time": "1.0.0",
"oblivious-set": "1.0.0",
"rimraf": "3.0.2",
"unload": "2.2.0"
}
},
"node_modules/browser-or-node": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz",
@ -1944,7 +1923,8 @@
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/confusing-browser-globals": {
"version": "1.0.10",
@ -2080,11 +2060,6 @@
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
"dev": true
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
},
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
@ -3619,7 +3594,8 @@
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
@ -3716,6 +3692,7 @@
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -3957,6 +3934,15 @@
"node": ">= 4"
}
},
"node_modules/immer": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.5.tgz",
"integrity": "sha512-2WuIehr2y4lmYz9gaQzetPR2ECniCifk4ORaQbU3g5EalLt+0IVTosEPJ5BoYl/75ky2mivzdRzV8wWgQGOSYQ==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
}
},
"node_modules/import-cwd": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
@ -4028,6 +4014,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@ -4479,11 +4466,6 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"node_modules/js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -5031,15 +5013,6 @@
"node": ">=10"
}
},
"node_modules/match-sorter": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.0.tgz",
"integrity": "sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ==",
"dependencies": {
"@babel/runtime": "^7.12.5",
"remove-accents": "0.4.2"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -5068,11 +5041,6 @@
"node": ">=8.6"
}
},
"node_modules/microseconds": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
"integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA=="
},
"node_modules/mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@ -5099,6 +5067,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@ -5153,14 +5122,6 @@
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"dev": true
},
"node_modules/nano-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
"integrity": "sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=",
"dependencies": {
"big-integer": "^1.6.16"
}
},
"node_modules/nanoid": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
@ -5352,15 +5313,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/oblivious-set": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
"integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw=="
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
@ -5518,6 +5475,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
@ -5889,31 +5847,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-query": {
"version": "3.19.2",
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.19.2.tgz",
"integrity": "sha512-YYQ+jZ4DaabnDWEbKCIvkouLWif2iPFgBIeKLPkUmhXM4cz+Kscb5Q7mz+U57Ip17tarhFiNwX86gWXM69ouQQ==",
"dependencies": {
"@babel/runtime": "^7.5.5",
"broadcast-channel": "^3.4.1",
"match-sorter": "^6.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/react-refresh": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
@ -6157,11 +6090,6 @@
"url": "https://github.com/sponsors/mysticatea"
}
},
"node_modules/remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U="
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -6233,6 +6161,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
@ -7113,15 +7042,6 @@
"node": ">= 10.0.0"
}
},
"node_modules/unload": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
"integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
"dependencies": {
"@babel/runtime": "^7.6.2",
"detect-node": "^2.0.4"
}
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@ -7303,7 +7223,8 @@
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"node_modules/write": {
"version": "1.0.3",
@ -8520,18 +8441,14 @@
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"big-integer": {
"version": "1.6.48",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
},
"binary-extensions": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@ -8542,6 +8459,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@ -8556,21 +8474,6 @@
"fill-range": "^7.0.1"
}
},
"broadcast-channel": {
"version": "3.7.0",
"resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz",
"integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==",
"requires": {
"@babel/runtime": "^7.7.2",
"detect-node": "^2.1.0",
"js-sha3": "0.8.0",
"microseconds": "0.2.0",
"nano-time": "1.0.0",
"oblivious-set": "1.0.0",
"rimraf": "3.0.2",
"unload": "2.2.0"
}
},
"browser-or-node": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.3.0.tgz",
@ -8795,7 +8698,8 @@
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"confusing-browser-globals": {
"version": "1.0.10",
@ -8900,11 +8804,6 @@
"integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
"dev": true
},
"detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="
},
"detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
@ -10086,7 +9985,8 @@
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"fsevents": {
"version": "2.3.2",
@ -10155,6 +10055,7 @@
"version": "7.1.7",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
"integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@ -10321,6 +10222,11 @@
"integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
"dev": true
},
"immer": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.5.tgz",
"integrity": "sha512-2WuIehr2y4lmYz9gaQzetPR2ECniCifk4ORaQbU3g5EalLt+0IVTosEPJ5BoYl/75ky2mivzdRzV8wWgQGOSYQ=="
},
"import-cwd": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
@ -10373,6 +10279,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
@ -10690,11 +10597,6 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true
},
"js-sha3": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
"integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -11119,15 +11021,6 @@
"yallist": "^4.0.0"
}
},
"match-sorter": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.0.tgz",
"integrity": "sha512-efYOf/wUpNb8FgNY+cOD2EIJI1S5I7YPKsw0LBp7wqPh5pmMS6i/wr3ZWwfwrAw1NvqTA2KUReVRWDX84lUcOQ==",
"requires": {
"@babel/runtime": "^7.12.5",
"remove-accents": "0.4.2"
}
},
"merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@ -11150,11 +11043,6 @@
"picomatch": "^2.2.3"
}
},
"microseconds": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz",
"integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA=="
},
"mimic-fn": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
@ -11174,6 +11062,7 @@
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@ -11216,14 +11105,6 @@
"integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=",
"dev": true
},
"nano-time": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz",
"integrity": "sha1-sFVPaa2J4i0JB/ehKwmTpdlhN+8=",
"requires": {
"big-integer": "^1.6.16"
}
},
"nanoid": {
"version": "3.1.23",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
@ -11366,15 +11247,11 @@
"es-abstract": "^1.18.2"
}
},
"oblivious-set": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz",
"integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw=="
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
@ -11486,7 +11363,8 @@
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"path-is-inside": {
"version": "1.0.2",
@ -11730,16 +11608,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-query": {
"version": "3.19.2",
"resolved": "https://registry.npmjs.org/react-query/-/react-query-3.19.2.tgz",
"integrity": "sha512-YYQ+jZ4DaabnDWEbKCIvkouLWif2iPFgBIeKLPkUmhXM4cz+Kscb5Q7mz+U57Ip17tarhFiNwX86gWXM69ouQQ==",
"requires": {
"@babel/runtime": "^7.5.5",
"broadcast-channel": "^3.4.1",
"match-sorter": "^6.0.2"
}
},
"react-refresh": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.10.0.tgz",
@ -11912,11 +11780,6 @@
"integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
"dev": true
},
"remove-accents": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.4.2.tgz",
"integrity": "sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U="
},
"require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@ -11969,6 +11832,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"dev": true,
"requires": {
"glob": "^7.1.3"
}
@ -12631,15 +12495,6 @@
"integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
"dev": true
},
"unload": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz",
"integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==",
"requires": {
"@babel/runtime": "^7.6.2",
"detect-node": "^2.0.4"
}
},
"uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@ -12771,7 +12626,8 @@
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"write": {
"version": "1.0.3",

View File

@ -23,13 +23,13 @@
"clipboard-copy": "^4.0.1",
"color2k": "^1.2.4",
"fuzzy": "^0.1.3",
"immer": "^9.0.5",
"lodash-es": "^4.17.21",
"mousetrap": "^1.6.5",
"postcss-import": "^14.0.2",
"query-string": "^7.0.1",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-query": "^3.19.2",
"react-router-dom": "^5.2.0",
"slugify": "^1.6.0",
"zustand": "^3.5.7"

View File

@ -1,17 +1,8 @@
import React, { useEffect } from 'react';
import Mousetrap from 'mousetrap';
import { BrowserRouter, Switch, Route, useHistory } from 'react-router-dom';
import { QueryClient, QueryClientProvider } from 'react-query';
import { Grid } from './pages/Grid';
export const queryClient = new QueryClient({
defaultOptions: {
queries: {
refetchOnWindowFocus: false
}
}
});
const AppRoutes = () => {
const { push } = useHistory();
@ -34,10 +25,8 @@ export function App() {
const base = import.meta.env.MODE === 'mock' ? undefined : '/apps/grid';
return (
<QueryClientProvider client={queryClient}>
<BrowserRouter basename={base}>
<AppRoutes />
</BrowserRouter>
</QueryClientProvider>
<BrowserRouter basename={base}>
<AppRoutes />
</BrowserRouter>
);
}

View File

@ -1,20 +1,38 @@
import clipboardCopy from 'clipboard-copy';
import { useCallback } from 'react';
import { useMutation, useQuery } from 'react-query';
import { pick } from 'lodash-es';
import { useCallback, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom';
import { installDocket, requestTreaty, treatyKey } from '../state/docket';
import useDocketState from '../state/docket';
import { Treaty } from '../state/docket-types';
type Status = 'initial' | 'loading' | 'success' | 'error';
export function useTreaty() {
const { ship, desk } = useParams<{ ship: string; desk: string }>();
const { data: treaty } = useQuery(treatyKey([ship, desk]), () => requestTreaty(ship, desk));
const { mutate, ...installStatus } = useMutation(() => installDocket(ship, desk));
const { requestTreaty, installDocket } = useDocketState((s) =>
pick(s, ['requestTreaty', 'installDocket'])
);
const [treaty, setTreaty] = useState<Treaty>();
const [installStatus, setInstallStatus] = useState<Status>('initial');
useEffect(() => {
async function getTreaty() {
setTreaty(await requestTreaty(ship, desk));
}
getTreaty();
}, [ship, desk]);
const copyApp = useCallback(async () => {
clipboardCopy(`${ship}/${desk}`);
}, [ship, desk]);
const installApp = useCallback(() => {
mutate();
const installApp = useCallback(async () => {
setInstallStatus('loading');
installDocket(ship, desk)
.then(() => setInstallStatus('success'))
.catch(() => setInstallStatus('error'));
}, []);
return {

View File

@ -161,14 +161,16 @@ export const Leap = React.forwardRef(({ menu, dropdown, showClose, className }:
push(pathBack);
}
if (arrow && selectedMatch) {
if (arrow) {
e.preventDefault();
const currentIndex = matches.findIndex((m) => {
const matchValue = m.display || m.value;
const searchValue = selectedMatch.display || selectedMatch.value;
return matchValue === searchValue;
});
const currentIndex = selectedMatch
? matches.findIndex((m) => {
const matchValue = m.display || m.value;
const searchValue = selectedMatch.display || selectedMatch.value;
return matchValue === searchValue;
})
: 0;
const unsafeIndex = e.key === 'ArrowUp' ? currentIndex - 1 : currentIndex + 1;
const index = (unsafeIndex + matches.length) % matches.length;

View File

@ -1,19 +1,18 @@
import React, { useEffect } from 'react';
import { useQuery } from 'react-query';
import { PillButton } from '../../components/Button';
import { DocketHeader } from '../../components/DocketHeader';
import { ShipName } from '../../components/ShipName';
import { Spinner } from '../../components/Spinner';
import { TreatyMeta } from '../../components/TreatyMeta';
import { useTreaty } from '../../logic/useTreaty';
import { chargesKey, fetchCharges } from '../../state/docket';
import { useLeapStore } from '../Nav';
import { useCharges } from '../../state/docket';
export const AppInfo = () => {
const select = useLeapStore((state) => state.select);
const { ship, desk, treaty, installStatus, copyApp, installApp } = useTreaty();
const { data: charges } = useQuery(chargesKey(), fetchCharges);
const installed = (charges || {})[desk] || installStatus.isSuccess;
const charges = useCharges();
const installed = (charges || {})[desk] || installStatus === 'success';
useEffect(() => {
select(
@ -43,8 +42,8 @@ export const AppInfo = () => {
)}
{!installed && (
<PillButton onClick={installApp}>
{installStatus.isIdle && 'Get App'}
{installStatus.isLoading && (
{installStatus === 'initial' && 'Get App'}
{installStatus === 'loading' && (
<>
<Spinner />
<span className="sr-only">Installing...</span>

View File

@ -1,34 +1,31 @@
import React, { useCallback, useEffect, useMemo } from 'react';
import { useQuery, useQueryClient } from 'react-query';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import fuzzy from 'fuzzy';
import slugify from 'slugify';
import classNames from 'classnames';
import { ShipName } from '../../components/ShipName';
import { fetchProviderTreaties, treatyKey } from '../../state/docket';
import useDocketState from '../../state/docket';
import { Treaty } from '../../state/docket-types';
import { useLeapStore } from '../Nav';
type AppsProps = RouteComponentProps<{ ship: string }>;
export const Apps = ({ match }: AppsProps) => {
const queryClient = useQueryClient();
const { searchInput, selectedMatch, select } = useLeapStore((state) => ({
searchInput: state.searchInput,
select: state.select,
selectedMatch: state.selectedMatch
}));
const provider = match?.params.ship;
const { data: apps } = useQuery(treatyKey([provider]), () => fetchProviderTreaties(provider), {
enabled: !!provider
});
const fetchProviderTreaties = useDocketState((s) => s.fetchProviderTreaties);
const [treaties, setTreaties] = useState<Treaty[]>();
const results = useMemo(
() =>
apps
treaties
? fuzzy
.filter(
searchInput,
apps.map((t) => t.title)
treaties.map((t) => t.title)
)
.sort((a, b) => {
const left = a.string.startsWith(searchInput) ? a.score + 1 : a.score;
@ -36,9 +33,9 @@ export const Apps = ({ match }: AppsProps) => {
return right - left;
})
.map((result) => apps[result.index])
.map((result) => treaties[result.index])
: undefined,
[apps, searchInput]
[treaties, searchInput]
);
const count = results?.length;
@ -58,12 +55,15 @@ export const Apps = ({ match }: AppsProps) => {
}
}, [results]);
const preloadApp = useCallback(
(app: Treaty) => {
queryClient.setQueryData(treatyKey([provider, app.desk]), app);
},
[queryClient]
);
useEffect(() => {
async function getTreaties() {
setTreaties(await fetchProviderTreaties(provider));
}
if (provider) {
getTreaties();
}
}, [provider]);
const isSelected = useCallback(
(target: Treaty) => {
@ -102,7 +102,6 @@ export const Apps = ({ match }: AppsProps) => {
'flex items-center space-x-3 default-ring ring-offset-2 rounded-lg',
isSelected(app) && 'ring-4'
)}
onClick={() => preloadApp(app)}
>
<div
className="flex-none relative w-12 h-12 bg-gray-200 rounded-lg"

View File

@ -1,11 +1,10 @@
import fuzzy from 'fuzzy';
import classNames from 'classnames';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useQuery } from 'react-query';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import { ShipName } from '../../components/ShipName';
import { fetchProviders, providersKey } from '../../state/docket';
import { Provider } from '../../state/docket-types';
import useDocketState from '../../state/docket';
import { useLeapStore } from '../Nav';
type ProvidersProps = RouteComponentProps<{ ship: string }>;
@ -16,10 +15,8 @@ export const Providers = ({ match }: ProvidersProps) => {
selectedMatch: state.selectedMatch
}));
const provider = match?.params.ship;
const { data: providers } = useQuery(providersKey(), () => fetchProviders(), {
enabled: !!provider,
keepPreviousData: true
});
const fetchProviders = useDocketState((s) => s.fetchProviders);
const [providers, setProviders] = useState<Provider[]>();
const search = provider || '';
const results = useMemo(
() =>
@ -42,8 +39,13 @@ export const Providers = ({ match }: ProvidersProps) => {
const count = results?.length;
useEffect(() => {
async function getProviders() {
setProviders(await fetchProviders(provider));
}
select(null, provider);
}, []);
getProviders();
}, [provider]);
useEffect(() => {
if (results) {

View File

@ -1,10 +1,8 @@
import { map } from 'lodash-es';
import React, { FunctionComponent } from 'react';
import { useQuery, useQueryClient } from 'react-query';
import { map, pick } from 'lodash-es';
import React, { FunctionComponent, useEffect } from 'react';
import { Route, RouteComponentProps } from 'react-router-dom';
import { MenuState, Nav } from '../nav/Nav';
import { chargesKey, fetchCharges } from '../state/docket';
import { Treaties } from '../state/docket-types';
import useDocketState from '../state/docket';
import { RemoveApp } from '../tiles/RemoveApp';
import { SuspendApp } from '../tiles/SuspendApp';
import { Tile } from '../tiles/Tile';
@ -14,18 +12,12 @@ type GridProps = RouteComponentProps<{
}>;
export const Grid: FunctionComponent<GridProps> = ({ match }) => {
const queryClient = useQueryClient();
const {
data: charges,
isLoading,
isSuccess
} = useQuery(chargesKey(), fetchCharges, {
onSuccess: (dockets: Treaties) => {
Object.entries(dockets).forEach(([k, v]) => {
queryClient.setQueryData(chargesKey([k]), v);
});
}
});
const { charges, fetchCharges } = useDocketState((s) => pick(s, ['charges', 'fetchCharges']));
const chargesLoaded = Object.keys(charges).length > 0;
useEffect(() => {
fetchCharges();
}, []);
return (
<div className="flex flex-col">
@ -34,8 +26,8 @@ export const Grid: FunctionComponent<GridProps> = ({ match }) => {
</header>
<main className="h-full w-full flex justify-center pt-24 pb-32 relative z-0">
{isLoading && <span>Loading...</span>}
{isSuccess && (
{!chargesLoaded && <span>Loading...</span>}
{chargesLoaded && (
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-6 px-4 md:px-8 w-full max-w-6xl">
{charges &&
map(charges, (charge, desk) => <Tile key={desk} docket={charge} desk={desk} />)}

View File

@ -21,16 +21,15 @@ export interface Treaty extends Docket {
hash: string;
}
export interface Dockets {
[ref: string]: Docket;
}
export interface Treaties {
[ref: string]: Treaty;
}
export interface Provider {
shipName: string;
nickname?: string;
status?: string;
treaties?: string[];
}
export type Dockets = Record<string, Docket>;
export type Treaties = Record<string, Treaty>;
export type Providers = Record<string, Provider>;

View File

@ -1,22 +1,30 @@
import fuzzy from 'fuzzy';
import create from 'zustand';
import produce from 'immer';
import { useCallback } from 'react';
import { omit } from 'lodash-es';
import { queryClient } from '../app';
import api from './api';
import { Treaty, Dockets, Docket, Provider } from './docket-types';
import { providers, treaties } from './mock-data';
import { Treaty, Dockets, Docket, Provider, Treaties, Providers } from './docket-types';
import { mockProviders, mockTreaties } from './mock-data';
const useMockData = import.meta.env.MODE === 'mock';
function makeKeyFn(key: string) {
return (childKeys: string[] = []) => {
return [key].concat(childKeys);
};
interface ChargesResponse {
initial: Dockets;
}
export const chargesKey = makeKeyFn('charges');
export const providersKey = makeKeyFn('providers');
export const treatyKey = makeKeyFn('treaty');
interface DocketState {
charges: Dockets;
treaties: Treaties;
providers: Providers;
fetchCharges: () => Promise<void>;
requestTreaty: (ship: string, desk: string) => Promise<Treaty>;
fetchProviders: (query?: string) => Promise<Provider[]>;
fetchProviderTreaties: (provider: string) => Promise<Treaty[]>;
toggleDocket: (desk: string) => Promise<void>;
installDocket: (ship: string, desk: string) => Promise<number | void>;
uninstallDocket: (desk: string) => Promise<number | void>;
}
async function fakeRequest<T>(data: T, time = 300): Promise<T> {
return new Promise((resolve) => {
@ -28,90 +36,115 @@ async function fakeRequest<T>(data: T, time = 300): Promise<T> {
const stableTreatyMap = new Map<string, Treaty[]>();
interface ChargesResponse {
initial: Dockets;
}
const useDocketState = create<DocketState>((set, get) => ({
fetchCharges: async () => {
const dockets = useMockData
? await fakeRequest(mockTreaties)
: ((await (await fetch('/~/scry/docket/charges.json')).json()) as ChargesResponse).initial;
export async function fetchCharges(): Promise<Dockets> {
const charges = queryClient.getQueryData<Dockets>(chargesKey());
if (useMockData && charges) {
return charges;
}
const charges = normalizeDockets(dockets);
const dockets = useMockData
? await fakeRequest(treaties)
: ((await (await fetch('/~/scry/docket/charges.json')).json()) as ChargesResponse).initial;
set({ charges });
},
fetchProviders: async (query?: string) => {
const providers = Object.values(mockProviders);
const searchTexts = providers.map((p) => p.shipName + (p.nickname || ''));
return fakeRequest(fuzzy.filter(query || '', searchTexts).map((el) => providers[el.index]));
},
fetchProviderTreaties: async (provider: string) => {
const { treaties, providers } = get();
const dev = providers[provider];
const treatyList = Object.values(treaties);
return Object.entries(dockets).reduce((obj: Dockets, [key, value]) => {
// eslint-disable-next-line no-param-reassign
obj[key] = normalizeDocket(value);
return obj;
}, {});
}
export async function fetchProviders(): Promise<Provider[]> {
return fakeRequest(providers);
}
export async function fetchProviderTreaties(provider: string): Promise<Treaty[]> {
const treatyList = Object.values(treaties).map(normalizeDocket);
if (!stableTreatyMap.has(provider)) {
stableTreatyMap.set(
provider,
treatyList.filter(() => !!Math.round(Math.random()))
);
}
return fakeRequest(stableTreatyMap.get(provider) || []);
}
export async function requestTreaty(ship: string, desk: string): Promise<Treaty> {
if (useMockData) {
return fakeRequest(treaties[desk]);
}
const key = `${ship}/${desk}`;
const result = await api.subscribeOnce('docket', `/treaty/${key}`, 20000);
return { ...normalizeDocket(result), ship, desk };
}
export async function installDocket(ship: string, desk: string): Promise<number | void> {
if (useMockData) {
const docket = normalizeDocket(await requestTreaty(ship, desk));
const charges = await queryClient.fetchQuery(chargesKey(), fetchCharges);
addCharge(charges, { desk, docket });
}
return api.poke({
app: 'hood',
mark: 'kiln-install',
json: {
ship,
desk,
local: desk
if (dev.treaties) {
return dev.treaties.map((key) => treaties[key]);
}
});
}
export async function uninstallDocket(desk: string): Promise<number | void> {
if (useMockData) {
const charges = await queryClient.fetchQuery(chargesKey(), fetchCharges);
delCharge(charges, desk);
}
if (!stableTreatyMap.has(provider)) {
stableTreatyMap.set(
provider,
treatyList.filter(() => !!Math.round(Math.random()))
);
}
return api.poke({
app: 'docket',
mark: 'docket-uninstall',
json: desk
});
}
const providerTreaties = stableTreatyMap.get(provider) || [];
export async function toggleDocket(desk: string): Promise<void> {
const charges = await queryClient.fetchQuery(chargesKey(), fetchCharges);
const docket = (charges || {})[desk];
docket.status = docket.status === 'active' ? 'suspended' : 'active';
}
set(
produce((draft: DocketState) => {
if (!draft.providers[provider].treaties) {
draft.providers[provider].treaties = [];
}
providerTreaties.forEach((treaty) => {
// may need to do this when not mock data
// const key = `${provider}/${treaty.desk}`;
// draft.treaties[key] = treaty;
draft.providers[provider].treaties?.push(treaty.desk);
});
})
);
return fakeRequest(providerTreaties);
},
requestTreaty: async (ship: string, desk: string) => {
const { treaties } = get();
if (useMockData) {
set({ treaties: await fakeRequest(treaties) });
return treaties[desk];
}
const key = `${ship}/${desk}`;
if (key in treaties) {
return treaties[key];
}
const result = await api.subscribeOnce('docket', `/treaty/${key}`, 20000);
const treaty = { ...normalizeDocket(result), ship, desk };
set((state) => ({
treaties: { ...state.treaties, [key]: treaty }
}));
return treaty;
},
installDocket: async (ship: string, desk: string) => {
if (useMockData) {
const docket = normalizeDocket(await get().requestTreaty(ship, desk));
set((state) => addCharge(state, { desk, docket }));
}
return api.poke({
app: 'hood',
mark: 'kiln-install',
json: {
ship,
desk,
local: desk
}
});
},
uninstallDocket: async (desk: string) => {
if (useMockData) {
set((state) => delCharge(state, desk));
}
return api.poke({
app: 'docket',
mark: 'docket-uninstall',
json: desk
});
},
toggleDocket: async (desk: string) => {
set(
produce((draft) => {
const docket = draft.charges[desk];
docket.status = docket.status === 'active' ? 'suspended' : 'active';
})
);
},
treaties: useMockData ? normalizeDockets(mockTreaties) : {},
charges: {},
providers: useMockData ? mockProviders : {},
set
}));
function normalizeDocket<T extends Docket>(docket: T): T {
return {
@ -121,6 +154,14 @@ function normalizeDocket<T extends Docket>(docket: T): T {
};
}
function normalizeDockets<T extends Docket>(dockets: Record<string, T>): Record<string, T> {
return Object.entries(dockets).reduce((obj: Record<string, T>, [key, value]) => {
// eslint-disable-next-line no-param-reassign
obj[key] = normalizeDocket(value);
return obj;
}, {});
}
interface AddDockEvent {
'add-dock': {
desk: string;
@ -134,46 +175,49 @@ interface DelDockEvent {
type DocketEvent = AddDockEvent | DelDockEvent;
function addCharge(charges: Dockets | undefined, { desk, docket }: AddDockEvent['add-dock']) {
queryClient.setQueryData(chargesKey(), { ...charges, [desk]: docket });
function addCharge(state: DocketState, { desk, docket }: AddDockEvent['add-dock']) {
return { charges: { ...state.charges, [desk]: docket } };
}
function delCharge(charges: Dockets | undefined, desk: DelDockEvent['del-dock']) {
queryClient.setQueryData(chargesKey(), omit(charges, desk));
function delCharge(state: DocketState, desk: DelDockEvent['del-dock']) {
return { charges: omit(state.charges, desk) };
}
api.subscribe({
app: 'docket',
path: '/charges',
event: (data: DocketEvent): void => {
const charges = queryClient.getQueryData<Dockets>(chargesKey());
console.log(data);
event: (data: DocketEvent) => {
useDocketState.setState((state) => {
console.log(data);
if ('add-dock' in data) {
addCharge(charges, data['add-dock']);
}
if ('add-dock' in data) {
return addCharge(state, data['add-dock']);
}
if ('del-dock' in data) {
delCharge(charges, data['del-dock']);
}
if ('del-dock' in data) {
return delCharge(state, data['del-dock']);
}
return { charges: state.charges };
});
}
});
// const selCharges = (s: DocketState) => {
// return omit(s.charges, "grid");
// };
const selCharges = (s: DocketState) => {
return omit(s.charges, 'grid');
};
// export function useCharges() {
// return useDocketState(selCharges);
// }
export function useCharges() {
return useDocketState(selCharges);
}
// export function useCharge(desk: string) {
// return useDocketState(useCallback(state => state.charges[desk], [desk]));
// }
export function useCharge(desk: string) {
return useDocketState(useCallback((state) => state.charges[desk], [desk]));
}
// const selRequest = (s: DocketState) => s.request;
// export function useRequestDocket() {
// return useDocketState(selRequest);
// }
const selRequest = (s: DocketState) => s.requestTreaty;
export function useRequestDocket() {
return useDocketState(selRequest);
}
// export default useDocketState;
export default useDocketState;

View File

@ -1,39 +1,39 @@
import systemUrl from '../assets/system.png';
import goUrl from '../assets/go.png';
import { Provider, Treaties, Treaty } from './docket-types';
import { Providers, Treaties, Treaty } from './docket-types';
export const providers: Provider[] = [
{
export const mockProviders: Providers = {
'~zod': {
shipName: '~zod',
nickname: 'Tlon Corporation'
},
{
'~nocsyx-lassul': {
shipName: '~nocsyx-lassul',
status: 'technomancing an electron wrapper for urbit'
},
{
'~nachus-hollyn': {
shipName: '~nachus-hollyn'
},
{
'~nalbel_litzod': {
shipName: '~nalbel_litzod',
status: 'congratulations'
},
{
'~litmus^ritten': {
shipName: '~litmus^ritten'
},
{
'~nalput_litzod': {
shipName: '~nalput_litzod',
status: 'Queen'
},
{
'~nalrex_bannus': {
shipName: '~nalrex_bannus',
status: 'Script, command and inspect your Urbit. Use TUI applications'
},
{
'~nalrys': {
shipName: '~nalrys',
status: 'hosting coming soon'
}
];
};
export const appMetaData: Pick<Treaty, 'cass' | 'hash' | 'website' | 'license' | 'version'> = {
cass: '~2021.8.11..05.11.10..b721',
@ -43,7 +43,7 @@ export const appMetaData: Pick<Treaty, 'cass' | 'hash' | 'website' | 'license' |
version: '2.0.1'
};
export const treaties: Treaties = {
export const mockTreaties: Treaties = {
groups: {
ship: '~zod',
desk: 'groups',

View File

@ -1,26 +1,20 @@
import React, { useCallback } from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useHistory, useParams } from 'react-router-dom';
import { Button } from '../components/Button';
import { Dialog, DialogContent } from '../components/Dialog';
import { chargesKey, uninstallDocket } from '../state/docket';
import { Docket } from '../state/docket-types';
import useDocketState, { useCharges } from '../state/docket';
export const RemoveApp = () => {
const queryClient = useQueryClient();
const history = useHistory();
const { desk } = useParams<{ desk: string }>();
const { data: docket } = useQuery<Docket>(chargesKey([desk]));
const { mutate } = useMutation(() => uninstallDocket(desk), {
onSuccess: () => {
history.push('/');
queryClient.invalidateQueries(chargesKey());
}
});
const charges = useCharges();
const docket = charges[desk];
const uninstallDocket = useDocketState((s) => s.uninstallDocket);
// TODO: add optimistic updates
const handleRemoveApp = useCallback(() => {
mutate();
uninstallDocket(desk);
history.push('/');
}, []);
return (

View File

@ -1,25 +1,21 @@
import React, { useCallback } from 'react';
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { Redirect, useHistory, useParams } from 'react-router-dom';
import { Button } from '../components/Button';
import { Dialog, DialogContent } from '../components/Dialog';
import { chargesKey, toggleDocket } from '../state/docket';
import { Docket } from '../state/docket-types';
import useDocketState, { useCharges } from '../state/docket';
export const SuspendApp = () => {
const queryClient = useQueryClient();
const history = useHistory();
const { desk } = useParams<{ desk: string }>();
const { data: docket } = useQuery<Docket>(chargesKey([desk]));
const { mutate } = useMutation(() => toggleDocket(desk), {
onSuccess: () => {
history.push('/');
queryClient.invalidateQueries(chargesKey());
}
});
const charges = useCharges();
const docket = charges[desk];
const toggleDocket = useDocketState((s) => s.toggleDocket);
// TODO: add optimistic updates
const handleSuspendApp = useCallback(() => mutate(), []);
const handleSuspendApp = useCallback(() => {
toggleDocket(desk);
history.push('/');
}, []);
if (docket?.status === 'suspended') {
<Redirect to="/" />;

View File

@ -3,8 +3,7 @@ import type * as Polymorphic from '@radix-ui/react-polymorphic';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
import { Link } from 'react-router-dom';
import { useMutation, useQueryClient } from 'react-query';
import { chargesKey, toggleDocket } from '../state/docket';
import useDocketState from '../state/docket';
export interface TileMenuProps {
desk: string;
@ -38,14 +37,8 @@ const Item = React.forwardRef(({ children, ...props }, ref) => (
)) as ItemComponent;
export const TileMenu = ({ desk, active, menuColor, lightText, className }: TileMenuProps) => {
const queryClient = useQueryClient();
const [open, setOpen] = useState(false);
const { mutate } = useMutation(() => toggleDocket(desk), {
onSuccess: () => {
queryClient.invalidateQueries(chargesKey());
}
});
const toggleDocket = useDocketState((s) => s.toggleDocket);
const menuBg = { backgroundColor: menuColor };
const linkOnSelect = useCallback((e: Event) => {
e.preventDefault();
@ -96,7 +89,7 @@ export const TileMenu = ({ desk, active, menuColor, lightText, className }: Tile
Suspend App
</Item>
)}
{!active && <Item onSelect={() => mutate()}>Resume App</Item>}
{!active && <Item onSelect={() => toggleDocket(desk)}>Resume App</Item>}
<Item as={Link} to={`/app/${desk}/remove`} onSelect={linkOnSelect}>
Remove App
</Item>