chore: use prettier
This commit is contained in:
parent
5ea3e3465d
commit
34105452f9
|
|
@ -0,0 +1,4 @@
|
|||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
.next
|
||||
e2e
|
||||
pnpm-lock.yaml
|
||||
dist
|
||||
|
|
@ -0,0 +1 @@
|
|||
{}
|
||||
|
|
@ -12,7 +12,11 @@
|
|||
"db-generate": "prisma generate",
|
||||
"start": "node server.js",
|
||||
"db-seed": "node -r esbuild-register prisma/seed.ts",
|
||||
"uno-generate": "unocss \"src/**/*.{ts,tsx}\" -o src/generated/uno.css"
|
||||
"uno-generate": "unocss \"src/**/*.{ts,tsx}\" -o src/generated/uno.css",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"lint-staged": {
|
||||
"**/*": "prettier --write --ignore-unknown"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/commands": "^0.20.0",
|
||||
|
|
@ -106,7 +110,10 @@
|
|||
"esbuild-register": "^3.3.2",
|
||||
"eslint": "^8.15.0",
|
||||
"eslint-config-next": "^12.1.6",
|
||||
"husky": "^8.0.1",
|
||||
"lint-staged": "^13.0.3",
|
||||
"postcss-import": "^14.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prisma": "^3.14.0",
|
||||
"tailwindcss": "^3.0.24",
|
||||
"typescript": "^4.5.5",
|
||||
|
|
|
|||
303
pnpm-lock.yaml
303
pnpm-lock.yaml
|
|
@ -55,8 +55,10 @@ specifiers:
|
|||
ethers: ^5.6.9
|
||||
fast-deep-equal: ^3.1.3
|
||||
form-data: ^4.0.0
|
||||
husky: ^8.0.1
|
||||
idb-keyval: ^6.2.0
|
||||
ioredis: ^5.2.2
|
||||
lint-staged: ^13.0.3
|
||||
mailgun.js: ^5.2.2
|
||||
mdast-util-to-string: ^3.1.0
|
||||
nanoid: ^3.3.3
|
||||
|
|
@ -64,6 +66,7 @@ specifiers:
|
|||
pica: ^9.0.1
|
||||
postcss-import: ^14.1.0
|
||||
posthtml: ^0.16.6
|
||||
prettier: ^2.7.1
|
||||
prisma: ^3.14.0
|
||||
prismjs: ^1.28.0
|
||||
react: ^18.1.0
|
||||
|
|
@ -189,7 +192,10 @@ devDependencies:
|
|||
esbuild-register: 3.3.3_esbuild@0.14.47
|
||||
eslint: 8.18.0
|
||||
eslint-config-next: 12.1.6_ngoqluhis4kr6sqtxgtlos2xtq
|
||||
husky: 8.0.1
|
||||
lint-staged: 13.0.3
|
||||
postcss-import: 14.1.0
|
||||
prettier: 2.7.1
|
||||
prisma: 3.15.2
|
||||
tailwindcss: 3.1.4
|
||||
typescript: 4.7.4
|
||||
|
|
@ -2283,6 +2289,14 @@ packages:
|
|||
resolution: {integrity: sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ==}
|
||||
dev: false
|
||||
|
||||
/aggregate-error/3.1.0:
|
||||
resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
clean-stack: 2.2.0
|
||||
indent-string: 4.0.0
|
||||
dev: true
|
||||
|
||||
/ajv/6.12.6:
|
||||
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
|
||||
dependencies:
|
||||
|
|
@ -2292,6 +2306,13 @@ packages:
|
|||
uri-js: 4.4.1
|
||||
dev: true
|
||||
|
||||
/ansi-escapes/4.3.2:
|
||||
resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
type-fest: 0.21.3
|
||||
dev: true
|
||||
|
||||
/ansi-regex/4.1.1:
|
||||
resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -2301,6 +2322,11 @@ packages:
|
|||
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/ansi-regex/6.0.1:
|
||||
resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/ansi-styles/3.2.1:
|
||||
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -2314,6 +2340,11 @@ packages:
|
|||
dependencies:
|
||||
color-convert: 2.0.1
|
||||
|
||||
/ansi-styles/6.1.0:
|
||||
resolution: {integrity: sha512-VbqNsoz55SYGczauuup0MFUyXNQviSpFTj1RQtFzmQLk18qbVSpTFFGMT293rmDaQuKCT6InmbuEyUne4mTuxQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/any-signal/2.1.2:
|
||||
resolution: {integrity: sha512-B+rDnWasMi/eWcajPcCWSlYc7muXOrcYrqgyzcdKisl2H/WTlQ0gip1KyQfr0ZlxJdsuWCj/LWwQm7fhyhRfIQ==}
|
||||
dependencies:
|
||||
|
|
@ -2409,6 +2440,11 @@ packages:
|
|||
resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==}
|
||||
dev: true
|
||||
|
||||
/astral-regex/2.0.0:
|
||||
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
|
||||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/async-busboy/1.1.0:
|
||||
resolution: {integrity: sha512-6PKzCbx//XQLMwi8IitM/kBcrw9RuUL7T5rvHWHwudZzcNp+dJPVnH2FmYIKO/8x//iCHunkDjxtEomfjRwjSQ==}
|
||||
dependencies:
|
||||
|
|
@ -2917,6 +2953,34 @@ packages:
|
|||
resolution: {integrity: sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==}
|
||||
dev: false
|
||||
|
||||
/clean-stack/2.2.0:
|
||||
resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/cli-cursor/3.1.0:
|
||||
resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
restore-cursor: 3.1.0
|
||||
dev: true
|
||||
|
||||
/cli-truncate/2.1.0:
|
||||
resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
slice-ansi: 3.0.0
|
||||
string-width: 4.2.3
|
||||
dev: true
|
||||
|
||||
/cli-truncate/3.1.0:
|
||||
resolution: {integrity: sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
slice-ansi: 5.0.0
|
||||
string-width: 5.1.2
|
||||
dev: true
|
||||
|
||||
/cliui/5.0.0:
|
||||
resolution: {integrity: sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==}
|
||||
dependencies:
|
||||
|
|
@ -2996,6 +3060,11 @@ packages:
|
|||
resolution: {integrity: sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==}
|
||||
dev: false
|
||||
|
||||
/commander/9.4.0:
|
||||
resolution: {integrity: sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==}
|
||||
engines: {node: ^12.20.0 || >=14}
|
||||
dev: true
|
||||
|
||||
/concat-map/0.0.1:
|
||||
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||
|
||||
|
|
@ -3361,6 +3430,10 @@ packages:
|
|||
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
|
||||
dev: true
|
||||
|
||||
/eastasianwidth/0.2.0:
|
||||
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
|
||||
dev: true
|
||||
|
||||
/eip1193-provider/1.0.1:
|
||||
resolution: {integrity: sha512-kSuqwQ26d7CzuS/t3yRXo2Su2cVH0QfvyKbr2H7Be7O5YDyIq4hQGCNTo5wRdP07bt+E2R/8nPCzey4ojBHf7g==}
|
||||
dependencies:
|
||||
|
|
@ -3403,7 +3476,6 @@ packages:
|
|||
|
||||
/emoji-regex/8.0.0:
|
||||
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
|
||||
dev: false
|
||||
|
||||
/emoji-regex/9.2.2:
|
||||
resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
|
||||
|
|
@ -4240,6 +4312,21 @@ packages:
|
|||
strip-final-newline: 2.0.0
|
||||
dev: true
|
||||
|
||||
/execa/6.1.0:
|
||||
resolution: {integrity: sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
cross-spawn: 7.0.3
|
||||
get-stream: 6.0.1
|
||||
human-signals: 3.0.1
|
||||
is-stream: 3.0.0
|
||||
merge-stream: 2.0.0
|
||||
npm-run-path: 5.1.0
|
||||
onetime: 6.0.0
|
||||
signal-exit: 3.0.7
|
||||
strip-final-newline: 3.0.0
|
||||
dev: true
|
||||
|
||||
/ext/1.6.0:
|
||||
resolution: {integrity: sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==}
|
||||
dependencies:
|
||||
|
|
@ -4759,6 +4846,17 @@ packages:
|
|||
engines: {node: '>=10.17.0'}
|
||||
dev: true
|
||||
|
||||
/human-signals/3.0.1:
|
||||
resolution: {integrity: sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==}
|
||||
engines: {node: '>=12.20.0'}
|
||||
dev: true
|
||||
|
||||
/husky/8.0.1:
|
||||
resolution: {integrity: sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==}
|
||||
engines: {node: '>=14'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/iconv-lite/0.6.3:
|
||||
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -4797,7 +4895,6 @@ packages:
|
|||
/indent-string/4.0.0:
|
||||
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/inflight/1.0.6:
|
||||
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
|
||||
|
|
@ -5105,7 +5202,11 @@ packages:
|
|||
/is-fullwidth-code-point/3.0.0:
|
||||
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
|
||||
engines: {node: '>=8'}
|
||||
dev: false
|
||||
|
||||
/is-fullwidth-code-point/4.0.0:
|
||||
resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/is-generator-function/1.0.10:
|
||||
resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==}
|
||||
|
|
@ -5209,6 +5310,11 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/is-stream/3.0.0:
|
||||
resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dev: true
|
||||
|
||||
/is-string/1.0.7:
|
||||
resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
|
@ -5515,6 +5621,48 @@ packages:
|
|||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: false
|
||||
|
||||
/lint-staged/13.0.3:
|
||||
resolution: {integrity: sha512-9hmrwSCFroTSYLjflGI8Uk+GWAwMB4OlpU4bMJEAT5d/llQwtYKoim4bLOyLCuWFAhWEupE0vkIFqtw/WIsPug==}
|
||||
engines: {node: ^14.13.1 || >=16.0.0}
|
||||
hasBin: true
|
||||
dependencies:
|
||||
cli-truncate: 3.1.0
|
||||
colorette: 2.0.19
|
||||
commander: 9.4.0
|
||||
debug: 4.3.4
|
||||
execa: 6.1.0
|
||||
lilconfig: 2.0.5
|
||||
listr2: 4.0.5
|
||||
micromatch: 4.0.5
|
||||
normalize-path: 3.0.0
|
||||
object-inspect: 1.12.2
|
||||
pidtree: 0.6.0
|
||||
string-argv: 0.3.1
|
||||
yaml: 2.1.1
|
||||
transitivePeerDependencies:
|
||||
- enquirer
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/listr2/4.0.5:
|
||||
resolution: {integrity: sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
enquirer: '>= 2.3.0 < 3'
|
||||
peerDependenciesMeta:
|
||||
enquirer:
|
||||
optional: true
|
||||
dependencies:
|
||||
cli-truncate: 2.1.0
|
||||
colorette: 2.0.19
|
||||
log-update: 4.0.0
|
||||
p-map: 4.0.0
|
||||
rfdc: 1.3.0
|
||||
rxjs: 7.5.6
|
||||
through: 2.3.8
|
||||
wrap-ansi: 7.0.0
|
||||
dev: true
|
||||
|
||||
/local-pkg/0.4.1:
|
||||
resolution: {integrity: sha512-lL87ytIGP2FU5PWwNDo0w3WhIo2gopIAxPg9RxDYF7m4rr5ahuZxP22xnJHIvaLTe4Z9P6uKKY2UHiwyB4pcrw==}
|
||||
engines: {node: '>=14'}
|
||||
|
|
@ -5574,6 +5722,16 @@ packages:
|
|||
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
|
||||
dev: false
|
||||
|
||||
/log-update/4.0.0:
|
||||
resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-escapes: 4.3.2
|
||||
cli-cursor: 3.1.0
|
||||
slice-ansi: 4.0.0
|
||||
wrap-ansi: 6.2.0
|
||||
dev: true
|
||||
|
||||
/long/4.0.0:
|
||||
resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==}
|
||||
dev: false
|
||||
|
|
@ -6106,6 +6264,11 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/mimic-fn/4.0.0:
|
||||
resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/min-indent/1.0.1:
|
||||
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -6375,6 +6538,13 @@ packages:
|
|||
path-key: 3.1.1
|
||||
dev: true
|
||||
|
||||
/npm-run-path/5.1.0:
|
||||
resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
dependencies:
|
||||
path-key: 4.0.0
|
||||
dev: true
|
||||
|
||||
/number-to-bn/1.7.0:
|
||||
resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==}
|
||||
engines: {node: '>=6.5.0', npm: '>=3'}
|
||||
|
|
@ -6467,6 +6637,13 @@ packages:
|
|||
mimic-fn: 2.1.0
|
||||
dev: true
|
||||
|
||||
/onetime/6.0.0:
|
||||
resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
mimic-fn: 4.0.0
|
||||
dev: true
|
||||
|
||||
/optionator/0.9.1:
|
||||
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
|
||||
engines: {node: '>= 0.8.0'}
|
||||
|
|
@ -6544,6 +6721,13 @@ packages:
|
|||
p-limit: 3.1.0
|
||||
dev: true
|
||||
|
||||
/p-map/4.0.0:
|
||||
resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
aggregate-error: 3.1.0
|
||||
dev: true
|
||||
|
||||
/p-retry/4.6.2:
|
||||
resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -6621,6 +6805,11 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/path-key/4.0.0:
|
||||
resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/path-parse/1.0.7:
|
||||
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
|
||||
|
||||
|
|
@ -6680,6 +6869,12 @@ packages:
|
|||
engines: {node: '>=8.6'}
|
||||
dev: true
|
||||
|
||||
/pidtree/0.6.0:
|
||||
resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==}
|
||||
engines: {node: '>=0.10'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/pify/2.3.0:
|
||||
resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
|
@ -6835,6 +7030,12 @@ packages:
|
|||
engines: {node: '>= 0.8.0'}
|
||||
dev: true
|
||||
|
||||
/prettier/2.7.1:
|
||||
resolution: {integrity: sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==}
|
||||
engines: {node: '>=10.13.0'}
|
||||
hasBin: true
|
||||
dev: true
|
||||
|
||||
/prisma/3.15.2:
|
||||
resolution: {integrity: sha512-nMNSMZvtwrvoEQ/mui8L/aiCLZRCj5t6L3yujKpcDhIPk7garp8tL4nMx2+oYsN0FWBacevJhazfXAbV1kfBzA==}
|
||||
engines: {node: '>=12.6'}
|
||||
|
|
@ -7331,6 +7532,14 @@ packages:
|
|||
supports-preserve-symlinks-flag: 1.0.0
|
||||
dev: true
|
||||
|
||||
/restore-cursor/3.1.0:
|
||||
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
onetime: 5.1.2
|
||||
signal-exit: 3.0.7
|
||||
dev: true
|
||||
|
||||
/retimer/2.0.0:
|
||||
resolution: {integrity: sha512-KLXY85WkEq2V2bKex/LOO1ViXVn2KGYe4PYysAdYdjmraYIUsVkXu8O4am+8+5UbaaGl1qho4aqAAPHNQ4GSbg==}
|
||||
dev: false
|
||||
|
|
@ -7345,6 +7554,10 @@ packages:
|
|||
engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/rfdc/1.3.0:
|
||||
resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==}
|
||||
dev: true
|
||||
|
||||
/rimraf/3.0.2:
|
||||
resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
|
||||
hasBin: true
|
||||
|
|
@ -7386,6 +7599,12 @@ packages:
|
|||
tslib: 1.14.1
|
||||
dev: false
|
||||
|
||||
/rxjs/7.5.6:
|
||||
resolution: {integrity: sha512-dnyv2/YsXhnm461G+R/Pe5bWP41Nm6LBXEYWI6eiFP4fiwx6WRI/CD0zbdVAudd9xwLEF2IDcKXLHit0FYjUzw==}
|
||||
dependencies:
|
||||
tslib: 2.4.0
|
||||
dev: true
|
||||
|
||||
/sade/1.8.1:
|
||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -7516,6 +7735,32 @@ packages:
|
|||
engines: {node: '>=8'}
|
||||
dev: true
|
||||
|
||||
/slice-ansi/3.0.0:
|
||||
resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
astral-regex: 2.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
dev: true
|
||||
|
||||
/slice-ansi/4.0.0:
|
||||
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
astral-regex: 2.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
dev: true
|
||||
|
||||
/slice-ansi/5.0.0:
|
||||
resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
ansi-styles: 6.1.0
|
||||
is-fullwidth-code-point: 4.0.0
|
||||
dev: true
|
||||
|
||||
/sortablejs/1.15.0:
|
||||
resolution: {integrity: sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==}
|
||||
dev: false
|
||||
|
|
@ -7600,6 +7845,11 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/string-argv/0.3.1:
|
||||
resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==}
|
||||
engines: {node: '>=0.6.19'}
|
||||
dev: true
|
||||
|
||||
/string-width/3.1.0:
|
||||
resolution: {integrity: sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==}
|
||||
engines: {node: '>=6'}
|
||||
|
|
@ -7616,7 +7866,15 @@ packages:
|
|||
emoji-regex: 8.0.0
|
||||
is-fullwidth-code-point: 3.0.0
|
||||
strip-ansi: 6.0.1
|
||||
dev: false
|
||||
|
||||
/string-width/5.1.2:
|
||||
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
eastasianwidth: 0.2.0
|
||||
emoji-regex: 9.2.2
|
||||
strip-ansi: 7.0.1
|
||||
dev: true
|
||||
|
||||
/string.prototype.matchall/4.0.7:
|
||||
resolution: {integrity: sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==}
|
||||
|
|
@ -7671,6 +7929,13 @@ packages:
|
|||
dependencies:
|
||||
ansi-regex: 5.0.1
|
||||
|
||||
/strip-ansi/7.0.1:
|
||||
resolution: {integrity: sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==}
|
||||
engines: {node: '>=12'}
|
||||
dependencies:
|
||||
ansi-regex: 6.0.1
|
||||
dev: true
|
||||
|
||||
/strip-bom/3.0.0:
|
||||
resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
@ -7681,6 +7946,11 @@ packages:
|
|||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/strip-final-newline/3.0.0:
|
||||
resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==}
|
||||
engines: {node: '>=12'}
|
||||
dev: true
|
||||
|
||||
/strip-hex-prefix/1.0.0:
|
||||
resolution: {integrity: sha1-DF8VX+8RUTczd96du1iNoFUA428=}
|
||||
engines: {node: '>=6.5.0', npm: '>=3'}
|
||||
|
|
@ -7781,6 +8051,10 @@ packages:
|
|||
resolution: {integrity: sha512-YGdk8sdmr4ge3g+doFj/7RLF5kLM+Mi7DEciu9PHxnMJZMeVuZeTj31g4VE7ekUffx/IdbvrtOCiz62afg0mkg==}
|
||||
dev: false
|
||||
|
||||
/through/2.3.8:
|
||||
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
|
||||
dev: true
|
||||
|
||||
/timeout-abort-controller/1.1.1:
|
||||
resolution: {integrity: sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==}
|
||||
dependencies:
|
||||
|
|
@ -7859,7 +8133,6 @@ packages:
|
|||
|
||||
/tslib/2.4.0:
|
||||
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
|
||||
dev: false
|
||||
|
||||
/tsutils/3.21.0_typescript@4.7.4:
|
||||
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
|
||||
|
|
@ -7893,6 +8166,11 @@ packages:
|
|||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/type-fest/0.21.3:
|
||||
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/type-fest/0.6.0:
|
||||
resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
|
||||
engines: {node: '>=8'}
|
||||
|
|
@ -8566,7 +8844,15 @@ packages:
|
|||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
dev: false
|
||||
|
||||
/wrap-ansi/7.0.0:
|
||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||
engines: {node: '>=10'}
|
||||
dependencies:
|
||||
ansi-styles: 4.3.0
|
||||
string-width: 4.2.3
|
||||
strip-ansi: 6.0.1
|
||||
dev: true
|
||||
|
||||
/wrappy/1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
|
@ -8631,6 +8917,11 @@ packages:
|
|||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yaml/2.1.1:
|
||||
resolution: {integrity: sha512-o96x3OPo8GjWeSLF+wOAbrPfhFOGY0W00GNaxCDv+9hkcDJEnev1yh8S7pgHF0ik6zc8sQLuL8hjHjJULZp8bw==}
|
||||
engines: {node: '>= 14'}
|
||||
dev: true
|
||||
|
||||
/yargs-parser/13.1.2:
|
||||
resolution: {integrity: sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==}
|
||||
dependencies:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { ConnectButton as RainbowConnectButton } from "@rainbow-me/rainbowkit"
|
||||
import { useGetUserSites } from "~/queries/site"
|
||||
import { useAccount, useDisconnect } from "wagmi"
|
||||
import { Avatar } from "~/components/ui/Avatar";
|
||||
import { Avatar } from "~/components/ui/Avatar"
|
||||
import type { HeaderLinkType } from "~/components/site/SiteHeader"
|
||||
import { DashboardIcon } from "../icons/DashboardIcon"
|
||||
import { LogoutIcon } from "../icons/LogoutIcon"
|
||||
|
|
@ -13,7 +13,7 @@ import { useEffect, useState } from "react"
|
|||
|
||||
export const ConnectButton: React.FC<{
|
||||
left?: boolean
|
||||
}> = ({ left, }) => {
|
||||
}> = ({ left }) => {
|
||||
const { address } = useAccount()
|
||||
const userSites = useGetUserSites(address)
|
||||
const { disconnect } = useDisconnect()
|
||||
|
|
@ -61,67 +61,88 @@ export const ConnectButton: React.FC<{
|
|||
openConnectModal,
|
||||
mounted,
|
||||
}) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
{...(!mounted && {
|
||||
'aria-hidden': true,
|
||||
'style': {
|
||||
"aria-hidden": true,
|
||||
style: {
|
||||
opacity: 0,
|
||||
pointerEvents: 'none',
|
||||
userSelect: 'none',
|
||||
pointerEvents: "none",
|
||||
userSelect: "none",
|
||||
},
|
||||
})}
|
||||
>
|
||||
{(() => {
|
||||
if (!mounted || !account || !chain) {
|
||||
return (
|
||||
<button className="text-indigo-600" onClick={openConnectModal} type="button" style={{ height: "30px" }}>
|
||||
<button
|
||||
className="text-indigo-600"
|
||||
onClick={openConnectModal}
|
||||
type="button"
|
||||
style={{ height: "30px" }}
|
||||
>
|
||||
Connect Wallet
|
||||
</button>
|
||||
);
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="flex relative group" style={{ gap: 12, height: "30px" }}>
|
||||
{userSites.isSuccess ?
|
||||
<>
|
||||
<button className="flex items-center" type="button">
|
||||
<Avatar
|
||||
className="align-middle mr-2"
|
||||
images={userSites.data?.[0]?.avatars || []}
|
||||
name={userSites.data?.[0]?.name}
|
||||
size={30}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-left leading-none text-gray-600 font-bold" style={{ "marginBottom": "0.15rem" }}>{userSites.data?.[0]?.name || account.displayName}</span>
|
||||
<span className="text-left leading-none text-xs text-gray-400">{"@" + userSites.data?.[0]?.username || account.displayName}</span>
|
||||
<div
|
||||
className="flex relative group"
|
||||
style={{ gap: 12, height: "30px" }}
|
||||
>
|
||||
{userSites.isSuccess ? (
|
||||
<>
|
||||
<button className="flex items-center" type="button">
|
||||
<Avatar
|
||||
className="align-middle mr-2"
|
||||
images={userSites.data?.[0]?.avatars || []}
|
||||
name={userSites.data?.[0]?.name}
|
||||
size={30}
|
||||
/>
|
||||
<div className="flex flex-col">
|
||||
<span
|
||||
className="text-left leading-none text-gray-600 font-bold"
|
||||
style={{ marginBottom: "0.15rem" }}
|
||||
>
|
||||
{userSites.data?.[0]?.name || account.displayName}
|
||||
</span>
|
||||
<span className="text-left leading-none text-xs text-gray-400">
|
||||
{"@" + userSites.data?.[0]?.username ||
|
||||
account.displayName}
|
||||
</span>
|
||||
</div>
|
||||
</button>
|
||||
<div
|
||||
className={`absolute hidden ${
|
||||
left ? "left" : "right"
|
||||
}-0 pt-2 group-hover:block top-full z-10 text-gray-600`}
|
||||
>
|
||||
<div className="bg-white rounded-lg ring-1 ring-zinc-100 min-w-[140px] shadow-md py-2 text-sm">
|
||||
{dropdownLinks.map((link, i) => {
|
||||
return (
|
||||
<UniLink
|
||||
key={i}
|
||||
href={link.url}
|
||||
onClick={link.onClick}
|
||||
className="px-4 h-8 flex items-center w-full whitespace-nowrap hover:bg-zinc-100"
|
||||
>
|
||||
<span className="mr-2">{link.icon}</span>
|
||||
{link.label}
|
||||
</UniLink>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
<div className={`absolute hidden ${left ? "left" : "right"}-0 pt-2 group-hover:block top-full z-10 text-gray-600`}>
|
||||
<div className="bg-white rounded-lg ring-1 ring-zinc-100 min-w-[140px] shadow-md py-2 text-sm">
|
||||
{dropdownLinks.map((link, i) => {
|
||||
return (
|
||||
<UniLink
|
||||
key={i}
|
||||
href={link.url}
|
||||
onClick={link.onClick}
|
||||
className="px-4 h-8 flex items-center w-full whitespace-nowrap hover:bg-zinc-100"
|
||||
>
|
||||
<span className="mr-2">{link.icon}</span>
|
||||
{link.label}
|
||||
</UniLink>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
: ""}
|
||||
</>
|
||||
) : (
|
||||
""
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
})()}
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}}
|
||||
</RainbowConnectButton.Custom>
|
||||
);
|
||||
};
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const AvatarEditorModal: React.FC<{
|
|||
const updateSite = useUpdateSite()
|
||||
|
||||
const useCropAndSave = async () => {
|
||||
let key;
|
||||
let key
|
||||
// Get cropped image
|
||||
if (editorRef.current) {
|
||||
const fromCanvas = editorRef.current?.getImage()
|
||||
|
|
@ -74,7 +74,11 @@ const AvatarEditorModal: React.FC<{
|
|||
</div>
|
||||
|
||||
<div className="h-16 border-t flex items-center px-5">
|
||||
<Button isBlock onClick={useCropAndSave} isLoading={updateSite.isLoading}>
|
||||
<Button
|
||||
isBlock
|
||||
onClick={useCropAndSave}
|
||||
isLoading={updateSite.isLoading}
|
||||
>
|
||||
Crop and Save
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { UniLink } from "../ui/UniLink"
|
|||
import { DashboardSidebar } from "./DashboardSidebar"
|
||||
import { SiteSwitcher } from "./SiteSwitcher"
|
||||
import { useGetUserSites } from "~/queries/site"
|
||||
import { useAccount } from 'wagmi'
|
||||
import { useAccount } from "wagmi"
|
||||
import { ConnectButton } from "~/components/common/ConnectButton"
|
||||
|
||||
export function DashboardLayout({
|
||||
|
|
@ -25,7 +25,7 @@ export function DashboardLayout({
|
|||
|
||||
const { address } = useAccount()
|
||||
|
||||
const userSite = useGetUserSites(address);
|
||||
const userSite = useGetUserSites(address)
|
||||
|
||||
useEffect(() => {
|
||||
if (!address) {
|
||||
|
|
|
|||
|
|
@ -8,7 +8,9 @@ export const DashboardMain: React.FC<{
|
|||
<div className="md:pl-sidebar w-full">
|
||||
<div
|
||||
className={clsx(
|
||||
fullWidth ? "relative" : "max-w-screen-xl relative px-5 py-5 md:px-10"
|
||||
fullWidth
|
||||
? "relative"
|
||||
: "max-w-screen-xl relative px-5 py-5 md:px-10",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export const PagesManager: React.FC<{
|
|||
router.query.visibility
|
||||
? (router.query.visibility as PageVisibilityEnum)
|
||||
: PageVisibilityEnum.All,
|
||||
[router.query.visibility]
|
||||
[router.query.visibility],
|
||||
)
|
||||
|
||||
const deletePage = useDeletePage()
|
||||
|
|
@ -128,7 +128,7 @@ export const PagesManager: React.FC<{
|
|||
onClick() {
|
||||
deletePage.mutate({
|
||||
site: subdomain,
|
||||
id: page.id
|
||||
id: page.id,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
|
@ -146,11 +146,11 @@ export const PagesManager: React.FC<{
|
|||
className={clsx(
|
||||
`space-x-2 px-3 h-9 inline-flex items-center justify-center text-white rounded-lg text-sm`,
|
||||
|
||||
isPost ? `bg-pink-500` : `bg-blue-500`
|
||||
isPost ? `bg-pink-500` : `bg-blue-500`,
|
||||
)}
|
||||
onClick={() =>
|
||||
router.push(
|
||||
`/dashboard/${subdomain}/editor?type=${isPost ? "post" : "page"}`
|
||||
`/dashboard/${subdomain}/editor?type=${isPost ? "post" : "page"}`,
|
||||
)
|
||||
}
|
||||
>
|
||||
|
|
@ -182,14 +182,18 @@ export const PagesManager: React.FC<{
|
|||
<a className="group relative hover:bg-zinc-100 rounded-lg py-3 px-3 transition-colors -mx-3 flex justify-between">
|
||||
<div>
|
||||
<div className="flex items-center">
|
||||
<span>{page.title || 'Untitled'}</span>
|
||||
<span>{page.title || "Untitled"}</span>
|
||||
</div>
|
||||
<div className="text-zinc-400 text-xs mt-1">
|
||||
<span className="capitalize">
|
||||
{getPageVisibility(page).toLowerCase()}
|
||||
</span>
|
||||
<span className="mx-2">·</span>
|
||||
<span>{getPageVisibility(page) === PageVisibilityEnum.Draft ? formatDate(page.date_updated) : formatDate(page.date_published)}</span>
|
||||
<span>
|
||||
{getPageVisibility(page) === PageVisibilityEnum.Draft
|
||||
? formatDate(page.date_updated)
|
||||
: formatDate(page.date_published)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="w-10 flex-shrink-0">
|
||||
|
|
@ -200,7 +204,7 @@ export const PagesManager: React.FC<{
|
|||
<button
|
||||
className={clsx(
|
||||
`text-gray-400 relative z-50 w-8 h-8 rounded inline-flex invisible group-hover:visible justify-center items-center`,
|
||||
open ? `bg-gray-200` : `hover:bg-gray-200`
|
||||
open ? `bg-gray-200` : `hover:bg-gray-200`,
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ export const SiteSwitcher: React.FC<Props> = ({
|
|||
subscriptions,
|
||||
viewer,
|
||||
}) => {
|
||||
const activeSubscription = subscriptions.find(
|
||||
(s) => s.username === subdomain
|
||||
)
|
||||
const activeSubscription = subscriptions.find((s) => s.username === subdomain)
|
||||
|
||||
return (
|
||||
<div className="px-3 pt-3 pb-2 text-sm">
|
||||
|
|
@ -63,7 +61,8 @@ export const SiteSwitcher: React.FC<Props> = ({
|
|||
<span className="truncate w-8/12">
|
||||
{subscription.name}
|
||||
</span>
|
||||
{activeSubscription?.username === subscription.username && (
|
||||
{activeSubscription?.username ===
|
||||
subscription.username && (
|
||||
<span className="text-accent">
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,25 @@
|
|||
import React from "react"
|
||||
|
||||
export const BlockchainIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" {...props} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M128 320v286.208a106.666667 106.666667 0 1 0 106.965333 182.912l256.128 144.085333a42.666667 42.666667 0 0 0 41.813334 0l256.128-144.085333A106.666667 106.666667 0 1 0 896 606.208V320a42.666667 42.666667 0 0 0-21.76-37.205333l-256.085333-144.042667a106.666667 106.666667 0 0 0-212.309334 0L149.76 282.794667A42.666667 42.666667 0 0 0 128 320z m362.666667-170.666667a21.333333 21.333333 0 1 1 42.666666 0 21.333333 21.333333 0 0 1-42.666666 0zM469.333333 247.125333v91.050667l-106.837333 62.293333A42.666667 42.666667 0 0 0 341.333333 437.333333v113.92l-111.744 63.829334c-5.12-3.413333-10.538667-6.4-16.256-8.874667V344.96l219.904-123.733333c10.026667 11.008 22.314667 19.882667 36.096 25.898666z m341.333334 359.082667a106.325333 106.325333 0 0 0-16.256 8.874667L682.666667 551.253333v-113.92a42.666667 42.666667 0 0 0-21.162667-36.864L554.666667 338.176V247.125333c13.781333-6.016 26.069333-14.933333 36.096-25.856L810.666667 344.96v261.248z m-62.634667 80.64a107.946667 107.946667 0 0 0-0.853333 27.904L512 847.018667l-235.221333-132.266667a107.946667 107.946667 0 0 0-0.853334-27.861333l98.602667-56.32 115.968 67.626666a42.666667 42.666667 0 0 0 43.008 0l115.968-67.669333 98.56 56.32zM597.333333 461.866667v100.352l-85.333333 49.749333-85.333333-49.749333v-100.352l85.333333-49.749334 85.333333 49.749334zM170.666667 682.666667a21.333333 21.333333 0 1 0 0 42.666666 21.333333 21.333333 0 0 0 0-42.666666z m661.333333 21.333333a21.333333 21.333333 0 1 1 42.666667 0 21.333333 21.333333 0 0 1-42.666667 0z" p-id="1166"></path><path d="M512 128a21.333333 21.333333 0 1 0 0 42.666667 21.333333 21.333333 0 0 0 0-42.666667zM597.333333 562.176v-100.352l-85.333333-49.749333-85.333333 49.749333v100.352l85.333333 49.749333 85.333333-49.749333zM149.333333 704a21.333333 21.333333 0 1 1 42.666667 0 21.333333 21.333333 0 0 1-42.666667 0zM853.333333 682.666667a21.333333 21.333333 0 1 0 0 42.666666 21.333333 21.333333 0 0 0 0-42.666666z" p-id="1167"></path></svg>
|
||||
<svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M128 320v286.208a106.666667 106.666667 0 1 0 106.965333 182.912l256.128 144.085333a42.666667 42.666667 0 0 0 41.813334 0l256.128-144.085333A106.666667 106.666667 0 1 0 896 606.208V320a42.666667 42.666667 0 0 0-21.76-37.205333l-256.085333-144.042667a106.666667 106.666667 0 0 0-212.309334 0L149.76 282.794667A42.666667 42.666667 0 0 0 128 320z m362.666667-170.666667a21.333333 21.333333 0 1 1 42.666666 0 21.333333 21.333333 0 0 1-42.666666 0zM469.333333 247.125333v91.050667l-106.837333 62.293333A42.666667 42.666667 0 0 0 341.333333 437.333333v113.92l-111.744 63.829334c-5.12-3.413333-10.538667-6.4-16.256-8.874667V344.96l219.904-123.733333c10.026667 11.008 22.314667 19.882667 36.096 25.898666z m341.333334 359.082667a106.325333 106.325333 0 0 0-16.256 8.874667L682.666667 551.253333v-113.92a42.666667 42.666667 0 0 0-21.162667-36.864L554.666667 338.176V247.125333c13.781333-6.016 26.069333-14.933333 36.096-25.856L810.666667 344.96v261.248z m-62.634667 80.64a107.946667 107.946667 0 0 0-0.853333 27.904L512 847.018667l-235.221333-132.266667a107.946667 107.946667 0 0 0-0.853334-27.861333l98.602667-56.32 115.968 67.626666a42.666667 42.666667 0 0 0 43.008 0l115.968-67.669333 98.56 56.32zM597.333333 461.866667v100.352l-85.333333 49.749333-85.333333-49.749333v-100.352l85.333333-49.749334 85.333333 49.749334zM170.666667 682.666667a21.333333 21.333333 0 1 0 0 42.666666 21.333333 21.333333 0 0 0 0-42.666666z m661.333333 21.333333a21.333333 21.333333 0 1 1 42.666667 0 21.333333 21.333333 0 0 1-42.666667 0z"
|
||||
p-id="1166"
|
||||
></path>
|
||||
<path
|
||||
d="M512 128a21.333333 21.333333 0 1 0 0 42.666667 21.333333 21.333333 0 0 0 0-42.666667zM597.333333 562.176v-100.352l-85.333333-49.749333-85.333333 49.749333v100.352l85.333333 49.749333 85.333333-49.749333zM149.333333 704a21.333333 21.333333 0 1 1 42.666667 0 21.333333 21.333333 0 0 1-42.666667 0zM853.333333 682.666667a21.333333 21.333333 0 1 0 0 42.666666 21.333333 21.333333 0 0 0 0-42.666666z"
|
||||
p-id="1167"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,22 @@
|
|||
import React from "react"
|
||||
|
||||
export const CopyIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" {...props} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5253"><path d="M832 128c-12.8-76.8-76.8-128-160-128h-448C102.4 0 0 102.4 0 224v448c0 76.8 57.6 140.8 128 160 12.8 76.8 76.8 128 160 128h512c89.6 0 160-70.4 160-160v-512c0-76.8-57.6-140.8-128-160zM64 672v-448C64 134.4 134.4 64 224 64h448c44.8 0 76.8 25.6 89.6 64H288C198.4 128 128 198.4 128 288v473.6c-38.4-12.8-64-44.8-64-89.6z m832 128c0 51.2-44.8 96-96 96h-512c-51.2 0-96-44.8-96-96v-512C192 236.8 236.8 192 288 192h512c51.2 0 96 44.8 96 96v512z" p-id="5254"></path></svg>
|
||||
<svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="5253"
|
||||
>
|
||||
<path
|
||||
d="M832 128c-12.8-76.8-76.8-128-160-128h-448C102.4 0 0 102.4 0 224v448c0 76.8 57.6 140.8 128 160 12.8 76.8 76.8 128 160 128h512c89.6 0 160-70.4 160-160v-512c0-76.8-57.6-140.8-128-160zM64 672v-448C64 134.4 134.4 64 224 64h448c44.8 0 76.8 25.6 89.6 64H288C198.4 128 128 198.4 128 288v473.6c-38.4-12.8-64-44.8-64-89.6z m832 128c0 51.2-44.8 96-96 96h-512c-51.2 0-96-44.8-96-96v-512C192 236.8 236.8 192 288 192h512c51.2 0 96 44.8 96 96v512z"
|
||||
p-id="5254"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
import React from "react"
|
||||
|
||||
export const CrossbellIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" {...props} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"><path d="M512 1024c70.64 0 127.94-57.3 127.94-128H384.06c0 70.7 57.3 128 127.94 128z m430.78-299.42c-38.64-41.52-110.94-103.98-110.94-308.58 0-155.4-108.96-279.8-255.88-310.32V64c0-35.34-28.64-64-63.96-64s-63.96 28.66-63.96 64v41.68C301.12 136.2 192.16 260.6 192.16 416c0 204.6-72.3 267.06-110.94 308.58-12 12.9-17.32 28.32-17.22 43.42 0.22 32.8 25.96 64 64.2 64h767.6c38.24 0 64-31.2 64.2-64 0.1-15.1-5.22-30.54-17.22-43.42z"></path></svg>
|
||||
<svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M512 1024c70.64 0 127.94-57.3 127.94-128H384.06c0 70.7 57.3 128 127.94 128z m430.78-299.42c-38.64-41.52-110.94-103.98-110.94-308.58 0-155.4-108.96-279.8-255.88-310.32V64c0-35.34-28.64-64-63.96-64s-63.96 28.66-63.96 64v41.68C301.12 136.2 192.16 260.6 192.16 416c0 204.6-72.3 267.06-110.94 308.58-12 12.9-17.32 28.32-17.22 43.42 0.22 32.8 25.96 64 64.2 64h767.6c38.24 0 64-31.2 64.2-64 0.1-15.1-5.22-30.54-17.22-43.42z"></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react"
|
||||
|
||||
export const DashboardIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" viewBox="0 0 24 24" {...props}>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,23 @@
|
|||
import React from "react"
|
||||
|
||||
export const LogoutIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" {...props} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2564"><path d="M896 512c0-14.16-6.128-26.896-15.888-35.68l-160-144a48 48 0 0 0-64.224 71.36L722.912 464H432a48 48 0 1 0 0 96h290.912l-67.008 60.32a48 48 0 1 0 64.208 71.36l160-144A47.84 47.84 0 0 0 896 512zM416 832H224V192h192a48 48 0 1 0 0-96H176a48 48 0 0 0-48 48v736a48 48 0 0 0 48 48h240a48 48 0 1 0 0-96z" fill="" p-id="2565"></path></svg>
|
||||
<svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2564"
|
||||
>
|
||||
<path
|
||||
d="M896 512c0-14.16-6.128-26.896-15.888-35.68l-160-144a48 48 0 0 0-64.224 71.36L722.912 464H432a48 48 0 1 0 0 96h290.912l-67.008 60.32a48 48 0 1 0 64.208 71.36l160-144A47.84 47.84 0 0 0 896 512zM416 832H224V192h192a48 48 0 1 0 0-96H176a48 48 0 0 0-48 48v736a48 48 0 0 0 48 48h240a48 48 0 1 0 0-96z"
|
||||
fill=""
|
||||
p-id="2565"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from "react"
|
||||
|
||||
export const MoreIcon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg
|
||||
|
|
|
|||
|
|
@ -1,9 +1,26 @@
|
|||
import React from "react"
|
||||
|
||||
export const RSS3Icon: React.FC<React.ComponentPropsWithoutRef<"svg">> = (
|
||||
props
|
||||
props,
|
||||
) => {
|
||||
return (
|
||||
<svg width="1em" height="1em" {...props} viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6994"><path d="M139.093333 974.336a96.426667 96.426667 0 1 0 0-192.853333 96.426667 96.426667 0 0 0 0 192.853333zM926.122667 971.264c-26.453333 0-46.634667-20.224-46.634667-46.677333 0-433.962667-353.066667-788.608-788.608-788.608-26.453333 0-46.634667-20.224-46.634667-46.634667C44.202667 62.890667 64.426667 42.666667 90.88 42.666667 577.706667 42.666667 972.8 439.296 972.8 924.586667c0 26.453333-20.224 46.634667-46.677333 46.634666z" p-id="6995"></path><path d="M601.045333 972.8c-26.453333 0-46.634667-20.224-46.634666-46.677333 0-255.061333-208.426667-463.488-463.530667-463.488-26.453333 0-46.634667-20.224-46.634667-46.677334 0-26.453333 20.181333-46.634667 46.634667-46.634666 307.968 0 556.842667 250.410667 556.842667 556.8 0 24.917333-21.76 46.677333-46.677334 46.677333z" p-id="6996"></path></svg>
|
||||
<svg
|
||||
width="1em"
|
||||
height="1em"
|
||||
{...props}
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="6994"
|
||||
>
|
||||
<path
|
||||
d="M139.093333 974.336a96.426667 96.426667 0 1 0 0-192.853333 96.426667 96.426667 0 0 0 0 192.853333zM926.122667 971.264c-26.453333 0-46.634667-20.224-46.634667-46.677333 0-433.962667-353.066667-788.608-788.608-788.608-26.453333 0-46.634667-20.224-46.634667-46.634667C44.202667 62.890667 64.426667 42.666667 90.88 42.666667 577.706667 42.666667 972.8 439.296 972.8 924.586667c0 26.453333-20.224 46.634667-46.677333 46.634666z"
|
||||
p-id="6995"
|
||||
></path>
|
||||
<path
|
||||
d="M601.045333 972.8c-26.453333 0-46.634667-20.224-46.634666-46.677333 0-255.061333-208.426667-463.488-463.530667-463.488-26.453333 0-46.634667-20.224-46.634667-46.677334 0-26.453333 20.181333-46.634667 46.634667-46.634666 307.968 0 556.842667 250.410667 556.842667 556.8 0 24.917333-21.76 46.677333-46.677334 46.677333z"
|
||||
p-id="6996"
|
||||
></path>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,15 @@ export function MainLayout({
|
|||
<footer className="mt-10 text-sm font-medium text-zinc-500">
|
||||
<div className="max-w-screen-md px-5 mx-auto flex justify-between">
|
||||
<div>
|
||||
<span className="align-middle">© <UniLink href={`https://blog.${OUR_DOMAIN}`} className="hover:text-indigo-500">{APP_NAME}</UniLink></span>
|
||||
<span className="align-middle">
|
||||
©{" "}
|
||||
<UniLink
|
||||
href={`https://blog.${OUR_DOMAIN}`}
|
||||
className="hover:text-indigo-500"
|
||||
>
|
||||
{APP_NAME}
|
||||
</UniLink>
|
||||
</span>
|
||||
<span className="text-zinc-400 ml-2 inline-flex items-center space-x-1 align-middle">
|
||||
<UniLink href={DISCORD_LINK}>
|
||||
<span className="inline-block i-mdi-discord text-xl hover:text-indigo-500"></span>
|
||||
|
|
|
|||
|
|
@ -12,34 +12,93 @@ export const SiteFooter: React.FC<{
|
|||
return (
|
||||
<footer className="text-zinc-500 border-t">
|
||||
<div className="max-w-screen-md mx-auto px-5 py-10 text-xs">
|
||||
<p className="mb-4">🔔 This {page ? (page.tags?.includes("post") ? "post" : "page") : "blog"} has been permanently stored on the blockchain and signed by its creator.</p>
|
||||
<p className="mb-4">
|
||||
🔔 This{" "}
|
||||
{page ? (page.tags?.includes("post") ? "post" : "page") : "blog"} has
|
||||
been permanently stored on the blockchain and signed by its creator.
|
||||
</p>
|
||||
<ul className="mb-6">
|
||||
<li className="mt-2">
|
||||
<div className="font-bold">Blockchain Transaction</div>
|
||||
<div>
|
||||
{page ?
|
||||
page?.related_urls?.filter((url) => url.startsWith("https://scan.crossbell.io/tx/")).map((url) => {
|
||||
return <a target="_blank" rel="noreferrer" className="inline-block mr-4 break-all" href={url} key={url}>{url.replace("https://scan.crossbell.io/tx/", "").slice(0, 10)}...{url.replace("https://scan.crossbell.io/tx/", "").slice(-10)}</a>
|
||||
}) :
|
||||
site?.metadata?.transactions.map((hash: string) => {
|
||||
return <a target="_blank" rel="noreferrer" className="inline-block mr-4 break-all" href={`https://scan.crossbell.io/tx/${hash}`} key={hash}>{hash.slice(0, 10)}...{hash.slice(-10)}</a>
|
||||
})
|
||||
}
|
||||
{page
|
||||
? page?.related_urls
|
||||
?.filter((url) =>
|
||||
url.startsWith("https://scan.crossbell.io/tx/"),
|
||||
)
|
||||
.map((url) => {
|
||||
return (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-block mr-4 break-all"
|
||||
href={url}
|
||||
key={url}
|
||||
>
|
||||
{url
|
||||
.replace("https://scan.crossbell.io/tx/", "")
|
||||
.slice(0, 10)}
|
||||
...
|
||||
{url
|
||||
.replace("https://scan.crossbell.io/tx/", "")
|
||||
.slice(-10)}
|
||||
</a>
|
||||
)
|
||||
})
|
||||
: site?.metadata?.transactions.map((hash: string) => {
|
||||
return (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-block mr-4 break-all"
|
||||
href={`https://scan.crossbell.io/tx/${hash}`}
|
||||
key={hash}
|
||||
>
|
||||
{hash.slice(0, 10)}...{hash.slice(-10)}
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</li>
|
||||
{
|
||||
page &&
|
||||
{page && (
|
||||
<li className="mt-2">
|
||||
<div className="font-bold">IPFS Address</div>
|
||||
<div>{page?.related_urls?.filter((url) => url.startsWith("https://gateway.ipfs.io/ipfs/")).map((url) => {
|
||||
return <a target="_blank" rel="noreferrer" className="inline-block mr-4 break-all" href={url} key={url}>{url.replace("https://gateway.ipfs.io/ipfs/", "ipfs://")}</a>
|
||||
})}</div>
|
||||
<div>
|
||||
{page?.related_urls
|
||||
?.filter((url) =>
|
||||
url.startsWith("https://gateway.ipfs.io/ipfs/"),
|
||||
)
|
||||
.map((url) => {
|
||||
return (
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-block mr-4 break-all"
|
||||
href={url}
|
||||
key={url}
|
||||
>
|
||||
{url.replace(
|
||||
"https://gateway.ipfs.io/ipfs/",
|
||||
"ipfs://",
|
||||
)}
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
)}
|
||||
<li className="mt-2">
|
||||
<div className="font-bold">Author Address</div>
|
||||
<div>
|
||||
<a target="_blank" rel="noreferrer" className="inline-block mr-4 break-all" href={`https://scan.crossbell.io/address/${site?.metadata?.owner}`} key={site?.metadata?.owner}>{site?.metadata?.owner}</a>
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className="inline-block mr-4 break-all"
|
||||
href={`https://scan.crossbell.io/address/${site?.metadata?.owner}`}
|
||||
key={site?.metadata?.owner}
|
||||
>
|
||||
{site?.metadata?.owner}
|
||||
</a>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
|||
|
|
@ -17,8 +17,12 @@ import { useAccount } from "wagmi"
|
|||
import unidata from "~/lib/unidata"
|
||||
import { Fragment, useEffect, useState } from "react"
|
||||
import toast from "react-hot-toast"
|
||||
import { useGetSubscription, useSubscribeToSite, useUnsubscribeFromSite } from "~/queries/site"
|
||||
import { useConnectModal } from '@rainbow-me/rainbowkit';
|
||||
import {
|
||||
useGetSubscription,
|
||||
useSubscribeToSite,
|
||||
useUnsubscribeFromSite,
|
||||
} from "~/queries/site"
|
||||
import { useConnectModal } from "@rainbow-me/rainbowkit"
|
||||
import { Menu } from "@headlessui/react"
|
||||
import { MoreIcon } from "~/components/icons/MoreIcon"
|
||||
import { RSS3Icon } from "~/components/icons/RSS3Icon"
|
||||
|
|
@ -79,19 +83,32 @@ export const SiteHeader: React.FC<{
|
|||
}
|
||||
|
||||
const subscription = useGetSubscription({
|
||||
userId: address || '',
|
||||
siteId: site?.username || '',
|
||||
userId: address || "",
|
||||
siteId: site?.username || "",
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (followProgress && address && subscription.isSuccess && !subscription.data && site?.username) {
|
||||
if (
|
||||
followProgress &&
|
||||
address &&
|
||||
subscription.isSuccess &&
|
||||
!subscription.data &&
|
||||
site?.username
|
||||
) {
|
||||
subscribeToSite.mutate({
|
||||
userId: address,
|
||||
siteId: site.username,
|
||||
})
|
||||
setFollowProgress(false)
|
||||
}
|
||||
}, [followProgress, address, subscription.isSuccess, subscription.data, site?.username, subscribeToSite])
|
||||
}, [
|
||||
followProgress,
|
||||
address,
|
||||
subscription.isSuccess,
|
||||
subscription.data,
|
||||
site?.username,
|
||||
subscribeToSite,
|
||||
])
|
||||
|
||||
const leftLinks: HeaderLinkType[] = [
|
||||
{ label: "Home", url: "/" },
|
||||
|
|
@ -134,14 +151,16 @@ export const SiteHeader: React.FC<{
|
|||
<div className="text-gray-500 text-sm">{site?.bio}</div>
|
||||
)}
|
||||
<div className="mt-3 text-sm">
|
||||
{subscription.data ?
|
||||
{subscription.data ? (
|
||||
<Button
|
||||
rounded="full"
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
onClick={handleClickSubscribe}
|
||||
className="space-x-1 group align-middle"
|
||||
isLoading={unsubscribeFromSite.isLoading || subscribeToSite.isLoading}
|
||||
isLoading={
|
||||
unsubscribeFromSite.isLoading || subscribeToSite.isLoading
|
||||
}
|
||||
>
|
||||
<span className="pl-1">
|
||||
<CrossbellIcon />
|
||||
|
|
@ -152,23 +171,26 @@ export const SiteHeader: React.FC<{
|
|||
<span className="pr-1 hidden group-hover:block w-16">
|
||||
Unfollow
|
||||
</span>
|
||||
</Button> :
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
rounded="full"
|
||||
size="sm"
|
||||
variant="crossbell"
|
||||
onClick={handleClickSubscribe}
|
||||
className="space-x-1 align-middle"
|
||||
isLoading={unsubscribeFromSite.isLoading || subscribeToSite.isLoading || subscription.isLoading}
|
||||
isLoading={
|
||||
unsubscribeFromSite.isLoading ||
|
||||
subscribeToSite.isLoading ||
|
||||
subscription.isLoading
|
||||
}
|
||||
>
|
||||
<span className="pl-1">
|
||||
<CrossbellIcon />
|
||||
</span>
|
||||
<span className="pr-1">
|
||||
Follow
|
||||
</span>
|
||||
<span className="pr-1">Follow</span>
|
||||
</Button>
|
||||
}
|
||||
)}
|
||||
<div className="relative inline-block align-middle h-7">
|
||||
<Menu>
|
||||
{() => (
|
||||
|
|
@ -194,7 +216,9 @@ export const SiteHeader: React.FC<{
|
|||
href={item.url}
|
||||
className="h-10 flex w-full space-x-2 items-center px-3 hover:bg-gray-100"
|
||||
>
|
||||
<span className="fill-gray-500">{item.icon}</span>
|
||||
<span className="fill-gray-500">
|
||||
{item.icon}
|
||||
</span>
|
||||
<span>{item.text}</span>
|
||||
</UniLink>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,10 +44,8 @@ export const SiteLayout: React.FC<SiteLayoutProps> = ({
|
|||
description={ogDescription ?? site?.bio}
|
||||
image={getUserContentsUrl(site?.avatars?.[0])}
|
||||
/>
|
||||
<SiteHeader
|
||||
site={site}
|
||||
/>
|
||||
<style>{ site?.css }</style>
|
||||
<SiteHeader site={site} />
|
||||
<style>{site?.css}</style>
|
||||
<div className={clsx(`max-w-screen-md mx-auto px-5 pb-12`, `pt-12`)}>
|
||||
{children}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { PostMeta } from "./PostMeta"
|
|||
import { Profile, Note } from "~/lib/types"
|
||||
|
||||
export const SitePage: React.FC<{
|
||||
site?: Profile,
|
||||
site?: Profile
|
||||
page?: Note
|
||||
}> = ({ site, page }) => {
|
||||
return (
|
||||
|
|
@ -19,18 +19,19 @@ export const SitePage: React.FC<{
|
|||
{page?.tags?.includes("post") && (
|
||||
<PostMeta
|
||||
publishedAt={page.date_published}
|
||||
authors={[{
|
||||
id: site?.username || "",
|
||||
name: site?.name || "",
|
||||
avatar: site?.avatars?.[0] || null,
|
||||
}] || []}
|
||||
authors={
|
||||
[
|
||||
{
|
||||
id: site?.username || "",
|
||||
name: site?.name || "",
|
||||
avatar: site?.avatars?.[0] || null,
|
||||
},
|
||||
] || []
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<PageContent
|
||||
contentHTML={page?.body?.content || ""}
|
||||
className="my-10"
|
||||
/>
|
||||
<PageContent contentHTML={page?.body?.content || ""} className="my-10" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const Avatar: React.FC<
|
|||
className={clsx(
|
||||
`inline-flex text-white bg-gray-400 items-center justify-center text-xl font-medium uppercase flex-shrink-0`,
|
||||
borderRadius,
|
||||
className
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
width: `${size}px`,
|
||||
|
|
@ -53,7 +53,7 @@ export const Avatar: React.FC<
|
|||
className={clsx(
|
||||
`inline-flex text-zinc-500 bg-gray-400 flex-shrink-0 items-center justify-center text-xl font-medium uppercase`,
|
||||
borderRadius,
|
||||
className
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
width: `${size}px`,
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export const Button = React.forwardRef<
|
|||
isAutoWidth,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
ref,
|
||||
) {
|
||||
return (
|
||||
<button
|
||||
|
|
@ -54,7 +54,7 @@ export const Button = React.forwardRef<
|
|||
isAutoWidth && `is-auto-width`,
|
||||
size && `is-${size}`,
|
||||
`is-${variant || "primary"}`,
|
||||
rounded === "full" ? "rounded-full" : "rounded-lg"
|
||||
rounded === "full" ? "rounded-full" : "rounded-lg",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,27 @@
|
|||
import { useCallback } from "react"
|
||||
import { Web3Storage } from 'web3.storage'
|
||||
import { Web3Storage } from "web3.storage"
|
||||
|
||||
export const useUploadFile = () => {
|
||||
const uploadFile = useCallback<UploadFile>(
|
||||
async (blob, filename) => {
|
||||
const file = new File([blob], filename)
|
||||
const web3Storage = new Web3Storage({
|
||||
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDAyMDIwODZmRjU5OUU0Y0YyMzM4MkUzNjg1Y0NmZUEyOGNBODBCOTAiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2NTIzNjM1Njk3NDUsIm5hbWUiOiJVbmlkYXRhIn0.XmsAuXvbTj4BFhZlJK4xXfbd0ltVZJCEhqdYcW_kLOo',
|
||||
} as any)
|
||||
const cid = await web3Storage.put([file], {
|
||||
name: file.name,
|
||||
maxRetries: 3,
|
||||
wrapWithDirectory: false,
|
||||
})
|
||||
return {
|
||||
key: `https://gateway.ipfs.io/ipfs/${cid}`
|
||||
}
|
||||
},
|
||||
[]
|
||||
)
|
||||
const uploadFile = useCallback<UploadFile>(async (blob, filename) => {
|
||||
const file = new File([blob], filename)
|
||||
const web3Storage = new Web3Storage({
|
||||
token:
|
||||
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJkaWQ6ZXRocjoweDAyMDIwODZmRjU5OUU0Y0YyMzM4MkUzNjg1Y0NmZUEyOGNBODBCOTAiLCJpc3MiOiJ3ZWIzLXN0b3JhZ2UiLCJpYXQiOjE2NTIzNjM1Njk3NDUsIm5hbWUiOiJVbmlkYXRhIn0.XmsAuXvbTj4BFhZlJK4xXfbd0ltVZJCEhqdYcW_kLOo",
|
||||
} as any)
|
||||
const cid = await web3Storage.put([file], {
|
||||
name: file.name,
|
||||
maxRetries: 3,
|
||||
wrapWithDirectory: false,
|
||||
})
|
||||
return {
|
||||
key: `https://gateway.ipfs.io/ipfs/${cid}`,
|
||||
}
|
||||
}, [])
|
||||
|
||||
return uploadFile
|
||||
}
|
||||
|
||||
export type UploadFile = (
|
||||
blob: Blob,
|
||||
filename: string
|
||||
filename: string,
|
||||
) => Promise<{ key: string }>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ export const logout = () => {
|
|||
if (location.host !== OUR_DOMAIN) {
|
||||
url.searchParams.set(
|
||||
"next",
|
||||
`${location.protocol}//${location.host}/api/logout`
|
||||
`${location.protocol}//${location.host}/api/logout`,
|
||||
)
|
||||
}
|
||||
location.href = url.href
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ const findUserFromToken = async (token: string) => {
|
|||
|
||||
export const getAuthUser = async <TRequireAuth extends boolean | undefined>(
|
||||
request: IncomingMessage,
|
||||
requireAuth?: TRequireAuth
|
||||
requireAuth?: TRequireAuth,
|
||||
) => {
|
||||
const token = getAuthTokenFromRequest(request)
|
||||
|
||||
|
|
@ -80,18 +80,18 @@ export const getAuthCookieOptions = ({
|
|||
export const generateCookie = (
|
||||
options:
|
||||
| { type: "clear"; domain?: string }
|
||||
| { type: "auth"; token: string; domain?: string }
|
||||
| { type: "auth"; token: string; domain?: string },
|
||||
) => {
|
||||
if (options.type === "clear") {
|
||||
return Cookie.serialize(
|
||||
AUTH_COOKIE_NAME,
|
||||
"",
|
||||
getAuthCookieOptions({ domain: options.domain, clearCookie: true })
|
||||
getAuthCookieOptions({ domain: options.domain, clearCookie: true }),
|
||||
)
|
||||
}
|
||||
return Cookie.serialize(
|
||||
AUTH_COOKIE_NAME,
|
||||
options.token,
|
||||
getAuthCookieOptions({ domain: options.domain })
|
||||
getAuthCookieOptions({ domain: options.domain }),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ const createPrisma = (readonly: boolean) => {
|
|||
}
|
||||
|
||||
export const prismaPrimary = /* @__PURE__ */ singleton("prisma-primary", () =>
|
||||
createPrisma(false)
|
||||
createPrisma(false),
|
||||
)
|
||||
|
||||
export const prismaRead = /* @__PURE__ */ singleton("prisma-read", () =>
|
||||
createPrisma(true)
|
||||
createPrisma(true),
|
||||
)
|
||||
|
||||
export * from "@prisma/client"
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ export const SITE_URL = `${IS_PROD ? "https" : "http"}://${OUR_DOMAIN}`
|
|||
export const R2_URL = process.env.NEXT_PUBLIC_R2_URL
|
||||
export const APP_DESCRIPTION = process.env.APP_DESCRIPTION
|
||||
export const DISCORD_LINK = process.env.NEXT_PUBLIC_DISCORD_LINK
|
||||
export const GITHUB_LINK = process.env.NEXT_PUBLIC_GITHUB_LINK
|
||||
export const GITHUB_LINK = process.env.NEXT_PUBLIC_GITHUB_LINK
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ export const getPageVisibility = ({
|
|||
date_published,
|
||||
}: {
|
||||
date_published?: string
|
||||
}) => {
|
||||
}) => {
|
||||
if (!date_published) {
|
||||
return PageVisibilityEnum.Draft
|
||||
} else if (dayjs(date_published).isBefore(new Date())) {
|
||||
return PageVisibilityEnum.Published
|
||||
} else if (dayjs(date_published).isBefore(new Date('9999-01-01'))) {
|
||||
} else if (dayjs(date_published).isBefore(new Date("9999-01-01"))) {
|
||||
return PageVisibilityEnum.Scheduled
|
||||
}
|
||||
return PageVisibilityEnum.Draft
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
import { get, set, del } from "idb-keyval";
|
||||
import { PersistedClient, Persister } from "@tanstack/react-query-persist-client";
|
||||
import { get, set, del } from "idb-keyval"
|
||||
import {
|
||||
PersistedClient,
|
||||
Persister,
|
||||
} from "@tanstack/react-query-persist-client"
|
||||
|
||||
/**
|
||||
* Creates an Indexed DB persister
|
||||
|
|
@ -8,13 +11,13 @@ import { PersistedClient, Persister } from "@tanstack/react-query-persist-client
|
|||
export function createIDBPersister(idbValidKey: IDBValidKey = "reactQuery") {
|
||||
return {
|
||||
persistClient: async (client: PersistedClient) => {
|
||||
set(idbValidKey, client);
|
||||
set(idbValidKey, client)
|
||||
},
|
||||
restoreClient: async () => {
|
||||
return await get<PersistedClient>(idbValidKey);
|
||||
return await get<PersistedClient>(idbValidKey)
|
||||
},
|
||||
removeClient: async () => {
|
||||
await del(idbValidKey);
|
||||
await del(idbValidKey)
|
||||
},
|
||||
} as Persister;
|
||||
}
|
||||
} as Persister
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
import { PersistedClient, Persister } from "@tanstack/react-query-persist-client";
|
||||
import {
|
||||
PersistedClient,
|
||||
Persister,
|
||||
} from "@tanstack/react-query-persist-client"
|
||||
import Redis from "ioredis"
|
||||
|
||||
let redis: Redis
|
||||
if (process.env.REDIS_URL) {
|
||||
redis = new Redis(process.env.REDIS_URL)
|
||||
|
||||
redis.on('error', (error: any) => {
|
||||
console.error('Redis error: ', error)
|
||||
redis.on("error", (error: any) => {
|
||||
console.error("Redis error: ", error)
|
||||
})
|
||||
redis.on('end', () => {
|
||||
console.log('Redis end')
|
||||
redis.on("end", () => {
|
||||
console.log("Redis end")
|
||||
})
|
||||
redis.on('connect', () => {
|
||||
console.log('Redis connected.')
|
||||
redis.on("connect", () => {
|
||||
console.log("Redis connected.")
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +26,7 @@ export function createRedisPersister(redisValidKey = "reactQuery") {
|
|||
redis.set(redisValidKey, JSON.stringify(client))
|
||||
},
|
||||
restoreClient: async () => {
|
||||
const data = await redis.get(redisValidKey);
|
||||
const data = await redis.get(redisValidKey)
|
||||
if (data) {
|
||||
return JSON.parse(data)
|
||||
} else {
|
||||
|
|
@ -31,10 +34,10 @@ export function createRedisPersister(redisValidKey = "reactQuery") {
|
|||
}
|
||||
},
|
||||
removeClient: async () => {
|
||||
await redis.del(redisValidKey);
|
||||
await redis.del(redisValidKey)
|
||||
},
|
||||
} as Persister;
|
||||
} as Persister
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { QueryClient } from '@tanstack/react-query'
|
||||
import { QueryClient } from "@tanstack/react-query"
|
||||
import { createRedisPersister } from "~/lib/persister.server"
|
||||
import { persistQueryClient } from '@tanstack/react-query-persist-client'
|
||||
import { persistQueryClient } from "@tanstack/react-query-persist-client"
|
||||
|
||||
const cacheTime = 30 * 60 * 60 * 1000 // 30 days
|
||||
|
||||
|
|
|
|||
|
|
@ -19,14 +19,14 @@ export const notFound = (message?: string) => new NotFound(message)
|
|||
export const isNotFoundError = (error: unknown) => error instanceof NotFound
|
||||
|
||||
export const serverSidePropsHandler = <
|
||||
TProps extends { [key: string]: any } = { [key: string]: any }
|
||||
TProps extends { [key: string]: any } = { [key: string]: any },
|
||||
>(
|
||||
fn: (
|
||||
ctx: GetServerSidePropsContext
|
||||
) => Promise<{ props: TProps } | Redirect | NotFound>
|
||||
ctx: GetServerSidePropsContext,
|
||||
) => Promise<{ props: TProps } | Redirect | NotFound>,
|
||||
) => {
|
||||
return async (
|
||||
ctx: GetServerSidePropsContext
|
||||
ctx: GetServerSidePropsContext,
|
||||
): Promise<GetServerSidePropsResult<TProps>> => {
|
||||
try {
|
||||
const result = await fn(ctx)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const singleton = <T>(id: string, factory: () => T): T => {
|
|||
export const singletonAsync = <T>(
|
||||
id: string,
|
||||
factory: () => Promise<T>,
|
||||
enableSingleton = true
|
||||
enableSingleton = true,
|
||||
): { readonly value: T; wait: Promise<void> } => {
|
||||
if (globalThis._singletons[id] && enableSingleton) {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -76,8 +76,8 @@ export type Note = UniNote & {
|
|||
}
|
||||
|
||||
export type Notes = {
|
||||
total: number,
|
||||
list: Note[],
|
||||
total: number
|
||||
list: Note[]
|
||||
}
|
||||
|
||||
export type Profile = UniProfile & {
|
||||
|
|
@ -86,6 +86,6 @@ export type Profile = UniProfile & {
|
|||
}
|
||||
|
||||
export type Profiles = {
|
||||
total: number,
|
||||
list: Note[],
|
||||
}
|
||||
total: number
|
||||
list: Note[]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { R2_URL } from "./env"
|
|||
export function getUserContentsUrl(filename: string): string
|
||||
export function getUserContentsUrl(filename: undefined | null): undefined
|
||||
export function getUserContentsUrl<T extends string | undefined | null>(
|
||||
filename: T
|
||||
filename: T,
|
||||
): T
|
||||
export function getUserContentsUrl(filename: string | undefined | null) {
|
||||
if (!filename) return undefined
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export const getMemberships = async ({
|
|||
|
||||
export const updateMembership = async (
|
||||
membershipId: string,
|
||||
input: { lastSwitchedTo?: Date }
|
||||
input: { lastSwitchedTo?: Date },
|
||||
) => {
|
||||
await prismaPrimary.membership.update({
|
||||
where: {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,6 @@ const checkPageSlug = async ({
|
|||
// if (!slug) {
|
||||
// throw new Error("Missing page slug")
|
||||
// }
|
||||
|
||||
// const page = await prismaPrimary.page.findFirst({
|
||||
// where: {
|
||||
// siteId,
|
||||
|
|
@ -37,7 +36,6 @@ const checkPageSlug = async ({
|
|||
// },
|
||||
// })
|
||||
// if (!page) return
|
||||
|
||||
// if (page.deletedAt) {
|
||||
// await prismaPrimary.page.delete({
|
||||
// where: {
|
||||
|
|
@ -46,48 +44,53 @@ const checkPageSlug = async ({
|
|||
// })
|
||||
// return
|
||||
// }
|
||||
|
||||
// throw new Error("Page slug already used")
|
||||
}
|
||||
|
||||
export async function createOrUpdatePage(
|
||||
input: {
|
||||
pageId?: string
|
||||
siteId: string
|
||||
slug?: string
|
||||
title?: string
|
||||
content?: string
|
||||
published?: boolean
|
||||
publishedAt?: string
|
||||
excerpt?: string
|
||||
/** Only needed when creating page */
|
||||
isPost?: boolean
|
||||
},
|
||||
) {
|
||||
return await unidata.notes.set({
|
||||
source: 'Crossbell Note',
|
||||
identity: input.siteId,
|
||||
platform: 'Crossbell',
|
||||
action: input.pageId ? 'update' : 'add',
|
||||
}, {
|
||||
...(input.pageId && { id: input.pageId }),
|
||||
...(input.title && { title: input.title }),
|
||||
...(input.content && {
|
||||
body: {
|
||||
content: input.content,
|
||||
mime_type: 'text/markdown',
|
||||
}}),
|
||||
...(input.publishedAt && { date_published: input.published ? input.publishedAt : new Date('9999-01-01').toISOString() }),
|
||||
...(input.excerpt && {
|
||||
summary: {
|
||||
content: input.excerpt,
|
||||
mime_type: 'text/markdown',
|
||||
}
|
||||
}),
|
||||
tags: [input.isPost ? "post" : "page"],
|
||||
applications: ["xlog"],
|
||||
...(input.slug && {_xlog_slug: input.slug})
|
||||
})
|
||||
export async function createOrUpdatePage(input: {
|
||||
pageId?: string
|
||||
siteId: string
|
||||
slug?: string
|
||||
title?: string
|
||||
content?: string
|
||||
published?: boolean
|
||||
publishedAt?: string
|
||||
excerpt?: string
|
||||
/** Only needed when creating page */
|
||||
isPost?: boolean
|
||||
}) {
|
||||
return await unidata.notes.set(
|
||||
{
|
||||
source: "Crossbell Note",
|
||||
identity: input.siteId,
|
||||
platform: "Crossbell",
|
||||
action: input.pageId ? "update" : "add",
|
||||
},
|
||||
{
|
||||
...(input.pageId && { id: input.pageId }),
|
||||
...(input.title && { title: input.title }),
|
||||
...(input.content && {
|
||||
body: {
|
||||
content: input.content,
|
||||
mime_type: "text/markdown",
|
||||
},
|
||||
}),
|
||||
...(input.publishedAt && {
|
||||
date_published: input.published
|
||||
? input.publishedAt
|
||||
: new Date("9999-01-01").toISOString(),
|
||||
}),
|
||||
...(input.excerpt && {
|
||||
summary: {
|
||||
content: input.excerpt,
|
||||
mime_type: "text/markdown",
|
||||
},
|
||||
}),
|
||||
tags: [input.isPost ? "post" : "page"],
|
||||
applications: ["xlog"],
|
||||
...(input.slug && { _xlog_slug: input.slug }),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function scheduleEmailForPost(
|
||||
|
|
@ -95,15 +98,12 @@ export async function scheduleEmailForPost(
|
|||
input: { pageId: string; emailSubject?: string },
|
||||
) {
|
||||
// const page = await getPage(gate, { page: input.pageId })
|
||||
|
||||
// if (!gate.allows({ type: "can-update-page", siteId: page.siteId })) {
|
||||
// throw gate.permissionError()
|
||||
// }
|
||||
|
||||
// if (page.emailStatus) {
|
||||
// throw new Error("Email already scheduled or sent")
|
||||
// }
|
||||
|
||||
// await prismaPrimary.page.update({
|
||||
// where: {
|
||||
// id: page.id,
|
||||
|
|
@ -113,24 +113,21 @@ export async function scheduleEmailForPost(
|
|||
// emailSubject: input.emailSubject,
|
||||
// },
|
||||
// })
|
||||
|
||||
// await notifySubscribersForNewPost(gate, {
|
||||
// pageId: page.id,
|
||||
// })
|
||||
}
|
||||
|
||||
export async function getPagesBySite(
|
||||
input: {
|
||||
site?: string
|
||||
type: "post" | "page"
|
||||
visibility?: PageVisibilityEnum | null
|
||||
take?: number | null
|
||||
cursor?: string | null
|
||||
includeContent?: boolean
|
||||
includeExcerpt?: boolean
|
||||
render?: boolean
|
||||
},
|
||||
) {
|
||||
export async function getPagesBySite(input: {
|
||||
site?: string
|
||||
type: "post" | "page"
|
||||
visibility?: PageVisibilityEnum | null
|
||||
take?: number | null
|
||||
cursor?: string | null
|
||||
includeContent?: boolean
|
||||
includeExcerpt?: boolean
|
||||
render?: boolean
|
||||
}) {
|
||||
if (!input.site) {
|
||||
return {
|
||||
total: 0,
|
||||
|
|
@ -140,94 +137,122 @@ export async function getPagesBySite(
|
|||
|
||||
const visibility = input.visibility || PageVisibilityEnum.All
|
||||
|
||||
let pages: Notes = await unidata.notes.get({
|
||||
source: 'Crossbell Note',
|
||||
let pages: Notes = (await unidata.notes.get({
|
||||
source: "Crossbell Note",
|
||||
identity: input.site,
|
||||
platform: 'Crossbell',
|
||||
platform: "Crossbell",
|
||||
limit: input.take || 1000,
|
||||
}) || {
|
||||
})) || {
|
||||
total: 0,
|
||||
list: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (pages?.list) {
|
||||
switch (visibility) {
|
||||
case PageVisibilityEnum.Published:
|
||||
pages.list = pages.list.filter(page => +new Date(page.date_published) <= +new Date())
|
||||
pages.list = pages.list.filter(
|
||||
(page) => +new Date(page.date_published) <= +new Date(),
|
||||
)
|
||||
break
|
||||
case PageVisibilityEnum.Draft:
|
||||
pages.list = pages.list.filter(page => page.date_published === new Date('9999-01-01').toISOString())
|
||||
pages.list = pages.list.filter(
|
||||
(page) =>
|
||||
page.date_published === new Date("9999-01-01").toISOString(),
|
||||
)
|
||||
break
|
||||
case PageVisibilityEnum.Scheduled:
|
||||
pages.list = pages.list.filter(page => +new Date(page.date_published) > +new Date() && page.date_published !== new Date('9999-01-01').toISOString())
|
||||
pages.list = pages.list.filter(
|
||||
(page) =>
|
||||
+new Date(page.date_published) > +new Date() &&
|
||||
page.date_published !== new Date("9999-01-01").toISOString(),
|
||||
)
|
||||
break
|
||||
}
|
||||
pages.list = pages.list.filter(page => page.applications?.includes("Crosslog") || page.applications?.includes("xlog")).filter(page => page.tags?.includes(input.type))
|
||||
pages.list = pages.list
|
||||
.filter(
|
||||
(page) =>
|
||||
page.applications?.includes("Crosslog") ||
|
||||
page.applications?.includes("xlog"),
|
||||
)
|
||||
.filter((page) => page.tags?.includes(input.type))
|
||||
pages.total = pages.list.length
|
||||
|
||||
pages.list = await Promise.all(pages?.list.map(async (page) => {
|
||||
if (page.body?.content && page.body?.mime_type === 'text/markdown' && input.render) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: 'text/html'
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
content: rendered.excerpt,
|
||||
mime_type: 'text/html'
|
||||
pages.list = await Promise.all(
|
||||
pages?.list.map(async (page) => {
|
||||
if (
|
||||
page.body?.content &&
|
||||
page.body?.mime_type === "text/markdown" &&
|
||||
input.render
|
||||
) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: "text/html",
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
content: rendered.excerpt,
|
||||
mime_type: "text/html",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
page.slug = page.metadata?.raw?._xlog_slug || page.metadata?.raw?._crosslog_slug || page.id
|
||||
return page
|
||||
}))
|
||||
page.slug =
|
||||
page.metadata?.raw?._xlog_slug ||
|
||||
page.metadata?.raw?._crosslog_slug ||
|
||||
page.id
|
||||
return page
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
return pages
|
||||
}
|
||||
|
||||
export async function deletePage({ site, id }: { site: string, id: string }) {
|
||||
return await unidata.notes.set({
|
||||
source: 'Crossbell Note',
|
||||
identity: site,
|
||||
platform: 'Crossbell',
|
||||
action: 'remove',
|
||||
}, {
|
||||
id,
|
||||
})
|
||||
export async function deletePage({ site, id }: { site: string; id: string }) {
|
||||
return await unidata.notes.set(
|
||||
{
|
||||
source: "Crossbell Note",
|
||||
identity: site,
|
||||
platform: "Crossbell",
|
||||
action: "remove",
|
||||
},
|
||||
{
|
||||
id,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function getPage<TRender extends boolean = false>(
|
||||
input: {
|
||||
/** page slug or id, `site` is needed when `page` is a slug */
|
||||
page?: string
|
||||
pageId?: string
|
||||
site?: string
|
||||
render?: TRender
|
||||
includeAuthors?: boolean
|
||||
},
|
||||
) {
|
||||
export async function getPage<TRender extends boolean = false>(input: {
|
||||
/** page slug or id, `site` is needed when `page` is a slug */
|
||||
page?: string
|
||||
pageId?: string
|
||||
site?: string
|
||||
render?: TRender
|
||||
includeAuthors?: boolean
|
||||
}) {
|
||||
if (!input.site || !(input.page || input.pageId)) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const pages: Notes | null = await unidata.notes.get({
|
||||
source: 'Crossbell Note',
|
||||
source: "Crossbell Note",
|
||||
identity: input.site,
|
||||
platform: 'Crossbell',
|
||||
platform: "Crossbell",
|
||||
limit: 1000,
|
||||
...(input.pageId && {
|
||||
filter: {
|
||||
id: input.pageId,
|
||||
}
|
||||
})
|
||||
},
|
||||
}),
|
||||
})
|
||||
|
||||
let page;
|
||||
let page
|
||||
if (input.page) {
|
||||
page = pages?.list.find((item) => {
|
||||
item.slug = item.metadata?.raw?._xlog_slug || item.metadata?.raw?._crosslog_slug || item.id
|
||||
item.slug =
|
||||
item.metadata?.raw?._xlog_slug ||
|
||||
item.metadata?.raw?._crosslog_slug ||
|
||||
item.id
|
||||
return item.slug === input.page
|
||||
})
|
||||
} else {
|
||||
|
|
@ -239,35 +264,48 @@ export async function getPage<TRender extends boolean = false>(
|
|||
}
|
||||
|
||||
if (pages?.list) {
|
||||
pages.list = await Promise.all(pages?.list.map(async (page) => {
|
||||
if (page.body?.content && page.body?.mime_type === 'text/markdown' && input.render) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: 'text/html'
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
content: rendered.excerpt,
|
||||
mime_type: 'text/html'
|
||||
pages.list = await Promise.all(
|
||||
pages?.list.map(async (page) => {
|
||||
if (
|
||||
page.body?.content &&
|
||||
page.body?.mime_type === "text/markdown" &&
|
||||
input.render
|
||||
) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: "text/html",
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
content: rendered.excerpt,
|
||||
mime_type: "text/html",
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
page.slug = page.metadata?.raw?._xlog_slug || page.metadata?.raw?._crosslog_slug || page.id
|
||||
return page
|
||||
}))
|
||||
page.slug =
|
||||
page.metadata?.raw?._xlog_slug ||
|
||||
page.metadata?.raw?._crosslog_slug ||
|
||||
page.id
|
||||
return page
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
if (page.body?.content && page.body?.mime_type === 'text/markdown' && input.render) {
|
||||
if (
|
||||
page.body?.content &&
|
||||
page.body?.mime_type === "text/markdown" &&
|
||||
input.render
|
||||
) {
|
||||
const rendered = await renderPageContent(page.body.content)
|
||||
page.body = {
|
||||
content: rendered.contentHTML,
|
||||
mime_type: 'text/html'
|
||||
mime_type: "text/html",
|
||||
}
|
||||
if (!page.summary) {
|
||||
page.summary = {
|
||||
content: rendered.excerpt,
|
||||
mime_type: 'text/html'
|
||||
mime_type: "text/html",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -283,23 +321,18 @@ export const notifySubscribersForNewPost = async (
|
|||
) => {
|
||||
// const page = await getPage(gate, { page: input.pageId, render: true })
|
||||
// const site = await getSite(page.siteId)
|
||||
|
||||
// if (page.emailStatus !== PageEmailStatus.PENDING) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// if (!page.published || page.publishedAt > new Date()) {
|
||||
// return
|
||||
// }
|
||||
|
||||
// if (page.type === "PAGE") {
|
||||
// throw new Error("You can only notify subscribers for post updates")
|
||||
// }
|
||||
|
||||
// if (!gate.allows({ type: "can-notify-site-subscribers", site })) {
|
||||
// throw gate.permissionError()
|
||||
// }
|
||||
|
||||
// await prismaPrimary.page.update({
|
||||
// where: {
|
||||
// id: page.id,
|
||||
|
|
@ -308,7 +341,6 @@ export const notifySubscribersForNewPost = async (
|
|||
// emailStatus: PageEmailStatus.RUNNING,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const memberships = await prismaPrimary.membership.findMany({
|
||||
// where: {
|
||||
// role: MembershipRole.SUBSCRIBER,
|
||||
|
|
@ -318,11 +350,9 @@ export const notifySubscribersForNewPost = async (
|
|||
// user: true,
|
||||
// },
|
||||
// })
|
||||
|
||||
// const emailSubscribers = memberships
|
||||
// .filter((member) => (member.config as any).email)
|
||||
// .map((member) => member.user)
|
||||
|
||||
// try {
|
||||
// await sendEmailForNewPost({
|
||||
// post: page,
|
||||
|
|
|
|||
|
|
@ -43,24 +43,26 @@ export const getUserSites = async (address?: string) => {
|
|||
return null
|
||||
}
|
||||
const profiles = await unidata.profiles.get({
|
||||
source: 'Crossbell Profile',
|
||||
source: "Crossbell Profile",
|
||||
identity: address,
|
||||
platform: 'Ethereum',
|
||||
});
|
||||
|
||||
const sites = profiles.list?.sort((a, b) => {
|
||||
if (a.metadata?.primary) {
|
||||
return -1
|
||||
} else if (b.metadata?.primary) {
|
||||
return 1
|
||||
} else {
|
||||
return +new Date(b.date_updated || 0) - +new Date(a.date_updated || 0)
|
||||
}
|
||||
}).map((profile) => {
|
||||
profile.name = profile.name || profile.username;
|
||||
return profile
|
||||
platform: "Ethereum",
|
||||
})
|
||||
|
||||
const sites = profiles.list
|
||||
?.sort((a, b) => {
|
||||
if (a.metadata?.primary) {
|
||||
return -1
|
||||
} else if (b.metadata?.primary) {
|
||||
return 1
|
||||
} else {
|
||||
return +new Date(b.date_updated || 0) - +new Date(a.date_updated || 0)
|
||||
}
|
||||
})
|
||||
.map((profile) => {
|
||||
profile.name = profile.name || profile.username
|
||||
return profile
|
||||
})
|
||||
|
||||
if (!sites || !sites.length) return null
|
||||
|
||||
return sites
|
||||
|
|
@ -68,14 +70,22 @@ export const getUserSites = async (address?: string) => {
|
|||
|
||||
export const getSite = async (input: string) => {
|
||||
const profiles = await unidata.profiles.get({
|
||||
source: 'Crossbell Profile',
|
||||
source: "Crossbell Profile",
|
||||
identity: input,
|
||||
platform: 'Crossbell',
|
||||
});
|
||||
platform: "Crossbell",
|
||||
})
|
||||
|
||||
const site: Profile = profiles.list?.sort((a, b) => +new Date(b.date_updated || 0) - +new Date(a.date_updated || 0))?.[0]
|
||||
site.navigation = site.metadata?.raw?.['_xlog_navigation'] || site.metadata?.raw?.['_crosslog_navigation'] || [{ id: nanoid(), label: "Archives", url: "/archives" }]
|
||||
site.css = site.metadata?.raw?.['_xlog_css'] || site.metadata?.raw?.['_crosslog_css'] || ''
|
||||
const site: Profile = profiles.list?.sort(
|
||||
(a, b) => +new Date(b.date_updated || 0) - +new Date(a.date_updated || 0),
|
||||
)?.[0]
|
||||
site.navigation = site.metadata?.raw?.["_xlog_navigation"] ||
|
||||
site.metadata?.raw?.["_crosslog_navigation"] || [
|
||||
{ id: nanoid(), label: "Archives", url: "/archives" },
|
||||
]
|
||||
site.css =
|
||||
site.metadata?.raw?.["_xlog_css"] ||
|
||||
site.metadata?.raw?.["_crosslog_css"] ||
|
||||
""
|
||||
site.name = site.name || site.username
|
||||
|
||||
return site
|
||||
|
|
@ -86,94 +96,103 @@ export const getSubscription = async (data: {
|
|||
siteId: string
|
||||
}) => {
|
||||
const links = await unidata.links.get({
|
||||
source: 'Crossbell Link',
|
||||
source: "Crossbell Link",
|
||||
identity: data.userId,
|
||||
platform: 'Ethereum',
|
||||
platform: "Ethereum",
|
||||
filter: {
|
||||
to: data.siteId
|
||||
}
|
||||
to: data.siteId,
|
||||
},
|
||||
})
|
||||
return !!links?.list?.length
|
||||
}
|
||||
|
||||
export async function updateSite(
|
||||
payload: {
|
||||
site: string
|
||||
name?: string
|
||||
description?: string
|
||||
icon?: string | null
|
||||
subdomain?: string
|
||||
navigation?: SiteNavigationItem[]
|
||||
css?: string
|
||||
},
|
||||
) {
|
||||
return await unidata.profiles.set({
|
||||
source: 'Crossbell Profile',
|
||||
identity: payload.site,
|
||||
platform: 'Crossbell',
|
||||
action: 'update',
|
||||
}, {
|
||||
...(payload.name && { name: payload.name }),
|
||||
...(payload.description && { bio: payload.description }),
|
||||
...(payload.icon && { avatars: [payload.icon] }),
|
||||
...(payload.subdomain && { username: payload.subdomain }),
|
||||
...(payload.navigation && { _xlog_navigation: payload.navigation }),
|
||||
...(payload.css && { _xlog_css: payload.css }),
|
||||
})
|
||||
export async function updateSite(payload: {
|
||||
site: string
|
||||
name?: string
|
||||
description?: string
|
||||
icon?: string | null
|
||||
subdomain?: string
|
||||
navigation?: SiteNavigationItem[]
|
||||
css?: string
|
||||
}) {
|
||||
return await unidata.profiles.set(
|
||||
{
|
||||
source: "Crossbell Profile",
|
||||
identity: payload.site,
|
||||
platform: "Crossbell",
|
||||
action: "update",
|
||||
},
|
||||
{
|
||||
...(payload.name && { name: payload.name }),
|
||||
...(payload.description && { bio: payload.description }),
|
||||
...(payload.icon && { avatars: [payload.icon] }),
|
||||
...(payload.subdomain && { username: payload.subdomain }),
|
||||
...(payload.navigation && { _xlog_navigation: payload.navigation }),
|
||||
...(payload.css && { _xlog_css: payload.css }),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function createSite(
|
||||
address: string,
|
||||
payload: { name: string; subdomain: string },
|
||||
) {
|
||||
return await unidata.profiles.set({
|
||||
source: 'Crossbell Profile',
|
||||
identity: address,
|
||||
platform: 'Ethereum',
|
||||
action: 'add',
|
||||
}, {
|
||||
username: payload.subdomain,
|
||||
name: payload.name,
|
||||
tags: ['navigation:' + JSON.stringify([
|
||||
{
|
||||
id: nanoid(),
|
||||
label: "Archives",
|
||||
url: "/archives",
|
||||
},
|
||||
])],
|
||||
})
|
||||
return await unidata.profiles.set(
|
||||
{
|
||||
source: "Crossbell Profile",
|
||||
identity: address,
|
||||
platform: "Ethereum",
|
||||
action: "add",
|
||||
},
|
||||
{
|
||||
username: payload.subdomain,
|
||||
name: payload.name,
|
||||
tags: [
|
||||
"navigation:" +
|
||||
JSON.stringify([
|
||||
{
|
||||
id: nanoid(),
|
||||
label: "Archives",
|
||||
url: "/archives",
|
||||
},
|
||||
]),
|
||||
],
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function subscribeToSite(
|
||||
input: {
|
||||
userId: string
|
||||
siteId: string
|
||||
},
|
||||
) {
|
||||
return unidata.links.set({
|
||||
source: 'Crossbell Link',
|
||||
identity: input.userId,
|
||||
platform: 'Ethereum',
|
||||
action: 'add',
|
||||
}, {
|
||||
to: input.siteId,
|
||||
type: 'follow',
|
||||
})
|
||||
export async function subscribeToSite(input: {
|
||||
userId: string
|
||||
siteId: string
|
||||
}) {
|
||||
return unidata.links.set(
|
||||
{
|
||||
source: "Crossbell Link",
|
||||
identity: input.userId,
|
||||
platform: "Ethereum",
|
||||
action: "add",
|
||||
},
|
||||
{
|
||||
to: input.siteId,
|
||||
type: "follow",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export async function unsubscribeFromSite(
|
||||
input: {
|
||||
userId: string
|
||||
siteId: string
|
||||
},
|
||||
) {
|
||||
return unidata.links.set({
|
||||
source: 'Crossbell Link',
|
||||
identity: input.userId,
|
||||
platform: 'Ethereum',
|
||||
action: 'remove',
|
||||
}, {
|
||||
to: input.siteId,
|
||||
type: 'follow',
|
||||
})
|
||||
export async function unsubscribeFromSite(input: {
|
||||
userId: string
|
||||
siteId: string
|
||||
}) {
|
||||
return unidata.links.set(
|
||||
{
|
||||
source: "Crossbell Link",
|
||||
identity: input.userId,
|
||||
platform: "Ethereum",
|
||||
action: "remove",
|
||||
},
|
||||
{
|
||||
to: input.siteId,
|
||||
type: "follow",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ export const userModel = {
|
|||
avatar?: string
|
||||
bio?: string
|
||||
email?: string
|
||||
}
|
||||
},
|
||||
) {
|
||||
const user = gate.getUser(true)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,62 +2,60 @@ import { Toaster } from "react-hot-toast"
|
|||
import "~/css/main.css"
|
||||
import "~/generated/uno.css"
|
||||
import { StoreProvider, createStore } from "~/lib/store"
|
||||
import { getDefaultWallets, RainbowKitProvider } from "@rainbow-me/rainbowkit"
|
||||
import { configureChains, createClient, WagmiConfig } from "wagmi"
|
||||
import { jsonRpcProvider } from "wagmi/providers/jsonRpc"
|
||||
import {
|
||||
getDefaultWallets,
|
||||
RainbowKitProvider,
|
||||
} from '@rainbow-me/rainbowkit';
|
||||
import {
|
||||
configureChains,
|
||||
createClient,
|
||||
WagmiConfig,
|
||||
} from 'wagmi'
|
||||
import { jsonRpcProvider } from 'wagmi/providers/jsonRpc'
|
||||
import { Hydrate, QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
|
||||
import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client'
|
||||
import { createIDBPersister } from '~/lib/persister.client'
|
||||
import { connectorsForWallets, wallet } from '@rainbow-me/rainbowkit'
|
||||
Hydrate,
|
||||
QueryClient,
|
||||
QueryClientProvider,
|
||||
} from "@tanstack/react-query"
|
||||
import { ReactQueryDevtools } from "@tanstack/react-query-devtools"
|
||||
import { PersistQueryClientProvider } from "@tanstack/react-query-persist-client"
|
||||
import { createIDBPersister } from "~/lib/persister.client"
|
||||
import { connectorsForWallets, wallet } from "@rainbow-me/rainbowkit"
|
||||
|
||||
import '@rainbow-me/rainbowkit/styles.css'
|
||||
import "@rainbow-me/rainbowkit/styles.css"
|
||||
|
||||
const { chains, provider } = configureChains(
|
||||
[{
|
||||
id: 3737,
|
||||
name: 'Crossbell',
|
||||
network: 'crossbell',
|
||||
rpcUrls: {
|
||||
default: 'https://rpc.crossbell.io',
|
||||
},
|
||||
iconUrl: 'https://gateway.ipfs.io/ipfs/QmS8zEetTb6pwdNpVjv5bz55BXiSMGP9BjTJmNcjcUT91t',
|
||||
nativeCurrency: {
|
||||
decimals: 18,
|
||||
name: 'Crossbell Token',
|
||||
symbol: 'CSB',
|
||||
},
|
||||
blockExplorers: {
|
||||
default: { name: 'Crossbell Explorer', url: 'https://scan.crossbell.io' },
|
||||
},
|
||||
testnet: false,
|
||||
} as any],
|
||||
[
|
||||
jsonRpcProvider({ rpc: chain => ({ http: chain.rpcUrls.default }) })
|
||||
]
|
||||
{
|
||||
id: 3737,
|
||||
name: "Crossbell",
|
||||
network: "crossbell",
|
||||
rpcUrls: {
|
||||
default: "https://rpc.crossbell.io",
|
||||
},
|
||||
iconUrl:
|
||||
"https://gateway.ipfs.io/ipfs/QmS8zEetTb6pwdNpVjv5bz55BXiSMGP9BjTJmNcjcUT91t",
|
||||
nativeCurrency: {
|
||||
decimals: 18,
|
||||
name: "Crossbell Token",
|
||||
symbol: "CSB",
|
||||
},
|
||||
blockExplorers: {
|
||||
default: {
|
||||
name: "Crossbell Explorer",
|
||||
url: "https://scan.crossbell.io",
|
||||
},
|
||||
},
|
||||
testnet: false,
|
||||
} as any,
|
||||
],
|
||||
[jsonRpcProvider({ rpc: (chain) => ({ http: chain.rpcUrls.default }) })],
|
||||
)
|
||||
|
||||
const connectors = connectorsForWallets([
|
||||
{
|
||||
groupName: 'Recommended',
|
||||
wallets: [
|
||||
wallet.metaMask({ chains }),
|
||||
wallet.walletConnect({ chains }),
|
||||
],
|
||||
groupName: "Recommended",
|
||||
wallets: [wallet.metaMask({ chains }), wallet.walletConnect({ chains })],
|
||||
},
|
||||
])
|
||||
|
||||
const wagmiClient = createClient({
|
||||
autoConnect: true,
|
||||
connectors,
|
||||
provider
|
||||
provider,
|
||||
})
|
||||
|
||||
const queryClient = new QueryClient({
|
||||
|
|
@ -66,7 +64,7 @@ const queryClient = new QueryClient({
|
|||
cacheTime: 1000 * 60 * 60 * 24, // 24 hours
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
|
||||
const persister = createIDBPersister()
|
||||
|
||||
|
|
@ -75,7 +73,10 @@ function MyApp({ Component, pageProps }: any) {
|
|||
<WagmiConfig client={wagmiClient}>
|
||||
<RainbowKitProvider chains={chains}>
|
||||
<StoreProvider createStore={createStore}>
|
||||
<PersistQueryClientProvider client={queryClient} persistOptions={{ persister }}>
|
||||
<PersistQueryClientProvider
|
||||
client={queryClient}
|
||||
persistOptions={{ persister }}
|
||||
>
|
||||
<Hydrate state={pageProps.dehydratedState}>
|
||||
<ReactQueryDevtools />
|
||||
<Component {...pageProps} />
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { Viewer, Profile, Note } from "~/lib/types"
|
|||
import { queryClientServer } from "~/lib/query-client.server"
|
||||
import { prefetchGetSite } from "~/queries/site.server"
|
||||
import { useGetSite } from "~/queries/site"
|
||||
import { dehydrate, QueryClient } from '@tanstack/react-query'
|
||||
import { dehydrate, QueryClient } from "@tanstack/react-query"
|
||||
import { fetchGetPage } from "~/queries/page.server"
|
||||
import { useGetPage } from "~/queries/page"
|
||||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
|
|
@ -20,7 +20,7 @@ export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
|
|||
async (ctx) => {
|
||||
const domainOrSubdomain = ctx.params!.site as string
|
||||
const pageSlug = ctx.params!.page as string
|
||||
|
||||
|
||||
await prefetchGetSite(domainOrSubdomain)
|
||||
const page = await fetchGetPage({
|
||||
site: domainOrSubdomain,
|
||||
|
|
@ -61,11 +61,7 @@ function SitePagePage({
|
|||
const site = useGetSite(domainOrSubdomain)
|
||||
|
||||
return (
|
||||
<SiteLayout
|
||||
site={site.data}
|
||||
ogDescription={ogDescription}
|
||||
page={page.data}
|
||||
>
|
||||
<SiteLayout site={site.data} ogDescription={ogDescription} page={page.data}>
|
||||
<SitePage site={site.data} page={page.data} />
|
||||
</SiteLayout>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { Viewer, Profile, Notes } from "~/lib/types"
|
|||
import { queryClientServer } from "~/lib/query-client.server"
|
||||
import { prefetchGetSite } from "~/queries/site.server"
|
||||
import { useGetSite } from "~/queries/site"
|
||||
import { dehydrate, QueryClient } from '@tanstack/react-query'
|
||||
import { dehydrate, QueryClient } from "@tanstack/react-query"
|
||||
import { useGetPagesBySite } from "~/queries/page"
|
||||
import { prefetchGetPagesBySite } from "~/queries/page.server"
|
||||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
|
|
@ -18,7 +18,7 @@ import { PageVisibilityEnum } from "~/lib/types"
|
|||
export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
|
||||
async (ctx) => {
|
||||
const domainOrSubdomain = ctx.params!.site as string
|
||||
|
||||
|
||||
await prefetchGetSite(domainOrSubdomain)
|
||||
await prefetchGetPagesBySite({
|
||||
site: domainOrSubdomain,
|
||||
|
|
@ -33,14 +33,14 @@ export const getServerSideProps: GetServerSideProps = serverSidePropsHandler(
|
|||
domainOrSubdomain,
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
function SiteArchivesPage({
|
||||
domainOrSubdomain,
|
||||
}: {
|
||||
site: Profile,
|
||||
posts: Notes,
|
||||
site: Profile
|
||||
posts: Notes
|
||||
domainOrSubdomain: string
|
||||
}) {
|
||||
const site = useGetSite(domainOrSubdomain)
|
||||
|
|
@ -52,10 +52,7 @@ function SiteArchivesPage({
|
|||
})
|
||||
|
||||
return (
|
||||
<SiteLayout
|
||||
site={site.data}
|
||||
title="Archives"
|
||||
>
|
||||
<SiteLayout site={site.data} title="Archives">
|
||||
<SiteArchives posts={posts.data} />
|
||||
</SiteLayout>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ import { createSSGHelpers } from "@trpc/react/ssg"
|
|||
import { getTRPCContext } from "~/lib/trpc.server"
|
||||
import { Viewer, Profile, Notes } from "~/lib/types"
|
||||
import { getViewer } from "~/lib/viewer"
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useEffect, useState } from "react"
|
||||
import { queryClientServer } from "~/lib/query-client.server"
|
||||
import { prefetchGetSite } from "~/queries/site.server"
|
||||
import { useGetSite } from "~/queries/site"
|
||||
import { dehydrate, QueryClient } from '@tanstack/react-query'
|
||||
import { dehydrate, QueryClient } from "@tanstack/react-query"
|
||||
import { useGetPagesBySite } from "~/queries/page"
|
||||
import { prefetchGetPagesBySite } from "~/queries/page.server"
|
||||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
|
|
@ -33,11 +33,7 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
|||
}
|
||||
}
|
||||
|
||||
function SiteIndexPage({
|
||||
domainOrSubdomain,
|
||||
}: {
|
||||
domainOrSubdomain: string
|
||||
}) {
|
||||
function SiteIndexPage({ domainOrSubdomain }: { domainOrSubdomain: string }) {
|
||||
const site = useGetSite(domainOrSubdomain)
|
||||
const posts = useGetPagesBySite({
|
||||
site: domainOrSubdomain,
|
||||
|
|
|
|||
|
|
@ -38,10 +38,13 @@ export default function SubdomainEditor() {
|
|||
const page = useGetPage({
|
||||
site: subdomain!,
|
||||
pageId: pageId,
|
||||
render: false
|
||||
render: false,
|
||||
})
|
||||
|
||||
const pageContent = useMemo(() => page.data?.body?.content, [page.data?.body?.content])
|
||||
const pageContent = useMemo(
|
||||
() => page.data?.body?.content,
|
||||
[page.data?.body?.content],
|
||||
)
|
||||
|
||||
const visibility = getPageVisibility({
|
||||
date_published: page.data?.date_published,
|
||||
|
|
@ -137,9 +140,13 @@ export default function SubdomainEditor() {
|
|||
if (!page.data) return
|
||||
|
||||
setValues({
|
||||
title: page.data.title || '',
|
||||
publishedAt: page.data.date_published === new Date('9999-01-01').toISOString() ? new Date().toISOString() : page.data.date_published,
|
||||
published: page.data.date_published !== new Date('9999-01-01').toISOString(),
|
||||
title: page.data.title || "",
|
||||
publishedAt:
|
||||
page.data.date_published === new Date("9999-01-01").toISOString()
|
||||
? new Date().toISOString()
|
||||
: page.data.date_published,
|
||||
published:
|
||||
page.data.date_published !== new Date("9999-01-01").toISOString(),
|
||||
excerpt: page.data.summary?.content || "",
|
||||
slug: page.data.slug!,
|
||||
})
|
||||
|
|
|
|||
|
|
@ -57,11 +57,9 @@ export default function SettingsDomainsPage() {
|
|||
id="subdomain"
|
||||
label="Custom CSS"
|
||||
className="w-full"
|
||||
style={
|
||||
{
|
||||
height: "400px",
|
||||
}
|
||||
}
|
||||
style={{
|
||||
height: "400px",
|
||||
}}
|
||||
multiline
|
||||
{...form.register("css")}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export default function SettingsDomainsPage() {
|
|||
if (updateSite.data?.code === 0) {
|
||||
toast.success("Saved!")
|
||||
router.replace(
|
||||
`/dashboard/${updateSite.variables?.subdomain}/settings/domains`
|
||||
`/dashboard/${updateSite.variables?.subdomain}/settings/domains`,
|
||||
)
|
||||
} else {
|
||||
toast.error("Failed to update site" + ": " + updateSite.data.message)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { redirect } from "~/lib/server-side-props"
|
||||
import { useGetUserSites } from "~/queries/site"
|
||||
import { useAccount } from 'wagmi'
|
||||
import { useAccount } from "wagmi"
|
||||
import { useEffect } from "react"
|
||||
import { useRouter } from 'next/router'
|
||||
import { useRouter } from "next/router"
|
||||
|
||||
export default function Dashboard() {
|
||||
const { address } = useAccount()
|
||||
|
|
@ -19,5 +19,9 @@ export default function Dashboard() {
|
|||
}
|
||||
}, [userSites, router])
|
||||
|
||||
return <div className="flex items-center justify-center w-full h-60">Loading...</div>
|
||||
return (
|
||||
<div className="flex items-center justify-center w-full h-60">
|
||||
Loading...
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ export default function NewSitePage() {
|
|||
const router = useRouter()
|
||||
const createSite = useCreateSite()
|
||||
|
||||
const [addressIn, setAddressIn] = useState<string>('')
|
||||
const [addressIn, setAddressIn] = useState<string>("")
|
||||
const { address } = useAccount()
|
||||
|
||||
useEffect(() => {
|
||||
if (address) {
|
||||
setAddressIn(address || '')
|
||||
setAddressIn(address || "")
|
||||
} else {
|
||||
router.push("/")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import { UniLink } from "~/components/ui/UniLink"
|
|||
import { getAuthUser } from "~/lib/auth.server"
|
||||
import { FLY_REGION } from "~/lib/env.server"
|
||||
import { useStore } from "~/lib/store"
|
||||
import { useAccount } from 'wagmi'
|
||||
import { useAccount } from "wagmi"
|
||||
import { ConnectButton } from "~/components/common/ConnectButton"
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
|
|
@ -17,19 +17,15 @@ export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
|||
}
|
||||
}
|
||||
|
||||
export default function Home({
|
||||
region,
|
||||
}: {
|
||||
region: string | null
|
||||
}) {
|
||||
export default function Home({ region }: { region: string | null }) {
|
||||
const setLoginModalOpened = useStore((store) => store.setLoginModalOpened)
|
||||
const [addressIn, setAddressIn] = useState<string>('')
|
||||
const [addressIn, setAddressIn] = useState<string>("")
|
||||
const { address } = useAccount()
|
||||
|
||||
useEffect(() => {
|
||||
console.log("-> region", region)
|
||||
|
||||
setAddressIn(address || '')
|
||||
setAddressIn(address || "")
|
||||
}, [region, address])
|
||||
|
||||
return (
|
||||
|
|
@ -43,7 +39,8 @@ export default function Home({
|
|||
for Absolutely Everyone
|
||||
</h2>
|
||||
<h3 className="mt-5 text-zinc-500">
|
||||
Meet xlog, the on-chain and open-source blogging platform for everyone.
|
||||
Meet xlog, the on-chain and open-source blogging platform for
|
||||
everyone.
|
||||
<br />
|
||||
Permanently stored on the blockchain and signed by you.
|
||||
</h3>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import * as pageModel from "~/models/page.model"
|
||||
import { queryClientServer } from "~/lib/query-client.server"
|
||||
|
||||
export const fetchGetPage = async (input: Parameters<typeof pageModel.getPage>[0]) => {
|
||||
const key = ['getPage', input.page, input]
|
||||
const data: ReturnType<typeof pageModel.getPage> | undefined = queryClientServer.getQueryData(key)
|
||||
export const fetchGetPage = async (
|
||||
input: Parameters<typeof pageModel.getPage>[0],
|
||||
) => {
|
||||
const key = ["getPage", input.page, input]
|
||||
const data: ReturnType<typeof pageModel.getPage> | undefined =
|
||||
queryClientServer.getQueryData(key)
|
||||
if (!data) {
|
||||
return await queryClientServer.fetchQuery(key, async () => {
|
||||
return pageModel.getPage(input)
|
||||
|
|
@ -16,8 +19,10 @@ export const fetchGetPage = async (input: Parameters<typeof pageModel.getPage>[0
|
|||
}
|
||||
}
|
||||
|
||||
export const prefetchGetPagesBySite = async (input: Parameters<typeof pageModel.getPagesBySite>[0]) => {
|
||||
const key = ['getPagesBySite', input.site, input]
|
||||
export const prefetchGetPagesBySite = async (
|
||||
input: Parameters<typeof pageModel.getPagesBySite>[0],
|
||||
) => {
|
||||
const key = ["getPagesBySite", input.site, input]
|
||||
const data = queryClientServer.getQueryData(key)
|
||||
if (!data) {
|
||||
await queryClientServer.prefetchQuery(key, async () => {
|
||||
|
|
|
|||
|
|
@ -1,41 +1,48 @@
|
|||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import * as pageModel from "~/models/page.model"
|
||||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
|
||||
export const useGetPagesBySite = (input: Parameters<typeof pageModel.getPagesBySite>[0]) => {
|
||||
return useQuery(['getPagesBySite', input.site, input], async () => {
|
||||
export const useGetPagesBySite = (
|
||||
input: Parameters<typeof pageModel.getPagesBySite>[0],
|
||||
) => {
|
||||
return useQuery(["getPagesBySite", input.site, input], async () => {
|
||||
return pageModel.getPagesBySite(input)
|
||||
})
|
||||
}
|
||||
|
||||
export const useGetPage = (input: Parameters<typeof pageModel.getPage>[0]) => {
|
||||
return useQuery(['getPage', input.page, input], async () => {
|
||||
return useQuery(["getPage", input.page, input], async () => {
|
||||
return pageModel.getPage(input)
|
||||
})
|
||||
}
|
||||
|
||||
export function useCreateOrUpdatePage() {
|
||||
const queryClient = useQueryClient();
|
||||
const mutation = useMutation(async (
|
||||
payload: Parameters<typeof pageModel.createOrUpdatePage>[0]) => {
|
||||
return pageModel.createOrUpdatePage(payload)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getPagesBySite', variables.siteId])
|
||||
queryClient.invalidateQueries(['getPage', variables.pageId])
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useMutation(
|
||||
async (payload: Parameters<typeof pageModel.createOrUpdatePage>[0]) => {
|
||||
return pageModel.createOrUpdatePage(payload)
|
||||
},
|
||||
})
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getPagesBySite", variables.siteId])
|
||||
queryClient.invalidateQueries(["getPage", variables.pageId])
|
||||
},
|
||||
},
|
||||
)
|
||||
return mutation
|
||||
}
|
||||
|
||||
export function useDeletePage() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(async (input: Parameters<typeof pageModel.deletePage>[0]) => {
|
||||
return pageModel.deletePage(input)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getPagesBySite', variables.site])
|
||||
queryClient.invalidateQueries(['getPage', variables.id])
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation(
|
||||
async (input: Parameters<typeof pageModel.deletePage>[0]) => {
|
||||
return pageModel.deletePage(input)
|
||||
},
|
||||
})
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getPagesBySite", variables.site])
|
||||
queryClient.invalidateQueries(["getPage", variables.id])
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,15 +2,15 @@ import * as siteModel from "~/models/site.model"
|
|||
import { queryClientServer } from "~/lib/query-client.server"
|
||||
|
||||
export const prefetchGetSite = async (input: string) => {
|
||||
const key = ['getSite', input]
|
||||
const key = ["getSite", input]
|
||||
const data = queryClientServer.getQueryData(key)
|
||||
if (!data) {
|
||||
await queryClientServer.prefetchQuery(['getSite', input], async () => {
|
||||
await queryClientServer.prefetchQuery(["getSite", input], async () => {
|
||||
return siteModel.getSite(input)
|
||||
})
|
||||
} else {
|
||||
queryClientServer.prefetchQuery(['getSite', input], async () => {
|
||||
queryClientServer.prefetchQuery(["getSite", input], async () => {
|
||||
return siteModel.getSite(input)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
|
||||
import * as siteModel from "~/models/site.model"
|
||||
import { SiteNavigationItem, Profile } from "~/lib/types"
|
||||
|
||||
export const useGetUserSites = (address?: string) => {
|
||||
return useQuery(['getUserSites', address], async () => {
|
||||
return useQuery(["getUserSites", address], async () => {
|
||||
if (!address) {
|
||||
return []
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ export const useGetUserSites = (address?: string) => {
|
|||
}
|
||||
|
||||
export const useGetSite = (input: string) => {
|
||||
return useQuery(['getSite', input], async () => {
|
||||
return useQuery(["getSite", input], async () => {
|
||||
return siteModel.getSite(input)
|
||||
})
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@ export const useGetSubscription = (data: {
|
|||
userId: string
|
||||
siteId: string
|
||||
}) => {
|
||||
return useQuery(['getSubscription', data], async () => {
|
||||
return useQuery(["getSubscription", data], async () => {
|
||||
if (!data.userId || !data.siteId) {
|
||||
return false
|
||||
}
|
||||
|
|
@ -30,51 +30,62 @@ export const useGetSubscription = (data: {
|
|||
}
|
||||
|
||||
export function useUpdateSite() {
|
||||
const queryClient = useQueryClient();
|
||||
const mutation = useMutation(async (
|
||||
payload: Parameters<typeof siteModel.updateSite>[0]) => {
|
||||
return siteModel.updateSite(payload)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getUserSites'])
|
||||
queryClient.invalidateQueries(['getSite'])
|
||||
const queryClient = useQueryClient()
|
||||
const mutation = useMutation(
|
||||
async (payload: Parameters<typeof siteModel.updateSite>[0]) => {
|
||||
return siteModel.updateSite(payload)
|
||||
},
|
||||
})
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getUserSites"])
|
||||
queryClient.invalidateQueries(["getSite"])
|
||||
},
|
||||
},
|
||||
)
|
||||
return mutation
|
||||
}
|
||||
|
||||
export function useCreateSite() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(async (input: {
|
||||
address: string,
|
||||
payload: { name: string; subdomain: string },
|
||||
}) => {
|
||||
return siteModel.createSite(input.address, input.payload)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getUserSites', variables.address])
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation(
|
||||
async (input: {
|
||||
address: string
|
||||
payload: { name: string; subdomain: string }
|
||||
}) => {
|
||||
return siteModel.createSite(input.address, input.payload)
|
||||
},
|
||||
})
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getUserSites", variables.address])
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export function useSubscribeToSite() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(async (input: Parameters<typeof siteModel.subscribeToSite>[0]) => {
|
||||
return siteModel.subscribeToSite(input)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getSubscription', variables])
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation(
|
||||
async (input: Parameters<typeof siteModel.subscribeToSite>[0]) => {
|
||||
return siteModel.subscribeToSite(input)
|
||||
},
|
||||
})
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getSubscription", variables])
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
export function useUnsubscribeFromSite() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation(async (input: Parameters<typeof siteModel.subscribeToSite>[0]) => {
|
||||
return siteModel.unsubscribeFromSite(input)
|
||||
}, {
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(['getSubscription', variables])
|
||||
const queryClient = useQueryClient()
|
||||
return useMutation(
|
||||
async (input: Parameters<typeof siteModel.subscribeToSite>[0]) => {
|
||||
return siteModel.unsubscribeFromSite(input)
|
||||
},
|
||||
})
|
||||
}
|
||||
{
|
||||
onSuccess: (data, variables) => {
|
||||
queryClient.invalidateQueries(["getSubscription", variables])
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": [
|
||||
"DOM",
|
||||
"DOM.Iterable",
|
||||
"esnext"
|
||||
],
|
||||
"lib": ["DOM", "DOM.Iterable", "esnext"],
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"jsx": "preserve",
|
||||
|
|
@ -14,9 +10,7 @@
|
|||
"strict": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"~/*": [
|
||||
"./src/*"
|
||||
]
|
||||
"~/*": ["./src/*"]
|
||||
},
|
||||
"noEmit": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
|
|
@ -25,12 +19,6 @@
|
|||
"incremental": true,
|
||||
"module": "esnext"
|
||||
},
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue