mirror of
https://github.com/urbit/shrub.git
synced 2024-12-24 20:47:27 +03:00
merge with base
This commit is contained in:
commit
eec41ab2f0
@ -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'] }],
|
||||
|
236
pkg/grid/package-lock.json
generated
236
pkg/grid/package-lock.json
generated
@ -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",
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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"
|
||||
|
@ -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) {
|
||||
|
@ -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} />)}
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
|
@ -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',
|
||||
|
@ -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 (
|
||||
|
@ -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="/" />;
|
||||
|
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user