mirror of
https://github.com/Troplo/Colubrina.git
synced 2024-12-24 23:45:15 +11:00
Run ESLint and update deps
This commit is contained in:
parent
ff7a4d0949
commit
43ccd477d4
40 changed files with 1666 additions and 2438 deletions
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"argon2": "^0.28.7",
|
||||
"axios": "^0.27.2",
|
||||
"axios": "^1.6.2",
|
||||
"clean-css": "^4.1.11",
|
||||
"constantinople": "3.1.1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
|
|
|
@ -402,13 +402,14 @@ aws4@^1.8.0:
|
|||
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
|
||||
integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
axios@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
|
||||
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
b4a@^1.6.4:
|
||||
version "1.6.4"
|
||||
|
@ -1538,7 +1539,7 @@ find-yarn-workspace-root@^2.0.0:
|
|||
dependencies:
|
||||
micromatch "^4.0.2"
|
||||
|
||||
follow-redirects@^1.14.9:
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
|
||||
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
|
||||
|
@ -3086,6 +3087,11 @@ proxy-addr@~2.0.7:
|
|||
forwarded "0.2.0"
|
||||
ipaddr.js "1.9.1"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
psl@^1.1.28:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
"name": "colubrina-cli",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"argon2": "^0.28.7",
|
||||
"axios": "^0.27.2",
|
||||
"argon2": "^0.31.2",
|
||||
"axios": "^1.6.2",
|
||||
"input": "^1.0.1",
|
||||
"mariadb": "^3.0.1",
|
||||
"pg": "^8.7.3",
|
||||
"sequelize": "^6.21.3",
|
||||
"sqlite3": "^5.0.10",
|
||||
"umzug": "^3.1.1"
|
||||
"mariadb": "^3.2.2",
|
||||
"pg": "^8.11.3",
|
||||
"sequelize": "^6.35.1",
|
||||
"sqlite3": "^5.1.6",
|
||||
"umzug": "^3.4.0"
|
||||
}
|
||||
}
|
||||
|
|
310
cli/yarn.lock
310
cli/yarn.lock
|
@ -7,10 +7,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6"
|
||||
integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==
|
||||
|
||||
"@mapbox/node-pre-gyp@^1.0.0", "@mapbox/node-pre-gyp@^1.0.9":
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz#8e6735ccebbb1581e5a7e652244cadc8a844d03c"
|
||||
integrity sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==
|
||||
"@mapbox/node-pre-gyp@^1.0.0", "@mapbox/node-pre-gyp@^1.0.11":
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz#417db42b7f5323d79e93b34a6d7a2a12c0df43fa"
|
||||
integrity sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==
|
||||
dependencies:
|
||||
detect-libc "^2.0.0"
|
||||
https-proxy-agent "^5.0.0"
|
||||
|
@ -44,9 +44,9 @@
|
|||
integrity sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==
|
||||
|
||||
"@rushstack/ts-command-line@^4.12.2":
|
||||
version "4.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.14.0.tgz#1719595bffc61e7a03e1df29a0fd29319f2e4843"
|
||||
integrity sha512-DWozCsKg+ALgrsul+6vJhyB7ZogqSycRlnqULjGsJ9dLRv+Pc0Wj6J7pX0xarmgX2kH3tTf0rXgBcl8QjJULIQ==
|
||||
version "4.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@rushstack/ts-command-line/-/ts-command-line-4.17.1.tgz#c78db928ce5b93f2e98fd9e14c24f3f3876e57f1"
|
||||
integrity sha512-2jweO1O57BYP5qdBGl6apJLB+aRIn5ccIRTPDyULh0KMwVzFqWtw6IZWt1qtUoZD/pD2RNkIOosH6Cq45rIYeg==
|
||||
dependencies:
|
||||
"@types/argparse" "1.0.38"
|
||||
argparse "~1.0.9"
|
||||
|
@ -63,37 +63,39 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/argparse/-/argparse-1.0.38.tgz#a81fd8606d481f873a3800c6ebae4f1d768a56a9"
|
||||
integrity sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==
|
||||
|
||||
"@types/debug@^4.1.7":
|
||||
version "4.1.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.8.tgz#cef723a5d0a90990313faec2d1e22aee5eecb317"
|
||||
integrity sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==
|
||||
"@types/debug@^4.1.8":
|
||||
version "4.1.12"
|
||||
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
|
||||
integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==
|
||||
dependencies:
|
||||
"@types/ms" "*"
|
||||
|
||||
"@types/geojson@^7946.0.10":
|
||||
version "7946.0.10"
|
||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.10.tgz#6dfbf5ea17142f7f9a043809f1cd4c448cb68249"
|
||||
integrity sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==
|
||||
version "7946.0.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.13.tgz#e6e77ea9ecf36564980a861e24e62a095988775e"
|
||||
integrity sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==
|
||||
|
||||
"@types/ms@*":
|
||||
version "0.7.31"
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
|
||||
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==
|
||||
version "0.7.34"
|
||||
resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433"
|
||||
integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==
|
||||
|
||||
"@types/node@*":
|
||||
version "20.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.0.tgz#719498898d5defab83c3560f45d8498f58d11938"
|
||||
integrity sha512-cumHmIAf6On83X7yP+LrsEyUOf/YlociZelmpRYaGFydoaPdxdt80MAbu6vWerQT2COCp2nPvHdsbD7tHn/YlQ==
|
||||
version "20.10.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.10.4.tgz#b246fd84d55d5b1b71bf51f964bd514409347198"
|
||||
integrity sha512-D08YG6rr8X90YB56tSIuBaddy/UXAA9RKJoFvrsnogAum/0pmjkgi4+2nx96A330FmioegBWmEYQ+syqCFaveg==
|
||||
dependencies:
|
||||
undici-types "~5.26.4"
|
||||
|
||||
"@types/node@^17.0.45":
|
||||
version "17.0.45"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
|
||||
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
|
||||
|
||||
"@types/validator@^13.7.1":
|
||||
version "13.7.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.7.17.tgz#0a6d1510395065171e3378a4afc587a3aefa7cc1"
|
||||
integrity sha512-aqayTNmeWrZcvnG2MG9eGYI6b7S5fl+yKgPs6bAjOTwPS316R5SxBGKvtSExfyoJU7pIeHJfsHI0Ji41RVMkvQ==
|
||||
"@types/validator@^13.7.17":
|
||||
version "13.11.7"
|
||||
resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.11.7.tgz#99e19760297667ae46b7069ec8b96cbfe0a08b98"
|
||||
integrity sha512-q0JomTsJ2I5Mv7dhHhQLGjMvX0JJm5dyZ1DXQySIUzU1UlwzB8bt+R6+LODUbz0UDIOvEzGc28tk27gBJw2N8Q==
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.1"
|
||||
|
@ -108,12 +110,10 @@ agent-base@6, agent-base@^6.0.2:
|
|||
debug "4"
|
||||
|
||||
agentkeepalive@^4.1.3:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.3.0.tgz#bb999ff07412653c1803b3ced35e50729830a255"
|
||||
integrity sha512-7Epl1Blf4Sy37j4v9f9FjICCh4+KAQOyXgHEwlyBiAQLbhKdq/i2QQU3amQalS/wPhdPzDXPL5DMR5bkn+YeWg==
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923"
|
||||
integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==
|
||||
dependencies:
|
||||
debug "^4.1.0"
|
||||
depd "^2.0.0"
|
||||
humanize-ms "^1.2.1"
|
||||
|
||||
aggregate-error@^3.0.0:
|
||||
|
@ -165,14 +165,14 @@ are-we-there-yet@^3.0.0:
|
|||
delegates "^1.0.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
argon2@^0.28.7:
|
||||
version "0.28.7"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.28.7.tgz#f6cc1f1c9e3ef5455d2186d4ec5b27cfeda41591"
|
||||
integrity sha512-pvsScM3Fq7b+jolXkZHh8nRQx0uD/WeelnwYPMRpn4pAydoa1gqeL/KRdWAag4Hnu1TJNBTAfqyTjV+ZHwNnYA==
|
||||
argon2@^0.31.2:
|
||||
version "0.31.2"
|
||||
resolved "https://registry.yarnpkg.com/argon2/-/argon2-0.31.2.tgz#bb6590a63b8ff71c4a3a1907572893ff8dd9ffff"
|
||||
integrity sha512-QSnJ8By5Mth60IEte45w9Y7v6bWcQw3YhRtJKKN8oNCxnTLDiv/AXXkDPf2srTMfxFVn3QJdVv2nhXESsUa+Yg==
|
||||
dependencies:
|
||||
"@mapbox/node-pre-gyp" "^1.0.9"
|
||||
"@mapbox/node-pre-gyp" "^1.0.11"
|
||||
"@phc/format" "^1.0.0"
|
||||
node-addon-api "^5.0.0"
|
||||
node-addon-api "^7.0.0"
|
||||
|
||||
argparse@~1.0.9:
|
||||
version "1.0.10"
|
||||
|
@ -186,13 +186,14 @@ asynckit@^0.4.0:
|
|||
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
|
||||
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
|
||||
|
||||
axios@^0.27.2:
|
||||
version "0.27.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
|
||||
integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
|
||||
axios@^1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.2.tgz#de67d42c755b571d3e698df1b6504cde9b0ee9f2"
|
||||
integrity sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.9"
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
babel-runtime@^6.6.1:
|
||||
version "6.26.0"
|
||||
|
@ -321,7 +322,7 @@ core-js@^2.4.0:
|
|||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
debug@4, debug@^4.1.0, debug@^4.3.3:
|
||||
debug@4, debug@^4.3.3, debug@^4.3.4:
|
||||
version "4.3.4"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
|
||||
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
|
||||
|
@ -343,25 +344,20 @@ denque@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1"
|
||||
integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==
|
||||
|
||||
depd@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||
|
||||
detect-libc@^2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd"
|
||||
integrity sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.2.tgz#8ccf2ba9315350e1241b88d0ac3b0e1fbd99605d"
|
||||
integrity sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==
|
||||
|
||||
dottie@^2.0.2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.4.tgz#9ce42965f45e577a6fa7d988d47852fac70c4e82"
|
||||
integrity sha512-iz64WUOmp/ECQhWMJjTWFzJN/wQ7RJ5v/a6A2OiCwjaGCpNo66WGIjlSf+IULO9DQd0b4cFawLOTbiKSrpKodw==
|
||||
dottie@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.6.tgz#34564ebfc6ec5e5772272d466424ad5b696484d4"
|
||||
integrity sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==
|
||||
|
||||
emittery@^0.12.1:
|
||||
version "0.12.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.12.1.tgz#cb9a4a18745816f7a1fa03a8953e7eaededb45f2"
|
||||
integrity sha512-pYyW59MIZo0HxPFf+Vb3+gacUu0gxVS3TZwB2ClwkEZywgF9f9OJDoVmNLojTn0vKX3tO9LC+pdQEcLP4Oz/bQ==
|
||||
emittery@^0.13.0:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
|
||||
integrity sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
|
@ -403,10 +399,10 @@ figures@^1.3.5:
|
|||
escape-string-regexp "^1.0.5"
|
||||
object-assign "^4.1.0"
|
||||
|
||||
follow-redirects@^1.14.9:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.3"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
|
||||
integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
|
@ -417,14 +413,6 @@ form-data@^4.0.0:
|
|||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fs-jetpack@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fs-jetpack/-/fs-jetpack-4.3.1.tgz#cdfd4b64e6bfdec7c7dc55c76b39efaa7853bb20"
|
||||
integrity sha512-dbeOK84F6BiQzk2yqqCVwCPWTxAvVGJ3fMQc6E2wuEohS28mR6yHngbrKuVCK1KHRx/ccByDylqu4H5PCP2urQ==
|
||||
dependencies:
|
||||
minimatch "^3.0.2"
|
||||
rimraf "^2.6.3"
|
||||
|
||||
fs-minipass@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
|
||||
|
@ -557,7 +545,7 @@ infer-owner@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467"
|
||||
integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==
|
||||
|
||||
inflection@^1.13.2:
|
||||
inflection@^1.13.4:
|
||||
version "1.13.4"
|
||||
resolved "https://registry.yarnpkg.com/inflection/-/inflection-1.13.4.tgz#65aa696c4e2da6225b148d7a154c449366633a32"
|
||||
integrity sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==
|
||||
|
@ -636,6 +624,11 @@ lodash@^4.17.21, lodash@^4.3.0, lodash@^4.6.1:
|
|||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
lru-cache@^10.0.1:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484"
|
||||
integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==
|
||||
|
||||
lru-cache@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
|
||||
|
@ -643,11 +636,6 @@ lru-cache@^6.0.0:
|
|||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lru-cache@^7.14.0:
|
||||
version "7.18.3"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
|
||||
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
|
||||
|
||||
make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
|
@ -677,16 +665,16 @@ make-fetch-happen@^9.1.0:
|
|||
socks-proxy-agent "^6.0.0"
|
||||
ssri "^8.0.0"
|
||||
|
||||
mariadb@^3.0.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/mariadb/-/mariadb-3.1.2.tgz#96f9f6c3f280a3a3c37b56ff7974400edbb88bda"
|
||||
integrity sha512-ILlC54fkXkvizTJZC1uP7f/REBxuu1k+OWzpiIITIEdS+dGIjFe/Ob3EW9KrdtBa38l3z+odz6elva0RG/y5og==
|
||||
mariadb@^3.2.2:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.yarnpkg.com/mariadb/-/mariadb-3.2.2.tgz#320a991c708c737e5ddeefa1852ddf925f2dcd8c"
|
||||
integrity sha512-9ClJCFsLcK7WnPXVxuKGd7p0CBvNch3i5nwAf1HEqERj7RV60DG/0dJu4DfO33gpYQd9Cr4jq17O76/2VjSbkg==
|
||||
dependencies:
|
||||
"@types/geojson" "^7946.0.10"
|
||||
"@types/node" "^17.0.45"
|
||||
denque "^2.1.0"
|
||||
iconv-lite "^0.6.3"
|
||||
lru-cache "^7.14.0"
|
||||
lru-cache "^10.0.1"
|
||||
|
||||
mime-db@1.52.0:
|
||||
version "1.52.0"
|
||||
|
@ -700,7 +688,7 @@ mime-types@^2.1.12:
|
|||
dependencies:
|
||||
mime-db "1.52.0"
|
||||
|
||||
minimatch@^3.0.2, minimatch@^3.1.1:
|
||||
minimatch@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
|
@ -778,14 +766,14 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
moment-timezone@^0.5.35:
|
||||
moment-timezone@^0.5.43:
|
||||
version "0.5.43"
|
||||
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.43.tgz#3dd7f3d0c67f78c23cd1906b9b2137a09b3c4790"
|
||||
integrity sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==
|
||||
dependencies:
|
||||
moment "^2.29.4"
|
||||
|
||||
moment@^2.29.1, moment@^2.29.4:
|
||||
moment@^2.29.4:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
|
||||
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
|
||||
|
@ -815,15 +803,15 @@ node-addon-api@^4.2.0:
|
|||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f"
|
||||
integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==
|
||||
|
||||
node-addon-api@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-5.1.0.tgz#49da1ca055e109a23d537e9de43c09cca21eb762"
|
||||
integrity sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==
|
||||
node-addon-api@^7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.0.0.tgz#8136add2f510997b3b94814f4af1cce0b0e3962e"
|
||||
integrity sha512-vgbBJTS4m5/KkE16t5Ly0WW9hz46swAstv0hYYwMtbG7AznRhNyfLRe8HZAiWIpcHzoO7HxhLuBQj9rJ/Ho0ZA==
|
||||
|
||||
node-fetch@^2.6.7:
|
||||
version "2.6.11"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.11.tgz#cde7fc71deef3131ef80a738919f999e6edfff25"
|
||||
integrity sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
|
||||
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==
|
||||
dependencies:
|
||||
whatwg-url "^5.0.0"
|
||||
|
||||
|
@ -909,25 +897,25 @@ path-is-absolute@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
pg-cloudflare@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.0.tgz#833d70870d610d14bf9df7afb40e1cba310c17a0"
|
||||
integrity sha512-tGM8/s6frwuAIyRcJ6nWcIvd3+3NmUKIs6OjviIm1HPPFEt5MzQDOTBQyhPWg/m0kCl95M6gA1JaIXtS8KovOA==
|
||||
pg-cloudflare@^1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz#e6d5833015b170e23ae819e8c5d7eaedb472ca98"
|
||||
integrity sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==
|
||||
|
||||
pg-connection-string@^2.5.0, pg-connection-string@^2.6.0:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.0.tgz#12a36cc4627df19c25cc1b9b736cc39ee1f73ae8"
|
||||
integrity sha512-x14ibktcwlHKoHxx9X3uTVW9zIGR41ZB6QNhHb21OPNdCCO3NaRnpJuwKIQSR4u+Yqjx4HCvy7Hh7VSy1U4dGg==
|
||||
pg-connection-string@^2.6.1, pg-connection-string@^2.6.2:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-2.6.2.tgz#713d82053de4e2bd166fab70cd4f26ad36aab475"
|
||||
integrity sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==
|
||||
|
||||
pg-int8@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
|
||||
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
|
||||
|
||||
pg-pool@^3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.0.tgz#3190df3e4747a0d23e5e9e8045bcd99bda0a712e"
|
||||
integrity sha512-clFRf2ksqd+F497kWFyM21tMjeikn60oGDmqMT8UBrynEwVEX/5R5xd2sdvdo1cZCFlguORNpVuqxIj+aK4cfQ==
|
||||
pg-pool@^3.6.1:
|
||||
version "3.6.1"
|
||||
resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7"
|
||||
integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==
|
||||
|
||||
pg-protocol@^1.6.0:
|
||||
version "1.6.0"
|
||||
|
@ -945,20 +933,20 @@ pg-types@^2.1.0:
|
|||
postgres-date "~1.0.4"
|
||||
postgres-interval "^1.1.0"
|
||||
|
||||
pg@^8.7.3:
|
||||
version "8.11.0"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.0.tgz#a37e534e94b57a7ed811e926f23a7c56385f55d9"
|
||||
integrity sha512-meLUVPn2TWgJyLmy7el3fQQVwft4gU5NGyvV0XbD41iU9Jbg8lCH4zexhIkihDzVHJStlt6r088G6/fWeNjhXA==
|
||||
pg@^8.11.3:
|
||||
version "8.11.3"
|
||||
resolved "https://registry.yarnpkg.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb"
|
||||
integrity sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==
|
||||
dependencies:
|
||||
buffer-writer "2.0.0"
|
||||
packet-reader "1.0.0"
|
||||
pg-connection-string "^2.6.0"
|
||||
pg-pool "^3.6.0"
|
||||
pg-connection-string "^2.6.2"
|
||||
pg-pool "^3.6.1"
|
||||
pg-protocol "^1.6.0"
|
||||
pg-types "^2.1.0"
|
||||
pgpass "1.x"
|
||||
optionalDependencies:
|
||||
pg-cloudflare "^1.1.0"
|
||||
pg-cloudflare "^1.1.1"
|
||||
|
||||
pgpass@1.x:
|
||||
version "1.0.5"
|
||||
|
@ -967,7 +955,7 @@ pgpass@1.x:
|
|||
dependencies:
|
||||
split2 "^4.1.0"
|
||||
|
||||
pony-cause@^2.1.2:
|
||||
pony-cause@^2.1.4:
|
||||
version "2.1.10"
|
||||
resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-2.1.10.tgz#828457ad6f13be401a075dbf14107a9057945174"
|
||||
integrity sha512-3IKLNXclQgkU++2fSi93sQ6BznFuxSLB11HdvZQ6JW/spahf/P1pAHBQEahr20rs0htZW0UDkM1HmA+nZkXKsw==
|
||||
|
@ -1007,6 +995,11 @@ promise-retry@^2.0.1:
|
|||
err-code "^2.0.2"
|
||||
retry "^0.12.0"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
readable-stream@^3.6.0:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
|
||||
|
@ -1038,7 +1031,7 @@ restore-cursor@^1.0.1:
|
|||
exit-hook "^1.0.0"
|
||||
onetime "^1.0.0"
|
||||
|
||||
retry-as-promised@^7.0.3:
|
||||
retry-as-promised@^7.0.4:
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/retry-as-promised/-/retry-as-promised-7.0.4.tgz#9df73adaeea08cb2948b9d34990549dc13d800a2"
|
||||
integrity sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==
|
||||
|
@ -1048,13 +1041,6 @@ retry@^0.12.0:
|
|||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
|
||||
integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==
|
||||
|
||||
rimraf@^2.6.3:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
|
||||
|
@ -1085,14 +1071,14 @@ safe-buffer@~5.2.0:
|
|||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||
|
||||
semver@^6.0.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||
|
||||
semver@^7.3.5:
|
||||
version "7.5.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec"
|
||||
integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==
|
||||
semver@^7.3.5, semver@^7.5.4:
|
||||
version "7.5.4"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
|
||||
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
|
||||
dependencies:
|
||||
lru-cache "^6.0.0"
|
||||
|
||||
|
@ -1101,26 +1087,26 @@ sequelize-pool@^7.1.0:
|
|||
resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-7.1.0.tgz#210b391af4002762f823188fd6ecfc7413020768"
|
||||
integrity sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==
|
||||
|
||||
sequelize@^6.21.3:
|
||||
version "6.32.0"
|
||||
resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.32.0.tgz#566488aa0fcf32c1baa2ff2344f462a4c9eb4a01"
|
||||
integrity sha512-gMd1M6kPANyrCeU/vtgEP5gnse7sVsiKbJyz7p4huuW8zZcRopj47UlglvdrMuIoqksZmsUPfApmMo6ZlJpcvg==
|
||||
sequelize@^6.35.1:
|
||||
version "6.35.1"
|
||||
resolved "https://registry.yarnpkg.com/sequelize/-/sequelize-6.35.1.tgz#e640bc11a7a37f6fa23a92974b5e5ca20affd150"
|
||||
integrity sha512-UlP5k33nJsN11wCDLaWZXw9bB8w4ESKc5QmG6D04qMimwBwKVNeqRJiaaBlEJdtg8cRK+OJh95dliP+uEi+g9Q==
|
||||
dependencies:
|
||||
"@types/debug" "^4.1.7"
|
||||
"@types/validator" "^13.7.1"
|
||||
debug "^4.3.3"
|
||||
dottie "^2.0.2"
|
||||
inflection "^1.13.2"
|
||||
"@types/debug" "^4.1.8"
|
||||
"@types/validator" "^13.7.17"
|
||||
debug "^4.3.4"
|
||||
dottie "^2.0.6"
|
||||
inflection "^1.13.4"
|
||||
lodash "^4.17.21"
|
||||
moment "^2.29.1"
|
||||
moment-timezone "^0.5.35"
|
||||
pg-connection-string "^2.5.0"
|
||||
retry-as-promised "^7.0.3"
|
||||
semver "^7.3.5"
|
||||
moment "^2.29.4"
|
||||
moment-timezone "^0.5.43"
|
||||
pg-connection-string "^2.6.1"
|
||||
retry-as-promised "^7.0.4"
|
||||
semver "^7.5.4"
|
||||
sequelize-pool "^7.1.0"
|
||||
toposort-class "^1.0.1"
|
||||
uuid "^8.3.2"
|
||||
validator "^13.7.0"
|
||||
validator "^13.9.0"
|
||||
wkx "^0.5.0"
|
||||
|
||||
set-blocking@^2.0.0:
|
||||
|
@ -1165,7 +1151,7 @@ sprintf-js@~1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
|
||||
|
||||
sqlite3@^5.0.10:
|
||||
sqlite3@^5.1.6:
|
||||
version "5.1.6"
|
||||
resolved "https://registry.yarnpkg.com/sqlite3/-/sqlite3-5.1.6.tgz#1d4fbc90fe4fbd51e952e0a90fd8f6c2b9098e97"
|
||||
integrity sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==
|
||||
|
@ -1233,9 +1219,9 @@ supports-color@^2.0.0:
|
|||
integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==
|
||||
|
||||
tar@^6.0.2, tar@^6.1.11, tar@^6.1.2:
|
||||
version "6.1.15"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.15.tgz#c9738b0b98845a3b344d334b8fa3041aaba53a69"
|
||||
integrity sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.0.tgz#b14ce49a79cb1cd23bc9b016302dea5474493f73"
|
||||
integrity sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==
|
||||
dependencies:
|
||||
chownr "^2.0.0"
|
||||
fs-minipass "^2.0.0"
|
||||
|
@ -1259,22 +1245,26 @@ tr46@~0.0.3:
|
|||
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
|
||||
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
|
||||
|
||||
type-fest@^2.18.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
|
||||
integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
|
||||
type-fest@^3.0.0:
|
||||
version "3.13.1"
|
||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-3.13.1.tgz#bb744c1f0678bea7543a2d1ec24e83e68e8c8706"
|
||||
integrity sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==
|
||||
|
||||
umzug@^3.1.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/umzug/-/umzug-3.2.1.tgz#01c3a109efb037a10a317d4191be22810c37b195"
|
||||
integrity sha512-XyWQowvP9CKZycKc/Zg9SYWrAWX/gJCE799AUTFqk8yC3tp44K1xWr3LoFF0MNEjClKOo1suCr5ASnoy+KltdA==
|
||||
umzug@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.yarnpkg.com/umzug/-/umzug-3.4.0.tgz#97819a2d2288c8ce2c156c3be8b18b02f2208423"
|
||||
integrity sha512-bTen9ElCBoWU1mhcaXqVZWXxB1PojsBQBs/4vW0YV8f5CfhuhkfRjQZj6SCb6IuHWPkccDzF+T+RGZCYUiXaKg==
|
||||
dependencies:
|
||||
"@rushstack/ts-command-line" "^4.12.2"
|
||||
emittery "^0.12.1"
|
||||
fs-jetpack "^4.3.1"
|
||||
emittery "^0.13.0"
|
||||
glob "^8.0.3"
|
||||
pony-cause "^2.1.2"
|
||||
type-fest "^2.18.0"
|
||||
pony-cause "^2.1.4"
|
||||
type-fest "^3.0.0"
|
||||
|
||||
undici-types@~5.26.4:
|
||||
version "5.26.5"
|
||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||
|
||||
unique-filename@^1.1.1:
|
||||
version "1.1.1"
|
||||
|
@ -1300,10 +1290,10 @@ uuid@^8.3.2:
|
|||
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
|
||||
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
|
||||
|
||||
validator@^13.7.0:
|
||||
version "13.9.0"
|
||||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.9.0.tgz#33e7b85b604f3bbce9bb1a05d5c3e22e1c2ff855"
|
||||
integrity sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==
|
||||
validator@^13.9.0:
|
||||
version "13.11.0"
|
||||
resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b"
|
||||
integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==
|
||||
|
||||
webidl-conversions@^3.0.0:
|
||||
version "3.0.1"
|
||||
|
|
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
es2020: true,
|
||||
node: true
|
||||
},
|
||||
extends: ["plugin:vue/essential", "eslint:recommended"],
|
||||
extends: ["plugin:vue/recommended", "eslint:recommended"],
|
||||
parserOptions: {
|
||||
parser: "@babel/eslint-parser"
|
||||
},
|
||||
|
@ -15,6 +15,7 @@ module.exports = {
|
|||
"error",
|
||||
{ "invalid-first-character-of-tag-name": false }
|
||||
],
|
||||
"vue/no-reserved-component-names": "off",
|
||||
"vue/no-mutating-props": "off",
|
||||
"vue/multi-word-component-names": "off"
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
"private": true,
|
||||
"author": "Troplo <troplo@troplo.com>",
|
||||
"scripts": {
|
||||
"dev": "vue-cli-service serve",
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build --no-clean",
|
||||
"lint": "vue-cli-service lint",
|
||||
|
@ -19,7 +20,7 @@
|
|||
"@babel/preset-env": "^7.17.10",
|
||||
"@mdi/font": "6.5.95",
|
||||
"@mdi/js": "^6.6.95",
|
||||
"axios": "^0.26.1",
|
||||
"axios": "^1.6.2",
|
||||
"brace": "^0.11.1",
|
||||
"chart.js": "^3.7.1",
|
||||
"core-js": "^3.6.5",
|
||||
|
@ -36,12 +37,11 @@
|
|||
"patch-package": "^6.4.7",
|
||||
"prettier": "^2.6.1",
|
||||
"register-service-worker": "^1.7.1",
|
||||
"request": "^2.88.2",
|
||||
"selfsigned": "^2.0.1",
|
||||
"socket.io-client": "^4.5.1",
|
||||
"twemoji": "^14.0.2",
|
||||
"vue": "^2.6.11",
|
||||
"vue-axios": "^3.4.1",
|
||||
"vue-axios": "^3.5.2",
|
||||
"vue-chartjs": "^4.0.1",
|
||||
"vue-final-modal": "^2.4.1",
|
||||
"vue-native-notification": "^1.1.1",
|
||||
|
@ -66,12 +66,12 @@
|
|||
"dotenv-webpack": "^7.1.0",
|
||||
"electron": "^28.0.0",
|
||||
"electron-devtools-installer": "^3.1.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"eslint": "^8.55.0",
|
||||
"eslint-plugin-vue": "^9.19.2",
|
||||
"material-design-icons-iconfont": "^6.5.0",
|
||||
"sass": "~1.32.0",
|
||||
"sass-loader": "^10.0.0",
|
||||
"vue-cli-plugin-electron-builder": "^2.1.1",
|
||||
"vue-cli-plugin-electron-builder": "https://github.com/nklayman/vue-cli-plugin-electron-builder.git#b51147f",
|
||||
"vue-cli-plugin-vuetify": "~2.5.8",
|
||||
"vue-template-babel-compiler": "^1.1.3",
|
||||
"vue-template-compiler": "^2.6.11",
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
"
|
||||
>
|
||||
<v-overlay :value="!$store.state.wsConnected" absolute style="z-index: 69">
|
||||
<v-progress-circular indeterminate size="64"></v-progress-circular>
|
||||
<v-progress-circular indeterminate size="64" />
|
||||
</v-overlay>
|
||||
<DevOverlay v-if="$store.state.site.release === 'dev'"></DevOverlay>
|
||||
<DevOverlay v-if="$store.state.site.release === 'dev'" />
|
||||
<v-overlay :value="$store.state.site.loading">
|
||||
<v-progress-circular indeterminate size="64"></v-progress-circular>
|
||||
<v-progress-circular indeterminate size="64" />
|
||||
</v-overlay>
|
||||
<!-- theme engine editors -->
|
||||
<vue-final-modal
|
||||
|
@ -39,8 +39,8 @@
|
|||
$store.state.themeEngine.type === "create" ? "Creator" : "Editor"
|
||||
}}
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<span v-on="on" v-bind="attrs">
|
||||
<template #activator="{ on, attrs }">
|
||||
<span v-bind="attrs" v-on="on">
|
||||
<v-btn
|
||||
fab
|
||||
small
|
||||
|
@ -54,7 +54,7 @@
|
|||
<span> Randomize theme </span>
|
||||
</v-tooltip>
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="$store.state.themeEngine.editor = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
|
@ -72,27 +72,30 @@
|
|||
$store.dispatch('saveTheme', { theme: null, type: null })
|
||||
$store.state.themeEngine.editor = false
|
||||
"
|
||||
>{{
|
||||
>
|
||||
{{
|
||||
$store.state.themeEngine.type === "create"
|
||||
? "Create & Apply"
|
||||
: "Save Edits"
|
||||
}}</v-btn
|
||||
>
|
||||
}}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="$store.state.themeEngine.type === 'edit'"
|
||||
color="primary"
|
||||
text
|
||||
@click="
|
||||
$store.dispatch('saveTheme', { theme: null, type: 'copy' })
|
||||
"
|
||||
v-if="$store.state.themeEngine.type === 'edit'"
|
||||
>Save a Copy</v-btn
|
||||
>
|
||||
Save a Copy
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="error darken-1"
|
||||
text
|
||||
@click="$store.dispatch('discardTheme')"
|
||||
>Discard</v-btn
|
||||
>
|
||||
Discard
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
<v-form>
|
||||
<v-text-field
|
||||
|
@ -100,28 +103,23 @@
|
|||
class="mx-3"
|
||||
label="Theme Name"
|
||||
required
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-select
|
||||
v-model="$store.state.themeEngine.theme.primaryType"
|
||||
:items="intendedFor"
|
||||
label="Intended for"
|
||||
class="mx-3"
|
||||
v-model="$store.state.themeEngine.theme.primaryType"
|
||||
>
|
||||
</v-select>
|
||||
<v-text-field
|
||||
v-model="creatorJSON"
|
||||
label="JSON"
|
||||
class="mx-3"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-text-field v-model="creatorJSON" label="JSON" class="mx-3" />
|
||||
<v-btn @click="$store.state.themeEngine.cssEditor = true">
|
||||
Custom CSS
|
||||
</v-btn>
|
||||
<h2
|
||||
class="ml-2 mt-2 mb-3"
|
||||
v-if="
|
||||
$store.state.themeEngine.theme.primaryType === 'dark' ||
|
||||
$store.state.themeEngine.theme.primaryType === 'all'
|
||||
"
|
||||
class="ml-2 mt-2 mb-3"
|
||||
>
|
||||
Dark:
|
||||
</h2>
|
||||
|
@ -132,44 +130,44 @@
|
|||
"
|
||||
>
|
||||
<v-col
|
||||
sm="3"
|
||||
v-for="(item, index) in $store.state.themeEngine.theme.dark"
|
||||
:key="index + '-dark-card'"
|
||||
sm="3"
|
||||
>
|
||||
<v-card color="card">
|
||||
<h3 class="ml-2 mt-2 mb-2">
|
||||
{{ friendlyName(index) }}
|
||||
</h3>
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-card
|
||||
class="mb-2 mx-2"
|
||||
:color="$store.state.themeEngine.theme.dark[index]"
|
||||
v-on="on"
|
||||
>
|
||||
<v-container></v-container>
|
||||
<v-container />
|
||||
</v-card>
|
||||
</template>
|
||||
<v-color-picker
|
||||
v-model="$store.state.themeEngine.theme.dark[index]"
|
||||
show-swatches
|
||||
hide-inputs
|
||||
></v-color-picker>
|
||||
/>
|
||||
</v-menu>
|
||||
<v-text-field
|
||||
v-model="$store.state.themeEngine.theme.dark[index]"
|
||||
class="mx-2"
|
||||
label="#HEX"
|
||||
v-model="$store.state.themeEngine.theme.dark[index]"
|
||||
></v-text-field>
|
||||
/>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<h2
|
||||
class="ml-2 mt-2 mb-3"
|
||||
v-if="
|
||||
$store.state.themeEngine.theme.primaryType === 'light' ||
|
||||
$store.state.themeEngine.theme.primaryType === 'all'
|
||||
"
|
||||
class="ml-2 mt-2 mb-3"
|
||||
>
|
||||
Light:
|
||||
</h2>
|
||||
|
@ -180,35 +178,35 @@
|
|||
"
|
||||
>
|
||||
<v-col
|
||||
sm="3"
|
||||
v-for="(item, index) in $store.state.themeEngine.theme.light"
|
||||
:key="index + '-light-card'"
|
||||
sm="3"
|
||||
>
|
||||
<v-card color="card">
|
||||
<h3 class="ml-2 mt-2 mb-2">
|
||||
{{ friendlyName(index) }}
|
||||
</h3>
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-card
|
||||
class="mb-2 mx-2"
|
||||
:color="$store.state.themeEngine.theme.light[index]"
|
||||
v-on="on"
|
||||
>
|
||||
<v-container></v-container>
|
||||
<v-container />
|
||||
</v-card>
|
||||
</template>
|
||||
<v-color-picker
|
||||
v-model="$store.state.themeEngine.theme.light[index]"
|
||||
show-swatches
|
||||
hide-inputs
|
||||
></v-color-picker>
|
||||
/>
|
||||
</v-menu>
|
||||
<v-text-field
|
||||
v-model="$store.state.themeEngine.theme.light[index]"
|
||||
class="mx-2"
|
||||
label="#HEX"
|
||||
v-model="$store.state.themeEngine.theme.light[index]"
|
||||
></v-text-field>
|
||||
/>
|
||||
</v-card>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
@ -221,27 +219,30 @@
|
|||
$store.dispatch('saveTheme', { theme: null, type: null })
|
||||
$store.state.themeEngine.editor = false
|
||||
"
|
||||
>{{
|
||||
>
|
||||
{{
|
||||
$store.state.themeEngine.type === "create"
|
||||
? "Create & Apply"
|
||||
: "Save Edits"
|
||||
}}</v-btn
|
||||
>
|
||||
}}
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="$store.state.themeEngine.type === 'edit'"
|
||||
color="primary"
|
||||
text
|
||||
@click="
|
||||
$store.dispatch('saveTheme', { theme: null, type: 'copy' })
|
||||
"
|
||||
v-if="$store.state.themeEngine.type === 'edit'"
|
||||
>Save a Copy</v-btn
|
||||
>
|
||||
Save a Copy
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="error darken-1"
|
||||
text
|
||||
@click="$store.dispatch('discardTheme')"
|
||||
>Discard</v-btn
|
||||
>
|
||||
Discard
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-container>
|
||||
</v-card>
|
||||
|
@ -271,7 +272,7 @@
|
|||
>
|
||||
<v-card-title color="toolbar" class="editor__toolbar v-toolbar">
|
||||
<v-toolbar-title>CSS Editor</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="$store.state.themeEngine.cssEditor = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
|
@ -281,13 +282,13 @@
|
|||
<v-col>
|
||||
<v-alert type="info" text class="editor__toolbar">
|
||||
CTRL + ALT + D / F9 will toggle all custom CSS styling, works
|
||||
anywhere, even outside the editor.</v-alert
|
||||
>
|
||||
anywhere, even outside the editor.
|
||||
</v-alert>
|
||||
<v-switch
|
||||
v-model="$store.state.themeEngine.autoCSS"
|
||||
inset
|
||||
label="Live update"
|
||||
v-model="$store.state.themeEngine.autoCSS"
|
||||
></v-switch>
|
||||
/>
|
||||
<v-btn
|
||||
icon
|
||||
class="mb-2"
|
||||
|
@ -306,26 +307,26 @@
|
|||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
<editor
|
||||
class="editor"
|
||||
v-model="$store.state.themeEngine.theme.css"
|
||||
@init="editorInit"
|
||||
class="editor"
|
||||
lang="css"
|
||||
:theme="$vuetify.theme.dark ? 'monokai' : 'chrome'"
|
||||
height="350"
|
||||
></editor>
|
||||
@init="editorInit"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col v-if="cssTips">
|
||||
<v-card-title>
|
||||
Tips
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="cssTips = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn></v-card-title
|
||||
>
|
||||
</v-btn>
|
||||
</v-card-title>
|
||||
<v-alert type="error" text>
|
||||
This is an alert.<br />
|
||||
Try to style it with .v-alert</v-alert
|
||||
>
|
||||
Try to style it with .v-alert
|
||||
</v-alert>
|
||||
Here's an example:<br />
|
||||
<code class="block"
|
||||
>.v-alert {<br />
|
||||
|
@ -334,15 +335,17 @@
|
|||
<v-btn
|
||||
class="mt-2 mr-2"
|
||||
@click="$toast.success('I have been pressed.')"
|
||||
>Here's a button</v-btn
|
||||
>
|
||||
Here's a button
|
||||
</v-btn>
|
||||
<v-btn
|
||||
class="mt-2"
|
||||
text
|
||||
color="info"
|
||||
@click="$toast.info('This is the second button\'s action.')"
|
||||
>Here's another one</v-btn
|
||||
>
|
||||
Here's another one
|
||||
</v-btn>
|
||||
<v-card-title> Fonts </v-card-title>
|
||||
<code
|
||||
class="block"
|
||||
|
@ -392,9 +395,8 @@
|
|||
</v-toolbar>
|
||||
<v-container v-if="$store.state.modals.search">
|
||||
<v-autocomplete
|
||||
@keydown.enter="handleEnter"
|
||||
auto-select-first
|
||||
v-model="search"
|
||||
auto-select-first
|
||||
:items="$store.state.quickSwitchCache"
|
||||
item-text="subjectLongName"
|
||||
label="Search"
|
||||
|
@ -402,13 +404,13 @@
|
|||
autofocus
|
||||
return-object
|
||||
:search-input.sync="searchInput"
|
||||
>
|
||||
</v-autocomplete>
|
||||
@keydown.enter="handleEnter"
|
||||
/>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-main>
|
||||
<Header></Header>
|
||||
<Header />
|
||||
<v-container
|
||||
v-if="
|
||||
$store.state.site.latestVersion > $store.state.versioning.version &&
|
||||
|
@ -453,7 +455,6 @@
|
|||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
<style></style>
|
||||
<script>
|
||||
import AjaxErrorHandler from "@/lib/errorHandler.js"
|
||||
import { VueFinalModal } from "vue-final-modal"
|
||||
|
@ -529,6 +530,123 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"$store.state.userPanel"(val) {
|
||||
localStorage.setItem("userPanel", val)
|
||||
},
|
||||
cssTips(val) {
|
||||
localStorage.setItem("cssTipsDismissed", !val)
|
||||
},
|
||||
"$store.state.themeEngine.theme": {
|
||||
handler() {
|
||||
this.$vuetify.theme.themes.dark =
|
||||
this.$store.state.themeEngine.theme.dark
|
||||
this.$vuetify.theme.themes.light =
|
||||
this.$store.state.themeEngine.theme.light
|
||||
this.$vuetify.theme.themes.name = this.$store.state.themeEngine.theme.id
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
"$store.state.themeEngine.theme.css"() {
|
||||
if (this.$store.state.themeEngine.autoCSS) {
|
||||
this.$store.dispatch("applyCSS", null)
|
||||
}
|
||||
},
|
||||
"$store.state.user.theme": {
|
||||
handler() {
|
||||
if (this.$store.state.user?.theme) {
|
||||
this.$vuetify.theme.dark = this.$store.state.user.theme === "dark"
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
$route(to, from) {
|
||||
document.title = to.name + " - " + this.$store.state.site.name
|
||||
this.$store.state.lastRoute = from.path
|
||||
},
|
||||
search() {
|
||||
if (this.search) {
|
||||
if (this.search.id) {
|
||||
this.$router.push("/communications/" + this.search.id)
|
||||
this.$store.commit("setSearch", false)
|
||||
this.search = null
|
||||
this.$nextTick(() => {
|
||||
this.searchInput = null
|
||||
})
|
||||
} else if (this.search.customType === 1) {
|
||||
this.$router.push(this.search.route)
|
||||
this.$store.commit("setSearch", false)
|
||||
this.search = null
|
||||
this.$nextTick(() => {
|
||||
this.searchInput = null
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (localStorage.getItem("forceEnableDevMode"))
|
||||
this.$store.state.release = "dev"
|
||||
await this.$store.dispatch("doInit")
|
||||
if (this.$vuetify.breakpoint.mobile) {
|
||||
this.$store.state.drawer = false
|
||||
}
|
||||
if (localStorage.getItem("cssTipsDismissed")) {
|
||||
this.cssTips = false
|
||||
}
|
||||
if (localStorage.getItem("userPanel")) {
|
||||
this.$store.state.userPanel = JSON.parse(
|
||||
localStorage.getItem("userPanel")
|
||||
)
|
||||
} else {
|
||||
this.$store.state.userPanel = true
|
||||
}
|
||||
if (this.$vuetify.breakpoint.mobile) {
|
||||
this.$store.state.userPanel = false
|
||||
}
|
||||
window.addEventListener("offline", () => {
|
||||
this.$store.commit("setOnline", false)
|
||||
this.$store.dispatch("getState")
|
||||
})
|
||||
window.addEventListener("online", () => {
|
||||
this.$store.commit("setOnline", true)
|
||||
this.$store.dispatch("getState")
|
||||
this.$store.dispatch("getUserInfo")
|
||||
})
|
||||
this.$socket.connect()
|
||||
this.$socket.on("unauthorized", () => {
|
||||
console.log("Reauth requested")
|
||||
this.$socket.emit("token", localStorage.getItem("token"))
|
||||
})
|
||||
document.title = this.$route.name
|
||||
? this.$route.name + " - " + this.$store.state.site.name
|
||||
: this.$store.state.site.name || "Colubrina"
|
||||
this.$store.commit("setLoading", true)
|
||||
this.$vuetify.theme.dark = this.$store.state.user?.theme === "dark" || true
|
||||
this.$store.dispatch("getState")
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
console.log(window.location.pathname)
|
||||
if (
|
||||
!window.location.pathname.includes("/email/confirm/") &&
|
||||
!window.location.pathname.includes("/email/verify") &&
|
||||
!this.$store.state.user.emailVerified &&
|
||||
this.$store.state.site.emailVerification
|
||||
) {
|
||||
this.$router.push("/email/verify")
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.dispatch("logout")
|
||||
if (!window.location.pathname.includes("/reset")) {
|
||||
this.$router.push("/login")
|
||||
}
|
||||
})
|
||||
this.getThemes()
|
||||
this.communicationsIdleCheck()
|
||||
this.registerSocket()
|
||||
},
|
||||
methods: {
|
||||
handleEnter() {
|
||||
if (
|
||||
|
@ -766,126 +884,10 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
if (localStorage.getItem("forceEnableDevMode"))
|
||||
this.$store.state.release = "dev"
|
||||
await this.$store.dispatch("doInit")
|
||||
if (this.$vuetify.breakpoint.mobile) {
|
||||
this.$store.state.drawer = false
|
||||
}
|
||||
if (localStorage.getItem("cssTipsDismissed")) {
|
||||
this.cssTips = false
|
||||
}
|
||||
if (localStorage.getItem("userPanel")) {
|
||||
this.$store.state.userPanel = JSON.parse(
|
||||
localStorage.getItem("userPanel")
|
||||
)
|
||||
} else {
|
||||
this.$store.state.userPanel = true
|
||||
}
|
||||
if (this.$vuetify.breakpoint.mobile) {
|
||||
this.$store.state.userPanel = false
|
||||
}
|
||||
window.addEventListener("offline", () => {
|
||||
this.$store.commit("setOnline", false)
|
||||
this.$store.dispatch("getState")
|
||||
})
|
||||
window.addEventListener("online", () => {
|
||||
this.$store.commit("setOnline", true)
|
||||
this.$store.dispatch("getState")
|
||||
this.$store.dispatch("getUserInfo")
|
||||
})
|
||||
this.$socket.connect()
|
||||
this.$socket.on("unauthorized", () => {
|
||||
console.log("Reauth requested")
|
||||
this.$socket.emit("token", localStorage.getItem("token"))
|
||||
})
|
||||
document.title = this.$route.name
|
||||
? this.$route.name + " - " + this.$store.state.site.name
|
||||
: this.$store.state.site.name || "Colubrina"
|
||||
this.$store.commit("setLoading", true)
|
||||
this.$vuetify.theme.dark = this.$store.state.user?.theme === "dark" || true
|
||||
this.$store.dispatch("getState")
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
console.log(window.location.pathname)
|
||||
if (
|
||||
!window.location.pathname.includes("/email/confirm/") &&
|
||||
!window.location.pathname.includes("/email/verify") &&
|
||||
!this.$store.state.user.emailVerified &&
|
||||
this.$store.state.site.emailVerification
|
||||
) {
|
||||
this.$router.push("/email/verify")
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.dispatch("logout")
|
||||
if (!window.location.pathname.includes("/reset")) {
|
||||
this.$router.push("/login")
|
||||
}
|
||||
})
|
||||
this.getThemes()
|
||||
this.communicationsIdleCheck()
|
||||
this.registerSocket()
|
||||
},
|
||||
watch: {
|
||||
"$store.state.userPanel"(val) {
|
||||
localStorage.setItem("userPanel", val)
|
||||
},
|
||||
cssTips(val) {
|
||||
localStorage.setItem("cssTipsDismissed", !val)
|
||||
},
|
||||
"$store.state.themeEngine.theme": {
|
||||
handler() {
|
||||
this.$vuetify.theme.themes.dark =
|
||||
this.$store.state.themeEngine.theme.dark
|
||||
this.$vuetify.theme.themes.light =
|
||||
this.$store.state.themeEngine.theme.light
|
||||
this.$vuetify.theme.themes.name = this.$store.state.themeEngine.theme.id
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
"$store.state.themeEngine.theme.css"() {
|
||||
if (this.$store.state.themeEngine.autoCSS) {
|
||||
this.$store.dispatch("applyCSS", null)
|
||||
}
|
||||
},
|
||||
"$store.state.user.theme": {
|
||||
handler() {
|
||||
if (this.$store.state.user?.theme) {
|
||||
this.$vuetify.theme.dark = this.$store.state.user.theme === "dark"
|
||||
}
|
||||
},
|
||||
deep: true
|
||||
},
|
||||
$route(to, from) {
|
||||
document.title = to.name + " - " + this.$store.state.site.name
|
||||
this.$store.state.lastRoute = from.path
|
||||
},
|
||||
search() {
|
||||
if (this.search) {
|
||||
if (this.search.id) {
|
||||
this.$router.push("/communications/" + this.search.id)
|
||||
this.$store.commit("setSearch", false)
|
||||
this.search = null
|
||||
this.$nextTick(() => {
|
||||
this.searchInput = null
|
||||
})
|
||||
} else if (this.search.customType === 1) {
|
||||
this.$router.push(this.search.route)
|
||||
this.$store.commit("setSearch", false)
|
||||
this.search = null
|
||||
this.$nextTick(() => {
|
||||
this.searchInput = null
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
<style scoped>
|
||||
::v-deep .modal-container {
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
padding: 10px;
|
||||
cursor: move;
|
||||
z-index: 2001;
|
||||
background-color: #2196F3;
|
||||
background-color: #2196f3;
|
||||
}
|
||||
|
||||
.chat-col {
|
||||
|
@ -28,7 +28,7 @@
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
>>>.max-v-list-height {
|
||||
>>> .max-v-list-height {
|
||||
max-height: 10px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
@ -89,8 +89,8 @@ img.emoji {
|
|||
pointer-events: none;
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('./fonts/JetBrainsMono-Regular.ttf') format('truetype');
|
||||
font-family: "JetBrains Mono";
|
||||
src: url("./fonts/JetBrainsMono-Regular.ttf") format("truetype");
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,8 @@
|
|||
</v-toolbar>
|
||||
<v-card-text>
|
||||
<v-container fluid>
|
||||
<v-text-field v-model="poll.title" label="Title"></v-text-field>
|
||||
<v-textarea
|
||||
v-model="poll.description"
|
||||
label="Description"
|
||||
></v-textarea>
|
||||
<v-text-field v-model="poll.title" label="Title" />
|
||||
<v-textarea v-model="poll.description" label="Description" />
|
||||
<v-text-field
|
||||
v-for="(value, index) in poll.options"
|
||||
:key="index"
|
||||
|
@ -20,19 +17,19 @@
|
|||
:maxlength="30"
|
||||
:append-outer-icon="poll.options.length > 2 ? 'mdi-close' : ''"
|
||||
@click:append-outer="poll.options.splice(index, 1)"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-btn
|
||||
@click="poll.options.push('')"
|
||||
v-if="poll.options.length <= 3"
|
||||
text
|
||||
block
|
||||
@click="poll.options.push('')"
|
||||
>
|
||||
<v-icon> mdi-plus </v-icon>
|
||||
</v-btn>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="red" text @click="poll.dialog = false"> Cancel </v-btn>
|
||||
<v-btn
|
||||
color="blue darken-1"
|
||||
|
@ -48,27 +45,27 @@
|
|||
</v-card>
|
||||
</v-dialog>
|
||||
<v-toolbar
|
||||
v-for="(embed, index) in embeds"
|
||||
:key="index"
|
||||
elevation="0"
|
||||
outlined
|
||||
height="40"
|
||||
color="card"
|
||||
v-for="(embed, index) in embeds"
|
||||
style="cursor: pointer; overflow: hidden"
|
||||
class="mb-2"
|
||||
:key="index"
|
||||
>
|
||||
<v-toolbar-title>
|
||||
<v-icon> mdi-attachment </v-icon>
|
||||
{{ embedName(embed.type) }}
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="embeds.splice(index, 1)" small>
|
||||
<v-spacer />
|
||||
<v-btn icon small @click="embeds.splice(index, 1)">
|
||||
<v-icon> mdi-close </v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-progress-linear
|
||||
v-model="uploadPercentage"
|
||||
v-if="uploading"
|
||||
v-model="uploadPercentage"
|
||||
height="15"
|
||||
color="toolbar"
|
||||
disabled
|
||||
|
@ -77,11 +74,11 @@
|
|||
<small>{{ uploadPercentage }}%</small>
|
||||
</v-progress-linear>
|
||||
<v-toolbar
|
||||
v-if="file"
|
||||
elevation="0"
|
||||
outlined
|
||||
height="40"
|
||||
color="card"
|
||||
v-if="file"
|
||||
style="cursor: pointer; overflow: hidden"
|
||||
class="mb-2"
|
||||
>
|
||||
|
@ -89,12 +86,14 @@
|
|||
<v-icon> mdi-attachment </v-icon>
|
||||
{{ file.name }}
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="file = null" small>
|
||||
<v-spacer />
|
||||
<v-btn icon small @click="file = null">
|
||||
<v-icon> mdi-close </v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-textarea
|
||||
:id="edit ? 'edit-input' : 'message-input'"
|
||||
ref="message-input"
|
||||
:style="
|
||||
!$vuetify.breakpoint.mobile
|
||||
? 'margin-bottom: 5px'
|
||||
|
@ -103,12 +102,15 @@
|
|||
autofocus
|
||||
label="Type a message"
|
||||
placeholder="Keep it civil"
|
||||
v-model="message"
|
||||
type="text"
|
||||
ref="message-input"
|
||||
:id="edit ? 'edit-input' : 'message-input'"
|
||||
outlined
|
||||
append-outer-icon="mdi-send"
|
||||
auto-grow
|
||||
rows="1"
|
||||
single-line
|
||||
dense
|
||||
hide-details
|
||||
@keyup.up="handleEditMessage"
|
||||
@keyup.esc="handleEsc"
|
||||
@click:append-outer="handleMessage()"
|
||||
|
@ -118,27 +120,22 @@
|
|||
completions = []
|
||||
completionWord = ''
|
||||
"
|
||||
v-model="message"
|
||||
@paste="handlePaste"
|
||||
rows="1"
|
||||
single-line
|
||||
dense
|
||||
hide-details
|
||||
@keydown.enter.shift.exact.prevent="newLine($event)"
|
||||
>
|
||||
<template v-slot:append-outer>
|
||||
<template #append-outer>
|
||||
<v-btn
|
||||
v-if="!edit"
|
||||
icon
|
||||
small
|
||||
@click="handleMessage()"
|
||||
v-if="!edit"
|
||||
:retain-focus-on-click="false"
|
||||
class="no-focus"
|
||||
@click="handleMessage()"
|
||||
>
|
||||
<v-icon> mdi-send </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<template v-slot:prepend-inner>
|
||||
<template #prepend-inner>
|
||||
<v-menu
|
||||
:nudge-top="10"
|
||||
:nudge-left="5"
|
||||
|
@ -148,13 +145,13 @@
|
|||
offset-y
|
||||
top
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
id="attachment-button"
|
||||
icon
|
||||
style="margin-top: -3px; margin-left: -4px"
|
||||
small
|
||||
v-on="on"
|
||||
@dblclick.stop="openFileInput"
|
||||
>
|
||||
<v-icon>mdi-plus-circle</v-icon>
|
||||
|
@ -168,21 +165,22 @@
|
|||
</v-list-item>
|
||||
<v-list-item @click="openFileInput">
|
||||
<v-file-input
|
||||
v-if="!edit"
|
||||
ref="file-input"
|
||||
v-model="file"
|
||||
style="margin-top: -10px"
|
||||
single-line
|
||||
hide-input
|
||||
v-model="file"
|
||||
@change="getURLForImage"
|
||||
v-if="!edit"
|
||||
ref="file-input"
|
||||
st
|
||||
></v-file-input>
|
||||
@change="getURLForImage"
|
||||
/>
|
||||
Upload a file
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
</v-menu>
|
||||
<v-menu
|
||||
v-if="false"
|
||||
:nudge-top="10"
|
||||
:nudge-left="5"
|
||||
:close-delay="100"
|
||||
|
@ -190,19 +188,18 @@
|
|||
bottom
|
||||
offset-y
|
||||
top
|
||||
v-if="false"
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
id="emoji-button"
|
||||
icon
|
||||
v-on="on"
|
||||
style="
|
||||
margin-top: -2px;
|
||||
margin-left: 1px;
|
||||
filter: grayscale(100%);
|
||||
"
|
||||
small
|
||||
v-on="on"
|
||||
@dblclick.stop="openFileInput"
|
||||
>
|
||||
<img
|
||||
|
@ -230,11 +227,10 @@
|
|||
v-for="emoji in emojisByCategory[category]"
|
||||
:key="emoji.emoji"
|
||||
sm="4"
|
||||
v-html="twemoji(emoji.emoji)"
|
||||
@click="addEmoji(emoji.emoji)"
|
||||
style="cursor: pointer"
|
||||
>
|
||||
</v-col>
|
||||
@click="addEmoji(emoji.emoji)"
|
||||
v-html="twemoji(emoji.emoji)"
|
||||
/>
|
||||
</v-row>
|
||||
</v-container>
|
||||
</v-card>
|
||||
|
@ -304,6 +300,16 @@ export default {
|
|||
completionWord: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.handleChange()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.edit) {
|
||||
this.message = this.edit.content
|
||||
}
|
||||
},
|
||||
/*
|
||||
computed: {
|
||||
emojis() {
|
||||
|
@ -582,16 +588,6 @@ export default {
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.edit) {
|
||||
this.message = this.edit.content
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
message() {
|
||||
this.handleChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<div class="dev-overlay" id="dev-overlay">
|
||||
<div class="dev-header" id="dev-header">Colubrina DevTools</div>
|
||||
<div id="dev-overlay" class="dev-overlay">
|
||||
<div id="dev-header" class="dev-header">Colubrina DevTools</div>
|
||||
<v-container>
|
||||
<v-btn @click="benchmark"
|
||||
>Benchmark
|
||||
<template v-if="isBenchmarking">({{ multiplier }}x)</template></v-btn
|
||||
<v-btn @click="benchmark">
|
||||
Benchmark
|
||||
<template v-if="isBenchmarking"> ({{ multiplier }}x) </template> </v-btn
|
||||
><br />
|
||||
<template v-if="isBenchmarking"
|
||||
>Please restart the Colubrina server to stop the benchmark.</template
|
||||
<template v-if="isBenchmarking">
|
||||
Please restart the Colubrina server to stop the benchmark. </template
|
||||
><br />
|
||||
<v-btn @click="deleteBenchmark">Delete benchuser messages</v-btn>
|
||||
<v-btn @click="deleteBenchmark"> Delete benchuser messages </v-btn>
|
||||
</v-container>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -24,6 +24,9 @@ export default {
|
|||
multiplier: 0
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.drag(document.getElementById("dev-overlay"))
|
||||
},
|
||||
methods: {
|
||||
deleteBenchmark() {
|
||||
this.axios.delete("/api/v1/debug/bench").catch((e) => {
|
||||
|
@ -81,9 +84,6 @@ export default {
|
|||
document.onmousemove = null
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.drag(document.getElementById("dev-overlay"))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,32 +1,29 @@
|
|||
<template>
|
||||
<span>
|
||||
<v-card
|
||||
v-if="embed.type === 'image'"
|
||||
:min-width="!$vuetify.breakpoint.mobile ? 400 : 0"
|
||||
:max-width="500"
|
||||
elevation="0"
|
||||
color="card"
|
||||
v-if="embed.type === 'image'"
|
||||
>
|
||||
<v-hover v-slot="{ hover }">
|
||||
<div>
|
||||
<v-img
|
||||
@click="setImagePreview(embed)"
|
||||
contain
|
||||
:max-width="500"
|
||||
:max-height="500"
|
||||
:min-height="250"
|
||||
:min-width="250"
|
||||
:src="$store.state.baseURL + embed.mediaProxyLink"
|
||||
@click="setImagePreview(embed)"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<template #placeholder>
|
||||
<v-row class="fill-height ma-0" align="center" justify="center">
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="grey lighten-5"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular indeterminate color="grey lighten-5" />
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<template #default>
|
||||
<v-fade-transition v-if="hover">
|
||||
<v-overlay absolute>
|
||||
<v-icon large>mdi-arrow-expand-all</v-icon>
|
||||
|
@ -48,9 +45,9 @@
|
|||
<v-container fluid>
|
||||
<v-row v-if="embed.type === 'openGraph'">
|
||||
<v-col
|
||||
v-if="embed.openGraph.ogImage"
|
||||
cols="12"
|
||||
class="text-xs-center"
|
||||
v-if="embed.openGraph.ogImage"
|
||||
>
|
||||
<v-img
|
||||
:src="
|
||||
|
@ -60,12 +57,9 @@
|
|||
contain
|
||||
:aspect-ratio="16 / 9"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<template #placeholder>
|
||||
<v-row class="fill-height ma-0" align="center" justify="center">
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="grey lighten-5"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular indeterminate color="grey lighten-5" />
|
||||
</v-row>
|
||||
</template>
|
||||
</v-img>
|
||||
|
@ -85,7 +79,7 @@
|
|||
</v-col>
|
||||
</v-row>
|
||||
<v-row v-else-if="embed.type === 'embed-v1'">
|
||||
<v-col cols="12" class="text-xs-center" v-if="embed.headerImage">
|
||||
<v-col v-if="embed.headerImage" cols="12" class="text-xs-center">
|
||||
<v-img
|
||||
:src="
|
||||
embed.openGraph.headerImage?.url ||
|
||||
|
@ -95,12 +89,9 @@
|
|||
contain
|
||||
:aspect-ratio="16 / 9"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<template #placeholder>
|
||||
<v-row class="fill-height ma-0" align="center" justify="center">
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
color="grey lighten-5"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular indeterminate color="grey lighten-5" />
|
||||
</v-row>
|
||||
</template>
|
||||
</v-img>
|
||||
|
@ -121,17 +112,17 @@
|
|||
{{ graph.name }}
|
||||
</h3>
|
||||
<Chart
|
||||
:chart-data="graph.data"
|
||||
v-if="graph.data"
|
||||
:chart-data="graph.data"
|
||||
:options="graphOptions"
|
||||
></Chart>
|
||||
/>
|
||||
<p v-else>Chart data could not be loaded.</p>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<v-row
|
||||
v-for="(field, index) in embed.fields"
|
||||
:key="'field-' + index"
|
||||
:id="'field-' + index"
|
||||
:key="'field-' + index"
|
||||
class="mt-1"
|
||||
>
|
||||
<v-col
|
||||
|
@ -144,8 +135,8 @@
|
|||
</v-col>
|
||||
</v-row>
|
||||
<a
|
||||
:href="embed.link.url"
|
||||
v-if="embed.link"
|
||||
:href="embed.link.url"
|
||||
target="_blank"
|
||||
style="text-decoration: none"
|
||||
>
|
||||
|
@ -193,10 +184,10 @@ ChartJS.register(
|
|||
|
||||
export default {
|
||||
name: "Embed",
|
||||
props: ["embed", "setImagePreview"],
|
||||
components: {
|
||||
Chart
|
||||
}
|
||||
},
|
||||
props: ["embed", "setImagePreview"]
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
class="rounded-l"
|
||||
style="z-index: 20"
|
||||
>
|
||||
<v-list class="rounded-l" v-if="context.user.item">
|
||||
<v-list v-if="context.user.item" class="rounded-l">
|
||||
<v-menu
|
||||
:nudge-right="10"
|
||||
:close-delay="100"
|
||||
|
@ -20,42 +20,43 @@
|
|||
offset-x
|
||||
open-on-hover
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-title>Notification Settings</v-list-item-title
|
||||
><v-icon class="ml-2">mdi-arrow-right</v-icon>
|
||||
><v-icon class="ml-2"> mdi-arrow-right </v-icon>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<div>
|
||||
<v-list>
|
||||
<v-list-item @click="setNotifications('all')">
|
||||
<v-list-item-title>All messages</v-list-item-title>
|
||||
<v-icon v-if="context.user.raw.notifications === 'all'"
|
||||
>mdi-check</v-icon
|
||||
>
|
||||
<v-icon v-if="context.user.raw.notifications === 'all'">
|
||||
mdi-check
|
||||
</v-icon>
|
||||
</v-list-item>
|
||||
<v-list-item two-line @click="setNotifications('mentions')">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title
|
||||
>Mentions only
|
||||
<v-list-item-title>
|
||||
Mentions only
|
||||
<v-icon
|
||||
style="float: right"
|
||||
v-if="context.user.raw.notifications === 'mentions'"
|
||||
>mdi-check</v-icon
|
||||
></v-list-item-title
|
||||
>
|
||||
style="float: right"
|
||||
>
|
||||
mdi-check
|
||||
</v-icon>
|
||||
</v-list-item-title>
|
||||
|
||||
<v-list-item-subtitle
|
||||
>Mentions are performed when your username is sent in the
|
||||
chat.</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle>
|
||||
Mentions are performed when your username is sent in the
|
||||
chat.
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item @click="setNotifications('none')">
|
||||
<v-list-item-title>None</v-list-item-title>
|
||||
<v-icon v-if="context.user.raw.notifications === 'none'"
|
||||
>mdi-check</v-icon
|
||||
>
|
||||
<v-icon v-if="context.user.raw.notifications === 'none'">
|
||||
mdi-check
|
||||
</v-icon>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</div>
|
||||
|
@ -72,22 +73,22 @@
|
|||
<v-list-item @click="groupSettings(context.user.raw.id)">
|
||||
<v-list-item-title>Group Settings</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="groupLeave(context.user.raw.id)" color="error">
|
||||
<v-list-item color="error" @click="groupLeave(context.user.raw.id)">
|
||||
<v-list-item-title>Leave Group</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-dialog
|
||||
v-if="settings.item"
|
||||
v-model="settings.addMembers.dialog"
|
||||
max-width="400px"
|
||||
v-if="settings.item"
|
||||
>
|
||||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title
|
||||
>Add User to {{ settings.item.chat.name }}</v-toolbar-title
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-toolbar-title>
|
||||
Add User to {{ settings.item.chat.name }}
|
||||
</v-toolbar-title>
|
||||
<v-spacer />
|
||||
<v-btn icon @click.native="settings.addMembers.dialog = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
|
@ -105,7 +106,7 @@
|
|||
item-value="id"
|
||||
multiple
|
||||
>
|
||||
<template v-slot:selection="data">
|
||||
<template #selection="data">
|
||||
<v-chip
|
||||
v-bind="data.attrs"
|
||||
:input-value="data.selected"
|
||||
|
@ -113,25 +114,25 @@
|
|||
@click="data.select"
|
||||
@click:close="remove(data.item)"
|
||||
>
|
||||
<v-avatar left v-if="data.item.avatar">
|
||||
<v-avatar v-if="data.item.avatar" left>
|
||||
<v-img
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + data.item.avatar
|
||||
"
|
||||
></v-img>
|
||||
/>
|
||||
</v-avatar>
|
||||
@{{ data.item.username }}
|
||||
</v-chip>
|
||||
</template>
|
||||
<template v-slot:item="data">
|
||||
<v-avatar left v-if="data.item.avatar" class="mr-3 mb-2 mt-2">
|
||||
<template #item="data">
|
||||
<v-avatar v-if="data.item.avatar" left class="mr-3 mb-2 mt-2">
|
||||
<v-img
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + data.item.avatar
|
||||
"
|
||||
></v-img>
|
||||
/>
|
||||
</v-avatar>
|
||||
<v-avatar left v-else class="mr-3 mb-2 mt-2">
|
||||
<v-avatar v-else left class="mr-3 mb-2 mt-2">
|
||||
<v-icon>mdi-account</v-icon>
|
||||
</v-avatar>
|
||||
<v-list-item-content>
|
||||
|
@ -141,60 +142,60 @@
|
|||
</v-autocomplete>
|
||||
</v-container>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="error" text @click="settings.addMembers.dialog = false">
|
||||
Cancel
|
||||
</v-btn>
|
||||
<v-btn
|
||||
color="primary"
|
||||
text
|
||||
@click="addMembersToGroup"
|
||||
:disabled="!settings.addMembers.users.length"
|
||||
@click="addMembersToGroup"
|
||||
>
|
||||
Add
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-dialog v-model="settings.dialog" max-width="500px" v-if="settings.item">
|
||||
<v-dialog v-if="settings.item" v-model="settings.dialog" max-width="500px">
|
||||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Group Settings</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click.native="settings.dialog = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-alert text type="info" v-if="settings.item.rank !== 'admin'">
|
||||
<v-alert v-if="settings.item.rank !== 'admin'" text type="info">
|
||||
You need to be an administrator of this group to change settings.
|
||||
</v-alert>
|
||||
<v-card-title v-if="settings.item.rank === 'admin'"
|
||||
>General</v-card-title
|
||||
>
|
||||
<v-card-title v-if="settings.item.rank === 'admin'">
|
||||
General
|
||||
</v-card-title>
|
||||
<v-text-field
|
||||
label="Group Name"
|
||||
v-if="
|
||||
settings.item.chat.type === 'group' &&
|
||||
settings.item.rank === 'admin'
|
||||
"
|
||||
v-model="settings.item.chat.name"
|
||||
></v-text-field>
|
||||
label="Group Name"
|
||||
/>
|
||||
<v-file-input
|
||||
ref="avatarUpload"
|
||||
v-model="settings.avatar"
|
||||
accept="image/png, image/jpeg, image/jpg, image/gif, image/webp"
|
||||
placeholder="Avatar"
|
||||
prepend-icon=""
|
||||
label="Profile Picture"
|
||||
v-model="settings.avatar"
|
||||
@change="doUpload"
|
||||
></v-file-input>
|
||||
<v-card-title
|
||||
>Members
|
||||
/>
|
||||
<v-card-title>
|
||||
Members
|
||||
<v-btn
|
||||
v-if="settings.item.rank === 'admin'"
|
||||
icon
|
||||
@click.native="settings.addMembers.dialog = true"
|
||||
v-if="settings.item.rank === 'admin'"
|
||||
>
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
|
@ -206,25 +207,25 @@
|
|||
>
|
||||
<v-list-item-avatar :color="$vuetify.theme.themes.dark?.primary">
|
||||
<v-img
|
||||
v-if="user.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + user.user.avatar
|
||||
"
|
||||
v-if="user.user.avatar"
|
||||
/>
|
||||
<v-icon v-else> mdi-account </v-icon>
|
||||
</v-list-item-avatar>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title
|
||||
>{{ user.user.username }}
|
||||
<v-btn text icon v-if="user.rank === 'admin'">
|
||||
<v-list-item-title>
|
||||
{{ user.user.username }}
|
||||
<v-btn v-if="user.rank === 'admin'" text icon>
|
||||
<v-icon> mdi-gavel </v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action v-if="settings.item.rank === 'admin'">
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<div v-on="on" v-bind="attrs">
|
||||
<template #activator="{ on, attrs }">
|
||||
<div v-bind="attrs" v-on="on">
|
||||
<v-btn icon @click="giveUserAdmin(user)">
|
||||
<v-icon>mdi-account-arrow-up</v-icon>
|
||||
</v-btn>
|
||||
|
@ -258,7 +259,7 @@
|
|||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Are you sure you want to leave?</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
icon
|
||||
@click.native="
|
||||
|
@ -276,7 +277,7 @@
|
|||
</p>
|
||||
</v-container>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="primary" text @click.native="leave.dialog = false">
|
||||
Cancel
|
||||
</v-btn>
|
||||
|
@ -288,7 +289,7 @@
|
|||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>New Communication</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click.native="dialogs.new = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
|
@ -306,7 +307,7 @@
|
|||
item-value="id"
|
||||
multiple
|
||||
>
|
||||
<template v-slot:selection="data">
|
||||
<template #selection="data">
|
||||
<v-chip
|
||||
v-bind="data.attrs"
|
||||
:input-value="data.selected"
|
||||
|
@ -314,25 +315,25 @@
|
|||
@click="data.select"
|
||||
@click:close="remove(data.item)"
|
||||
>
|
||||
<v-avatar left v-if="data.item.avatar">
|
||||
<v-avatar v-if="data.item.avatar" left>
|
||||
<v-img
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + data.item.avatar
|
||||
"
|
||||
></v-img>
|
||||
/>
|
||||
</v-avatar>
|
||||
@{{ data.item.username }}
|
||||
</v-chip>
|
||||
</template>
|
||||
<template v-slot:item="data">
|
||||
<v-avatar left v-if="data.item.avatar" class="mr-3 mb-2 mt-2">
|
||||
<template #item="data">
|
||||
<v-avatar v-if="data.item.avatar" left class="mr-3 mb-2 mt-2">
|
||||
<v-img
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + data.item.avatar
|
||||
"
|
||||
></v-img>
|
||||
/>
|
||||
</v-avatar>
|
||||
<v-avatar left v-else class="mr-3 mb-2 mt-2">
|
||||
<v-avatar v-else left class="mr-3 mb-2 mt-2">
|
||||
<v-icon>mdi-account</v-icon>
|
||||
</v-avatar>
|
||||
<v-list-item-content>
|
||||
|
@ -347,7 +348,7 @@
|
|||
>
|
||||
</v-container>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="error" text @click="dialogs.new = false">
|
||||
Cancel
|
||||
</v-btn>
|
||||
|
@ -355,8 +356,8 @@
|
|||
color="primary"
|
||||
:loading="newConversation.loading"
|
||||
text
|
||||
@click="createConversation"
|
||||
:disabled="!newConversation.users.length"
|
||||
@click="createConversation"
|
||||
>
|
||||
Create
|
||||
</v-btn>
|
||||
|
@ -423,17 +424,17 @@
|
|||
color="yellow darken-3"
|
||||
empty-icon="$ratingFull"
|
||||
hover
|
||||
></v-rating>
|
||||
/>
|
||||
</v-col>
|
||||
<v-col cols="12">
|
||||
<v-textarea
|
||||
class="rounded-xl"
|
||||
v-model="feedback.text"
|
||||
class="rounded-xl"
|
||||
label="Enter your Feedback"
|
||||
required
|
||||
autofocus
|
||||
placeholder="Enter your Feedback"
|
||||
></v-textarea>
|
||||
/>
|
||||
</v-col>
|
||||
<small
|
||||
>Your feedback will be used to make
|
||||
|
@ -443,7 +444,7 @@
|
|||
</v-container>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="rounded-xl"
|
||||
color="blue darken-1"
|
||||
|
@ -471,17 +472,17 @@
|
|||
<v-card-text>
|
||||
<v-container>
|
||||
<v-text-field
|
||||
class="rounded-xl"
|
||||
v-model="route.value"
|
||||
class="rounded-xl"
|
||||
autofocus
|
||||
@keyup.enter="goToRoute()"
|
||||
label="Route"
|
||||
required
|
||||
></v-text-field>
|
||||
@keyup.enter="goToRoute()"
|
||||
/>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn class="rounded-xl" text @click="route.modal = false">
|
||||
Close
|
||||
</v-btn>
|
||||
|
@ -498,54 +499,54 @@
|
|||
</v-dialog>
|
||||
<v-app-bar app color="dark" elevation="5" style="z-index: 15">
|
||||
<v-app-bar-nav-icon
|
||||
@click.stop="$store.state.drawer = !$store.state.drawer"
|
||||
v-if="$vuetify.breakpoint.mobile || !$store.state.drawer"
|
||||
></v-app-bar-nav-icon>
|
||||
@click.stop="$store.state.drawer = !$store.state.drawer"
|
||||
/>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['ctrl', 'k']"
|
||||
style="display: none"
|
||||
@shortkey="$store.commit('setSearch', true)"
|
||||
>
|
||||
Debug
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['meta', 'k']"
|
||||
style="display: none"
|
||||
@shortkey="$store.commit('setSearch', true)"
|
||||
>
|
||||
Debug
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['ctrl', 'alt', 'd']"
|
||||
style="display: none"
|
||||
@shortkey="$store.dispatch('toggleCSS')"
|
||||
>
|
||||
Style Toggle
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['f9']"
|
||||
style="display: none"
|
||||
@shortkey="$store.dispatch('toggleCSS')"
|
||||
>
|
||||
Style Toggle
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['ctrl', 'f']"
|
||||
style="display: none"
|
||||
@shortkey="$store.state.searchPanel = true"
|
||||
>
|
||||
Debug
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['ctrl', 'b']"
|
||||
style="display: none"
|
||||
@shortkey="route.modal = true"
|
||||
>
|
||||
Debug
|
||||
</button>
|
||||
<button
|
||||
style="display: none"
|
||||
v-shortkey="['ctrl', '/']"
|
||||
style="display: none"
|
||||
@shortkey="shortcuts = true"
|
||||
>
|
||||
Debug
|
||||
|
@ -558,22 +559,22 @@
|
|||
: chat?.chat?.name
|
||||
}}
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-tooltip bottom>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn v-on="on" icon @click="feedback.modal = true">
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon v-on="on" @click="feedback.modal = true">
|
||||
<v-icon>mdi-bug</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Provide Feedback</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip bottom>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
icon
|
||||
v-model="$store.state.context.pins.value"
|
||||
@click="show($event, 'pins', null, null, true)"
|
||||
id="pin-button"
|
||||
v-model="$store.state.context.pins.value"
|
||||
icon
|
||||
@click="show($event, 'pins', null, null, true)"
|
||||
v-on="on"
|
||||
>
|
||||
<v-icon>mdi-pin-outline</v-icon>
|
||||
|
@ -582,7 +583,7 @@
|
|||
<span>Chat Pins</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip bottom>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
icon
|
||||
@click="$store.state.searchPanel = !$store.state.searchPanel"
|
||||
|
@ -594,10 +595,10 @@
|
|||
<span>Search Messages</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip bottom>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
icon
|
||||
v-on="on"
|
||||
@click="$store.state.userPanel = !$store.state.userPanel"
|
||||
>
|
||||
<v-icon>mdi-account-group-outline</v-icon>
|
||||
|
@ -616,9 +617,10 @@
|
|||
?.primary
|
||||
"
|
||||
class="troplo-title"
|
||||
@click="$router.push('/')"
|
||||
style="cursor: pointer"
|
||||
>{{ $store.state.site.name }}</v-toolbar-title
|
||||
@click="$router.push('/')"
|
||||
>
|
||||
{{ $store.state.site.name }} </v-toolbar-title
|
||||
><v-app-bar-nav-icon
|
||||
v-if="
|
||||
!$vuetify.breakpoint.mobile &&
|
||||
|
@ -626,12 +628,13 @@
|
|||
"
|
||||
style="z-index: 1000"
|
||||
disabled
|
||||
>{{ $store.state.site.release }}</v-app-bar-nav-icon
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
{{ $store.state.site.release }}
|
||||
</v-app-bar-nav-icon>
|
||||
<v-spacer />
|
||||
<v-tooltip bottom>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn v-on="on" icon @click="feedback.modal = true">
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon v-on="on" @click="feedback.modal = true">
|
||||
<v-icon>mdi-bug</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
@ -640,16 +643,16 @@
|
|||
</template>
|
||||
</v-app-bar>
|
||||
<v-navigation-drawer
|
||||
v-model="$store.state.drawer"
|
||||
color="dark"
|
||||
app
|
||||
floating
|
||||
style="max-height: 100%; z-index: 15"
|
||||
class="elevation-5"
|
||||
v-model="$store.state.drawer"
|
||||
:width="$vuetify.breakpoint.mobile ? 270 : 320"
|
||||
>
|
||||
<v-container>
|
||||
<v-list dense nav id="comms-sidebar-list">
|
||||
<v-list id="comms-sidebar-list" dense nav>
|
||||
<template v-if="$vuetify.breakpoint.mobile">
|
||||
<v-btn
|
||||
color="toolbar"
|
||||
|
@ -658,7 +661,7 @@
|
|||
class="mb-3 mr-1 rounded-xl"
|
||||
elevation="2"
|
||||
>
|
||||
<v-icon left>mdi-account-multiple</v-icon>
|
||||
<v-icon left> mdi-account-multiple </v-icon>
|
||||
Friends
|
||||
</v-btn>
|
||||
<v-btn
|
||||
|
@ -668,7 +671,7 @@
|
|||
elevation="2"
|
||||
@click="dialogs.new = true"
|
||||
>
|
||||
<v-icon left>mdi-plus</v-icon>
|
||||
<v-icon left> mdi-plus </v-icon>
|
||||
New
|
||||
</v-btn>
|
||||
</template>
|
||||
|
@ -680,10 +683,11 @@
|
|||
class="mb-3 rounded-xl"
|
||||
elevation="2"
|
||||
>
|
||||
<v-icon left>mdi-account-multiple</v-icon>
|
||||
<v-icon left> mdi-account-multiple </v-icon>
|
||||
Friends
|
||||
</v-btn>
|
||||
<v-text-field
|
||||
v-model="search"
|
||||
class="rounded-xl"
|
||||
filled
|
||||
solo
|
||||
|
@ -692,19 +696,18 @@
|
|||
background-color="sheet"
|
||||
style="margin-bottom: -18px"
|
||||
elevation="2"
|
||||
v-model="search"
|
||||
autocomplete="none"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-toolbar color="sheet" class="rounded-xl mb-3" elevation="2">
|
||||
<v-toolbar-title class="subtitle-1">
|
||||
CHATS ({{ chats.length }})
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="dialogs.new = true">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar></template
|
||||
>
|
||||
</v-toolbar>
|
||||
</template>
|
||||
<v-list v-for="item in chats" :key="item.id">
|
||||
<template>
|
||||
<v-list-item
|
||||
|
@ -714,10 +717,10 @@
|
|||
"
|
||||
>
|
||||
<v-badge
|
||||
v-if="item.chat.type === 'direct'"
|
||||
bordered
|
||||
bottom
|
||||
:color="getStatus(item)"
|
||||
v-if="item.chat.type === 'direct'"
|
||||
dot
|
||||
offset-x="24"
|
||||
offset-y="20"
|
||||
|
@ -741,7 +744,7 @@
|
|||
</v-icon>
|
||||
</v-list-item-avatar>
|
||||
</v-badge>
|
||||
<v-badge dot color="none" v-else>
|
||||
<v-badge v-else dot color="none">
|
||||
<v-list-item-avatar
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
>
|
||||
|
@ -777,8 +780,7 @@
|
|||
$route.params.id !== item.id.toString()
|
||||
"
|
||||
>
|
||||
<v-badge color="red" inline :content="item.unread">
|
||||
</v-badge>
|
||||
<v-badge color="red" inline :content="item.unread" />
|
||||
</v-list-item-action>
|
||||
</template>
|
||||
</v-list-item>
|
||||
|
@ -786,12 +788,12 @@
|
|||
</v-list>
|
||||
</v-list>
|
||||
</v-container>
|
||||
<template v-slot:append>
|
||||
<template #append>
|
||||
<v-card tile color="bg" elevation="0">
|
||||
<v-divider></v-divider>
|
||||
<v-divider />
|
||||
<v-list-item>
|
||||
<v-menu top offset-y>
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-badge
|
||||
bordered
|
||||
bottom
|
||||
|
@ -799,13 +801,13 @@
|
|||
dot
|
||||
offset-x="26"
|
||||
offset-y="19"
|
||||
v-on="on"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
<v-list-item-avatar
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
v-on="on"
|
||||
v-bind="attrs"
|
||||
v-on="on"
|
||||
>
|
||||
<v-img
|
||||
v-if="$store.state.user.avatar"
|
||||
|
@ -830,29 +832,28 @@
|
|||
<v-list-item two-line @click="setStatus('busy')">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Do not Disturb</v-list-item-title>
|
||||
<v-list-item-subtitle class="text-wrap"
|
||||
>You will not receive any
|
||||
notifications.</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle class="text-wrap">
|
||||
You will not receive any notifications.
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
<v-list-item two-line @click="setStatus('invisible')">
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Invisible</v-list-item-title>
|
||||
<v-list-item-subtitle class="text-wrap"
|
||||
>You will appear as offline, and the typing indicator will
|
||||
be disabled.</v-list-item-subtitle
|
||||
>
|
||||
<v-list-item-subtitle class="text-wrap">
|
||||
You will appear as offline, and the typing indicator will
|
||||
be disabled.
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
<v-tooltip v-model="copyTooltip" top>
|
||||
<template v-slot:activator="{ attrs }">
|
||||
<template #activator="{ attrs }">
|
||||
<v-list-item-content
|
||||
@click="copyUsername"
|
||||
v-bind="attrs"
|
||||
style="cursor: pointer; min-width: 100px"
|
||||
@click="copyUsername"
|
||||
>
|
||||
<v-list-item-title>
|
||||
{{ $store.state.user.username }}
|
||||
|
@ -864,12 +865,12 @@
|
|||
</template>
|
||||
<span>Copied!</span>
|
||||
</v-tooltip>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
v-if="$store.state.user.admin"
|
||||
icon
|
||||
text
|
||||
to="/admin"
|
||||
v-if="$store.state.user.admin"
|
||||
style="margin-right: 0; padding-right: 0"
|
||||
>
|
||||
<v-icon>mdi-gavel</v-icon>
|
||||
|
@ -989,6 +990,73 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
this.feedback.route = to.path
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.feedback.route = this.$route.path
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("token")
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
this.$store.dispatch("getChats")
|
||||
this.$socket.on("friendUpdate", () => {
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
})
|
||||
this.$socket.on("siteState", () => {
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
})
|
||||
this.$socket.on("userSettings", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
this.$socket.on("chatUpdated", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
this.$socket.on("chatAdded", (chat) => {
|
||||
this.$store.commit("addChat", chat)
|
||||
})
|
||||
this.$socket.on("userStatus", (event) => {
|
||||
this.$store.state.chats.forEach((item) => {
|
||||
item.chat.associations.forEach((a) => {
|
||||
if (a.user.id === event.userId) {
|
||||
a.user.status = event.status
|
||||
}
|
||||
})
|
||||
item.chat.users.forEach((u) => {
|
||||
if (u.id === event.userId) {
|
||||
u.status = event.status
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$socket.on("message", (message) => {
|
||||
const chat = this.$store.state.chats.find(
|
||||
(item) => item.chatId === message.chatId
|
||||
)
|
||||
if (chat) {
|
||||
const index = this.$store.state.chats.indexOf(chat)
|
||||
this.$store.state.chats.splice(index, 1)
|
||||
this.$store.state.chats.unshift(chat)
|
||||
}
|
||||
})
|
||||
this.$socket.on("readChat", (chat) => {
|
||||
const item = this.$store.state.chats.find((item) => item.id === chat.id)
|
||||
if (item) {
|
||||
const index = this.$store.state.chats.indexOf(item)
|
||||
console.log(this.$store.state.chats[index].lastRead)
|
||||
this.$store.state.chats[index].lastRead = chat.lastRead
|
||||
this.$store.state.communicationNotifications = 0
|
||||
this.$store.state.chats.forEach((item) => {
|
||||
this.$store.state.communicationNotifications +=
|
||||
this.getLastRead(item).count
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
goToRoute() {
|
||||
if (this.route.value === "forceEnableDevMode") {
|
||||
|
@ -1332,73 +1400,6 @@ export default {
|
|||
})
|
||||
.catch(() => {})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.feedback.route = this.$route.path
|
||||
Vue.axios.defaults.headers.common["Authorization"] =
|
||||
localStorage.getItem("token")
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
this.$store.dispatch("getChats")
|
||||
this.$socket.on("friendUpdate", () => {
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
})
|
||||
this.$socket.on("siteState", () => {
|
||||
this.searchUsers()
|
||||
this.searchUsersForGroupAdmin()
|
||||
})
|
||||
this.$socket.on("userSettings", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
this.$socket.on("chatUpdated", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
this.$socket.on("chatAdded", (chat) => {
|
||||
this.$store.commit("addChat", chat)
|
||||
})
|
||||
this.$socket.on("userStatus", (event) => {
|
||||
this.$store.state.chats.forEach((item) => {
|
||||
item.chat.associations.forEach((a) => {
|
||||
if (a.user.id === event.userId) {
|
||||
a.user.status = event.status
|
||||
}
|
||||
})
|
||||
item.chat.users.forEach((u) => {
|
||||
if (u.id === event.userId) {
|
||||
u.status = event.status
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
this.$socket.on("message", (message) => {
|
||||
const chat = this.$store.state.chats.find(
|
||||
(item) => item.chatId === message.chatId
|
||||
)
|
||||
if (chat) {
|
||||
const index = this.$store.state.chats.indexOf(chat)
|
||||
this.$store.state.chats.splice(index, 1)
|
||||
this.$store.state.chats.unshift(chat)
|
||||
}
|
||||
})
|
||||
this.$socket.on("readChat", (chat) => {
|
||||
const item = this.$store.state.chats.find((item) => item.id === chat.id)
|
||||
if (item) {
|
||||
const index = this.$store.state.chats.indexOf(item)
|
||||
console.log(this.$store.state.chats[index].lastRead)
|
||||
this.$store.state.chats[index].lastRead = chat.lastRead
|
||||
this.$store.state.communicationNotifications = 0
|
||||
this.$store.state.chats.forEach((item) => {
|
||||
this.$store.state.communicationNotifications +=
|
||||
this.getLastRead(item).count
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
$route(to) {
|
||||
this.feedback.route = to.path
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,27 +2,27 @@
|
|||
<div>
|
||||
<template>
|
||||
<v-toolbar
|
||||
@click="jumpToMessage(message.replyId)"
|
||||
v-if="message.reply"
|
||||
:key="message.keyId + '-reply-toolbar'"
|
||||
elevation="0"
|
||||
height="40"
|
||||
color="card"
|
||||
v-if="message.reply"
|
||||
style="cursor: pointer"
|
||||
@click="jumpToMessage(message.replyId)"
|
||||
>
|
||||
<v-icon class="mr-2">mdi-reply</v-icon>
|
||||
<v-icon class="mr-2"> mdi-reply </v-icon>
|
||||
<v-avatar size="24" class="mr-2">
|
||||
<v-img
|
||||
v-if="message.reply.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + message.reply.user.avatar
|
||||
"
|
||||
v-if="message.reply.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
</v-avatar>
|
||||
<template v-if="message.reply.attachments.length">
|
||||
<v-icon class="mr-2">mdi-file-image</v-icon>
|
||||
<v-icon class="mr-2"> mdi-file-image </v-icon>
|
||||
</template>
|
||||
<template
|
||||
v-if="!message.reply.content && message.reply.attachments.length"
|
||||
|
@ -32,6 +32,7 @@
|
|||
{{ message.reply.content.substring(0, 100) }}
|
||||
</v-toolbar>
|
||||
<v-list-item
|
||||
:id="'message-' + index"
|
||||
:key="message.keyId"
|
||||
:class="{
|
||||
'pa-0': $vuetify.breakpoint.mobile,
|
||||
|
@ -39,22 +40,21 @@
|
|||
}"
|
||||
class="message"
|
||||
:dense="lastMessage"
|
||||
:id="'message-' + index"
|
||||
@contextmenu="show($event, 'message', message)"
|
||||
:style="lastMessage ? 'margin-bottom: -5px; margin-top: -5px;' : ''"
|
||||
@contextmenu="show($event, 'message', message)"
|
||||
>
|
||||
<v-avatar
|
||||
v-if="!lastMessage"
|
||||
size="45"
|
||||
class="mr-2"
|
||||
v-if="!lastMessage"
|
||||
:class="{ 'hide-on-hover': message.type }"
|
||||
>
|
||||
<v-img
|
||||
:src="$store.state.baseURL + '/usercontent/' + message.user.avatar"
|
||||
v-if="message.user.avatar && !message.type"
|
||||
:src="$store.state.baseURL + '/usercontent/' + message.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon class="elevation-1" v-else-if="!message.type">
|
||||
<v-icon v-else-if="!message.type" class="elevation-1">
|
||||
mdi-account
|
||||
</v-icon>
|
||||
<v-icon
|
||||
|
@ -86,12 +86,12 @@
|
|||
</v-icon>
|
||||
</v-avatar>
|
||||
<v-tooltip top style="z-index: 15">
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<small
|
||||
v-on="on"
|
||||
v-if="lastMessage || message.type"
|
||||
style="font-size: 9px; position: absolute"
|
||||
class="grey--text message-date"
|
||||
v-if="lastMessage || message.type"
|
||||
v-on="on"
|
||||
>
|
||||
{{ $date(message.createdAt).format("hh:mm A") }}
|
||||
</small>
|
||||
|
@ -110,14 +110,14 @@
|
|||
color="calendarNormalActivity"
|
||||
small
|
||||
>
|
||||
<v-icon small>mdi-robot</v-icon>
|
||||
<v-icon small> mdi-robot </v-icon>
|
||||
</v-chip>
|
||||
<small>
|
||||
{{ $date(message.createdAt).format("hh:mm A, DD/MM/YYYY") }}
|
||||
</small>
|
||||
<v-tooltip top v-if="message.edited">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<span v-on="on" v-bind="attrs">
|
||||
<v-tooltip v-if="message.edited" top>
|
||||
<template #activator="{ on, attrs }">
|
||||
<span v-bind="attrs" v-on="on">
|
||||
<v-icon
|
||||
color="grey"
|
||||
small
|
||||
|
@ -140,9 +140,9 @@
|
|||
<span v-markdown>
|
||||
{{ message.content }}
|
||||
</span>
|
||||
<v-tooltip top v-if="message.edited && lastMessage">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-icon color="grey" small v-on="on" style="">
|
||||
<v-tooltip v-if="message.edited && lastMessage" top>
|
||||
<template #activator="{ on }">
|
||||
<v-icon color="grey" small style="" v-on="on">
|
||||
mdi-pencil
|
||||
</v-icon>
|
||||
</template>
|
||||
|
@ -155,37 +155,36 @@
|
|||
<template v-if="edit.id !== message.id">
|
||||
<Embed
|
||||
v-for="(embed, index) in message.embeds"
|
||||
:key="index"
|
||||
:id="'embed-' + index"
|
||||
:key="index"
|
||||
:embed="embed"
|
||||
:setImagePreview="setImagePreview"
|
||||
></Embed>
|
||||
:set-image-preview="setImagePreview"
|
||||
/>
|
||||
<v-row v-if="message.poll" no-gutters>
|
||||
<Poll :message="message"></Poll>
|
||||
<Poll :message="message" />
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-if="edit.id !== message.id">
|
||||
<v-card
|
||||
v-for="(attachment, index) in message.attachments"
|
||||
:key="attachment.id"
|
||||
:id="'attachment-' + index"
|
||||
:key="attachment.id"
|
||||
:max-width="500"
|
||||
:min-width="!$vuetify.breakpoint.mobile ? 400 : 0"
|
||||
elevation="0"
|
||||
color="card"
|
||||
>
|
||||
<v-hover
|
||||
v-slot="{ hover }"
|
||||
v-if="
|
||||
attachment.extension === 'jpg' ||
|
||||
attachment.extension === 'png' ||
|
||||
attachment.extension === 'jpeg' ||
|
||||
attachment.extension === 'gif'
|
||||
"
|
||||
v-slot="{ hover }"
|
||||
>
|
||||
<div>
|
||||
<v-img
|
||||
@click="setImagePreview(attachment)"
|
||||
contain
|
||||
:max-width="500"
|
||||
:max-height="500"
|
||||
|
@ -196,8 +195,9 @@
|
|||
"
|
||||
:min-height="250"
|
||||
:min-width="250"
|
||||
@click="setImagePreview(attachment)"
|
||||
>
|
||||
<template v-slot:placeholder>
|
||||
<template #placeholder>
|
||||
<v-row
|
||||
class="fill-height ma-0"
|
||||
align="center"
|
||||
|
@ -206,13 +206,13 @@
|
|||
<v-progress-circular
|
||||
indeterminate
|
||||
color="grey lighten-5"
|
||||
></v-progress-circular>
|
||||
/>
|
||||
</v-row>
|
||||
</template>
|
||||
<template v-slot:default>
|
||||
<template #default>
|
||||
<v-fade-transition v-if="hover">
|
||||
<v-overlay absolute>
|
||||
<v-icon large>mdi-arrow-expand-all</v-icon>
|
||||
<v-icon large> mdi-arrow-expand-all </v-icon>
|
||||
</v-overlay>
|
||||
</v-fade-transition>
|
||||
</template>
|
||||
|
@ -254,29 +254,29 @@
|
|||
</v-card>
|
||||
</template>
|
||||
<CommsInput
|
||||
v-if="edit.id === message.id"
|
||||
:edit="edit"
|
||||
:chat="chat"
|
||||
:auto-scroll="autoScroll"
|
||||
:end-edit="endEdit"
|
||||
v-if="edit.id === message.id"
|
||||
></CommsInput>
|
||||
/>
|
||||
</v-list-item-content>
|
||||
<v-card
|
||||
v-if="!$vuetify.breakpoint.mobile"
|
||||
elevation="8"
|
||||
color="card"
|
||||
class="message-action-card"
|
||||
v-if="!$vuetify.breakpoint.mobile"
|
||||
>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<span v-on="on">
|
||||
<v-btn
|
||||
icon
|
||||
v-on="on"
|
||||
v-if="
|
||||
message.userId === $store.state.user.id ||
|
||||
chat.rank === 'admin'
|
||||
"
|
||||
icon
|
||||
v-on="on"
|
||||
@click="deleteMessage(message)"
|
||||
>
|
||||
<v-icon> mdi-delete </v-icon>
|
||||
|
@ -286,9 +286,13 @@
|
|||
<span> Delete </span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<span v-on="on">
|
||||
<v-btn
|
||||
v-if="
|
||||
message.userId === $store.state.user.id &&
|
||||
edit.id !== message.id
|
||||
"
|
||||
icon
|
||||
v-on="on"
|
||||
@click="
|
||||
|
@ -296,10 +300,6 @@
|
|||
edit.editing = true
|
||||
edit.id = message.id
|
||||
"
|
||||
v-if="
|
||||
message.userId === $store.state.user.id &&
|
||||
edit.id !== message.id
|
||||
"
|
||||
>
|
||||
<v-icon> mdi-pencil </v-icon>
|
||||
</v-btn>
|
||||
|
@ -308,20 +308,20 @@
|
|||
<span> Edit </span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<span v-on="on">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
v-if="
|
||||
message.userId === $store.state.user.id &&
|
||||
edit.id === message.id
|
||||
"
|
||||
icon
|
||||
v-on="on"
|
||||
@click="
|
||||
edit.content = ''
|
||||
edit.editing = false
|
||||
edit.id = null
|
||||
"
|
||||
v-if="
|
||||
message.userId === $store.state.user.id &&
|
||||
edit.id === message.id
|
||||
"
|
||||
>
|
||||
<v-icon> mdi-close </v-icon>
|
||||
</v-btn>
|
||||
|
@ -330,7 +330,7 @@
|
|||
<span> Discard Edits </span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<span v-on="on">
|
||||
<v-btn
|
||||
icon
|
||||
|
@ -347,12 +347,12 @@
|
|||
<span> Reply </span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<span v-on="on">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
icon
|
||||
v-if="chat.rank === 'admin' || chat.chat.type === 'direct'"
|
||||
icon
|
||||
v-on="on"
|
||||
@click="
|
||||
pinMessage()
|
||||
focusInput()
|
||||
|
@ -364,9 +364,9 @@
|
|||
</template>
|
||||
<span> Pin to Chat </span>
|
||||
</v-tooltip>
|
||||
<v-menu offset-y v-if="$store.state.site.release === 'dev'">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<v-btn v-on="on" icon v-bind="attrs">
|
||||
<v-menu v-if="$store.state.site.release === 'dev'" offset-y>
|
||||
<template #activator="{ on, attrs }">
|
||||
<v-btn icon v-bind="attrs" v-on="on">
|
||||
<v-icon> mdi-dots-horizontal </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
@ -388,6 +388,11 @@ import Poll from "@/components/Poll"
|
|||
|
||||
export default {
|
||||
name: "Message",
|
||||
components: {
|
||||
Poll,
|
||||
CommsInput,
|
||||
Embed
|
||||
},
|
||||
props: [
|
||||
"message",
|
||||
"edit",
|
||||
|
@ -404,11 +409,6 @@ export default {
|
|||
"deleteMessage",
|
||||
"lastMessage"
|
||||
],
|
||||
components: {
|
||||
Poll,
|
||||
CommsInput,
|
||||
Embed
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
graphOptions: {
|
||||
|
|
|
@ -10,11 +10,11 @@
|
|||
label="Nickname"
|
||||
autofocus
|
||||
@keyup.enter="setFriendNickname"
|
||||
></v-text-field>
|
||||
/>
|
||||
<small>Friend nicknames only show to you.</small>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
color="blue darken-1"
|
||||
text
|
||||
|
|
|
@ -74,6 +74,16 @@ export default {
|
|||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.on(`pollAnswer-${this.message.id}`, (data) => {
|
||||
this.message.poll.answers = this.message.poll.answers.filter(
|
||||
(answer) => answer.id !== data.id
|
||||
)
|
||||
if (data.answer) {
|
||||
this.message.poll.answers.push(data.answer)
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
votePoll(option) {
|
||||
this.axios
|
||||
|
@ -84,16 +94,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.on(`pollAnswer-${this.message.id}`, (data) => {
|
||||
this.message.poll.answers = this.message.poll.answers.filter(
|
||||
(answer) => answer.id !== data.id
|
||||
)
|
||||
if (data.answer) {
|
||||
this.message.poll.answers.push(data.answer)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
<template>
|
||||
<div v-if="!message.type" class="rounded-l">
|
||||
<v-toolbar
|
||||
@click="jumpToMessage(message.replyId)"
|
||||
v-if="message.reply"
|
||||
:key="message.keyId + '-reply-toolbar'"
|
||||
elevation="0"
|
||||
height="40"
|
||||
color="card"
|
||||
v-if="message.reply"
|
||||
style="cursor: pointer"
|
||||
@click="jumpToMessage(message.replyId)"
|
||||
>
|
||||
<v-icon class="mr-2">mdi-reply</v-icon>
|
||||
<v-icon class="mr-2"> mdi-reply </v-icon>
|
||||
<v-avatar size="24" class="mr-2">
|
||||
<v-img
|
||||
v-if="message.reply.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent/' + message.reply.user.avatar
|
||||
"
|
||||
v-if="message.reply.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
</v-avatar>
|
||||
<template v-if="message.reply.attachments.length">
|
||||
<v-icon class="mr-2">mdi-file-image</v-icon>
|
||||
<v-icon class="mr-2"> mdi-file-image </v-icon>
|
||||
</template>
|
||||
<template
|
||||
v-if="!message.reply.content && message.reply.attachments.length"
|
||||
|
@ -31,17 +31,17 @@
|
|||
{{ message.reply.content.substring(0, 100) }}
|
||||
</v-toolbar>
|
||||
<v-list-item
|
||||
:id="'message-' + index"
|
||||
:key="message.keyId"
|
||||
:class="{
|
||||
'text-xs-right': message.userId === $store.state.user.id,
|
||||
'text-xs-left': message.userId !== $store.state.user.id
|
||||
}"
|
||||
:id="'message-' + index"
|
||||
>
|
||||
<v-avatar size="48" class="mr-2">
|
||||
<v-img
|
||||
:src="$store.state.baseURL + '/usercontent/' + message.user.avatar"
|
||||
v-if="message.user.avatar"
|
||||
:src="$store.state.baseURL + '/usercontent/' + message.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
|
@ -50,14 +50,14 @@
|
|||
<v-list-item-subtitle>
|
||||
{{ getName(message.user) }}
|
||||
<v-chip v-if="message.user.bot" color="calendarNormalActivity" small>
|
||||
<v-icon small>mdi-robot</v-icon>
|
||||
<v-icon small> mdi-robot </v-icon>
|
||||
</v-chip>
|
||||
<small>
|
||||
{{ $date(message.createdAt).format("hh:mm A, DD/MM/YYYY") }}
|
||||
</small>
|
||||
<v-tooltip top v-if="message.edited">
|
||||
<template v-slot:activator="{ on, attrs }">
|
||||
<span v-on="on" v-bind="attrs">
|
||||
<v-tooltip v-if="message.edited" top>
|
||||
<template #activator="{ on, attrs }">
|
||||
<span v-bind="attrs" v-on="on">
|
||||
<v-icon
|
||||
color="grey"
|
||||
small
|
||||
|
|
|
@ -4,42 +4,42 @@
|
|||
<v-toolbar color="toolbar" height="100">
|
||||
<v-avatar size="64" class="mr-3 mb-2 mt-2">
|
||||
<v-img
|
||||
:src="$store.state.baseURL + '/usercontent/' + user.item.avatar"
|
||||
v-if="user.item.avatar"
|
||||
:src="$store.state.baseURL + '/usercontent/' + user.item.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
</v-avatar>
|
||||
<v-toolbar-title>
|
||||
{{ getName(user.item) }}
|
||||
<v-tooltip top v-if="user.item.admin">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="user.item.admin" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-crown </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Colubrina Instance Administrator</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top v-if="user.item.id < 35">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="user.item.id < 35" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-alpha-a-circle </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Early User</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top v-if="user.item.bot">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="user.item.bot" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-robot </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Bot</span>
|
||||
</v-tooltip>
|
||||
<div class="subheading subtitle-1 text--lighten-2">
|
||||
<template v-if="user.item.nickname">{{
|
||||
user.item.username
|
||||
}}</template>
|
||||
<template v-if="user.item.nickname">
|
||||
{{ user.item.username }}
|
||||
</template>
|
||||
</div>
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
|
@ -62,10 +62,7 @@
|
|||
"
|
||||
>
|
||||
<v-overlay :value="loading.mutualFriends" absolute>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
size="64"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular indeterminate size="64" />
|
||||
</v-overlay>
|
||||
<v-list-item
|
||||
v-for="item in mutualFriends"
|
||||
|
@ -75,8 +72,8 @@
|
|||
<v-list-item-title>
|
||||
<v-avatar size="24">
|
||||
<v-img
|
||||
:src="$store.state.baseURL + '/usercontent/' + item.avatar"
|
||||
v-if="item.avatar"
|
||||
:src="$store.state.baseURL + '/usercontent/' + item.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
|
@ -100,10 +97,7 @@
|
|||
"
|
||||
>
|
||||
<v-overlay :value="loading.mutualFriends" absolute>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
size="64"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular indeterminate size="64" />
|
||||
</v-overlay>
|
||||
<v-list-item
|
||||
v-for="item in mutualGroups"
|
||||
|
@ -126,7 +120,7 @@
|
|||
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light'].card
|
||||
"
|
||||
>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="primary" text @click="user.value = false"> Close </v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
|
@ -149,6 +143,9 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.onMounted()
|
||||
},
|
||||
methods: {
|
||||
openUserPanel(user) {
|
||||
this.user.item = user
|
||||
|
@ -199,9 +196,6 @@ export default {
|
|||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.onMounted()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div id="admin">
|
||||
<v-overlay :value="loading" absolute>
|
||||
<v-progress-circular indeterminate size="64"></v-progress-circular>
|
||||
<v-progress-circular indeterminate size="64" />
|
||||
</v-overlay>
|
||||
<v-container v-if="admin">
|
||||
<v-card color="card" class="rounded-xl">
|
||||
|
@ -30,7 +30,7 @@
|
|||
<span>Config</span>
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
<router-view :admin="admin" :metrics="metrics"></router-view>
|
||||
<router-view :admin="admin" :metrics="metrics" />
|
||||
</v-card>
|
||||
</v-container>
|
||||
</div>
|
||||
|
@ -48,6 +48,10 @@ export default {
|
|||
loading: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getAdminInfo()
|
||||
this.getAdminMetrics()
|
||||
},
|
||||
methods: {
|
||||
getAdminMetrics() {
|
||||
this.axios
|
||||
|
@ -73,10 +77,6 @@ export default {
|
|||
this.$router.push("/")
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getAdminInfo()
|
||||
this.getAdminMetrics()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div id="admin-feedback">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Feedback ({{ feedback.count }})</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="getFeedback" icon>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="getFeedback">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
@ -43,6 +43,9 @@ export default {
|
|||
feedback: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFeedback()
|
||||
},
|
||||
methods: {
|
||||
getFeedback() {
|
||||
this.axios
|
||||
|
@ -51,9 +54,6 @@ export default {
|
|||
this.feedback = res.data
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getFeedback()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -109,10 +109,10 @@ ChartJS.register(
|
|||
)
|
||||
export default {
|
||||
name: "AdminHome",
|
||||
props: ["admin", "metrics"],
|
||||
components: {
|
||||
Chart
|
||||
},
|
||||
props: ["admin", "metrics"],
|
||||
data() {
|
||||
return {
|
||||
options: {
|
||||
|
|
|
@ -12,6 +12,9 @@ export default {
|
|||
logLines: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLogs()
|
||||
},
|
||||
methods: {
|
||||
getLogs() {
|
||||
this.axios
|
||||
|
@ -23,9 +26,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getLogs()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,46 +3,44 @@
|
|||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Site Config</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-text-field
|
||||
class="mx-3"
|
||||
label="Notification"
|
||||
v-model="notification"
|
||||
></v-text-field>
|
||||
<v-text-field v-model="notification" class="mx-3" label="Notification" />
|
||||
<v-select
|
||||
v-model="notificationType"
|
||||
:items="notificationTypes"
|
||||
label="Notification Type"
|
||||
class="mx-3"
|
||||
v-model="notificationType"
|
||||
text-text="text"
|
||||
text-value="value"
|
||||
>
|
||||
</v-select>
|
||||
/>
|
||||
<v-select
|
||||
v-model="broadcastType"
|
||||
:items="broadcastTypes"
|
||||
label="Broadcast Type"
|
||||
class="mx-3"
|
||||
v-model="broadcastType"
|
||||
text-text="text"
|
||||
text-value="value"
|
||||
>
|
||||
</v-select>
|
||||
/>
|
||||
<v-switch
|
||||
v-model="allowRegistrations"
|
||||
inset
|
||||
class="mx-3"
|
||||
label="Allow registrations"
|
||||
v-model="allowRegistrations"
|
||||
></v-switch>
|
||||
<v-textarea ref="rules" label="Instance Rules" v-model="rules" class="mx-3">
|
||||
</v-textarea>
|
||||
/>
|
||||
<v-textarea
|
||||
ref="rules"
|
||||
v-model="rules"
|
||||
label="Instance Rules"
|
||||
class="mx-3"
|
||||
/>
|
||||
<v-card-title>
|
||||
<v-icon class="mr-1">mdi-language-markdown</v-icon>Rules Preview:
|
||||
<v-icon class="mr-1"> mdi-language-markdown </v-icon>Rules Preview:
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<span v-markdown class="mx-3" :key="rules">{{ rules }}</span>
|
||||
<span :key="rules" v-markdown class="mx-3">{{ rules }}</span>
|
||||
</v-card-text>
|
||||
<v-btn text class="mx-3 mb-3" color="primary" @click="updateState"
|
||||
>Save</v-btn
|
||||
>
|
||||
<v-btn text class="mx-3 mb-3" color="primary" @click="updateState">
|
||||
Save
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -75,6 +73,12 @@ export default {
|
|||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.notification = this.$store.state.site.notification
|
||||
this.notificationType = this.$store.state.site.notificationType
|
||||
this.allowRegistrations = this.$store.state.site.allowRegistrations
|
||||
this.rules = this.$store.state.site.rules
|
||||
},
|
||||
methods: {
|
||||
updateState() {
|
||||
this.axios
|
||||
|
@ -92,12 +96,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.notification = this.$store.state.site.notification
|
||||
this.notificationType = this.$store.state.site.notificationType
|
||||
this.allowRegistrations = this.$store.state.site.allowRegistrations
|
||||
this.rules = this.$store.state.site.rules
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
<div id="admin-themes">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Themes ({{ themes.count }})</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="getThemes" icon>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="getThemes">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
@ -16,10 +16,10 @@
|
|||
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light'].card
|
||||
"
|
||||
>
|
||||
<template v-slot:[`item.actions`]="{ item }">
|
||||
<template #[`item.actions`]="{ item }">
|
||||
<v-btn text color="primary" @click="applyTheme(item)"> Apply </v-btn>
|
||||
</template>
|
||||
<template v-slot:[`item.theme.css`]="{ item }">
|
||||
<template #[`item.theme.css`]="{ item }">
|
||||
{{ item.theme.css ? "Yes" : "No" }}
|
||||
</template>
|
||||
</v-data-table>
|
||||
|
@ -78,6 +78,9 @@ export default {
|
|||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getThemes()
|
||||
},
|
||||
methods: {
|
||||
applyTheme(theme) {
|
||||
this.axios
|
||||
|
@ -110,9 +113,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getThemes()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,39 +1,36 @@
|
|||
<template>
|
||||
<div id="admin-users">
|
||||
<v-dialog width="500" v-model="create.dialog">
|
||||
<v-dialog v-model="create.dialog" width="500">
|
||||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Create User</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-form @submit.prevent="createUser">
|
||||
<v-text-field v-model="create.username" label="Username" />
|
||||
<v-text-field v-model="create.email" label="Email" />
|
||||
<v-text-field
|
||||
label="Username"
|
||||
v-model="create.username"
|
||||
></v-text-field>
|
||||
<v-text-field label="Email" v-model="create.email"></v-text-field>
|
||||
<v-text-field
|
||||
v-model="create.password"
|
||||
label="Password"
|
||||
type="password"
|
||||
v-model="create.password"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-switch
|
||||
v-model="create.emailVerified"
|
||||
inset
|
||||
label="Email Verified?"
|
||||
v-model="create.emailVerified"
|
||||
></v-switch>
|
||||
<v-btn text type="submit" color="primary">Create</v-btn>
|
||||
/>
|
||||
<v-btn text type="submit" color="primary"> Create </v-btn>
|
||||
</v-form>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>Users ({{ users.count }})</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn @click="create.dialog = true" icon>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="create.dialog = true">
|
||||
<v-icon>mdi-plus</v-icon>
|
||||
</v-btn>
|
||||
<v-btn @click="getUsers" icon>
|
||||
<v-btn icon @click="getUsers">
|
||||
<v-icon>mdi-refresh</v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
|
@ -46,17 +43,17 @@
|
|||
$vuetify.theme.themes[$vuetify.theme.dark ? 'dark' : 'light'].card
|
||||
"
|
||||
>
|
||||
<template v-slot:[`item.index`]="{ index }">
|
||||
<template #[`item.index`]="{ index }">
|
||||
{{ index }}
|
||||
</template>
|
||||
<template v-slot:[`item.actions`]="{ item }">
|
||||
<template #[`item.actions`]="{ item }">
|
||||
<v-tooltip top>
|
||||
<template v-slot:activator="{ on }">
|
||||
<template #activator="{ on }">
|
||||
<v-btn
|
||||
v-on="on"
|
||||
icon
|
||||
@click="banUser(item)"
|
||||
:disabled="item.id === $store.state.user.id || item.admin"
|
||||
v-on="on"
|
||||
@click="banUser(item)"
|
||||
>
|
||||
<v-icon>mdi-gavel</v-icon>
|
||||
</v-btn>
|
||||
|
@ -141,6 +138,9 @@ export default {
|
|||
]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getUsers()
|
||||
},
|
||||
methods: {
|
||||
createUser() {
|
||||
this.axios
|
||||
|
@ -197,9 +197,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getUsers()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
:chat="selectedChat"
|
||||
:loading="false"
|
||||
:items="$store.state.chats"
|
||||
></router-view>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -23,6 +23,11 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedChat() {
|
||||
this.$store.commit("setSelectedChat", this.selectedChat)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.on("memberListUpdate", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
|
@ -30,11 +35,6 @@ export default {
|
|||
if (!this.$route.params.id) {
|
||||
this.$router.push("/communications/friends")
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedChat() {
|
||||
this.$store.commit("setSelectedChat", this.selectedChat)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<div id="communications-chat" @dragover.prevent @drop.prevent="handleDrag">
|
||||
<v-menu
|
||||
v-model="$store.state.context.pins.value"
|
||||
:position-x="$store.state.context.pins.x"
|
||||
:position-y="60"
|
||||
v-model="$store.state.context.pins.value"
|
||||
class="rounded-l elevation-7"
|
||||
absolute
|
||||
transition="scroll-y-transition"
|
||||
|
@ -12,24 +12,24 @@
|
|||
>
|
||||
<v-card min-width="400" max-width="400" color="toolbar">
|
||||
<v-toolbar color="toolbar lighten-1">
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-toolbar-title> Pins </v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-divider></v-divider>
|
||||
<v-divider />
|
||||
<v-container>
|
||||
<v-list dense v-if="pins.length" :max-height="600">
|
||||
<v-list v-if="pins.length" dense :max-height="600">
|
||||
<v-list-item
|
||||
@click="jumpToMessage(pin.message.id)"
|
||||
v-for="(pin, index) in pins"
|
||||
:key="index"
|
||||
@click="jumpToMessage(pin.message.id)"
|
||||
>
|
||||
<SimpleMessage
|
||||
:key="pin.message.keyId"
|
||||
:message="pin.message"
|
||||
:index="index"
|
||||
:key="pin.message.keyId"
|
||||
></SimpleMessage>
|
||||
<v-spacer></v-spacer>
|
||||
/>
|
||||
<v-spacer />
|
||||
<v-btn icon text @click.stop="removePin(pin.messageId)">
|
||||
<v-icon> mdi-close </v-icon>
|
||||
</v-btn>
|
||||
|
@ -52,7 +52,7 @@
|
|||
offset-y
|
||||
class="rounded-l"
|
||||
>
|
||||
<v-list class="rounded-l" v-if="context.message.item">
|
||||
<v-list v-if="context.message.item" class="rounded-l">
|
||||
<v-list-item @click="copy(context.message.item.content)">
|
||||
<v-list-item-title>Copy Message Content</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
@ -60,15 +60,15 @@
|
|||
<v-list-item-title>Reply to Message</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item
|
||||
v-if="
|
||||
context.message.item.userId === $store.state.user.id &&
|
||||
edit.id !== context.message.item.id
|
||||
"
|
||||
@click="
|
||||
edit.content = context.message.item.content
|
||||
edit.editing = true
|
||||
edit.id = context.message.item.id
|
||||
"
|
||||
v-if="
|
||||
context.message.item.userId === $store.state.user.id &&
|
||||
edit.id !== context.message.item.id
|
||||
"
|
||||
>
|
||||
<v-list-item-title>Edit Message</v-list-item-title>
|
||||
</v-list-item>
|
||||
|
@ -81,9 +81,9 @@
|
|||
</v-list>
|
||||
</v-menu>
|
||||
<UserDialog
|
||||
:user="context.userPopout"
|
||||
:key="context.userPopout.item?.id || 0"
|
||||
></UserDialog>
|
||||
:user="context.userPopout"
|
||||
/>
|
||||
<NicknameDialog :nickname="nickname" />
|
||||
<v-dialog
|
||||
v-model="preview.dialog"
|
||||
|
@ -100,7 +100,7 @@
|
|||
:max-height="600"
|
||||
:min-height="300"
|
||||
contain
|
||||
></v-img>
|
||||
/>
|
||||
<v-container>
|
||||
<a :href="preview.src" style="text-decoration: none" target="_blank">
|
||||
<small> Open Externally </small>
|
||||
|
@ -115,10 +115,10 @@
|
|||
</v-card>
|
||||
</v-dialog>
|
||||
<v-navigation-drawer
|
||||
v-if="$vuetify.breakpoint.mobile"
|
||||
v-model="$store.state.userPanel"
|
||||
color="bg"
|
||||
floating
|
||||
v-if="$vuetify.breakpoint.mobile"
|
||||
app
|
||||
right
|
||||
style="z-index: 100"
|
||||
|
@ -127,10 +127,10 @@
|
|||
<v-list-item-group class="rounded-xl">
|
||||
<template v-for="item in associations">
|
||||
<v-list-item
|
||||
:id="'user-popout-' + item.userId"
|
||||
:key="item.title"
|
||||
@contextmenu="show($event, 'user', item.user)"
|
||||
@click="openUserPanel(item.user)"
|
||||
:id="'user-popout-' + item.userId"
|
||||
>
|
||||
<v-badge
|
||||
bordered
|
||||
|
@ -162,10 +162,10 @@
|
|||
</v-list-item-group>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
<v-row @drop="handleDrag" no-gutters style="overflow: hidden">
|
||||
<v-row no-gutters style="overflow: hidden" @drop="handleDrag">
|
||||
<v-col
|
||||
class="flex-grow-1 flex-shrink-1 pb-0"
|
||||
id="chat-col"
|
||||
class="flex-grow-1 flex-shrink-1 pb-0"
|
||||
style="overflow: hidden"
|
||||
>
|
||||
<v-card
|
||||
|
@ -176,40 +176,41 @@
|
|||
>
|
||||
<v-card-text>
|
||||
<v-toolbar
|
||||
@click="jumpToMessage(replying?.id)"
|
||||
v-if="replying"
|
||||
elevation="0"
|
||||
height="35"
|
||||
color="card"
|
||||
v-if="replying"
|
||||
style="cursor: pointer; overflow: hidden"
|
||||
@click="jumpToMessage(replying?.id)"
|
||||
>
|
||||
<v-icon class="mr-2">mdi-reply</v-icon>
|
||||
<v-icon class="mr-2"> mdi-reply </v-icon>
|
||||
<v-avatar size="24" class="mr-2">
|
||||
<v-img
|
||||
v-if="replying.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent/' +
|
||||
replying.user.avatar
|
||||
"
|
||||
v-if="replying.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else class="elevation-1"> mdi-account </v-icon>
|
||||
</v-avatar>
|
||||
<template v-if="replying.attachments.length">
|
||||
<v-icon class="mr-2">mdi-file-image</v-icon>
|
||||
<v-icon class="mr-2"> mdi-file-image </v-icon>
|
||||
</template>
|
||||
<template v-if="!replying.content && replying.attachments.length">
|
||||
Click to view attachment
|
||||
</template>
|
||||
{{ replying.content.substring(0, 100) }}
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn icon @click="replying = null" class="mr-2" small>
|
||||
<v-spacer />
|
||||
<v-btn icon class="mr-2" small @click="replying = null">
|
||||
<v-icon> mdi-close </v-icon>
|
||||
</v-btn>
|
||||
</v-toolbar>
|
||||
<v-fade-transition v-model="avoidAutoScroll">
|
||||
<v-toolbar
|
||||
v-if="avoidAutoScroll"
|
||||
height="24"
|
||||
color="toolbar"
|
||||
elevation="0"
|
||||
|
@ -223,7 +224,6 @@
|
|||
"
|
||||
width="100%"
|
||||
@click="forceScroll"
|
||||
v-if="avoidAutoScroll"
|
||||
>
|
||||
<div>
|
||||
<v-icon size="16px"> mdi-arrow-down </v-icon>
|
||||
|
@ -232,17 +232,17 @@
|
|||
</v-toolbar>
|
||||
</v-fade-transition>
|
||||
<v-fade-transition
|
||||
v-model="usersTyping.length"
|
||||
v-if="$vuetify.breakpoint.mobile"
|
||||
v-model="usersTyping.length"
|
||||
>
|
||||
<div
|
||||
v-if="usersTyping.length"
|
||||
style="
|
||||
border-radius: 0 0 20px 20px;
|
||||
position: relative;
|
||||
top: -30px;
|
||||
margin-bottom: -22px;
|
||||
"
|
||||
v-if="usersTyping.length"
|
||||
>
|
||||
{{ usersTyping.map((user) => getName(user)).join(", ") }}
|
||||
{{ usersTyping.length > 1 ? " are" : " is" }} typing...
|
||||
|
@ -251,29 +251,29 @@
|
|||
<CommsInput
|
||||
:chat="chat"
|
||||
:replying="replying"
|
||||
:editLastMessage="editLastMessage"
|
||||
:autoScroll="autoScroll"
|
||||
:endSend="endSend"
|
||||
></CommsInput>
|
||||
:edit-last-message="editLastMessage"
|
||||
:auto-scroll="autoScroll"
|
||||
:end-send="endSend"
|
||||
/>
|
||||
<v-fade-transition
|
||||
v-model="usersTyping.length"
|
||||
v-if="!$vuetify.breakpoint.mobile"
|
||||
v-model="usersTyping.length"
|
||||
>
|
||||
<div
|
||||
v-if="usersTyping.length"
|
||||
style="
|
||||
border-radius: 0 0 20px 20px;
|
||||
position: absolute;
|
||||
margin-top: -2px;
|
||||
bottom: 1px;
|
||||
"
|
||||
v-if="usersTyping.length"
|
||||
>
|
||||
{{ usersTyping.map((user) => getName(user)).join(", ") }}
|
||||
{{ usersTyping.length > 1 ? " are" : " is" }} typing...
|
||||
</div>
|
||||
</v-fade-transition>
|
||||
</v-card-text>
|
||||
<v-card-text class="flex-grow-1 overflow-y-auto" id="message-list">
|
||||
<v-card-text id="message-list" class="flex-grow-1 overflow-y-auto">
|
||||
<v-card-title
|
||||
v-if="
|
||||
reachedTop && $store.state.selectedChat?.chat?.type === 'group'
|
||||
|
@ -299,11 +299,11 @@
|
|||
indeterminate
|
||||
size="64"
|
||||
style="display: block; width: 100px; margin: 0 auto"
|
||||
></v-progress-circular>
|
||||
/>
|
||||
<template v-for="(message, index) in messages">
|
||||
<div
|
||||
:key="'div2-' + message.keyId"
|
||||
v-if="message.readReceipts.length"
|
||||
:key="'div2-' + message.keyId"
|
||||
>
|
||||
<v-tooltip
|
||||
v-for="association in message.readReceipts"
|
||||
|
@ -311,8 +311,8 @@
|
|||
top
|
||||
>
|
||||
<template
|
||||
v-slot:activator="{ on }"
|
||||
v-if="association.user.id !== $store.state.user.id"
|
||||
#activator="{ on }"
|
||||
>
|
||||
<v-btn
|
||||
icon
|
||||
|
@ -324,7 +324,7 @@
|
|||
style="float: right"
|
||||
@click="openUserPanel(association.user)"
|
||||
>
|
||||
<v-avatar size="20" v-on="on" color="primary">
|
||||
<v-avatar size="20" color="primary" v-on="on">
|
||||
<img
|
||||
v-if="association.user.avatar"
|
||||
:src="
|
||||
|
@ -371,16 +371,16 @@
|
|||
!message.replyId &&
|
||||
!message.type
|
||||
"
|
||||
></Message>
|
||||
/>
|
||||
</template>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="$store.state.searchPanel && !$vuetify.breakpoint.mobile"
|
||||
id="search-col"
|
||||
cols="3"
|
||||
class=""
|
||||
id="search-col"
|
||||
v-if="$store.state.searchPanel && !$vuetify.breakpoint.mobile"
|
||||
style="z-index: 15"
|
||||
>
|
||||
<v-card
|
||||
|
@ -393,7 +393,7 @@
|
|||
<v-toolbar-title>
|
||||
Search ({{ search.pager.totalItems || 0 }})
|
||||
</v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn icon @click="$store.state.searchPanel = false">
|
||||
<v-icon>mdi-close</v-icon>
|
||||
</v-btn>
|
||||
|
@ -405,13 +405,13 @@
|
|||
outlined
|
||||
autofocus
|
||||
@keydown.enter="doSearch"
|
||||
></v-text-field>
|
||||
<v-list two-line color="card" ref="message-list-search">
|
||||
/>
|
||||
<v-list ref="message-list-search" two-line color="card">
|
||||
<template v-for="(message, index) in search.results">
|
||||
<div
|
||||
@click="jumpToMessage(message.id)"
|
||||
:key="message.keyId"
|
||||
style="cursor: pointer"
|
||||
@click="jumpToMessage(message.id)"
|
||||
>
|
||||
<Message
|
||||
:message="message"
|
||||
|
@ -428,7 +428,7 @@
|
|||
:set-image-preview="setImagePreview"
|
||||
:delete-message="deleteMessage"
|
||||
:last-message="false"
|
||||
></Message>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<v-pagination
|
||||
|
@ -436,19 +436,19 @@
|
|||
class="my-4"
|
||||
:length="search.pager.totalPages"
|
||||
@input="doSearch"
|
||||
></v-pagination>
|
||||
/>
|
||||
</v-list>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-col>
|
||||
<v-col
|
||||
:cols="$vuetify.breakpoint.xl ? 2 : 3"
|
||||
id="user-col"
|
||||
v-if="
|
||||
$store.state.userPanel &&
|
||||
!$vuetify.breakpoint.mobile &&
|
||||
!$store.state.searchPanel
|
||||
"
|
||||
id="user-col"
|
||||
:cols="$vuetify.breakpoint.xl ? 2 : 3"
|
||||
>
|
||||
<v-card
|
||||
class="d-flex flex-column fill-height rounded-0"
|
||||
|
@ -464,17 +464,17 @@
|
|||
offset-y
|
||||
class="rounded-l"
|
||||
>
|
||||
<v-list class="rounded-l" v-if="context.user.item">
|
||||
<v-list v-if="context.user.item" class="rounded-l">
|
||||
<v-list-item
|
||||
@click="
|
||||
nickname.dialog = true
|
||||
nickname.user = context.user.item
|
||||
"
|
||||
>
|
||||
<v-list-item-title
|
||||
>Change Friend Nickname for
|
||||
{{ context.user.item.username }}</v-list-item-title
|
||||
>
|
||||
<v-list-item-title>
|
||||
Change Friend Nickname for
|
||||
{{ context.user.item.username }}
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
|
@ -482,10 +482,10 @@
|
|||
<v-list-item-group class="rounded-xl">
|
||||
<template v-for="item in associations">
|
||||
<v-list-item
|
||||
:id="'user-popout-' + item.userId"
|
||||
:key="item.title"
|
||||
@contextmenu="show($event, 'user', item.user)"
|
||||
@click="openUserPanel(item.user)"
|
||||
:id="'user-popout-' + item.userId"
|
||||
>
|
||||
<v-badge
|
||||
bordered
|
||||
|
@ -513,25 +513,25 @@
|
|||
<v-list-item-content>
|
||||
<v-list-item-title>
|
||||
{{ getName(item.user) }}
|
||||
<v-tooltip top v-if="item.user.admin">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="item.user.admin" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-crown </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Colubrina Instance Administrator</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top v-if="item.user.bot">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="item.user.bot" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-robot </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<span>Bot</span>
|
||||
</v-tooltip>
|
||||
<v-tooltip top v-if="item.user.id < 35">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" small>
|
||||
<v-tooltip v-if="item.user.id < 35" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon small v-on="on">
|
||||
<v-icon> mdi-alpha-a-circle </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
@ -709,6 +709,178 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"$store.state.context.pins.value"(val) {
|
||||
if (val) {
|
||||
this.getPins()
|
||||
}
|
||||
},
|
||||
userPanel() {
|
||||
localStorage.setItem("userPanel", JSON.stringify(this.userPanel))
|
||||
},
|
||||
"$route.path"() {
|
||||
const tryParse = this.$route.params.id
|
||||
if (!tryParse) {
|
||||
// remove event listeners
|
||||
document.removeEventListener("keypress", this.focusKey)
|
||||
document.removeEventListener("keydown", this.escPressed)
|
||||
document
|
||||
.getElementById("message-list")
|
||||
.removeEventListener("scroll", this.scrollEvent)
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
},
|
||||
"$route.params.id"(val, oldVal) {
|
||||
this.focusInput()
|
||||
let drafts = {}
|
||||
if (localStorage.getItem("drafts")) {
|
||||
drafts = JSON.parse(localStorage.getItem("drafts"))
|
||||
}
|
||||
if (this.message && drafts[oldVal]) {
|
||||
drafts[oldVal] = this.message
|
||||
localStorage.setItem("drafts", JSON.stringify(drafts))
|
||||
} else if (!this.message && drafts[oldVal]) {
|
||||
drafts[oldVal] = ""
|
||||
}
|
||||
this.message = drafts[val] || ""
|
||||
this.usersTyping = []
|
||||
this.replying = null
|
||||
this.reachedTop = false
|
||||
this.avoidAutoScroll = false
|
||||
this.offset = null
|
||||
this.pins = []
|
||||
this.messages = []
|
||||
this.getMessages()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.on("memberListUpdate", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
if (!this.$route.params.id) {
|
||||
this.$router.push("/communications/friends")
|
||||
return
|
||||
}
|
||||
document.addEventListener("keypress", this.focusKey)
|
||||
document.addEventListener("keydown", this.escPressed)
|
||||
document
|
||||
.getElementById("message-list")
|
||||
.addEventListener("scroll", this.scrollEvent)
|
||||
this.interval = setInterval(() => {
|
||||
this.typing()
|
||||
if (
|
||||
document.hasFocus() &&
|
||||
this.messages[this.messages.length - 1]?.id !== this.lastRead
|
||||
) {
|
||||
this.markRead()
|
||||
}
|
||||
}, 1000)
|
||||
this.getMessages()
|
||||
if (localStorage.getItem("userPanel")) {
|
||||
this.userPanel = JSON.parse(localStorage.getItem("userPanel"))
|
||||
} else {
|
||||
localStorage.setItem("userPanel", true)
|
||||
}
|
||||
let drafts = {}
|
||||
if (localStorage.getItem("drafts")) {
|
||||
drafts = JSON.parse(localStorage.getItem("drafts"))
|
||||
}
|
||||
if (drafts[this.$route.params.id]) {
|
||||
this.message = drafts[this.$route.params.id]
|
||||
}
|
||||
this.$socket.on("readChat", (data) => {
|
||||
if (!this.chat) return
|
||||
if (data.id === this.chat?.id) {
|
||||
this.lastRead = data.lastRead
|
||||
}
|
||||
})
|
||||
this.$socket.on("readReceipt", (data) => {
|
||||
if (!this.chat) return
|
||||
try {
|
||||
if (
|
||||
data.messageId &&
|
||||
data.chatId === this.chat.chatId &&
|
||||
this.messages?.length
|
||||
) {
|
||||
this.messages.forEach((message) => {
|
||||
message.readReceipts = message.readReceipts.filter(
|
||||
(readReceipt) => readReceipt.id !== data.id
|
||||
)
|
||||
})
|
||||
this.messages
|
||||
.find((message) => message.id === data.messageId)
|
||||
.readReceipts?.push(data)
|
||||
this.autoScroll()
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Read receipt error", e)
|
||||
}
|
||||
})
|
||||
this.$socket.on("message", (message) => {
|
||||
try {
|
||||
if (!this.chat) return
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
this.messages.push(message)
|
||||
this.autoScroll()
|
||||
if (document.hasFocus()) {
|
||||
this.markRead()
|
||||
}
|
||||
if (this.messages.length > 50 && !this.avoidAutoScroll) {
|
||||
this.messages.shift()
|
||||
this.reachedTop = false
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Message error", e)
|
||||
}
|
||||
})
|
||||
this.$socket.on("editMessage", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages[index].content = message.content
|
||||
this.messages[index].edited = message.edited
|
||||
this.messages[index].editedAt = message.editedAt
|
||||
this.messages[index].keyId = message.id + "-" + message.editedAt
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$socket.on("messageEmbedResolved", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages[index].keyId = message.id + "-" + message.editedAt
|
||||
this.messages[index].embeds = message.embeds
|
||||
this.autoScroll()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$socket.on("typing", (event) => {
|
||||
if (event.chatId === this.chat.chatId) {
|
||||
const index = this.usersTyping.findIndex(
|
||||
(item) => item.userId === event.userId
|
||||
)
|
||||
if (index > -1) {
|
||||
this.usersTyping.splice(index, 1)
|
||||
}
|
||||
this.usersTyping.push(event)
|
||||
}
|
||||
})
|
||||
this.$socket.on("deleteMessage", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener("keypress", this.focusKey)
|
||||
document.removeEventListener("keydown", this.escPressed)
|
||||
document.removeEventListener("scroll", this.scrollEvent)
|
||||
clearInterval(this.interval)
|
||||
},
|
||||
methods: {
|
||||
copy(content) {
|
||||
navigator.clipboard.writeText(content)
|
||||
|
@ -1090,178 +1262,6 @@ export default {
|
|||
this.$store.state.searchPanel = false
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$socket.on("memberListUpdate", () => {
|
||||
this.$store.dispatch("getChats")
|
||||
})
|
||||
if (!this.$route.params.id) {
|
||||
this.$router.push("/communications/friends")
|
||||
return
|
||||
}
|
||||
document.addEventListener("keypress", this.focusKey)
|
||||
document.addEventListener("keydown", this.escPressed)
|
||||
document
|
||||
.getElementById("message-list")
|
||||
.addEventListener("scroll", this.scrollEvent)
|
||||
this.interval = setInterval(() => {
|
||||
this.typing()
|
||||
if (
|
||||
document.hasFocus() &&
|
||||
this.messages[this.messages.length - 1]?.id !== this.lastRead
|
||||
) {
|
||||
this.markRead()
|
||||
}
|
||||
}, 1000)
|
||||
this.getMessages()
|
||||
if (localStorage.getItem("userPanel")) {
|
||||
this.userPanel = JSON.parse(localStorage.getItem("userPanel"))
|
||||
} else {
|
||||
localStorage.setItem("userPanel", true)
|
||||
}
|
||||
let drafts = {}
|
||||
if (localStorage.getItem("drafts")) {
|
||||
drafts = JSON.parse(localStorage.getItem("drafts"))
|
||||
}
|
||||
if (drafts[this.$route.params.id]) {
|
||||
this.message = drafts[this.$route.params.id]
|
||||
}
|
||||
this.$socket.on("readChat", (data) => {
|
||||
if (!this.chat) return
|
||||
if (data.id === this.chat?.id) {
|
||||
this.lastRead = data.lastRead
|
||||
}
|
||||
})
|
||||
this.$socket.on("readReceipt", (data) => {
|
||||
if (!this.chat) return
|
||||
try {
|
||||
if (
|
||||
data.messageId &&
|
||||
data.chatId === this.chat.chatId &&
|
||||
this.messages?.length
|
||||
) {
|
||||
this.messages.forEach((message) => {
|
||||
message.readReceipts = message.readReceipts.filter(
|
||||
(readReceipt) => readReceipt.id !== data.id
|
||||
)
|
||||
})
|
||||
this.messages
|
||||
.find((message) => message.id === data.messageId)
|
||||
.readReceipts?.push(data)
|
||||
this.autoScroll()
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Read receipt error", e)
|
||||
}
|
||||
})
|
||||
this.$socket.on("message", (message) => {
|
||||
try {
|
||||
if (!this.chat) return
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
this.messages.push(message)
|
||||
this.autoScroll()
|
||||
if (document.hasFocus()) {
|
||||
this.markRead()
|
||||
}
|
||||
if (this.messages.length > 50 && !this.avoidAutoScroll) {
|
||||
this.messages.shift()
|
||||
this.reachedTop = false
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Message error", e)
|
||||
}
|
||||
})
|
||||
this.$socket.on("editMessage", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages[index].content = message.content
|
||||
this.messages[index].edited = message.edited
|
||||
this.messages[index].editedAt = message.editedAt
|
||||
this.messages[index].keyId = message.id + "-" + message.editedAt
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$socket.on("messageEmbedResolved", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages[index].keyId = message.id + "-" + message.editedAt
|
||||
this.messages[index].embeds = message.embeds
|
||||
this.autoScroll()
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$socket.on("typing", (event) => {
|
||||
if (event.chatId === this.chat.chatId) {
|
||||
const index = this.usersTyping.findIndex(
|
||||
(item) => item.userId === event.userId
|
||||
)
|
||||
if (index > -1) {
|
||||
this.usersTyping.splice(index, 1)
|
||||
}
|
||||
this.usersTyping.push(event)
|
||||
}
|
||||
})
|
||||
this.$socket.on("deleteMessage", (message) => {
|
||||
if (message.chatId === this.chat.chatId) {
|
||||
const index = this.messages.findIndex((item) => item.id === message.id)
|
||||
if (index !== -1) {
|
||||
this.messages.splice(index, 1)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
"$store.state.context.pins.value"(val) {
|
||||
if (val) {
|
||||
this.getPins()
|
||||
}
|
||||
},
|
||||
userPanel() {
|
||||
localStorage.setItem("userPanel", JSON.stringify(this.userPanel))
|
||||
},
|
||||
"$route.path"() {
|
||||
const tryParse = this.$route.params.id
|
||||
if (!tryParse) {
|
||||
// remove event listeners
|
||||
document.removeEventListener("keypress", this.focusKey)
|
||||
document.removeEventListener("keydown", this.escPressed)
|
||||
document
|
||||
.getElementById("message-list")
|
||||
.removeEventListener("scroll", this.scrollEvent)
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
},
|
||||
"$route.params.id"(val, oldVal) {
|
||||
this.focusInput()
|
||||
let drafts = {}
|
||||
if (localStorage.getItem("drafts")) {
|
||||
drafts = JSON.parse(localStorage.getItem("drafts"))
|
||||
}
|
||||
if (this.message && drafts[oldVal]) {
|
||||
drafts[oldVal] = this.message
|
||||
localStorage.setItem("drafts", JSON.stringify(drafts))
|
||||
} else if (!this.message && drafts[oldVal]) {
|
||||
drafts[oldVal] = ""
|
||||
}
|
||||
this.message = drafts[val] || ""
|
||||
this.usersTyping = []
|
||||
this.replying = null
|
||||
this.reachedTop = false
|
||||
this.avoidAutoScroll = false
|
||||
this.offset = null
|
||||
this.pins = []
|
||||
this.messages = []
|
||||
this.getMessages()
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener("keypress", this.focusKey)
|
||||
document.removeEventListener("keydown", this.escPressed)
|
||||
document.removeEventListener("scroll", this.scrollEvent)
|
||||
clearInterval(this.interval)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div id="communications-friends">
|
||||
<v-card color="card" class="rounded-0" :height="viewport()" elevation="0">
|
||||
<v-tabs centered background-color="card" v-model="tab">
|
||||
<v-tab :key="0">Users</v-tab>
|
||||
<v-tabs v-model="tab" centered background-color="card">
|
||||
<v-tab :key="0"> Users </v-tab>
|
||||
<v-tab :key="1"> Friends </v-tab>
|
||||
<v-tab :key="2"> Add new friend </v-tab>
|
||||
<v-tab-item
|
||||
|
@ -16,31 +16,31 @@
|
|||
<v-toolbar-title> Users </v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-card color="card" elevation="0">
|
||||
<v-list color="card" v-if="$store.state.site.publicUsers">
|
||||
<v-list v-if="$store.state.site.publicUsers" color="card">
|
||||
<v-list-item v-for="user in users" :key="user.id">
|
||||
<v-list-item-avatar
|
||||
@click="userProfile(user)"
|
||||
style="cursor: pointer"
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
@click="userProfile(user)"
|
||||
>
|
||||
<v-img
|
||||
v-if="user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL + '/usercontent//' + user.avatar
|
||||
"
|
||||
v-if="user.avatar"
|
||||
/>
|
||||
<v-icon v-else> mdi-account </v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
||||
<v-list-item-content
|
||||
@click="userProfile(user)"
|
||||
style="cursor: pointer"
|
||||
@click="userProfile(user)"
|
||||
>
|
||||
<v-list-item-title>
|
||||
{{ user.username }}
|
||||
<v-tooltip top v-if="user.admin">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn icon v-on="on" class="ml-1">
|
||||
<v-tooltip v-if="user.admin" top>
|
||||
<template #activator="{ on }">
|
||||
<v-btn icon class="ml-1" v-on="on">
|
||||
<v-icon> mdi-crown </v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
@ -55,7 +55,9 @@
|
|||
"
|
||||
>
|
||||
<v-btn icon>
|
||||
<v-icon @click="addFriend(user)">mdi-account-plus</v-icon>
|
||||
<v-icon @click="addFriend(user)">
|
||||
mdi-account-plus
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
<v-list-item-action
|
||||
|
@ -70,9 +72,9 @@
|
|||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
<v-card-title v-else
|
||||
>Public users are not enabled on this instance.</v-card-title
|
||||
>
|
||||
<v-card-title v-else>
|
||||
Public users are not enabled on this instance.
|
||||
</v-card-title>
|
||||
</v-card>
|
||||
</v-card>
|
||||
</v-tab-item>
|
||||
|
@ -100,16 +102,16 @@
|
|||
:key="friend.id"
|
||||
>
|
||||
<v-list-item-avatar
|
||||
@click="userProfile(friend.user2)"
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
@click="userProfile(friend.user2)"
|
||||
>
|
||||
<v-img
|
||||
v-if="friend.user2.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent//' +
|
||||
friend.user2.avatar
|
||||
"
|
||||
v-if="friend.user2.avatar"
|
||||
/>
|
||||
<v-icon v-else> mdi-account </v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
@ -121,16 +123,16 @@
|
|||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-btn icon>
|
||||
<v-icon color="error" @click="removeFriend(friend)"
|
||||
>mdi-close</v-icon
|
||||
>
|
||||
<v-icon color="error" @click="removeFriend(friend)">
|
||||
mdi-close
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
<v-list-item-action>
|
||||
<v-btn icon>
|
||||
<v-icon color="success" @click="acceptFriend(friend)">
|
||||
mdi-check</v-icon
|
||||
>
|
||||
mdi-check
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
|
@ -153,24 +155,24 @@
|
|||
:key="friend.id"
|
||||
>
|
||||
<v-list-item-avatar
|
||||
@click="userProfile(friend.user2)"
|
||||
style="cursor: pointer"
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
@click="userProfile(friend.user2)"
|
||||
>
|
||||
<v-img
|
||||
v-if="friend.user2.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent//' +
|
||||
friend.user2.avatar
|
||||
"
|
||||
v-if="friend.user2.avatar"
|
||||
/>
|
||||
<v-icon v-else> mdi-account </v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
||||
<v-list-item-content
|
||||
@click="userProfile(friend.user2)"
|
||||
style="cursor: pointer"
|
||||
@click="userProfile(friend.user2)"
|
||||
>
|
||||
<v-list-item-title>
|
||||
{{ friend.user2.username }}
|
||||
|
@ -178,9 +180,9 @@
|
|||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-btn icon>
|
||||
<v-icon color="error" @click="removeFriend(friend)"
|
||||
>mdi-close</v-icon
|
||||
>
|
||||
<v-icon color="error" @click="removeFriend(friend)">
|
||||
mdi-close
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
|
@ -200,17 +202,17 @@
|
|||
</v-list-item>
|
||||
<v-list-item v-for="friend in computeAccepted" :key="friend.id">
|
||||
<v-list-item-avatar
|
||||
@click="userProfile(friend.user2)"
|
||||
style="cursor: pointer"
|
||||
:color="$vuetify.theme.themes.dark?.primary"
|
||||
@click="userProfile(friend.user2)"
|
||||
>
|
||||
<v-img
|
||||
v-if="friend.user2.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent//' +
|
||||
friend.user2.avatar
|
||||
"
|
||||
v-if="friend.user2.avatar"
|
||||
/>
|
||||
<v-icon v-else> mdi-account </v-icon>
|
||||
</v-list-item-avatar>
|
||||
|
@ -222,9 +224,9 @@
|
|||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-btn icon>
|
||||
<v-icon color="error" @click="removeFriend(friend)"
|
||||
>mdi-close</v-icon
|
||||
>
|
||||
<v-icon color="error" @click="removeFriend(friend)">
|
||||
mdi-close
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
|
@ -246,15 +248,14 @@
|
|||
friends with them. You can add them here.
|
||||
</p>
|
||||
<v-text-field
|
||||
@keyup.enter="addFriend(null)"
|
||||
v-model="friend"
|
||||
label="Friend username"
|
||||
:placeholder="'BTR0001'"
|
||||
v-model="friend"
|
||||
>
|
||||
</v-text-field>
|
||||
@keyup.enter="addFriend(null)"
|
||||
/>
|
||||
</v-container>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn color="primary" text @click="addFriend(null)">
|
||||
Send Request
|
||||
</v-btn>
|
||||
|
@ -292,6 +293,19 @@ export default {
|
|||
)
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.getFriends()
|
||||
this.getUsers()
|
||||
this.$socket.on("friendRequest", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
this.$socket.on("friendUpdate", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
this.$socket.on("friendAccepted", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
userProfile() {
|
||||
// todo
|
||||
|
@ -372,19 +386,6 @@ export default {
|
|||
this.friends = res.data
|
||||
})
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.getFriends()
|
||||
this.getUsers()
|
||||
this.$socket.on("friendRequest", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
this.$socket.on("friendUpdate", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
this.$socket.on("friendAccepted", () => {
|
||||
this.getFriends()
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -6,11 +6,7 @@
|
|||
<v-toolbar-title> Email Confirmation </v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-container v-if="loading" class="text-center justify-center">
|
||||
<v-progress-circular
|
||||
size="64"
|
||||
:indeterminate="true"
|
||||
class="mb-3"
|
||||
></v-progress-circular>
|
||||
<v-progress-circular size="64" :indeterminate="true" class="mb-3" />
|
||||
<h3>We're currently confirming your email address. Please wait.</h3>
|
||||
</v-container>
|
||||
<v-container v-else-if="failed" class="text-center justify-center">
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
follow the instructions provided.
|
||||
</h3>
|
||||
<p class="mt-2">Haven't received it?</p>
|
||||
<v-btn color="primary" text @click="resend" :loading="loading"
|
||||
>Resend</v-btn
|
||||
>
|
||||
<v-btn color="primary" text :loading="loading" @click="resend">
|
||||
Resend
|
||||
</v-btn>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
@ -30,6 +30,9 @@ export default {
|
|||
loading: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.resend()
|
||||
},
|
||||
methods: {
|
||||
resend() {
|
||||
this.loading = true
|
||||
|
@ -44,9 +47,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.resend()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
<template>
|
||||
<div id="login" v-if="!$store.state.user?.bcUser?.id">
|
||||
<div v-if="!$store.state.user?.bcUser?.id" id="login">
|
||||
<v-dialog v-model="totpDialog" max-width="500px">
|
||||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title> Two-Factor Authentication </v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-card-text
|
||||
>You are seeing this because you have enabled Two-Factor
|
||||
<v-card-text>
|
||||
You are seeing this because you have enabled Two-Factor
|
||||
Authentication on {{ $store.state.site.name }}.<br />
|
||||
Please check your phone, or authenticator app to obtain the 6 digit
|
||||
code and enter it here.</v-card-text
|
||||
>
|
||||
code and enter it here.
|
||||
</v-card-text>
|
||||
<v-otp-input
|
||||
v-model="totp"
|
||||
length="6"
|
||||
:disabled="loading"
|
||||
@keyup.enter="doLogin()"
|
||||
@finish="doLogin()"
|
||||
v-model="totp"
|
||||
:disabled="loading"
|
||||
></v-otp-input>
|
||||
/>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
|
@ -33,64 +33,60 @@
|
|||
<span class="troplo-title">{{ $store.state.site.name }}</span>
|
||||
</p>
|
||||
<v-text-field
|
||||
@keyup.enter="doLogin()"
|
||||
class="rounded-xl"
|
||||
v-model="instance"
|
||||
v-if="isElectron()"
|
||||
v-model="instance"
|
||||
class="rounded-xl"
|
||||
label="Instance URL"
|
||||
placeholder="https://colubrina.troplo.com"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<small style="float: right" v-if="isElectron()">{{
|
||||
@keyup.enter="doLogin()"
|
||||
/>
|
||||
<small v-if="isElectron()" style="float: right">{{
|
||||
instanceString
|
||||
}}</small
|
||||
><br v-if="isElectron()" />
|
||||
<v-text-field
|
||||
@keyup.enter="doLogin()"
|
||||
class="rounded-xl"
|
||||
v-model="customHeaders[header.name]"
|
||||
v-for="header in $store.state.site.customHeaders"
|
||||
:key="header.name"
|
||||
v-model="customHeaders[header.name]"
|
||||
class="rounded-xl"
|
||||
:label="header.friendlyName"
|
||||
:placeholder="header.placeholder"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
@keyup.enter="doLogin()"
|
||||
class="rounded-xl"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="username"
|
||||
class="rounded-xl"
|
||||
label="Username"
|
||||
placeholder="FOO1000"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
@keyup.enter="doLogin()"
|
||||
class="rounded-xl"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
class="rounded-xl"
|
||||
color="blue accent-7"
|
||||
label="Password"
|
||||
type="password"
|
||||
></v-text-field>
|
||||
@keyup.enter="doLogin()"
|
||||
/>
|
||||
<p
|
||||
style="float: right; color: #2196f3; cursor: pointer"
|
||||
@click="doPasswordReset()"
|
||||
>
|
||||
Reset your Password
|
||||
</p>
|
||||
<v-switch
|
||||
inset
|
||||
label="Remember Me"
|
||||
v-model="rememberMe"
|
||||
></v-switch>
|
||||
<v-switch v-model="rememberMe" inset label="Remember Me" />
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
v-if="$store.state.site.allowRegistrations"
|
||||
class="rounded-xl"
|
||||
:loading="loading"
|
||||
color="primary"
|
||||
text
|
||||
@click="$router.push('/register')"
|
||||
v-if="$store.state.site.allowRegistrations"
|
||||
>
|
||||
Register
|
||||
</v-btn>
|
||||
|
@ -133,18 +129,40 @@ export default {
|
|||
customHeaders: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
instance() {
|
||||
this.testInstance()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
methods: {
|
||||
doPasswordReset() {
|
||||
this.loading = true
|
||||
this.axios.post("/api/v1/user/reset/send", {
|
||||
email: this.username
|
||||
}).then(() => {
|
||||
this.loading = false
|
||||
this.$toast.success("Password reset sent, check your email!")
|
||||
}).catch((e) => {
|
||||
this.loading = false
|
||||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
this.axios
|
||||
.post("/api/v1/user/reset/send", {
|
||||
email: this.username
|
||||
})
|
||||
.then(() => {
|
||||
this.loading = false
|
||||
this.$toast.success("Password reset sent, check your email!")
|
||||
})
|
||||
.catch((e) => {
|
||||
this.loading = false
|
||||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
},
|
||||
isElectron() {
|
||||
return process.env.IS_ELECTRON
|
||||
|
@ -223,25 +241,6 @@ export default {
|
|||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
watch: {
|
||||
instance() {
|
||||
this.testInstance()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
<v-container>
|
||||
<v-card color="card" class="rounded-xl">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-toolbar-title> Not Found </v-toolbar-title>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
</v-toolbar>
|
||||
<v-container class="text-center justify-center">
|
||||
<h1>The page you were looking for couldn't be found.</h1>
|
||||
<v-btn color="primary" text to="/">Home</v-btn>
|
||||
<v-btn color="primary" text to="/"> Home </v-btn>
|
||||
</v-container>
|
||||
</v-card>
|
||||
</v-container>
|
||||
|
|
|
@ -8,23 +8,23 @@
|
|||
<v-card-text>
|
||||
<v-form>
|
||||
<v-text-field
|
||||
@keyup.enter="doPasswordReset()"
|
||||
class="rounded-xl"
|
||||
v-model="password"
|
||||
class="rounded-xl"
|
||||
label="Password"
|
||||
type="password"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
@keyup.enter="doPasswordReset()"
|
||||
class="rounded-xl"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="confirmPassword"
|
||||
class="rounded-xl"
|
||||
label="Confirm Password"
|
||||
type="password"
|
||||
></v-text-field>
|
||||
@keyup.enter="doPasswordReset()"
|
||||
/>
|
||||
</v-form>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="rounded-xl"
|
||||
:loading="loading"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div id="login" v-if="!$store.state.user?.id">
|
||||
<div v-if="!$store.state.user?.id" id="login">
|
||||
<v-dialog v-model="rulesDialog" max-width="700px">
|
||||
<v-card color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
|
@ -8,7 +8,7 @@
|
|||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-card-text class="mt-3" style="color: unset">
|
||||
<span v-markdown :key="$store.state.site.rules">{{
|
||||
<span :key="$store.state.site.rules" v-markdown>{{
|
||||
$store.state.site.rules
|
||||
}}</span>
|
||||
</v-card-text>
|
||||
|
@ -25,80 +25,80 @@
|
|||
<span class="troplo-title">{{ $store.state.site.name }}</span>
|
||||
</p>
|
||||
<v-text-field
|
||||
@keyup.enter="doRegister()"
|
||||
class="rounded-xl"
|
||||
v-model="instance"
|
||||
v-if="isElectron()"
|
||||
v-model="instance"
|
||||
class="rounded-xl"
|
||||
label="Instance URL"
|
||||
placeholder="https://colubrina.troplo.com"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<small style="float: right" v-if="isElectron()">{{
|
||||
@keyup.enter="doRegister()"
|
||||
/>
|
||||
<small v-if="isElectron()" style="float: right">{{
|
||||
instanceString
|
||||
}}</small
|
||||
><br v-if="isElectron()" />
|
||||
<v-text-field
|
||||
@keyup.enter="doRegister()"
|
||||
class="rounded-xl"
|
||||
v-model="username"
|
||||
class="rounded-xl"
|
||||
label="Username"
|
||||
placeholder="FOO1000"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
@keyup.enter="doRegister()"
|
||||
class="rounded-xl"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="email"
|
||||
class="rounded-xl"
|
||||
label="Email"
|
||||
placeholder="troplo@troplo.com"
|
||||
type="email"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
@keyup.enter="doRegister()"
|
||||
class="rounded-xl"
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="password"
|
||||
class="rounded-xl"
|
||||
color="blue accent-7"
|
||||
label="Password"
|
||||
type="password"
|
||||
></v-text-field>
|
||||
@keyup.enter="doRegister()"
|
||||
/>
|
||||
<small v-if="$store.state.site.emailVerification"
|
||||
>This instance has email verification enforced, ensure your
|
||||
email is correct.</small
|
||||
>
|
||||
<v-row align="center">
|
||||
<v-tooltip top v-if="!rulesOpenedOnce">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-tooltip v-if="!rulesOpenedOnce" top>
|
||||
<template #activator="{ on }">
|
||||
<div v-on="on">
|
||||
<v-switch
|
||||
v-model="rules"
|
||||
class="ml-4 mt-5"
|
||||
inset
|
||||
v-model="rules"
|
||||
:disabled="!rulesOpenedOnce"
|
||||
></v-switch>
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<span>You need to view the rules first.</span>
|
||||
</v-tooltip>
|
||||
<v-switch
|
||||
v-else
|
||||
v-model="rules"
|
||||
class="ml-4 mt-5"
|
||||
inset
|
||||
v-model="rules"
|
||||
v-else
|
||||
:disabled="!rulesOpenedOnce"
|
||||
></v-switch>
|
||||
/>
|
||||
I have read and agree to the
|
||||
<a
|
||||
target="_blank"
|
||||
@click="
|
||||
rulesDialog = true
|
||||
rulesOpenedOnce = true
|
||||
"
|
||||
target="_blank"
|
||||
>
|
||||
instance rules </a
|
||||
>.
|
||||
</v-row>
|
||||
<v-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-spacer />
|
||||
<v-btn
|
||||
class="rounded-xl"
|
||||
:loading="loading"
|
||||
|
@ -149,6 +149,25 @@ export default {
|
|||
instanceString: ""
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
instance() {
|
||||
this.testInstance()
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
methods: {
|
||||
isElectron() {
|
||||
return process.env.IS_ELECTRON
|
||||
|
@ -229,25 +248,6 @@ export default {
|
|||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store
|
||||
.dispatch("getUserInfo")
|
||||
.then(() => {
|
||||
this.$router.push("/")
|
||||
})
|
||||
.catch(() => {
|
||||
this.$store.state.user = {
|
||||
bcUser: null,
|
||||
loggedIn: false
|
||||
}
|
||||
})
|
||||
this.testInstance()
|
||||
},
|
||||
watch: {
|
||||
instance() {
|
||||
this.testInstance()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<v-tab to="/settings/security"> Security </v-tab>
|
||||
<v-tab to="/settings/sessions"> Sessions </v-tab>
|
||||
</v-tabs>
|
||||
<router-view> </router-view>
|
||||
<router-view />
|
||||
<div class="mx-4">
|
||||
<small
|
||||
>Troplo/Colubrina version {{ $store.state.versioning.version }},
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
v-model="$store.state.user.theme"
|
||||
true-value="dark"
|
||||
false-value="light"
|
||||
@change="saveSettings"
|
||||
inset
|
||||
label="Dark theme"
|
||||
></v-switch>
|
||||
@change="saveSettings"
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-alert
|
||||
v-if="
|
||||
|
@ -23,41 +23,41 @@
|
|||
You currently have a theme enabled that is not designed for your selected
|
||||
base theme.
|
||||
</v-alert>
|
||||
<v-card-text
|
||||
><v-switch
|
||||
inset
|
||||
<v-card-text>
|
||||
<v-switch
|
||||
v-model="defineAccent"
|
||||
inset
|
||||
label="Use a custom accent color (overrides theme's primary attribute)."
|
||||
></v-switch>
|
||||
/>
|
||||
<v-color-picker
|
||||
v-if="defineAccent"
|
||||
v-model="accent"
|
||||
hide-canvas
|
||||
value="hex"
|
||||
hide-inputs
|
||||
show-swatches
|
||||
swatches-max-height="132"
|
||||
v-model="accent"
|
||||
></v-color-picker>
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-col sm="4">
|
||||
<v-select
|
||||
v-model="$store.state.user.font"
|
||||
:items="fonts"
|
||||
@change="setFont"
|
||||
label="Font"
|
||||
item-text="name"
|
||||
item-value="name"
|
||||
></v-select>
|
||||
@change="setFont"
|
||||
/>
|
||||
</v-col>
|
||||
<v-card-text>
|
||||
<v-card
|
||||
class="my-2"
|
||||
@click="setTheme(theme)"
|
||||
hover
|
||||
outlined
|
||||
v-for="(theme, index) in computeThemes"
|
||||
:key="index"
|
||||
class="my-2"
|
||||
hover
|
||||
outlined
|
||||
color="card"
|
||||
@click="setTheme(theme)"
|
||||
>
|
||||
<v-list-item>
|
||||
<v-list-item-content>
|
||||
|
@ -67,20 +67,20 @@
|
|||
<v-icon>mdi-download</v-icon>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="theme.userId === $store.state.user.id"
|
||||
text
|
||||
fab
|
||||
small
|
||||
@click="initEditTheme(theme)"
|
||||
v-if="theme.userId === $store.state.user.id"
|
||||
>
|
||||
<v-icon>mdi-pencil</v-icon>
|
||||
</v-btn>
|
||||
<v-btn
|
||||
v-if="theme.userId === $store.state.user.id"
|
||||
text
|
||||
fab
|
||||
small
|
||||
@click="doDeleteTheme(theme)"
|
||||
v-if="theme.userId === $store.state.user.id"
|
||||
>
|
||||
<v-icon>mdi-delete</v-icon>
|
||||
</v-btn>
|
||||
|
@ -95,44 +95,44 @@
|
|||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-avatar color="success" size="30" v-if="name === theme.id">
|
||||
<v-avatar v-if="name === theme.id" color="success" size="30">
|
||||
<v-icon>mdi-check</v-icon>
|
||||
</v-avatar>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
<div class="my-2" v-if="$vuetify.theme.dark">
|
||||
<div v-if="$vuetify.theme.dark" class="my-2">
|
||||
<v-chip-group>
|
||||
<v-chip
|
||||
v-for="(key, index) in Object.keys(theme.dark)"
|
||||
:key="index"
|
||||
disabled
|
||||
style="opacity: 1"
|
||||
class="mx-1"
|
||||
label
|
||||
:color="theme.dark[key]"
|
||||
v-for="(key, index) in Object.keys(theme.dark)"
|
||||
:key="index"
|
||||
>
|
||||
{{ friendlyName(key) }}</v-chip
|
||||
>
|
||||
{{ friendlyName(key) }}
|
||||
</v-chip>
|
||||
</v-chip-group>
|
||||
</div>
|
||||
<div class="my-2" v-if="!$vuetify.theme.dark">
|
||||
<div v-if="!$vuetify.theme.dark" class="my-2">
|
||||
<v-chip-group column>
|
||||
<v-chip
|
||||
v-for="(key, index) in Object.keys(theme.light)"
|
||||
:key="index"
|
||||
class="mx-1"
|
||||
label
|
||||
:color="theme.light[key]"
|
||||
v-for="(key, index) in Object.keys(theme.light)"
|
||||
:key="index"
|
||||
>
|
||||
{{ key }}</v-chip
|
||||
>
|
||||
{{ key }}
|
||||
</v-chip>
|
||||
</v-chip-group>
|
||||
</div>
|
||||
</v-card>
|
||||
<v-container class="text-center justify-center">
|
||||
<v-chip @click="initThemeCreator" x-large outlined fab
|
||||
><v-icon x-large>mdi-plus</v-icon></v-chip
|
||||
>
|
||||
<v-chip x-large outlined fab @click="initThemeCreator">
|
||||
<v-icon x-large> mdi-plus </v-icon>
|
||||
</v-chip>
|
||||
</v-container>
|
||||
</v-card-text>
|
||||
</div>
|
||||
|
@ -229,6 +229,52 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
"$store.state.themeEngine.editor"() {
|
||||
this.getThemes()
|
||||
},
|
||||
"$store.state.themeEngine.cssEditor"() {
|
||||
this.getThemes()
|
||||
},
|
||||
"creator.css"() {
|
||||
if (this.autoCSS) {
|
||||
this.applyCSS(null)
|
||||
}
|
||||
},
|
||||
creator() {
|
||||
this.$vuetify.theme.themes.dark = this.creator.dark
|
||||
this.$vuetify.theme.themes.light = this.creator.light
|
||||
this.$vuetify.theme.themes.name = this.creator.id
|
||||
},
|
||||
accent() {
|
||||
this.setTheme(
|
||||
this.themes.find(
|
||||
(theme) => theme.id === this.$vuetify.theme.themes.name
|
||||
)
|
||||
)
|
||||
},
|
||||
defineAccent() {
|
||||
if (!this.defineAccent) {
|
||||
this.accent = null
|
||||
this.$store.state.user.accentColor = null
|
||||
this.getThemes()
|
||||
} else {
|
||||
this.accent = this.$store.state.user.accentColor || "#0190ea"
|
||||
}
|
||||
},
|
||||
"$store.state.user.theme": {
|
||||
handler() {
|
||||
this.$vuetify.theme.dark = this.$store.state.user.theme === "dark"
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.defineAccent = this.$store.state.user.accentColor !== null
|
||||
this.accent = this.$store.state.user.accentColor
|
||||
this.name = this.$vuetify.theme.themes.name
|
||||
this.getThemes()
|
||||
},
|
||||
methods: {
|
||||
setFont() {
|
||||
const element = document.getElementById("user-font")
|
||||
|
@ -461,52 +507,6 @@ div {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.defineAccent = this.$store.state.user.accentColor !== null
|
||||
this.accent = this.$store.state.user.accentColor
|
||||
this.name = this.$vuetify.theme.themes.name
|
||||
this.getThemes()
|
||||
},
|
||||
watch: {
|
||||
"$store.state.themeEngine.editor"() {
|
||||
this.getThemes()
|
||||
},
|
||||
"$store.state.themeEngine.cssEditor"() {
|
||||
this.getThemes()
|
||||
},
|
||||
"creator.css"() {
|
||||
if (this.autoCSS) {
|
||||
this.applyCSS(null)
|
||||
}
|
||||
},
|
||||
creator() {
|
||||
this.$vuetify.theme.themes.dark = this.creator.dark
|
||||
this.$vuetify.theme.themes.light = this.creator.light
|
||||
this.$vuetify.theme.themes.name = this.creator.id
|
||||
},
|
||||
accent() {
|
||||
this.setTheme(
|
||||
this.themes.find(
|
||||
(theme) => theme.id === this.$vuetify.theme.themes.name
|
||||
)
|
||||
)
|
||||
},
|
||||
defineAccent() {
|
||||
if (!this.defineAccent) {
|
||||
this.accent = null
|
||||
this.$store.state.user.accentColor = null
|
||||
this.getThemes()
|
||||
} else {
|
||||
this.accent = this.$store.state.user.accentColor || "#0190ea"
|
||||
}
|
||||
},
|
||||
"$store.state.user.theme": {
|
||||
handler() {
|
||||
this.$vuetify.theme.dark = this.$store.state.user.theme === "dark"
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,18 +2,16 @@
|
|||
<div>
|
||||
<v-card-text>
|
||||
<v-switch
|
||||
inset
|
||||
v-model="messageAudio"
|
||||
label="Play sound effect on new message"
|
||||
>
|
||||
</v-switch>
|
||||
<v-switch
|
||||
inset
|
||||
label="Play sound effect on new message"
|
||||
/>
|
||||
<v-switch
|
||||
v-model="nativeNotifications"
|
||||
inset
|
||||
label="Desktop notifications"
|
||||
@change="setNativeNotifications"
|
||||
>
|
||||
</v-switch>
|
||||
/>
|
||||
<v-btn v-if="nativeNotifications" @click="testNativeNotification">
|
||||
Test desktop notifications
|
||||
</v-btn>
|
||||
|
@ -30,6 +28,24 @@ export default {
|
|||
nativeNotifications: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
nativeNotifications(val) {
|
||||
localStorage.setItem("nativeNotifications", val)
|
||||
},
|
||||
messageAudio(val) {
|
||||
localStorage.setItem("messageAudio", val)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.getItem("messageAudio")) {
|
||||
this.messageAudio = JSON.parse(localStorage.getItem("messageAudio"))
|
||||
}
|
||||
if (localStorage.getItem("nativeNotifications")) {
|
||||
this.nativeNotifications = JSON.parse(
|
||||
localStorage.getItem("nativeNotifications")
|
||||
)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setNativeNotifications() {
|
||||
if (this.nativeNotifications) {
|
||||
|
@ -68,24 +84,6 @@ export default {
|
|||
"A desktop notification has been sent, if you don't see it, check your site permissions."
|
||||
)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (localStorage.getItem("messageAudio")) {
|
||||
this.messageAudio = JSON.parse(localStorage.getItem("messageAudio"))
|
||||
}
|
||||
if (localStorage.getItem("nativeNotifications")) {
|
||||
this.nativeNotifications = JSON.parse(
|
||||
localStorage.getItem("nativeNotifications")
|
||||
)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
nativeNotifications(val) {
|
||||
localStorage.setItem("nativeNotifications", val)
|
||||
},
|
||||
messageAudio(val) {
|
||||
localStorage.setItem("messageAudio", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -13,15 +13,14 @@
|
|||
accessed by anyone else, and that you don't loose it.
|
||||
</p>
|
||||
<v-text-field
|
||||
v-model="totp.password"
|
||||
type="password"
|
||||
label="Password"
|
||||
v-model="totp.password"
|
||||
color="white"
|
||||
@keydown.enter="totpEnable"
|
||||
autocomplete="false"
|
||||
>
|
||||
</v-text-field>
|
||||
<v-btn @click="totpEnable" text>Proceed</v-btn>
|
||||
@keydown.enter="totpEnable"
|
||||
/>
|
||||
<v-btn text @click="totpEnable"> Proceed </v-btn>
|
||||
</template>
|
||||
<template v-else-if="totp.stage === 2">
|
||||
<p class="text-h6">Enable 2 Factor Authentication</p>
|
||||
|
@ -29,27 +28,25 @@
|
|||
<code>{{ totp.secret }}</code>
|
||||
<p>Please enter the 6 digit code from your authenticator app.</p>
|
||||
<v-text-field
|
||||
v-model="totp.code"
|
||||
type="number"
|
||||
label="Code"
|
||||
v-model="totp.code"
|
||||
@keydown.enter="totpConfirm"
|
||||
color="white"
|
||||
>
|
||||
</v-text-field>
|
||||
<v-btn @click="totpConfirm" text>Enable</v-btn>
|
||||
@keydown.enter="totpConfirm"
|
||||
/>
|
||||
<v-btn text @click="totpConfirm"> Enable </v-btn>
|
||||
</template>
|
||||
<template v-else-if="totp.stage === 3">
|
||||
<p class="text-h6">2 Factor Authentication Enabled</p>
|
||||
<p>You have successfully enabled 2 Factor Authentication.</p>
|
||||
<v-text-field
|
||||
v-model="totp.code"
|
||||
type="password"
|
||||
label="2FA Code"
|
||||
v-model="totp.code"
|
||||
color="white"
|
||||
@keydown.enter="totpDisable"
|
||||
>
|
||||
</v-text-field>
|
||||
<v-btn @click="totpDisable" text>Disable</v-btn>
|
||||
/>
|
||||
<v-btn text @click="totpDisable"> Disable </v-btn>
|
||||
</template>
|
||||
</v-alert>
|
||||
<v-alert>
|
||||
|
@ -58,15 +55,15 @@
|
|||
<p class="text-h6">Change Password</p>
|
||||
<p>You may set a custom password here.</p>
|
||||
<v-text-field
|
||||
label="Current Password"
|
||||
v-model="password.current"
|
||||
label="Current Password"
|
||||
type="password"
|
||||
color="white"
|
||||
@keydown.enter="passwordChange"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-text-field
|
||||
label="New Password"
|
||||
v-model="password.new"
|
||||
label="New Password"
|
||||
type="password"
|
||||
color="white"
|
||||
:rules="[
|
||||
|
@ -75,10 +72,10 @@
|
|||
v.length >= 8 || 'Password must be at least 8 characters.'
|
||||
]"
|
||||
@keydown.enter="passwordChange"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-text-field
|
||||
label="Confirm New Password"
|
||||
v-model="password.confirm"
|
||||
label="Confirm New Password"
|
||||
type="password"
|
||||
color="white"
|
||||
:rules="[
|
||||
|
@ -87,8 +84,8 @@
|
|||
v.length >= 8 || 'Password must be at least 8 characters.'
|
||||
]"
|
||||
@keydown.enter="passwordChange"
|
||||
></v-text-field>
|
||||
<v-btn @click="passwordChange" text>Change</v-btn>
|
||||
/>
|
||||
<v-btn text @click="passwordChange"> Change </v-btn>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-alert>
|
||||
|
@ -121,6 +118,11 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.state.user.totpEnabled
|
||||
? (this.totp.stage = 3)
|
||||
: (this.totp.stage = 1)
|
||||
},
|
||||
methods: {
|
||||
passwordChange() {
|
||||
if (this.password.new === this.password.confirm) {
|
||||
|
@ -188,11 +190,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$store.state.user.totpEnabled
|
||||
? (this.totp.stage = 3)
|
||||
: (this.totp.stage = 1)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -2,22 +2,22 @@
|
|||
<div id="settings-sessions">
|
||||
<v-container fluid>
|
||||
<v-row>
|
||||
<v-col md="3" v-for="session in sessions" :key="session.id">
|
||||
<v-col v-for="session in sessions" :key="session.id" md="3">
|
||||
<v-card class="mb-2 rounded-xl" color="card">
|
||||
<v-toolbar color="toolbar">
|
||||
<v-toolbar-title>{{
|
||||
session.other.osString || "Unknown Session"
|
||||
}}</v-toolbar-title>
|
||||
<v-toolbar-title>
|
||||
{{ session.other.osString || "Unknown Session" }}
|
||||
</v-toolbar-title>
|
||||
</v-toolbar>
|
||||
<v-container>
|
||||
<v-card-text>
|
||||
Browser: {{ session.other.browserString }}
|
||||
</v-card-text>
|
||||
<v-card-text
|
||||
>Login IP address: {{ session.other.ip }}
|
||||
<v-card-text>
|
||||
Login IP address: {{ session.other.ip }}
|
||||
</v-card-text>
|
||||
<v-card-text
|
||||
>Operating System: {{ session.other.osString }}
|
||||
<v-card-text>
|
||||
Operating System: {{ session.other.osString }}
|
||||
</v-card-text>
|
||||
<v-card-text>
|
||||
Time of login:
|
||||
|
@ -30,7 +30,7 @@
|
|||
<v-card-text> Country: {{ session.other.location }} </v-card-text>
|
||||
<v-card-text> ISP: {{ session.other.isp }} </v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn @click="deleteSession(session.id)" color="error" text>
|
||||
<v-btn color="error" text @click="deleteSession(session.id)">
|
||||
Invalidate
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
|
@ -52,6 +52,9 @@ export default {
|
|||
sessions: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getSessions()
|
||||
},
|
||||
methods: {
|
||||
deleteSession(id) {
|
||||
this.axios
|
||||
|
@ -74,9 +77,6 @@ export default {
|
|||
AjaxErrorHandler(this.$store)(e)
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getSessions()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div id="settings-site" v-if="$store.state.user?.id">
|
||||
<div v-if="$store.state.user?.id" id="settings-site">
|
||||
<v-card-text>
|
||||
<div class="d-flex">
|
||||
<v-btn
|
||||
|
@ -22,16 +22,16 @@
|
|||
>
|
||||
<v-fade-transition v-if="hover">
|
||||
<v-overlay absolute>
|
||||
<v-icon large>mdi-upload</v-icon>
|
||||
<v-icon large> mdi-upload </v-icon>
|
||||
</v-overlay>
|
||||
</v-fade-transition>
|
||||
<v-img
|
||||
v-if="$store.state.user.avatar"
|
||||
:src="
|
||||
$store.state.baseURL +
|
||||
'/usercontent/' +
|
||||
$store.state.user.avatar
|
||||
"
|
||||
v-if="$store.state.user.avatar"
|
||||
class="elevation-1"
|
||||
/>
|
||||
<v-icon v-else-if="!hover" class="elevation-1">
|
||||
|
@ -40,15 +40,15 @@
|
|||
</v-avatar>
|
||||
</v-hover>
|
||||
<v-file-input
|
||||
class="ml-3"
|
||||
ref="avatarUpload"
|
||||
v-model="avatar.file"
|
||||
class="ml-3"
|
||||
accept="image/png, image/jpeg, image/jpg, image/gif, image/webp"
|
||||
placeholder="Avatar"
|
||||
prepend-icon=""
|
||||
label="Profile Picture"
|
||||
v-model="avatar.file"
|
||||
@change="doUpload"
|
||||
></v-file-input>
|
||||
/>
|
||||
</div>
|
||||
<v-text-field
|
||||
v-model="$store.state.user.email"
|
||||
|
@ -57,7 +57,7 @@
|
|||
(v) => !!v || 'Email is required',
|
||||
(v) => /^.+@.+\..+$/.test(v) || 'Email must be valid'
|
||||
]"
|
||||
></v-text-field>
|
||||
/>
|
||||
<v-text-field
|
||||
v-model="$store.state.user.username"
|
||||
label="Username"
|
||||
|
@ -67,17 +67,17 @@
|
|||
(v) => /^[a-zA-Z0-9]+$/.test(v) || 'Username must be alphanumeric',
|
||||
(v) => v.length >= 2 || 'Username must be at least 2 characters'
|
||||
]"
|
||||
></v-text-field>
|
||||
/>
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn
|
||||
text
|
||||
color="primary"
|
||||
:disabled="!$store.state.user.email || !$store.state.user.username"
|
||||
@click="
|
||||
$store.dispatch('saveOnlineSettings')
|
||||
$toast.success('Updated successfully.')
|
||||
"
|
||||
:disabled="!$store.state.user.email || !$store.state.user.username"
|
||||
>
|
||||
Save
|
||||
</v-btn>
|
||||
|
@ -88,8 +88,9 @@
|
|||
$store.dispatch('logout')
|
||||
$router.push('/login')
|
||||
"
|
||||
>Logout</v-btn
|
||||
>
|
||||
Logout
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</div>
|
||||
</template>
|
||||
|
|
1346
frontend/yarn.lock
1346
frontend/yarn.lock
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue