Refactoring invite modal (#375)

* Refactoring invite modal
* Infinite Scroll in user search
This commit is contained in:
Ilya Y 2024-01-25 12:57:57 +03:00 committed by GitHub
parent 83e3cf1d19
commit afed10dfd2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 444 additions and 295 deletions

255
package-lock.json generated
View File

@ -11,6 +11,7 @@
"license": "MIT",
"dependencies": {
"@authorizerdev/authorizer-js": "1.2.11",
"@solid-primitives/pagination": "0.2.10",
"form-data": "4.0.0",
"i18next": "22.4.15",
"i18next-icu": "2.3.0",
@ -2260,9 +2261,9 @@
}
},
"node_modules/@graphql-codegen/cli/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -2767,9 +2768,9 @@
}
},
"node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -2817,13 +2818,13 @@
}
},
"node_modules/@graphql-tools/code-file-loader": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.0.3.tgz",
"integrity": "sha512-gVnnlWs0Ua+5FkuHHEriFUOI3OIbHv6DS1utxf28n6NkfGMJldC4j0xlJRY0LS6dWK34IGYgD4HelKYz2l8KiA==",
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.0.tgz",
"integrity": "sha512-HKWW/B2z15ves8N9+xnVbGmFEVGyHEK80a4ghrjeTa6nwNZaKDVfq5CoYFfF0xpfjtH6gOVUExo2XCOEz4B8mQ==",
"dev": true,
"dependencies": {
"@graphql-tools/graphql-tag-pluck": "8.1.0",
"@graphql-tools/utils": "^10.0.0",
"@graphql-tools/graphql-tag-pluck": "8.2.0",
"@graphql-tools/utils": "^10.0.13",
"globby": "^11.0.3",
"tslib": "^2.4.0",
"unixify": "^1.0.0"
@ -3012,9 +3013,9 @@
}
},
"node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -3097,13 +3098,13 @@
}
},
"node_modules/@graphql-tools/git-loader": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.3.tgz",
"integrity": "sha512-Iz9KbRUAkuOe8JGTS0qssyJ+D5Snle17W+z9anwWrLFrkBhHrRFUy5AdjZqgJuhls0x30QkZBnnCtnHDBdQ4nA==",
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.4.tgz",
"integrity": "sha512-fBmKtnOVqzMT2N8L6nggM4skPq3y2t0eBITZJXCOuxeIlIRAeCOdjNLPKgyGb0rezIyGsn55DKMua5101VN0Sg==",
"dev": true,
"dependencies": {
"@graphql-tools/graphql-tag-pluck": "8.1.0",
"@graphql-tools/utils": "^10.0.0",
"@graphql-tools/graphql-tag-pluck": "8.2.0",
"@graphql-tools/utils": "^10.0.13",
"is-glob": "4.0.3",
"micromatch": "^4.0.4",
"tslib": "^2.4.0",
@ -3160,9 +3161,9 @@
}
},
"node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -3201,9 +3202,9 @@
}
},
"node_modules/@graphql-tools/graphql-tag-pluck": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.1.0.tgz",
"integrity": "sha512-kt5l6H/7QxQcIaewInTcune6NpATojdFEW98/8xWcgmy7dgXx5vU9e0AicFZIH+ewGyZzTpwFqO2RI03roxj2w==",
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.2.0.tgz",
"integrity": "sha512-aGIuHxyrJB+LlUfXrH73NVlQTA6LkFbLKQzHojFuwXZJpf7wPkxceN2yp7VjMedARkLJg589IoXgZeMb1EztGQ==",
"dev": true,
"dependencies": {
"@babel/core": "^7.22.9",
@ -3211,7 +3212,7 @@
"@babel/plugin-syntax-import-assertions": "^7.20.0",
"@babel/traverse": "^7.16.8",
"@babel/types": "^7.16.8",
"@graphql-tools/utils": "^10.0.0",
"@graphql-tools/utils": "^10.0.13",
"tslib": "^2.4.0"
},
"engines": {
@ -3502,9 +3503,9 @@
}
},
"node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -3697,9 +3698,9 @@
}
},
"node_modules/@graphql-tools/utils": {
"version": "10.0.12",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.12.tgz",
"integrity": "sha512-+yS1qlFwXlwU3Gv8ek/h2aJ95quog4yF22haC11M0zReMSTddbGJZ5yXKkE3sXoY2BcL1utilSFjylJ9uXpSNQ==",
"version": "10.0.13",
"resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.13.tgz",
"integrity": "sha512-fMILwGr5Dm2zefNItjQ6C2rauigklv69LIwppccICuGTnGaOp3DspLt/6Lxj72cbg5d9z60Sr+Egco3CJKLsNg==",
"dev": true,
"dependencies": {
"@graphql-typed-document-node/core": "^3.1.1",
@ -4625,9 +4626,9 @@
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"version": "0.3.22",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz",
"integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
@ -5016,16 +5017,16 @@
}
},
"node_modules/@peculiar/webcrypto": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz",
"integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==",
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.5.tgz",
"integrity": "sha512-oDk93QCDGdxFRM8382Zdminzs44dg3M2+E5Np+JWkpqLDyJC9DviMh8F8mEJkYuUcUOGA5jHO5AJJ10MFWdbZw==",
"dev": true,
"dependencies": {
"@peculiar/asn1-schema": "^2.3.6",
"@peculiar/asn1-schema": "^2.3.8",
"@peculiar/json-schema": "^1.1.12",
"pvtsutils": "^1.3.2",
"tslib": "^2.5.0",
"webcrypto-core": "^1.7.7"
"pvtsutils": "^1.3.5",
"tslib": "^2.6.2",
"webcrypto-core": "^1.7.8"
},
"engines": {
"node": ">=10.12.0"
@ -5229,9 +5230,9 @@
"dev": true
},
"node_modules/@sinonjs/commons": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz",
"integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
"integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
"dev": true,
"dependencies": {
"type-detect": "4.0.8"
@ -5247,12 +5248,12 @@
}
},
"node_modules/@solid-primitives/event-listener": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.3.0.tgz",
"integrity": "sha512-0DS7DQZvCExWSpurVZC9/wjI8RmkhuOtWOy6Pp1Woq9ElMT9/bfjNpkwXsOwisLpcTqh9eUs17kp7jtpWcC20w==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/@solid-primitives/event-listener/-/event-listener-2.3.1.tgz",
"integrity": "sha512-S1AfFYatOJ3g/ZUbGDoKplSGLTTfarQ3Mfd3F/fXb9SnzGtROtd+Y6yLkPVzK4AVw83r2wUSaS0GS6dg8izTEQ==",
"dev": true,
"dependencies": {
"@solid-primitives/utils": "^6.2.1"
"@solid-primitives/utils": "^6.2.2"
},
"peerDependencies": {
"solid-js": "^1.6.12"
@ -5286,34 +5287,45 @@
"solid-js": "^1.6.12"
}
},
"node_modules/@solid-primitives/pagination": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/@solid-primitives/pagination/-/pagination-0.2.10.tgz",
"integrity": "sha512-HVRW8NgNkjB2PPg4f4E4ava+PI6AO8INQpsARylzQcxeBW+RMY5bYJoSIQ2QSp+hHiJhNlYozdBdLUY39Vxtxg==",
"dependencies": {
"@solid-primitives/utils": "^6.2.2"
},
"peerDependencies": {
"solid-js": "^1.6.12"
}
},
"node_modules/@solid-primitives/refs": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@solid-primitives/refs/-/refs-1.0.5.tgz",
"integrity": "sha512-5hmYmYbm6rs43nMHHozyyUngGA7P7q2WtlaCLJEfmlUJf67GWI1PZmqAiol6m9F37XSMZRuvZLoQ7HA/0q3GYg==",
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@solid-primitives/refs/-/refs-1.0.6.tgz",
"integrity": "sha512-ruh4YdVMxThEVnvqbpeLXKojW442vpFU8q7dSKtElGOTa31aKOAkRb9BTbdaTwVjN4BEq79fiiYIXozJNl4dSw==",
"dev": true,
"dependencies": {
"@solid-primitives/utils": "^6.2.1"
"@solid-primitives/utils": "^6.2.2"
},
"peerDependencies": {
"solid-js": "^1.6.12"
}
},
"node_modules/@solid-primitives/rootless": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.4.2.tgz",
"integrity": "sha512-ynI/2aEOPyc14IKCX6yDBqnsAYCoLbaP9V/jejEWMVKOT2ZdV2ZxdftaLimOpWPpvjyti5DUJIGTOfLaNb7jlg==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/@solid-primitives/rootless/-/rootless-1.4.3.tgz",
"integrity": "sha512-IPsfUhKsqQOxLtRMQWK2EZAYbL9RKJMLBelLwpaXl9+oa1tl5aNvA6GHgrNrK+85oUhiYh7/OuogO18AuHepqQ==",
"dev": true,
"dependencies": {
"@solid-primitives/utils": "^6.2.1"
"@solid-primitives/utils": "^6.2.2"
},
"peerDependencies": {
"solid-js": "^1.6.12"
}
},
"node_modules/@solid-primitives/scheduled": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.4.1.tgz",
"integrity": "sha512-OLcNXwYpX7HUOEqNPcmR31dkyI1E2imkMDBRlqsGT0ZhJV1L2g0TEREpo4nm/kUhh8LVQzkfnxS+GONx9kh90A==",
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@solid-primitives/scheduled/-/scheduled-1.4.2.tgz",
"integrity": "sha512-duKaugDQtPk0v6MnkBuEalWk66/vA2G7zzoimQEvmUdh2+K2o8t908HIfI2NdBfwakQMQBV4epE3TFeN2Vsveg==",
"dev": true,
"peerDependencies": {
"solid-js": "^1.6.12"
@ -5353,9 +5365,9 @@
}
},
"node_modules/@solid-primitives/transition-group": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.0.3.tgz",
"integrity": "sha512-TnFADZhx9sibdoW5gxkU1QmLabzV2H2OBKYGS2aR5IC61Q/+7v8wlxOJEevxXNbPiRo6qlE3STLU3L9XS8hDbA==",
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@solid-primitives/transition-group/-/transition-group-1.0.4.tgz",
"integrity": "sha512-9nPg6HYAmEi7riH0C2bSCVw/2asgGSzHuN0yFFYyK9JgmXqJgyeyA+6thZbj7GgUQMRhtBxpH8yG7N2nEh8ttA==",
"dev": true,
"peerDependencies": {
"solid-js": "^1.6.12"
@ -5383,10 +5395,9 @@
}
},
"node_modules/@solid-primitives/utils": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.1.tgz",
"integrity": "sha512-TsecNzxiO5bLfzqb4OOuzfUmdOROcssuGqgh5rXMMaasoFZ3GoveUgdY1wcf17frMJM7kCNGNuK34EjErneZkg==",
"dev": true,
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/@solid-primitives/utils/-/utils-6.2.2.tgz",
"integrity": "sha512-11ypVbp987XxETeRqY5Y3OmmTpm8/jZqJXRvo6AyqBthzkvvjEdReuUMU2yVb+pwWGxfZpWHZ6EUCcGXUMhfwg==",
"peerDependencies": {
"solid-js": "^1.6.12"
}
@ -6728,9 +6739,9 @@
}
},
"node_modules/axios": {
"version": "1.6.5",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
"integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.6.tgz",
"integrity": "sha512-XZLZDFfXKM9U/Y/B4nNynfCRUqNyVZ4sBC/n9GDRCkq9vd2mIvKjKKsbIh1WPmHmNbg6ND7cTBY3Y2+u1G3/2Q==",
"dependencies": {
"follow-redirects": "^1.15.4",
"form-data": "^4.0.0",
@ -6908,9 +6919,9 @@
}
},
"node_modules/babel-plugin-jsx-dom-expressions": {
"version": "0.37.13",
"resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.37.13.tgz",
"integrity": "sha512-oAEMMIgU0h1DmHn4ZDaBBFc08nsVJciLq9pF7g0ZdpeIDKfY4zXjXr8+/oBjKhXG8nyomhnTodPjeG+/ZXcWXQ==",
"version": "0.37.16",
"resolved": "https://registry.npmjs.org/babel-plugin-jsx-dom-expressions/-/babel-plugin-jsx-dom-expressions-0.37.16.tgz",
"integrity": "sha512-ItMD16axbk+FqVb9vIbc7AOpNowy46VaSUHaMYPn+erPGpMCxsahQ1Iv+qhPMthjxtn5ROVMZ5AJtQvzjxjiNA==",
"dev": true,
"dependencies": {
"@babel/helper-module-imports": "7.18.6",
@ -7368,9 +7379,9 @@
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001576",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001576.tgz",
"integrity": "sha512-ff5BdakGe2P3SQsMsiqmt1Lc8221NR1VzHj5jXN5vBny9A6fpze94HiVV/n7XRosOlsShJcvMv5mdnpjOGCEgg==",
"version": "1.0.30001580",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001580.tgz",
"integrity": "sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==",
"dev": true,
"funding": [
{
@ -8012,8 +8023,7 @@
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/damerau-levenshtein": {
"version": "1.0.8",
@ -8286,9 +8296,9 @@
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"version": "16.4.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz",
"integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==",
"dev": true,
"engines": {
"node": ">=12"
@ -8328,9 +8338,9 @@
}
},
"node_modules/electron-to-chromium": {
"version": "1.4.628",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.628.tgz",
"integrity": "sha512-2k7t5PHvLsufpP6Zwk0nof62yLOsCf032wZx7/q0mv8gwlXjhcxI3lz6f0jBr0GrnWKcm3burXzI3t5IrcdUxw==",
"version": "1.4.645",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.645.tgz",
"integrity": "sha512-EeS1oQDCmnYsRDRy2zTeC336a/4LZ6WKqvSaM1jLocEk5ZuyszkQtCpsqvuvaIXGOUjwtvF6LTcS8WueibXvSw==",
"dev": true
},
"node_modules/emittery": {
@ -9773,9 +9783,9 @@
"dev": true
},
"node_modules/follow-redirects": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.4.tgz",
"integrity": "sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==",
"version": "1.15.5",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.5.tgz",
"integrity": "sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==",
"funding": [
{
"type": "individual",
@ -10372,9 +10382,9 @@
}
},
"node_modules/graphql-config/node_modules/@whatwg-node/node-fetch": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.3.tgz",
"integrity": "sha512-toMC8N53RxgprcuU7Fc05KOrJhZV49njJCHPZvXBsjZMQBKrDm9o14Y56CsrUC85cvjQu862MaYOjd8rKgHdDw==",
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.4.tgz",
"integrity": "sha512-5AXi4B44/6SOlQG+X3cO5lsUdRTWSXqaWLkGKnwWfeJoMgRfA53RnYVnvTV+4CoatNBStPrIoDorjgQv+ouiMQ==",
"dev": true,
"dependencies": {
"@kamilkisiela/fast-url-parser": "^1.1.4",
@ -13790,9 +13800,9 @@
"dev": true
},
"node_modules/json-stable-stringify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.0.tgz",
"integrity": "sha512-zfA+5SuwYN2VWqN1/5HZaDzQKLJHaBVMZIIM+wuYjdptkaQsqzDdqjqf+lZZJUuJq1aanHiY8LhH8LmH+qBYJA==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.1.1.tgz",
"integrity": "sha512-SU/971Kt5qVQfJpyDveVhQ/vya+5hvrjClFOcr8c0Fq5aODJjMwutrOfCU+eCnVD5gpx1Q3fEqkyom77zH1iIg==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.5",
@ -16905,9 +16915,9 @@
}
},
"node_modules/rfdc": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
"integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz",
"integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==",
"dev": true
},
"node_modules/rimraf": {
@ -16989,13 +16999,13 @@
}
},
"node_modules/safe-array-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz",
"integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz",
"integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.2.1",
"call-bind": "^1.0.5",
"get-intrinsic": "^1.2.2",
"has-symbols": "^1.0.3",
"isarray": "^2.0.5"
},
@ -17027,9 +17037,9 @@
]
},
"node_modules/safe-regex-test": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.1.tgz",
"integrity": "sha512-Y5NejJTTliTyY4H7sipGqY+RX5P87i3F7c4Rcepy72nq+mNLhIsD0W4c7kEmduMDQCSqtPsXPlSTsFhh2LQv+g==",
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz",
"integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.5",
@ -17113,7 +17123,6 @@
"version": "0.15.1",
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.15.1.tgz",
"integrity": "sha512-OPVtf0qmeC7RW+ScVX+7aOS+xoIM7pWcZ0jOWg2aTZigCydgRB04adfteBRbecZnnrO1WuGQ+C3tLeBBzX2zSQ==",
"dev": true,
"engines": {
"node": ">=10"
}
@ -17125,15 +17134,16 @@
"dev": true
},
"node_modules/set-function-length": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.1.1.tgz",
"integrity": "sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==",
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz",
"integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==",
"dev": true,
"dependencies": {
"define-data-property": "^1.1.1",
"get-intrinsic": "^1.2.1",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.2",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.0"
"has-property-descriptors": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
@ -17305,7 +17315,6 @@
"version": "1.8.7",
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.8.7.tgz",
"integrity": "sha512-9dzrSVieh2zj3SnJ02II6xZkonR6c+j/91b7XZUNcC6xSaldlqjjGh98F1fk5cRJ8ZTkzqF5fPIWDxEOs6QZXA==",
"dev": true,
"dependencies": {
"csstype": "^3.1.0",
"seroval": "^0.15.1"
@ -17516,9 +17525,9 @@
}
},
"node_modules/spdx-exceptions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
"integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz",
"integrity": "sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw==",
"dev": true
},
"node_modules/spdx-expression-parse": {
@ -19276,9 +19285,9 @@
}
},
"node_modules/vue-eslint-parser": {
"version": "9.4.0",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.0.tgz",
"integrity": "sha512-7KsNBb6gHFA75BtneJsoK/dbZ281whUIwFYdQxA68QrCrGMXYzUMbPDHGcOQ0OocIVKrWSKWXZ4mL7tonCXoUw==",
"version": "9.4.2",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.2.tgz",
"integrity": "sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==",
"dev": true,
"dependencies": {
"debug": "^4.3.4",
@ -19367,16 +19376,16 @@
}
},
"node_modules/webcrypto-core": {
"version": "1.7.7",
"resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz",
"integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==",
"version": "1.7.8",
"resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.8.tgz",
"integrity": "sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg==",
"dev": true,
"dependencies": {
"@peculiar/asn1-schema": "^2.3.6",
"@peculiar/asn1-schema": "^2.3.8",
"@peculiar/json-schema": "^1.1.12",
"asn1js": "^3.0.1",
"pvtsutils": "^1.3.2",
"tslib": "^2.4.0"
"pvtsutils": "^1.3.5",
"tslib": "^2.6.2"
}
},
"node_modules/webidl-conversions": {

View File

@ -31,6 +31,7 @@
},
"dependencies": {
"@authorizerdev/authorizer-js": "1.2.11",
"@solid-primitives/pagination": "0.2.10",
"form-data": "4.0.0",
"i18next": "22.4.15",
"i18next-icu": "2.3.0",

View File

@ -203,6 +203,7 @@
"Invalid email": "Check if your email is correct",
"Invalid image URL": "Invalid image URL",
"Invalid url format": "Invalid url format",
"Invite": "Invite",
"Invite co-authors": "Invite co-authors",
"Invite collaborators": "Invite collaborators",
"Invite to collab": "Invite to Collab",
@ -343,6 +344,7 @@
"Special projects": "Special projects",
"Specify the source and the name of the author": "Specify the source and the name of the author",
"Start conversation": "Start a conversation",
"Start dialog": "Start dialog",
"Subsccriptions": "Subscriptions",
"Subscribe": "Subscribe",
"Subscribe to the best publications newsletter": "Subscribe to the best publications newsletter",

View File

@ -213,6 +213,7 @@
"Invalid email": "Проверьте правильность ввода почты",
"Invalid image URL": "Некорректная ссылка на изображение",
"Invalid url format": "Неверный формат ссылки",
"Invite": "Пригласить",
"Invite co-authors": "Пригласить соавторов",
"Invite collaborators": "Пригласить соавторов",
"Invite experts": "Пригласить экспертов",
@ -364,6 +365,7 @@
"Special projects": "Спецпроекты",
"Specify the source and the name of the author": "Укажите источник и имя автора",
"Start conversation": "Начать беседу",
"Start dialog": "Начать диалог",
"Subheader": "Подзаголовок",
"Subscribe": "Подписаться",
"Subscribe to comments": "Подписаться на комментарии",

View File

@ -19,7 +19,7 @@ import { getImageUrl, getOpenGraphImageUrl } from '../../utils/getImageUrl'
import { getDescription, getKeywords } from '../../utils/meta'
import { Icon } from '../_shared/Icon'
import { Image } from '../_shared/Image'
import { InviteCoAuthorsModal } from '../_shared/InviteCoAuthorsModal'
import { InviteMembers } from '../_shared/InviteMembers'
import { Lightbox } from '../_shared/Lightbox'
import { Popover } from '../_shared/Popover'
import { ShareModal } from '../_shared/ShareModal'
@ -555,7 +555,7 @@ export const FullArticle = (props: Props) => {
isOwner={canEdit()}
containerCssClass={clsx(stylesHeader.control, styles.articlePopupOpener)}
onShareClick={() => showModal('share')}
onInviteClick={() => showModal('inviteCoAuthors')}
onInviteClick={() => showModal('inviteMembers')}
onVisibilityChange={(isVisible) => setIsActionPopupActive(isVisible)}
trigger={
<button>
@ -618,7 +618,7 @@ export const FullArticle = (props: Props) => {
<Show when={selectedImage()}>
<Lightbox image={selectedImage()} onClose={handleLightboxClose} />
</Show>
<InviteCoAuthorsModal title={t('Invite experts')} />
<InviteMembers variant={'coauthors'} title={t('Invite experts')} />
<ShareModal
title={props.article.title}
description={description}

View File

@ -43,21 +43,23 @@
&:hover {
background: unset;
}
}
.name {
color: var(--default-color);
font-weight: 500;
.name {
@include font-size(1.4rem);
& span:hover {
color: var(--default-color-invert);
background: var(--background-color-invert);
}
color: var(--default-color);
font-weight: 500;
& span:hover {
color: var(--default-color-invert);
background: var(--background-color-invert);
}
}
.bio {
color: var(--black-400);
font-weight: 500;
}
.bio {
color: var(--black-400);
font-weight: 500;
}
.actions {

View File

@ -1,4 +1,4 @@
import { openPage } from '@nanostores/router'
import { getPagePath, openPage } from '@nanostores/router'
import { clsx } from 'clsx'
import { createEffect, createMemo, createSignal, Match, Show, Switch } from 'solid-js'
@ -13,6 +13,7 @@ import { isCyrillic } from '../../../utils/cyrillic'
import { translit } from '../../../utils/ru2en'
import { Button } from '../../_shared/Button'
import { CheckButton } from '../../_shared/CheckButton'
import { ConditionalWrapper } from '../../_shared/ConditionalWrapper'
import { Icon } from '../../_shared/Icon'
import { Userpic } from '../Userpic'
@ -25,6 +26,9 @@ type Props = {
showMessageButton?: boolean
iconButtons?: boolean
nameOnly?: boolean
inviteView?: boolean
onInvite?: (id: number) => void
selected?: boolean
}
export const AuthorBadge = (props: Props) => {
const { mediaMatches } = useMediaQuery()
@ -94,7 +98,14 @@ export const AuthorBadge = (props: Props) => {
userpic={props.author.pic}
slug={props.author.slug}
/>
<a href={`/author/${props.author.slug}`} class={styles.info}>
<ConditionalWrapper
condition={!props.inviteView}
wrapper={(children) => (
<a href={`/author/${props.author.slug}`} class={styles.info}>
{children}
</a>
)}
>
<div class={styles.name}>
<span>{name()}</span>
</div>
@ -118,7 +129,7 @@ export const AuthorBadge = (props: Props) => {
</Match>
</Switch>
</Show>
</a>
</ConditionalWrapper>
</div>
<Show when={props.author.slug !== author()?.slug && !props.nameOnly}>
<div class={styles.actions}>
@ -195,6 +206,13 @@ export const AuthorBadge = (props: Props) => {
</Show>
</div>
</Show>
<Show when={props.inviteView}>
<CheckButton
text={t('Invite')}
checked={props.selected}
onClick={() => props.onInvite(props.author.id)}
/>
</Show>
</div>
)
}

View File

@ -92,7 +92,7 @@ export const Panel = (props: Props) => {
<section>
<p>
<span class={styles.link} onClick={() => showModal('inviteCoAuthors')}>
<span class={styles.link} onClick={() => showModal('inviteMembers')}>
{t('Invite co-authors')}
</span>
</p>

View File

@ -33,7 +33,7 @@ const DialogCard = (props: DialogProps) => {
const names = createMemo<string>(() => (companions() || []).map((companion) => companion.name).join(', '))
return (
<Show when={props.members}>
<Show when={props.members.length > 0} fallback={<div>'No chat members'</div>}>
<div
class={clsx(styles.DialogCard, {
[styles.opened]: props.isOpened,
@ -47,7 +47,7 @@ const DialogCard = (props: DialogProps) => {
when={props.isChatHeader}
fallback={
<div class={styles.avatar}>
<DialogAvatar name={props.members[0].slug} url={props.members[0].pic} />
<DialogAvatar name={props.members[0]?.slug} url={props.members[0]?.pic} />
</div>
}
>

View File

@ -14,7 +14,7 @@ import { isDesktop } from '../../utils/media-query'
import { slugify } from '../../utils/slugify'
import { DropArea } from '../_shared/DropArea'
import { Icon } from '../_shared/Icon'
import { InviteCoAuthorsModal } from '../_shared/InviteCoAuthorsModal'
import { InviteMembers } from '../_shared/InviteMembers'
import { Popover } from '../_shared/Popover'
import { EditorSwiper } from '../_shared/SolidSwiper'
import { Editor, Panel } from '../Editor'
@ -413,7 +413,7 @@ export const EditView = (props: Props) => {
<PublishSettings shoutId={props.shout.id} form={form} />
</Show>
<Panel shoutId={props.shout.id} />
<InviteCoAuthorsModal />
<InviteMembers variant={'coauthors'} title={t('Invite experts')} />
</>
)
}

View File

@ -17,7 +17,7 @@ import { useTopicsStore } from '../../../stores/zine/topics'
import { getImageUrl } from '../../../utils/getImageUrl'
import { DropDown } from '../../_shared/DropDown'
import { Icon } from '../../_shared/Icon'
import { InviteCoAuthorsModal } from '../../_shared/InviteCoAuthorsModal'
import { InviteMembers } from '../../_shared/InviteMembers'
import { Loading } from '../../_shared/Loading'
import { ShareModal } from '../../_shared/ShareModal'
import { CommentDate } from '../../Article/CommentDate'
@ -305,7 +305,7 @@ export const FeedView = (props: Props) => {
{(article) => (
<ArticleCard
onShare={(shared) => handleShare(shared)}
onInvite={() => showModal('inviteCoAuthors')}
onInvite={() => showModal('inviteMembers')}
article={article}
settings={{ isFeedMode: true }}
desktopCoverSize="M"
@ -432,7 +432,7 @@ export const FeedView = (props: Props) => {
shareUrl={getShareUrl({ pathname: `/${shareData().slug}` })}
/>
</Show>
<InviteCoAuthorsModal title={t('Invite experts')} />
<InviteMembers title={t('Invite experts')} variant={'coauthors'} />
</div>
)
}

View File

@ -36,7 +36,6 @@ main {
display: flex;
flex-direction: column;
padding: 10px;
height: calc(100% - 10px);
$fadeHeight: 10px;
@ -52,26 +51,6 @@ main {
position: relative;
padding: $fadeHeight 0;
&::before,
&::after {
content: '';
position: absolute;
width: 100%;
right: 0;
z-index: 1;
height: $fadeHeight;
}
&::before {
top: 0;
background: linear-gradient(white, transparent $fadeHeight);
}
&::after {
bottom: 0;
background: linear-gradient(transparent, white $fadeHeight);
}
.dialogs {
scroll-behavior: smooth;
display: flex;

View File

@ -1,27 +1,26 @@
import type { Chat, Message as MessageType } from '../../graphql/schema/chat.gen'
import type { Author } from '../../graphql/schema/core.gen'
import type { Chat, Message as MessageType } from '../../../graphql/schema/chat.gen'
import type { Author } from '../../../graphql/schema/core.gen'
import { clsx } from 'clsx'
import { For, createSignal, Show, onMount, createEffect, createMemo, on } from 'solid-js'
import { useInbox } from '../../context/inbox'
import { useLocalize } from '../../context/localize'
import { useSession } from '../../context/session'
import { useRouter } from '../../stores/router'
import { showModal } from '../../stores/ui'
// import { AuthorsSortBy, useAuthorsStore } from '../../stores/zine/authors'
import { Icon } from '../_shared/Icon'
import { Popover } from '../_shared/Popover'
import SimplifiedEditor from '../Editor/SimplifiedEditor'
import CreateModalContent from '../Inbox/CreateModalContent'
import DialogCard from '../Inbox/DialogCard'
import DialogHeader from '../Inbox/DialogHeader'
import { Message } from '../Inbox/Message'
import MessagesFallback from '../Inbox/MessagesFallback'
import Search from '../Inbox/Search'
import { Modal } from '../Nav/Modal'
import { useInbox } from '../../../context/inbox'
import { useLocalize } from '../../../context/localize'
import { useSession } from '../../../context/session'
import { useRouter } from '../../../stores/router'
import { showModal } from '../../../stores/ui'
import { useAuthorsStore } from '../../../stores/zine/authors'
import { Icon } from '../../_shared/Icon'
import { InviteMembers } from '../../_shared/InviteMembers'
import { Popover } from '../../_shared/Popover'
import SimplifiedEditor from '../../Editor/SimplifiedEditor'
import DialogCard from '../../Inbox/DialogCard'
import DialogHeader from '../../Inbox/DialogHeader'
import { Message } from '../../Inbox/Message'
import MessagesFallback from '../../Inbox/MessagesFallback'
import Search from '../../Inbox/Search'
import styles from '../../styles/Inbox.module.scss'
import styles from './Inbox.module.scss'
type InboxSearchParams = {
by?: string
@ -34,7 +33,7 @@ const userSearch = (array: Author[], keyword: string) => {
}
const handleOpenInviteModal = () => {
showModal('inviteToChat')
showModal('inviteMembers')
}
type Props = {
@ -64,16 +63,12 @@ export const InboxView = (props: Props) => {
current: null,
}
// Поиск по диалогам
const getQuery = (query) => {
if (query().length >= 2) {
const match = userSearch(recipients(), query())
setRecipients(match)
} else {
// setRecipients(cashedRecipients())
}
}
const handleOpenChat = async (chat: Chat) => {
setCurrentDialog(chat)
changeSearchParams({
@ -91,8 +86,6 @@ export const InboxView = (props: Props) => {
}
}
onMount(loadChats)
const handleSubmit = async (message: string) => {
sendMessage({
body: message,
@ -129,6 +122,7 @@ export const InboxView = (props: Props) => {
})
const chatsToShow = () => {
if (!chats()) return
const sorted = chats().sort((a, b) => {
return b.updated_at - a.updated_at
})
@ -181,11 +175,14 @@ export const InboxView = (props: Props) => {
setIsScrollToNewVisible(false)
}
onMount(async () => {
await loadChats()
})
return (
<div class={clsx('container', styles.Inbox)}>
<Modal variant="narrow" name="inviteToChat">
<CreateModalContent users={recipients()} />
</Modal>
<InviteMembers title={t('Create Chat')} variant={'recipients'} />
{/*<CreateModalContent users={recipients()} />*/}
<div class={clsx('row', styles.row)}>
<div class={clsx(styles.chatList, 'col-md-8')}>
<div class={styles.sidebarHeader}>
@ -195,7 +192,7 @@ export const InboxView = (props: Props) => {
</button>
</div>
<Show when={chatsToShow}>
<Show when={chatsToShow()}>
<ul class="view-switcher">
<li class={clsx({ 'view-switcher__item--selected': !sortByPerToPer() && !sortByGroup() })}>
<button

View File

@ -234,7 +234,7 @@ export const PublishSettings = (props: Props) => {
<h4>{t('Collaborators')}</h4>
<Button
variant="primary"
onClick={() => showModal('inviteCoAuthors')}
onClick={() => showModal('inviteMembers')}
value={t('Invite collaborators')}
/>
</div>

View File

@ -1,17 +0,0 @@
import { useLocalize } from '../../../context/localize'
import { Modal } from '../../Nav/Modal'
import { UserSearch } from '../UserSearch'
type Props = {
title?: string
}
export const InviteCoAuthorsModal = (props: Props) => {
const { t } = useLocalize()
return (
<Modal variant="medium" name="inviteCoAuthors">
<h2>{props.title || t('Invite collaborators')}</h2>
<UserSearch placeholder={t('Write your colleagues name or email')} onChange={() => {}} />
</Modal>
)
}

View File

@ -1 +0,0 @@
export { InviteCoAuthorsModal } from './InviteCoAuthorsModal'

View File

@ -1,4 +1,4 @@
.UserSearch {
.InviteMembers {
.searchHeader {
display: flex;
flex-flow: row nowrap;
@ -32,10 +32,40 @@
}
}
.searchButton {
margin: 0;
}
.authors {
height: 400px;
height: 300px;
overflow: auto;
padding: 1rem 0;
margin-top: 1rem;
.author {
cursor: pointer;
&:hover {
background: var(--black-100);
}
}
}
.loading {
@include font-size(1.4rem);
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
width: 100%;
flex-direction: row;
opacity: 0.5;
.icon {
position: relative;
width: 18px;
height: 18px;
}
}
.teaser {
@ -46,4 +76,11 @@
justify-content: center;
text-align: center;
}
.actions {
display: flex;
margin-top: 1rem;
flex-direction: row;
justify-content: space-between;
}
}

View File

@ -0,0 +1,185 @@
import { createInfiniteScroll } from '@solid-primitives/pagination'
import { clsx } from 'clsx'
import { createEffect, createSignal, For, on, Show } from 'solid-js'
import { useInbox } from '../../../context/inbox'
import { useLocalize } from '../../../context/localize'
import { Author } from '../../../graphql/schema/core.gen'
import { hideModal } from '../../../stores/ui'
import { useAuthorsStore } from '../../../stores/zine/authors'
import { AuthorBadge } from '../../Author/AuthorBadge'
import { Modal } from '../../Nav/Modal'
import { Button } from '../Button'
import { DropdownSelect } from '../DropdownSelect'
import { Loading } from '../Loading'
import styles from './InviteMembers.module.scss'
type InviteAuthor = Author & { selected: boolean }
type Props = {
title?: string
variant?: 'coauthors' | 'recipients'
}
const PAGE_SIZE = 50
export const InviteMembers = (props: Props) => {
const { t } = useLocalize()
const roles = [
{
title: t('Editor'),
description: t('Can write and edit text directly, and accept or reject suggestions from others'),
},
{
title: t('Co-author'),
description: t('Can make any changes, accept or reject suggestions, and share access with others'),
},
{
title: t('Commentator'),
description: t('Can offer edits and comments, but cannot edit the post or share access with others'),
},
]
const { sortedAuthors } = useAuthorsStore({ sortBy: 'name' })
const { actions } = useInbox()
const [authorsToInvite, setAuthorsToInvite] = createSignal<InviteAuthor[]>()
const [searchResultAuthors, setSearchResultAuthors] = createSignal<Author[]>()
const [collectionToInvite, setCollectionToInvite] = createSignal<number[]>([])
const fetcher = async (page: number) => {
await new Promise((resolve, reject) => {
const checkDataLoaded = () => {
if (sortedAuthors().length > 0) {
resolve(true)
} else {
setTimeout(checkDataLoaded, 100)
}
}
setTimeout(() => reject(new Error('Timeout waiting for sortedAuthors')), 10000)
checkDataLoaded()
})
const start = page * PAGE_SIZE
const end = start + PAGE_SIZE
const authors = authorsToInvite().map((author) => ({ ...author, selected: false }))
return authors.slice(start, end)
}
const [pages, infiniteScrollLoader, { end }] = createInfiniteScroll(fetcher)
createEffect(
on(
() => sortedAuthors(),
(currentAuthors) => {
setAuthorsToInvite(currentAuthors.map((author) => ({ ...author, selected: false })))
},
{ defer: true },
),
)
const handleInputChange = async (value: string) => {
if (value.length > 1) {
const match = authorsToInvite().filter((author) =>
author.name.toLowerCase().includes(value.toLowerCase()),
)
setSearchResultAuthors(match)
} else {
setSearchResultAuthors()
}
}
const handleInvite = (id) => {
setCollectionToInvite((prev) => [...prev, id])
}
const handleCloseModal = () => {
setSearchResultAuthors()
setCollectionToInvite()
hideModal()
}
const handleCreate = async () => {
try {
const initChat = await actions.createChat(collectionToInvite(), 'chat Title')
console.debug('[components.Inbox] create chat result:', initChat)
hideModal()
await actions.loadChats()
} catch (error) {
console.error('handleCreate chat', error)
}
}
return (
<Modal variant="medium" name="inviteMembers">
<h2>{props.title || t('Invite collaborators')}</h2>
<div class={clsx(styles.InviteMembers)}>
<div class={styles.searchHeader}>
<div class={styles.field}>
<input
class={styles.input}
type="text"
placeholder={t('Write your colleagues name or email')}
onChange={(e) => {
if (props.variant === 'recipients') return
handleInputChange(e.target.value)
}}
onInput={(e) => {
if (props.variant === 'coauthors') return
handleInputChange(e.target.value)
}}
/>
<Show when={props.variant === 'coauthors'}>
<DropdownSelect selectItems={roles} />
</Show>
</div>
<Show when={props.variant === 'coauthors'}>
<Button class={styles.searchButton} variant={'bordered'} size={'M'} value={t('Search')} />
</Show>
</div>
<Show when={props.variant === 'coauthors'}>
<div class={styles.teaser}>
<h3>{t('Coming soon')}</h3>
<p>
{t(
'We are working on collaborative editing of articles and in the near future you will have an amazing opportunity - to create together with your colleagues',
)}
</p>
</div>
</Show>
<Show when={props.variant === 'recipients'}>
<div class={styles.authors}>
<For each={searchResultAuthors() ?? pages()}>
{(author) => (
<div class={styles.author}>
<AuthorBadge
author={author}
nameOnly={true}
inviteView={true}
onInvite={(id) => handleInvite(id)}
/>
</div>
)}
</For>
<Show when={!end()}>
<div use:infiniteScrollLoader class={styles.loading}>
<div class={styles.icon}>
<Loading size="tiny" />
</div>
<div>{t('Loading')}</div>
</div>
</Show>
</div>
</Show>
<div class={styles.actions}>
<Button variant={'bordered'} size={'M'} value={t('Cancel')} onClick={handleCloseModal} />
<Button
variant={'primary'}
size={'M'}
disabled={collectionToInvite().length === 0}
value={t('Start dialog')}
onClick={handleCreate}
/>
</div>
</div>
</Modal>
)
}

View File

@ -0,0 +1 @@
export { InviteMembers } from './InviteMembers'

View File

@ -1,61 +0,0 @@
import { clsx } from 'clsx'
import { useLocalize } from '../../../context/localize'
import { Button } from '../Button'
import { DropdownSelect } from '../DropdownSelect'
import styles from './UserSearch.module.scss'
type Props = {
class?: string
placeholder: string
onChange: (value: string) => void
}
export const UserSearch = (props: Props) => {
const { t } = useLocalize()
const roles = [
{
title: t('Editor'),
description: t('Can write and edit text directly, and accept or reject suggestions from others'),
},
{
title: t('Co-author'),
description: t('Can make any changes, accept or reject suggestions, and share access with others'),
},
{
title: t('Commentator'),
description: t('Can offer edits and comments, but cannot edit the post or share access with others'),
},
]
const handleInputChange = (value: string) => {
props.onChange(value)
}
return (
<div class={clsx(styles.UserSearch, props.class)}>
<div class={styles.searchHeader}>
<div class={styles.field}>
<input
class={styles.input}
type="text"
placeholder={props.placeholder ?? t('Search')}
onChange={(e) => handleInputChange(e.target.value)}
/>
<DropdownSelect selectItems={roles} />
</div>
<Button variant={'bordered'} size={'M'} value={t('Add')} />
</div>
<div class={styles.teaser}>
<h3>{t('Coming soon')}</h3>
<p>
{t(
'We are working on collaborative editing of articles and in the near future you will have an amazing opportunity - to create together with your colleagues',
)}
</p>
</div>
</div>
)
}

View File

@ -1 +0,0 @@
export { UserSearch } from './UserSearch'

View File

@ -28,6 +28,7 @@ export const inboxClient = {
loadChats: async (options: QueryLoad_ChatsArgs): Promise<Chat[]> => {
const resp = await inboxClient.private.query(myChats, options).toPromise()
console.log('!!! resp:', resp)
return resp.data.load_chats.chats
},

View File

@ -4,7 +4,7 @@ import { createSignal, onMount } from 'solid-js'
import { PageLayout } from '../components/_shared/PageLayout'
import { ShowOnlyOnClient } from '../components/_shared/ShowOnlyOnClient'
import { InboxView } from '../components/Views/Inbox'
import { InboxView } from '../components/Views/Inbox/Inbox'
import { InboxProvider } from '../context/inbox'
import { useLocalize } from '../context/localize'
import { loadAllAuthors } from '../stores/zine/authors'

View File

@ -16,7 +16,6 @@ export type ModalType =
| 'thank'
| 'confirm'
| 'donate'
| 'inviteToChat'
| 'uploadImage'
| 'simplifiedEditorUploadImage'
| 'uploadCoverImage'
@ -24,7 +23,7 @@ export type ModalType =
| 'followers'
| 'following'
| 'search'
| 'inviteCoAuthors'
| 'inviteMembers'
| 'share'
export const MODALS: Record<ModalType, ModalType> = {
@ -34,14 +33,13 @@ export const MODALS: Record<ModalType, ModalType> = {
thank: 'thank',
confirm: 'confirm',
donate: 'donate',
inviteToChat: 'inviteToChat',
inviteMembers: 'inviteMembers',
uploadImage: 'uploadImage',
simplifiedEditorUploadImage: 'simplifiedEditorUploadImage',
uploadCoverImage: 'uploadCoverImage',
editorInsertLink: 'editorInsertLink',
followers: 'followers',
following: 'following',
inviteCoAuthors: 'inviteCoAuthors',
search: 'search',
share: 'share',
}

View File

@ -1,5 +1,5 @@
import { createLazyMemo } from '@solid-primitives/memo'
import { createSignal } from 'solid-js'
import { createMemo, createSignal } from 'solid-js'
import { apiClient } from '../../graphql/client/core'
import { Author, QueryLoad_Authors_ByArgs } from '../../graphql/schema/core.gen'
@ -18,16 +18,13 @@ const sortedAuthors = createLazyMemo(() => {
const authors = Object.values(authorEntities())
switch (sortAllBy()) {
case 'followers': {
authors.sort(byStat('followers'))
break
return authors.sort(byStat('followers'))
}
case 'shouts': {
authors.sort(byStat('shouts'))
break
return authors.sort(byStat('shouts'))
}
case 'name': {
authors.sort((a, b) => a.name.localeCompare(b.name))
break
return authors.sort((a, b) => a.name.localeCompare(b.name))
}
}
return authors