mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-17 06:14:27 +01:00
feat: more work on the commenting system
This commit is contained in:
@@ -139,7 +139,7 @@ export interface NexusGenObjects {
|
|||||||
PostComment: { // root type
|
PostComment: { // root type
|
||||||
author: NexusGenRootTypes['Author']; // Author!
|
author: NexusGenRootTypes['Author']; // Author!
|
||||||
body: string; // String!
|
body: string; // String!
|
||||||
createdAt: NexusGenScalars['Date']; // Date!
|
created_at: NexusGenScalars['Date']; // Date!
|
||||||
id: number; // Int!
|
id: number; // Int!
|
||||||
parentId?: number | null; // Int
|
parentId?: number | null; // Int
|
||||||
votes_count: number; // Int!
|
votes_count: number; // Int!
|
||||||
@@ -158,7 +158,6 @@ export interface NexusGenObjects {
|
|||||||
}
|
}
|
||||||
Query: {};
|
Query: {};
|
||||||
Question: { // root type
|
Question: { // root type
|
||||||
answers_count: number; // Int!
|
|
||||||
body: string; // String!
|
body: string; // String!
|
||||||
createdAt: NexusGenScalars['Date']; // Date!
|
createdAt: NexusGenScalars['Date']; // Date!
|
||||||
excerpt: string; // String!
|
excerpt: string; // String!
|
||||||
@@ -316,7 +315,7 @@ export interface NexusGenFieldTypes {
|
|||||||
PostComment: { // field return type
|
PostComment: { // field return type
|
||||||
author: NexusGenRootTypes['Author']; // Author!
|
author: NexusGenRootTypes['Author']; // Author!
|
||||||
body: string; // String!
|
body: string; // String!
|
||||||
createdAt: NexusGenScalars['Date']; // Date!
|
created_at: NexusGenScalars['Date']; // Date!
|
||||||
id: number; // Int!
|
id: number; // Int!
|
||||||
parentId: number | null; // Int
|
parentId: number | null; // Int
|
||||||
votes_count: number; // Int!
|
votes_count: number; // Int!
|
||||||
@@ -358,10 +357,8 @@ export interface NexusGenFieldTypes {
|
|||||||
searchProjects: NexusGenRootTypes['Project'][]; // [Project!]!
|
searchProjects: NexusGenRootTypes['Project'][]; // [Project!]!
|
||||||
}
|
}
|
||||||
Question: { // field return type
|
Question: { // field return type
|
||||||
answers_count: number; // Int!
|
|
||||||
author: NexusGenRootTypes['Author']; // Author!
|
author: NexusGenRootTypes['Author']; // Author!
|
||||||
body: string; // String!
|
body: string; // String!
|
||||||
comments: NexusGenRootTypes['PostComment'][]; // [PostComment!]!
|
|
||||||
createdAt: NexusGenScalars['Date']; // Date!
|
createdAt: NexusGenScalars['Date']; // Date!
|
||||||
excerpt: string; // String!
|
excerpt: string; // String!
|
||||||
id: number; // Int!
|
id: number; // Int!
|
||||||
@@ -375,8 +372,6 @@ export interface NexusGenFieldTypes {
|
|||||||
Story: { // field return type
|
Story: { // field return type
|
||||||
author: NexusGenRootTypes['Author']; // Author!
|
author: NexusGenRootTypes['Author']; // Author!
|
||||||
body: string; // String!
|
body: string; // String!
|
||||||
comments: NexusGenRootTypes['PostComment'][]; // [PostComment!]!
|
|
||||||
comments_count: number; // Int!
|
|
||||||
cover_image: string | null; // String
|
cover_image: string | null; // String
|
||||||
createdAt: NexusGenScalars['Date']; // Date!
|
createdAt: NexusGenScalars['Date']; // Date!
|
||||||
excerpt: string; // String!
|
excerpt: string; // String!
|
||||||
@@ -524,7 +519,7 @@ export interface NexusGenFieldTypeNames {
|
|||||||
PostComment: { // field return type name
|
PostComment: { // field return type name
|
||||||
author: 'Author'
|
author: 'Author'
|
||||||
body: 'String'
|
body: 'String'
|
||||||
createdAt: 'Date'
|
created_at: 'Date'
|
||||||
id: 'Int'
|
id: 'Int'
|
||||||
parentId: 'Int'
|
parentId: 'Int'
|
||||||
votes_count: 'Int'
|
votes_count: 'Int'
|
||||||
@@ -566,10 +561,8 @@ export interface NexusGenFieldTypeNames {
|
|||||||
searchProjects: 'Project'
|
searchProjects: 'Project'
|
||||||
}
|
}
|
||||||
Question: { // field return type name
|
Question: { // field return type name
|
||||||
answers_count: 'Int'
|
|
||||||
author: 'Author'
|
author: 'Author'
|
||||||
body: 'String'
|
body: 'String'
|
||||||
comments: 'PostComment'
|
|
||||||
createdAt: 'Date'
|
createdAt: 'Date'
|
||||||
excerpt: 'String'
|
excerpt: 'String'
|
||||||
id: 'Int'
|
id: 'Int'
|
||||||
@@ -583,8 +576,6 @@ export interface NexusGenFieldTypeNames {
|
|||||||
Story: { // field return type name
|
Story: { // field return type name
|
||||||
author: 'Author'
|
author: 'Author'
|
||||||
body: 'String'
|
body: 'String'
|
||||||
comments: 'PostComment'
|
|
||||||
comments_count: 'Int'
|
|
||||||
cover_image: 'String'
|
cover_image: 'String'
|
||||||
createdAt: 'Date'
|
createdAt: 'Date'
|
||||||
excerpt: 'String'
|
excerpt: 'String'
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ interface PostBase {
|
|||||||
type PostComment {
|
type PostComment {
|
||||||
author: Author!
|
author: Author!
|
||||||
body: String!
|
body: String!
|
||||||
createdAt: Date!
|
created_at: Date!
|
||||||
id: Int!
|
id: Int!
|
||||||
parentId: Int
|
parentId: Int
|
||||||
votes_count: Int!
|
votes_count: Int!
|
||||||
@@ -169,10 +169,8 @@ type Query {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Question implements PostBase {
|
type Question implements PostBase {
|
||||||
answers_count: Int!
|
|
||||||
author: Author!
|
author: Author!
|
||||||
body: String!
|
body: String!
|
||||||
comments: [PostComment!]!
|
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
excerpt: String!
|
excerpt: String!
|
||||||
id: Int!
|
id: Int!
|
||||||
@@ -187,8 +185,6 @@ type Question implements PostBase {
|
|||||||
type Story implements PostBase {
|
type Story implements PostBase {
|
||||||
author: Author!
|
author: Author!
|
||||||
body: String!
|
body: String!
|
||||||
comments: [PostComment!]!
|
|
||||||
comments_count: Int!
|
|
||||||
cover_image: String
|
cover_image: String
|
||||||
createdAt: Date!
|
createdAt: Date!
|
||||||
excerpt: String!
|
excerpt: String!
|
||||||
|
|||||||
@@ -70,29 +70,29 @@ const Story = objectType({
|
|||||||
resolve: () => t.typeName
|
resolve: () => t.typeName
|
||||||
});
|
});
|
||||||
t.string('cover_image');
|
t.string('cover_image');
|
||||||
t.nonNull.list.nonNull.field('comments', {
|
// t.nonNull.list.nonNull.field('comments', {
|
||||||
type: "PostComment",
|
// type: "PostComment",
|
||||||
resolve: (parent) => prisma.story.findUnique({ where: { id: parent.id } }).comments()
|
// resolve: (parent) => prisma.story.findUnique({ where: { id: parent.id } }).comments()
|
||||||
});
|
// });
|
||||||
t.nonNull.list.nonNull.field('tags', {
|
t.nonNull.list.nonNull.field('tags', {
|
||||||
type: "Tag",
|
type: "Tag",
|
||||||
resolve: (parent) => prisma.story.findUnique({ where: { id: parent.id } }).tags()
|
resolve: (parent) => prisma.story.findUnique({ where: { id: parent.id } }).tags()
|
||||||
});
|
});
|
||||||
t.nonNull.int('comments_count', {
|
// t.nonNull.int('comments_count', {
|
||||||
resolve: async (parent) => {
|
// resolve: async (parent) => {
|
||||||
const post = await prisma.story.findUnique({
|
// const post = await prisma.story.findUnique({
|
||||||
where: { id: parent.id },
|
// where: { id: parent.id },
|
||||||
include: {
|
// include: {
|
||||||
_count: {
|
// _count: {
|
||||||
select: {
|
// select: {
|
||||||
comments: true
|
// comments: true
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
})
|
// })
|
||||||
return post._count.comments;
|
// return post._count.comments;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
t.nonNull.field('author', {
|
t.nonNull.field('author', {
|
||||||
type: "Author",
|
type: "Author",
|
||||||
resolve: (parent) =>
|
resolve: (parent) =>
|
||||||
@@ -170,13 +170,13 @@ const Question = objectType({
|
|||||||
resolve: (parent) => prisma.question.findUnique({ where: { id: parent.id } }).tags()
|
resolve: (parent) => prisma.question.findUnique({ where: { id: parent.id } }).tags()
|
||||||
});
|
});
|
||||||
|
|
||||||
t.nonNull.int('answers_count');
|
// t.nonNull.int('answers_count');
|
||||||
t.nonNull.list.nonNull.field('comments', {
|
// t.nonNull.list.nonNull.field('comments', {
|
||||||
type: "PostComment",
|
// type: "PostComment",
|
||||||
resolve: (parent) => {
|
// resolve: (parent) => {
|
||||||
return prisma.question.findUnique({ where: { id: parent.id } }).comments();
|
// return prisma.question.findUnique({ where: { id: parent.id } }).comments();
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
t.nonNull.field('author', {
|
t.nonNull.field('author', {
|
||||||
type: "Author",
|
type: "Author",
|
||||||
@@ -191,7 +191,7 @@ const PostComment = objectType({
|
|||||||
name: 'PostComment',
|
name: 'PostComment',
|
||||||
definition(t) {
|
definition(t) {
|
||||||
t.nonNull.int('id');
|
t.nonNull.int('id');
|
||||||
t.nonNull.date('createdAt');
|
t.nonNull.date('created_at');
|
||||||
t.nonNull.string('body');
|
t.nonNull.string('body');
|
||||||
t.nonNull.field('author', {
|
t.nonNull.field('author', {
|
||||||
type: "Author"
|
type: "Author"
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ const { createExpressApp } = require('../../modules');
|
|||||||
const express = require('express');
|
const express = require('express');
|
||||||
const extractKeyFromCookie = require('../../utils/extractKeyFromCookie');
|
const extractKeyFromCookie = require('../../utils/extractKeyFromCookie');
|
||||||
const { getUserByPubKey } = require('../../auth/utils/helperFuncs');
|
const { getUserByPubKey } = require('../../auth/utils/helperFuncs');
|
||||||
const { generatePrivateKey, getPublicKey, signEvent: signNostrEvent } = require('nostr-tools');
|
const { generatePrivateKey, getPublicKey, signEvent: signNostrEvent } = require('../../utils/nostr-tools');
|
||||||
const { prisma } = require('../../prisma');
|
const { prisma } = require('../../prisma');
|
||||||
|
|
||||||
|
|
||||||
const signEvent = async (req, res) => {
|
const signEvent = async (req, res) => {
|
||||||
|
console.log(req.body);
|
||||||
try {
|
try {
|
||||||
const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie)
|
const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie)
|
||||||
const user = await getUserByPubKey(userPubKey);
|
const user = await getUserByPubKey(userPubKey);
|
||||||
@@ -33,16 +34,18 @@ const signEvent = async (req, res) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const { content, tags } = req.body
|
const { content, tags, kind = 1 } = req.body.event
|
||||||
const event = {
|
const event = {
|
||||||
kind: 1,
|
kind,
|
||||||
pubkey,
|
pubkey,
|
||||||
content,
|
content,
|
||||||
tags,
|
tags,
|
||||||
created_at: Date.now(),
|
created_at: Date.now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
event.sig = await signNostrEvent(event, prvkey)
|
event.sig = await signNostrEvent(event, prvkey);
|
||||||
|
|
||||||
|
console.log(event);
|
||||||
|
|
||||||
return res
|
return res
|
||||||
.status(200)
|
.status(200)
|
||||||
@@ -59,11 +62,11 @@ let app;
|
|||||||
|
|
||||||
if (process.env.LOCAL) {
|
if (process.env.LOCAL) {
|
||||||
app = createExpressApp()
|
app = createExpressApp()
|
||||||
app.get('/sign-event', signEvent);
|
app.post('/sign-event', signEvent);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
router.get('/sign-event', signEvent)
|
router.post('/sign-event', signEvent)
|
||||||
app = createExpressApp(router)
|
app = createExpressApp(router)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
var cors = require('cors');
|
const cors = require('cors');
|
||||||
const cookieParser = require('cookie-parser');
|
const cookieParser = require('cookie-parser');
|
||||||
|
const bodyParser = require('body-parser')
|
||||||
|
|
||||||
|
|
||||||
const createExpressApp = (router) => {
|
const createExpressApp = (router) => {
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const routerBasePath = process.env.LOCAL ? `/dev` : `/.netlify/functions`
|
const routerBasePath = process.env.LOCAL ? `/dev` : `/.netlify/functions`
|
||||||
|
|
||||||
|
// parse application/x-www-form-urlencoded
|
||||||
|
app.use(bodyParser.urlencoded({ extended: false }))
|
||||||
|
|
||||||
|
// parse application/json
|
||||||
|
app.use(bodyParser.json())
|
||||||
|
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(cors({
|
app.use(cors({
|
||||||
origin: ['http://localhost:3000', 'https://studio.apollographql.com'],
|
origin: ['http://localhost:3000', 'https://studio.apollographql.com'],
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
CONSTS: require('./consts')
|
CONSTS: require('./consts'),
|
||||||
|
nostr_tools: require('./nostr-tools')
|
||||||
}
|
}
|
||||||
45
api/utils/nostr-tools.js
Normal file
45
api/utils/nostr-tools.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// import * as secp256k1 from '@noble/secp256k1'
|
||||||
|
// import { Buffer } from 'buffer'
|
||||||
|
const secp256k1 = require('@noble/secp256k1');
|
||||||
|
const crypto = require('crypto')
|
||||||
|
|
||||||
|
function generatePrivateKey() {
|
||||||
|
return Buffer.from(secp256k1.utils.randomPrivateKey()).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPublicKey(privateKey) {
|
||||||
|
return Buffer.from(secp256k1.schnorr.getPublicKey(privateKey)).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function serializeEvent(evt) {
|
||||||
|
return JSON.stringify([
|
||||||
|
0,
|
||||||
|
evt.pubkey,
|
||||||
|
evt.created_at,
|
||||||
|
evt.kind,
|
||||||
|
evt.tags,
|
||||||
|
evt.content
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getEventHash(event) {
|
||||||
|
let eventHash = crypto.createHash('sha256')
|
||||||
|
.update(Buffer.from(serializeEvent(event)))
|
||||||
|
.digest()
|
||||||
|
return Buffer.from(eventHash).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function signEvent(event, key) {
|
||||||
|
return Buffer.from(
|
||||||
|
await secp256k1.schnorr.sign(getEventHash(event), key)
|
||||||
|
).toString('hex')
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
generatePrivateKey,
|
||||||
|
getPublicKey,
|
||||||
|
signEvent,
|
||||||
|
}
|
||||||
241
package-lock.json
generated
241
package-lock.json
generated
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.5.10",
|
"@apollo/client": "^3.5.10",
|
||||||
"@hookform/resolvers": "^2.8.8",
|
"@hookform/resolvers": "^2.8.8",
|
||||||
|
"@noble/secp256k1": "^1.6.3",
|
||||||
"@prisma/client": "^3.12.0",
|
"@prisma/client": "^3.12.0",
|
||||||
"@react-hookz/web": "^13.2.1",
|
"@react-hookz/web": "^13.2.1",
|
||||||
"@react-spring/web": "^9.4.4",
|
"@react-spring/web": "^9.4.4",
|
||||||
@@ -84,8 +85,8 @@
|
|||||||
"react-tooltip": "^4.2.21",
|
"react-tooltip": "^4.2.21",
|
||||||
"react-topbar-progress-indicator": "^4.1.1",
|
"react-topbar-progress-indicator": "^4.1.1",
|
||||||
"remirror": "^1.0.77",
|
"remirror": "^1.0.77",
|
||||||
"secp256k1": "^4.0.3",
|
|
||||||
"serverless-http": "^3.0.1",
|
"serverless-http": "^3.0.1",
|
||||||
|
"stream": "npm:stream-browserify",
|
||||||
"turndown": "^7.1.1",
|
"turndown": "^7.1.1",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.6.3",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
@@ -123,6 +124,7 @@
|
|||||||
"msw": "^0.39.2",
|
"msw": "^0.39.2",
|
||||||
"netlify-cli": "^10.0.0",
|
"netlify-cli": "^10.0.0",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
|
"readable-stream": "^4.1.0",
|
||||||
"serverless-offline": "^8.7.0",
|
"serverless-offline": "^8.7.0",
|
||||||
"tailwindcss": "^3.0.24",
|
"tailwindcss": "^3.0.24",
|
||||||
"webpack": "^5.72.0"
|
"webpack": "^5.72.0"
|
||||||
@@ -17048,6 +17050,19 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/are-we-there-yet/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/arg": {
|
"node_modules/arg": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz",
|
||||||
@@ -18233,6 +18248,19 @@
|
|||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.1.13"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/bl/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bluebird": {
|
"node_modules/bluebird": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
@@ -18578,6 +18606,20 @@
|
|||||||
"safe-buffer": "^5.2.0"
|
"safe-buffer": "^5.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/browserify-sign/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/browserify-sign/node_modules/safe-buffer": {
|
"node_modules/browserify-sign/node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -25222,6 +25264,19 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hash-base/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/hash-base/node_modules/safe-buffer": {
|
"node_modules/hash-base/node_modules/safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -55868,6 +55923,19 @@
|
|||||||
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-gyp/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-int64": {
|
"node_modules/node-int64": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||||
@@ -60797,16 +60865,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/readable-stream": {
|
"node_modules/readable-stream": {
|
||||||
"version": "3.6.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz",
|
||||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
"integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"inherits": "^2.0.3",
|
"abort-controller": "^3.0.0"
|
||||||
"string_decoder": "^1.1.1",
|
|
||||||
"util-deprecate": "^1.0.1"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
@@ -63591,6 +63658,19 @@
|
|||||||
"wbuf": "^1.7.3"
|
"wbuf": "^1.7.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/spdy-transport/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/split-string": {
|
"node_modules/split-string": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
|
||||||
@@ -63907,6 +63987,16 @@
|
|||||||
"integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==",
|
"integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/stream": {
|
||||||
|
"name": "stream-browserify",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "~2.0.4",
|
||||||
|
"readable-stream": "^3.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/stream-browserify": {
|
"node_modules/stream-browserify": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
|
||||||
@@ -63994,6 +64084,19 @@
|
|||||||
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
|
"integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/stream/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/strict-event-emitter": {
|
"node_modules/strict-event-emitter": {
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz",
|
||||||
@@ -64666,6 +64769,19 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tar-stream/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tar/node_modules/mkdirp": {
|
"node_modules/tar/node_modules/mkdirp": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
@@ -80925,6 +81041,18 @@
|
|||||||
"requires": {
|
"requires": {
|
||||||
"delegates": "^1.0.0",
|
"delegates": "^1.0.0",
|
||||||
"readable-stream": "^3.6.0"
|
"readable-stream": "^3.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"arg": {
|
"arg": {
|
||||||
@@ -81851,6 +81979,16 @@
|
|||||||
"base64-js": "^1.3.1",
|
"base64-js": "^1.3.1",
|
||||||
"ieee754": "^1.1.13"
|
"ieee754": "^1.1.13"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -82153,6 +82291,17 @@
|
|||||||
"safe-buffer": "^5.2.0"
|
"safe-buffer": "^5.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -87282,6 +87431,16 @@
|
|||||||
"safe-buffer": "^5.2.0"
|
"safe-buffer": "^5.2.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"safe-buffer": {
|
"safe-buffer": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||||
@@ -110601,6 +110760,16 @@
|
|||||||
"gauge": "^4.0.3",
|
"gauge": "^4.0.3",
|
||||||
"set-blocking": "^2.0.0"
|
"set-blocking": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -114164,13 +114333,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
"version": "3.6.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.1.0.tgz",
|
||||||
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
"integrity": "sha512-sVisi3+P2lJ2t0BPbpK629j8wRW06yKGJUcaLAGXPAUhyUxVJm7VsCTit1PFgT4JHUDMrGNR+ZjSKpzGaRF3zw==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"inherits": "^2.0.3",
|
"abort-controller": "^3.0.0"
|
||||||
"string_decoder": "^1.1.1",
|
|
||||||
"util-deprecate": "^1.0.1"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
@@ -116356,6 +116524,18 @@
|
|||||||
"obuf": "^1.1.2",
|
"obuf": "^1.1.2",
|
||||||
"readable-stream": "^3.0.6",
|
"readable-stream": "^3.0.6",
|
||||||
"wbuf": "^1.7.3"
|
"wbuf": "^1.7.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"split-string": {
|
"split-string": {
|
||||||
@@ -116620,6 +116800,27 @@
|
|||||||
"integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==",
|
"integrity": "sha512-CMtO2Uneg3SAz/d6fZ/6qbqqQHi2ynq6/KzMD/26gTkiEShCcpqFfTHgOxsE0egAq6SX3FmN4CeSqn8BzXQkJg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"stream": {
|
||||||
|
"version": "npm:stream-browserify@3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "~2.0.4",
|
||||||
|
"readable-stream": "^3.5.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"stream-browserify": {
|
"stream-browserify": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
|
||||||
@@ -117231,6 +117432,18 @@
|
|||||||
"fs-constants": "^1.0.0",
|
"fs-constants": "^1.0.0",
|
||||||
"inherits": "^2.0.3",
|
"inherits": "^2.0.3",
|
||||||
"readable-stream": "^3.1.1"
|
"readable-stream": "^3.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"telejson": {
|
"telejson": {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.5.10",
|
"@apollo/client": "^3.5.10",
|
||||||
"@hookform/resolvers": "^2.8.8",
|
"@hookform/resolvers": "^2.8.8",
|
||||||
|
"@noble/secp256k1": "^1.6.3",
|
||||||
"@prisma/client": "^3.12.0",
|
"@prisma/client": "^3.12.0",
|
||||||
"@react-hookz/web": "^13.2.1",
|
"@react-hookz/web": "^13.2.1",
|
||||||
"@react-spring/web": "^9.4.4",
|
"@react-spring/web": "^9.4.4",
|
||||||
@@ -79,8 +80,8 @@
|
|||||||
"react-tooltip": "^4.2.21",
|
"react-tooltip": "^4.2.21",
|
||||||
"react-topbar-progress-indicator": "^4.1.1",
|
"react-topbar-progress-indicator": "^4.1.1",
|
||||||
"remirror": "^1.0.77",
|
"remirror": "^1.0.77",
|
||||||
"secp256k1": "^4.0.3",
|
|
||||||
"serverless-http": "^3.0.1",
|
"serverless-http": "^3.0.1",
|
||||||
|
"stream": "npm:stream-browserify",
|
||||||
"turndown": "^7.1.1",
|
"turndown": "^7.1.1",
|
||||||
"typescript": "^4.6.3",
|
"typescript": "^4.6.3",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
@@ -174,6 +175,7 @@
|
|||||||
"msw": "^0.39.2",
|
"msw": "^0.39.2",
|
||||||
"netlify-cli": "^10.0.0",
|
"netlify-cli": "^10.0.0",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
|
"readable-stream": "^4.1.0",
|
||||||
"serverless-offline": "^8.7.0",
|
"serverless-offline": "^8.7.0",
|
||||||
"tailwindcss": "^3.0.24",
|
"tailwindcss": "^3.0.24",
|
||||||
"webpack": "^5.72.0"
|
"webpack": "^5.72.0"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
Warnings:
|
||||||
|
|
||||||
|
- You are about to drop the column `createdAt` on the `PostComment` table. All the data in the column will be lost.
|
||||||
|
|
||||||
|
*/
|
||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "PostComment" DROP COLUMN "createdAt",
|
||||||
|
ADD COLUMN "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP;
|
||||||
@@ -156,7 +156,7 @@ model Question {
|
|||||||
model PostComment {
|
model PostComment {
|
||||||
id Int @id @default(autoincrement())
|
id Int @id @default(autoincrement())
|
||||||
body String
|
body String
|
||||||
createdAt DateTime @default(now())
|
created_at DateTime @default(now())
|
||||||
votes_count Int @default(0)
|
votes_count Int @default(0)
|
||||||
|
|
||||||
replies PostComment[] @relation("PostComment_Replies")
|
replies PostComment[] @relation("PostComment_Replies")
|
||||||
|
|||||||
@@ -51,6 +51,9 @@ functions:
|
|||||||
sign-event:
|
sign-event:
|
||||||
handler: api/functions/sign-event/sign-event.handler
|
handler: api/functions/sign-event/sign-event.handler
|
||||||
events:
|
events:
|
||||||
|
- http:
|
||||||
|
path: sign-event
|
||||||
|
method: get
|
||||||
- http:
|
- http:
|
||||||
path: sign-event
|
path: sign-event
|
||||||
method: post
|
method: post
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ interface Props {
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
autoFocus?: boolean
|
autoFocus?: boolean
|
||||||
|
onSubmit?: (comment: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function AddComment({ initialContent, placeholder, name, autoFocus }: Props) {
|
export default function AddComment({ initialContent, placeholder, name, autoFocus, onSubmit }: Props) {
|
||||||
|
|
||||||
const containerRef = useRef<HTMLDivElement>(null)
|
const containerRef = useRef<HTMLDivElement>(null)
|
||||||
const linkExtension = useMemo(() => {
|
const linkExtension = useMemo(() => {
|
||||||
@@ -85,8 +86,8 @@ export default function AddComment({ initialContent, placeholder, name, autoFocu
|
|||||||
|
|
||||||
|
|
||||||
const submitComment = () => {
|
const submitComment = () => {
|
||||||
console.log(valueRef.current);
|
onSubmit?.(valueRef.current);
|
||||||
manager.view.updateState(manager.createState({ content: manager.createEmptyDoc() }))
|
// manager.view.updateState(manager.createState({ content: manager.createEmptyDoc() }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,8 +97,8 @@ export default function AddComment({ initialContent, placeholder, name, autoFocu
|
|||||||
manager={manager}
|
manager={manager}
|
||||||
state={state}
|
state={state}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
const html = e.helpers.getHTML(e.state)
|
const md = e.helpers.getMarkdown(e.state)
|
||||||
valueRef.current = html;
|
valueRef.current = md;
|
||||||
onChange(e);
|
onChange(e);
|
||||||
}}
|
}}
|
||||||
autoFocus={autoFocus}
|
autoFocus={autoFocus}
|
||||||
|
|||||||
@@ -18,9 +18,10 @@ export const Default = Template.bind({});
|
|||||||
Default.args = {
|
Default.args = {
|
||||||
comment: {
|
comment: {
|
||||||
...MOCK_DATA.generatePostComments(1)[0],
|
...MOCK_DATA.generatePostComments(1)[0],
|
||||||
|
created_at: Date.now(),
|
||||||
replies: [
|
replies: [
|
||||||
{ ...MOCK_DATA.generatePostComments(1)[0], replies: [] },
|
{ ...MOCK_DATA.generatePostComments(1)[0], replies: [], created_at: Date.now() },
|
||||||
{ ...MOCK_DATA.generatePostComments(1)[0], replies: [] }
|
{ ...MOCK_DATA.generatePostComments(1)[0], replies: [], created_at: Date.now() }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import { CommentWithReplies } from "../types";
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
comment: CommentWithReplies
|
comment: CommentWithReplies
|
||||||
|
isRoot?: boolean;
|
||||||
onClickedReply?: () => void
|
onClickedReply?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Comment({ comment, onClickedReply }: Props) {
|
export default function Comment({ comment, isRoot, onClickedReply }: Props) {
|
||||||
|
|
||||||
const [replyOpen, setReplyOpen] = useState(false)
|
const [replyOpen, setReplyOpen] = useState(false)
|
||||||
const isRootComment = !comment.parentId;
|
|
||||||
|
|
||||||
|
|
||||||
const clickReply = () => {
|
const clickReply = () => {
|
||||||
if (isRootComment)
|
if (isRoot)
|
||||||
setReplyOpen(true);
|
setReplyOpen(true);
|
||||||
else
|
else
|
||||||
onClickedReply?.()
|
onClickedReply?.()
|
||||||
|
|||||||
@@ -16,9 +16,8 @@ const Template: ComponentStory<typeof CommentCard> = (args) => <div className="m
|
|||||||
|
|
||||||
export const Default = Template.bind({});
|
export const Default = Template.bind({});
|
||||||
Default.args = {
|
Default.args = {
|
||||||
comment: {
|
comment: MOCK_DATA.generatePostComments(1)[0]
|
||||||
...MOCK_DATA.posts.stories[0].comments[0],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,12 +12,12 @@ interface Props {
|
|||||||
export default function CommentCard({ comment, onReply }: Props) {
|
export default function CommentCard({ comment, onReply }: Props) {
|
||||||
return (
|
return (
|
||||||
<div className="border rounded-12 p-24">
|
<div className="border rounded-12 p-24">
|
||||||
<Header author={comment.author} date={comment.createdAt} />
|
<Header author={comment.author} date={new Date(comment.created_at).toISOString()} />
|
||||||
<p className="text-body4 mt-16">
|
<p className="text-body4 mt-16">
|
||||||
{comment.body}
|
{comment.body}
|
||||||
</p>
|
</p>
|
||||||
<div className="flex gap-24 mt-16 items-center">
|
<div className="flex gap-24 mt-16 items-center">
|
||||||
<VotesCount count={comment.votes_count} />
|
<VotesCount count={0} />
|
||||||
<button
|
<button
|
||||||
className="text-gray-600 font-medium hover:bg-gray-100 py-8 px-12 rounded-8"
|
className="text-gray-600 font-medium hover:bg-gray-100 py-8 px-12 rounded-8"
|
||||||
onClick={onReply}
|
onClick={onReply}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ const Template: ComponentStory<typeof CommentsSection> = (args) => <div classNam
|
|||||||
|
|
||||||
export const Default = Template.bind({});
|
export const Default = Template.bind({});
|
||||||
Default.args = {
|
Default.args = {
|
||||||
comments: MOCK_DATA.generatePostComments(15)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,44 +1,55 @@
|
|||||||
import React, { useEffect, useMemo } from 'react'
|
import React, { useEffect, useMemo, useState } from 'react'
|
||||||
import Comment from '../Comment/Comment'
|
import CommentRoot from '../Comment/Comment'
|
||||||
import AddComment from '../AddComment/AddComment'
|
import AddComment from '../AddComment/AddComment'
|
||||||
import { convertCommentsToTree } from '../helpers'
|
import { } from '../helpers'
|
||||||
import { Comment as IComment } from '../types'
|
import { Comment, } from '../types'
|
||||||
import { createWorkerFactory, useWorker } from '@shopify/react-web-worker'
|
import { createWorkerFactory, useWorker } from '@shopify/react-web-worker'
|
||||||
|
|
||||||
|
import * as CommentsWorker from './comments.worker'
|
||||||
|
import { Post_Type } from 'src/graphql'
|
||||||
|
|
||||||
const createWorker = createWorkerFactory(() => import('./comments.worker'));
|
// const createWorker = createWorkerFactory(() => import('./comments.worker'));
|
||||||
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
comments: IComment[]
|
type: Post_Type,
|
||||||
}
|
id: number | string
|
||||||
|
};
|
||||||
|
|
||||||
export default function CommentsSection({ comments }: Props) {
|
|
||||||
const worker = useWorker(createWorker);
|
export default function CommentsSection({ type, id }: Props) {
|
||||||
|
// const worker = useWorker(createWorker);
|
||||||
// const commentsTree = useMemo(() => convertCommentsToTree(comments), [comments])
|
// const commentsTree = useMemo(() => convertCommentsToTree(comments), [comments])
|
||||||
|
|
||||||
useEffect(() => {
|
const [commentsTree, setCommentsTree] = useState<Comment[]>([])
|
||||||
(async () => {
|
|
||||||
// Note: in your actual app code, make sure to check if Home
|
|
||||||
// is still mounted before setting state asynchronously!
|
|
||||||
const webWorkerMessage = await worker.now('prefix');
|
|
||||||
// worker
|
|
||||||
// alert(webWorkerMessage);
|
|
||||||
|
|
||||||
// setMessage(webWorkerMessage);
|
const filter = useMemo(() => `boltfun ${type}_comment ${id}` + (process.env.NODE_ENV === 'development' ? 'dev' : ""), [id, type])
|
||||||
})();
|
|
||||||
}, [worker])
|
useEffect(() => {
|
||||||
|
CommentsWorker.connect();
|
||||||
|
const unsub = CommentsWorker.sub(filter, (newComments) => {
|
||||||
|
setCommentsTree(newComments)
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unsub();
|
||||||
|
}
|
||||||
|
}, [filter]);
|
||||||
|
|
||||||
|
const handleNewComment = (newComment: string) => {
|
||||||
|
CommentsWorker.post(newComment, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="border border-gray-200 rounded-10 p-32 bg-white">
|
<div className="border border-gray-200 rounded-10 p-32 bg-white">
|
||||||
<h6 className="text-body2 font-bolder">Discussion ({comments.length})</h6>
|
<h6 className="text-body2 font-bolder">Discussion</h6>
|
||||||
<div className="mt-24">
|
<div className="mt-24">
|
||||||
<AddComment placeholder='Leave a comment...' />
|
<AddComment placeholder='Leave a comment...' onSubmit={handleNewComment} />
|
||||||
|
</div>
|
||||||
|
<div className='flex flex-col gap-16 mt-32'>
|
||||||
|
{commentsTree.map(comment => <CommentRoot key={comment.id} comment={comment} />)}
|
||||||
</div>
|
</div>
|
||||||
{/* <div className='flex flex-col gap-16 mt-32'>
|
|
||||||
{commentsTree.map(comment => <Comment key={comment.id} comment={comment} />)}
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,27 @@
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
import { relayPool } from 'nostr-tools'
|
import { generatePrivateKey, getPublicKey, relayPool } from 'nostr-tools'
|
||||||
import { Nullable } from 'remirror';
|
import { Nullable } from 'remirror';
|
||||||
import { CONSTS } from 'src/utils';
|
import { CONSTS } from 'src/utils';
|
||||||
|
import { Comment } from '../types';
|
||||||
import { mapPubkeysToUsers, } from './comment.server';
|
import { mapPubkeysToUsers, } from './comment.server';
|
||||||
|
|
||||||
|
|
||||||
const pool = relayPool()
|
type Author = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
avatar: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const pool = relayPool();
|
||||||
|
const globalKeys = {
|
||||||
|
prvkey: '',
|
||||||
|
pubkey: ''
|
||||||
|
}
|
||||||
|
|
||||||
export function now(prefix: string) {
|
export function now(prefix: string) {
|
||||||
const hell = window.localStorage.getItem('test');
|
const hell = window.localStorage.getItem('test');
|
||||||
@@ -16,31 +31,38 @@ export function now(prefix: string) {
|
|||||||
|
|
||||||
export function connect() {
|
export function connect() {
|
||||||
const RELAYS = [
|
const RELAYS = [
|
||||||
'wss://rsslay.fiatjaf.com',
|
'wss://nostr.drss.io',
|
||||||
'wss://nostr-pub.wellorder.net',
|
'wss://nostr-relay.freeberty.net',
|
||||||
'wss://expensive-relay.fiatjaf.com',
|
'wss://nostr.unknown.place',
|
||||||
'wss://nostr.bitcoiner.social',
|
'wss://nostr-relay.untethr.me',
|
||||||
'wss://relayer.fiatjaf.com',
|
'wss://relay.damus.io'
|
||||||
'wss://nostr.rocks'
|
|
||||||
];
|
];
|
||||||
RELAYS.forEach(url => {
|
RELAYS.forEach(url => {
|
||||||
pool.addRelay(url, { read: true, write: true })
|
pool.addRelay(url, { read: true, write: true })
|
||||||
})
|
})
|
||||||
|
pool.onNotice((notice: string, relay: any) => {
|
||||||
|
console.log(`${relay.url} says: ${notice}`)
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const events: Record<string, Required<NostrEvent>> = {};
|
const events: Record<string, Required<NostrEvent>> = {};
|
||||||
|
|
||||||
export function sub(filter: any) {
|
export function sub(filter: string, cb: (data: Comment[]) => void) {
|
||||||
|
|
||||||
let sub = pool.sub({
|
let sub = pool.sub({
|
||||||
filter,
|
filter: {
|
||||||
cb: (event: Required<NostrEvent>) => {
|
"#r": [filter]
|
||||||
|
},
|
||||||
|
cb: async (event: Required<NostrEvent>) => {
|
||||||
//Got a new event
|
//Got a new event
|
||||||
|
console.log(event);
|
||||||
|
|
||||||
if (!event.id) return;
|
if (!event.id) return;
|
||||||
|
|
||||||
if (event.id in events) return
|
if (event.id in events) return
|
||||||
events[event.id] = event
|
events[event.id] = event
|
||||||
eventsUpdated();
|
const newComments = await constructTree();
|
||||||
|
cb(newComments)
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -53,28 +75,55 @@ export function sub(filter: any) {
|
|||||||
|
|
||||||
const getSignedEvents = async (event: any) => {
|
const getSignedEvents = async (event: any) => {
|
||||||
const res = await fetch(CONSTS.apiEndpoint + '/sign-event', {
|
const res = await fetch(CONSTS.apiEndpoint + '/sign-event', {
|
||||||
|
method: "post",
|
||||||
|
body: JSON.stringify({ event }),
|
||||||
credentials: 'include'
|
credentials: 'include'
|
||||||
})
|
})
|
||||||
const data = await res.json()
|
const data = await res.json()
|
||||||
return data.event;
|
return data.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function post(data: string, filter: any) {
|
function setKeys() {
|
||||||
|
if (globalKeys.prvkey) return;
|
||||||
|
|
||||||
|
let privateKey = localStorage.getItem('nostrkey')
|
||||||
|
if (!privateKey) {
|
||||||
|
privateKey = generatePrivateKey()
|
||||||
|
localStorage.setItem('nostrkey', privateKey)
|
||||||
|
}
|
||||||
|
pool.setPrivateKey(privateKey)
|
||||||
|
const pubkey = getPublicKey(privateKey)
|
||||||
|
globalKeys.prvkey = privateKey
|
||||||
|
globalKeys.pubkey = pubkey;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function post(data: string, filter: string) {
|
||||||
|
|
||||||
|
// setKeys();
|
||||||
|
let event: NostrEvent;
|
||||||
|
try {
|
||||||
|
event = await getSignedEvents({
|
||||||
|
// pubkey: globalKeys.pubkey,
|
||||||
|
// created_at: Math.round(Date.now() / 1000),
|
||||||
|
kind: 1,
|
||||||
|
tags: [['r', filter]],
|
||||||
|
content: data
|
||||||
|
}) as NostrEvent;
|
||||||
|
console.log(event);
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
alert("Couldn't sign the object successfully...")
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
let event: NostrEvent = {
|
|
||||||
created_at: Math.round(Date.now() / 1000),
|
|
||||||
kind: 1,
|
|
||||||
tags: filter,
|
|
||||||
content: data
|
|
||||||
};
|
|
||||||
|
|
||||||
event = await getSignedEvents(event);
|
|
||||||
const publishTimeout = setTimeout(() => {
|
const publishTimeout = setTimeout(() => {
|
||||||
alert(
|
alert(
|
||||||
`failed to publish event ${event.id?.slice(0, 5)}… to any relay.`
|
`failed to publish comment to any relay.`
|
||||||
)
|
);
|
||||||
}, 4000)
|
}, 5000)
|
||||||
|
|
||||||
pool.publish(event, (status: number, relay: string) => {
|
pool.publish(event, (status: number, relay: string) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@@ -102,27 +151,14 @@ function extractParentId(event: NostrEvent): Nullable<string> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function eventsUpdated() {
|
export async function constructTree() {
|
||||||
// This function is responsible for transforming the object shaped events into a tree of comments
|
// This function is responsible for transforming the object shaped events into a tree of comments
|
||||||
// ----------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Sort them chronologically from oldest to newest
|
// Sort them chronologically from oldest to newest
|
||||||
let sortedEvenets = Object.values(events).sort((a, b) => a.created_at - b.created_at);
|
let sortedEvenets = Object.values(events).sort((a, b) => a.created_at - b.created_at);
|
||||||
|
|
||||||
type Author = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
avatar: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Comment = {
|
|
||||||
id: string,
|
|
||||||
pubkey: string;
|
|
||||||
author?: Author;
|
|
||||||
content: any;
|
|
||||||
created_at: number;
|
|
||||||
replies: Comment[]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract the pubkeys used
|
// Extract the pubkeys used
|
||||||
const pubkeysSet = new Set();
|
const pubkeysSet = new Set();
|
||||||
@@ -138,13 +174,19 @@ export async function eventsUpdated() {
|
|||||||
const parentId = extractParentId(e);
|
const parentId = extractParentId(e);
|
||||||
if (parentId) {
|
if (parentId) {
|
||||||
eventsTree[parentId]?.replies.push({
|
eventsTree[parentId]?.replies.push({
|
||||||
...e,
|
id: e.id,
|
||||||
|
body: e.content,
|
||||||
|
created_at: e.created_at,
|
||||||
|
pubkey: e.pubkey,
|
||||||
author: pubkeyToUser[e.pubkey],
|
author: pubkeyToUser[e.pubkey],
|
||||||
replies: [],
|
replies: [],
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
eventsTree[e.id] = ({
|
eventsTree[e.id] = ({
|
||||||
...e,
|
id: e.id,
|
||||||
|
body: e.content,
|
||||||
|
created_at: e.created_at,
|
||||||
|
pubkey: e.pubkey,
|
||||||
author: pubkeyToUser[e.pubkey],
|
author: pubkeyToUser[e.pubkey],
|
||||||
replies: [],
|
replies: [],
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import { Comment, CommentWithReplies } from "./types";
|
import { Comment, CommentWithReplies } from "./types";
|
||||||
|
|
||||||
|
|
||||||
export function convertCommentsToTree(comments: Comment[]) {
|
// export function convertCommentsToTree(comments: Comment[]) {
|
||||||
let tree: Record<Comment['id'], CommentWithReplies> = {};
|
// let tree: Record<Comment['id'], CommentWithReplies> = {};
|
||||||
|
|
||||||
for (const comment of comments)
|
// for (const comment of comments)
|
||||||
tree[comment.id] = { ...comment, replies: [] }
|
// tree[comment.id] = { ...comment, replies: [] }
|
||||||
|
|
||||||
for (const comment of Object.values(tree)) {
|
// for (const comment of Object.values(tree)) {
|
||||||
if (comment.parentId)
|
// if (comment.parentId)
|
||||||
tree[comment.parentId].replies = [...tree[comment.parentId].replies, comment]
|
// tree[comment.parentId].replies = [...tree[comment.parentId].replies, comment]
|
||||||
}
|
// }
|
||||||
|
|
||||||
// TODO
|
// // TODO
|
||||||
// Sort the comments according to date
|
// // Sort the comments according to date
|
||||||
|
|
||||||
return Object.values(tree).filter(node => !node.parentId);
|
// return Object.values(tree).filter(node => !node.parentId);
|
||||||
}
|
// }
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
import { Author } from "src/features/Posts/types";
|
import { Author } from "src/features/Posts/types";
|
||||||
|
|
||||||
export interface Comment {
|
export interface Comment {
|
||||||
id: number
|
id: string | number,
|
||||||
author: Author
|
pubkey: string;
|
||||||
createdAt: string
|
author?: Pick<Author, 'id' | 'name' | 'avatar'>;
|
||||||
body: string
|
body: any;
|
||||||
votes_count: number
|
created_at: number;
|
||||||
parentId: number | null
|
replies: Comment[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CommentWithReplies extends Comment {
|
export interface CommentWithReplies extends Comment {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Link } from 'react-router-dom';
|
|||||||
import { createRoute } from 'src/utils/routing';
|
import { createRoute } from 'src/utils/routing';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
author: {
|
author?: {
|
||||||
id: number,
|
id: number,
|
||||||
name: string,
|
name: string,
|
||||||
avatar: string
|
avatar: string
|
||||||
@@ -45,11 +45,15 @@ export default function Header({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex gap-8'>
|
<div className='flex gap-8'>
|
||||||
<Link to={createRoute({ type: 'profile', id: props.author.id, username: props.author.name })}>
|
{props.author ?
|
||||||
<Avatar width={avatarSize[size]} src={props.author.avatar} />
|
<Link to={createRoute({ type: 'profile', id: props.author.id, username: props.author.name })}>
|
||||||
</Link>
|
<Avatar width={avatarSize[size]} src={props.author.avatar} />
|
||||||
|
</Link>
|
||||||
|
:
|
||||||
|
<></>
|
||||||
|
}
|
||||||
<div className='overflow-hidden'>
|
<div className='overflow-hidden'>
|
||||||
<p className={`${nameSize[size]} text-black font-medium overflow-hidden text-ellipsis`}>{trimText(props.author.name, 30)}</p>
|
<p className={`${nameSize[size]} text-black font-medium overflow-hidden text-ellipsis`}>{props.author ? trimText(props.author.name, 30) : "Anonymouse"}</p>
|
||||||
<p className={`text-body6 text-gray-600`}>{dateToShow()}</p>
|
<p className={`text-body6 text-gray-600`}>{dateToShow()}</p>
|
||||||
</div>
|
</div>
|
||||||
{/* {showTimeAgo && <p className={`${nameSize[size]} text-gray-500 ml-auto `}>
|
{/* {showTimeAgo && <p className={`${nameSize[size]} text-gray-500 ml-auto `}>
|
||||||
|
|||||||
@@ -16,14 +16,13 @@ export type QuestionCardType = Pick<Question,
|
|||||||
| 'author'
|
| 'author'
|
||||||
| 'excerpt'
|
| 'excerpt'
|
||||||
| 'votes_count'
|
| 'votes_count'
|
||||||
| "answers_count"
|
|
||||||
> & {
|
> & {
|
||||||
comments: Array<Pick<Question['comments'][number],
|
// comments: Array<Pick<Question['comments'][number],
|
||||||
| 'id'
|
// | 'id'
|
||||||
| 'author'
|
// | 'author'
|
||||||
| 'body'
|
// | 'body'
|
||||||
| 'createdAt'
|
// | 'createdAt'
|
||||||
>>
|
// >>
|
||||||
tags: Array<Pick<Tag, 'id' | "title">>
|
tags: Array<Pick<Tag, 'id' | "title">>
|
||||||
};
|
};
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -54,24 +53,24 @@ export default function QuestionCard({ question }: Props) {
|
|||||||
<hr className="my-16 bg-gray-200" />
|
<hr className="my-16 bg-gray-200" />
|
||||||
<div className="flex gap-24 items-center">
|
<div className="flex gap-24 items-center">
|
||||||
<VoteButton votes={question.votes_count} dense />
|
<VoteButton votes={question.votes_count} dense />
|
||||||
<div className="text-gray-600">
|
{/* <div className="text-gray-600">
|
||||||
<FiUsers /> <span className="align-middle text-body5">{question.answers_count} Answers</span>
|
<FiUsers /> <span className="align-middle text-body5">{question.answers_count} Answers</span>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex p-16 mt-16 flex-col gap-10 bg-gray-50">
|
<div className="flex p-16 mt-16 flex-col gap-10 bg-gray-50">
|
||||||
<div className="flex flex-col gap-10">
|
<div className="flex flex-col gap-10">
|
||||||
{question.comments.slice(0, 2).map(comment => <div key={comment.id} className="border-b last-of-type:border-b-0 pb-8 " >
|
{/* {question.comments.slice(0, 2).map(comment => <div key={comment.id} className="border-b last-of-type:border-b-0 pb-8 " >
|
||||||
<Header author={comment.author} size='sm' date={comment.createdAt} />
|
<Header author={comment.author} size='sm' date={comment.createdAt} />
|
||||||
<p className="text-body5 text-gray-600 mt-8">{trimText(comment.body, 80)}</p>
|
<p className="text-body5 text-gray-600 mt-8">{trimText(comment.body, 80)}</p>
|
||||||
</div>)}
|
</div>)} */}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex">
|
{/* <div className="flex">
|
||||||
<Link to={`/blog/post/Question/${question.id}`} className="text-black font-medium p-8 hover:bg-gray-100 rounded">
|
<Link to={`/blog/post/Question/${question.id}`} className="text-black font-medium p-8 hover:bg-gray-100 rounded">
|
||||||
See all {question.answers_count} comments
|
See all {question.answers_count} comments
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ export type StoryCardType = Pick<Story,
|
|||||||
| 'author'
|
| 'author'
|
||||||
| 'excerpt'
|
| 'excerpt'
|
||||||
| 'votes_count'
|
| 'votes_count'
|
||||||
| 'comments_count'
|
|
||||||
> & {
|
> & {
|
||||||
tags: Array<Pick<Tag, 'id' | "title">>
|
tags: Array<Pick<Tag, 'id' | "title">>
|
||||||
};
|
};
|
||||||
@@ -51,9 +50,9 @@ export default function StoryCard({ story }: Props) {
|
|||||||
<hr className="my-16 bg-gray-200" />
|
<hr className="my-16 bg-gray-200" />
|
||||||
<div className="flex gap-24 items-center">
|
<div className="flex gap-24 items-center">
|
||||||
<VoteButton votes={story.votes_count} dense onVote={vote} />
|
<VoteButton votes={story.votes_count} dense onVote={vote} />
|
||||||
<div className="text-gray-600">
|
{/* <div className="text-gray-600">
|
||||||
<BiComment /> <span className="align-middle text-body5">{story.comments_count} Comments</span>
|
<BiComment /> <span className="align-middle text-body5">{story.comments_count} Comments</span>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ mutation createStory($data: StoryInputType) {
|
|||||||
is_published
|
is_published
|
||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
comments_count
|
# comments_count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ query Feed($take: Int, $skip: Int, $sortBy: String, $tag: Int) {
|
|||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
comments_count
|
# comments_count
|
||||||
}
|
}
|
||||||
... on Bounty {
|
... on Bounty {
|
||||||
id
|
id
|
||||||
@@ -59,18 +59,18 @@ query Feed($take: Int, $skip: Int, $sortBy: String, $tag: Int) {
|
|||||||
}
|
}
|
||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
answers_count
|
# answers_count
|
||||||
comments {
|
# comments {
|
||||||
id
|
# id
|
||||||
createdAt
|
# created_at
|
||||||
body
|
# body
|
||||||
author {
|
# author {
|
||||||
id
|
# id
|
||||||
name
|
# name
|
||||||
avatar
|
# avatar
|
||||||
join_date
|
# join_date
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Helmet } from 'react-helmet'
|
|||||||
import { useParams } from 'react-router-dom'
|
import { useParams } from 'react-router-dom'
|
||||||
import LoadingPage from 'src/Components/LoadingPage/LoadingPage'
|
import LoadingPage from 'src/Components/LoadingPage/LoadingPage'
|
||||||
import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage'
|
import NotFoundPage from 'src/features/Shared/pages/NotFoundPage/NotFoundPage'
|
||||||
import { usePostDetailsQuery } from 'src/graphql'
|
import { Post_Type, usePostDetailsQuery } from 'src/graphql'
|
||||||
import { capitalize } from 'src/utils/helperFunctions'
|
import { capitalize } from 'src/utils/helperFunctions'
|
||||||
import { useAppSelector, } from 'src/utils/hooks'
|
import { useAppSelector, } from 'src/utils/hooks'
|
||||||
import { CommentsSection } from '../../Components/Comments'
|
import { CommentsSection } from '../../Components/Comments'
|
||||||
@@ -72,7 +72,7 @@ export default function PostDetailsPage() {
|
|||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
<div id="comments">
|
<div id="comments">
|
||||||
<CommentsSection comments={[]} />
|
<CommentsSection id={post.id} type={type as Post_Type} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -19,19 +19,19 @@ query PostDetails($id: Int!, $type: POST_TYPE!) {
|
|||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
is_published
|
is_published
|
||||||
comments_count
|
# comments_count
|
||||||
comments {
|
# comments {
|
||||||
id
|
# id
|
||||||
createdAt
|
# created_at
|
||||||
body
|
# body
|
||||||
votes_count
|
# votes_count
|
||||||
parentId
|
# parentId
|
||||||
author {
|
# author {
|
||||||
id
|
# id
|
||||||
name
|
# name
|
||||||
avatar
|
# avatar
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
... on Bounty {
|
... on Bounty {
|
||||||
id
|
id
|
||||||
@@ -82,19 +82,19 @@ query PostDetails($id: Int!, $type: POST_TYPE!) {
|
|||||||
}
|
}
|
||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
answers_count
|
# answers_count
|
||||||
comments {
|
# comments {
|
||||||
id
|
# id
|
||||||
createdAt
|
# created_at
|
||||||
body
|
# body
|
||||||
votes_count
|
# votes_count
|
||||||
parentId
|
# parentId
|
||||||
author {
|
# author {
|
||||||
id
|
# id
|
||||||
name
|
# name
|
||||||
avatar
|
# avatar
|
||||||
}
|
# }
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export type PostComment = {
|
|||||||
__typename?: 'PostComment';
|
__typename?: 'PostComment';
|
||||||
author: Author;
|
author: Author;
|
||||||
body: Scalars['String'];
|
body: Scalars['String'];
|
||||||
createdAt: Scalars['Date'];
|
created_at: Scalars['Date'];
|
||||||
id: Scalars['Int'];
|
id: Scalars['Int'];
|
||||||
parentId: Maybe<Scalars['Int']>;
|
parentId: Maybe<Scalars['Int']>;
|
||||||
votes_count: Scalars['Int'];
|
votes_count: Scalars['Int'];
|
||||||
@@ -311,10 +311,8 @@ export type QuerySearchProjectsArgs = {
|
|||||||
|
|
||||||
export type Question = PostBase & {
|
export type Question = PostBase & {
|
||||||
__typename?: 'Question';
|
__typename?: 'Question';
|
||||||
answers_count: Scalars['Int'];
|
|
||||||
author: Author;
|
author: Author;
|
||||||
body: Scalars['String'];
|
body: Scalars['String'];
|
||||||
comments: Array<PostComment>;
|
|
||||||
createdAt: Scalars['Date'];
|
createdAt: Scalars['Date'];
|
||||||
excerpt: Scalars['String'];
|
excerpt: Scalars['String'];
|
||||||
id: Scalars['Int'];
|
id: Scalars['Int'];
|
||||||
@@ -330,8 +328,6 @@ export type Story = PostBase & {
|
|||||||
__typename?: 'Story';
|
__typename?: 'Story';
|
||||||
author: Author;
|
author: Author;
|
||||||
body: Scalars['String'];
|
body: Scalars['String'];
|
||||||
comments: Array<PostComment>;
|
|
||||||
comments_count: Scalars['Int'];
|
|
||||||
cover_image: Maybe<Scalars['String']>;
|
cover_image: Maybe<Scalars['String']>;
|
||||||
createdAt: Scalars['Date'];
|
createdAt: Scalars['Date'];
|
||||||
excerpt: Scalars['String'];
|
excerpt: Scalars['String'];
|
||||||
@@ -482,7 +478,7 @@ export type CreateStoryMutationVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type CreateStoryMutation = { __typename?: 'Mutation', createStory: { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, is_published: boolean | null, type: string, cover_image: string | null, comments_count: number, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | null };
|
export type CreateStoryMutation = { __typename?: 'Mutation', createStory: { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, is_published: boolean | null, type: string, cover_image: string | null, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | null };
|
||||||
|
|
||||||
export type DeleteStoryMutationVariables = Exact<{
|
export type DeleteStoryMutationVariables = Exact<{
|
||||||
deleteStoryId: Scalars['Int'];
|
deleteStoryId: Scalars['Int'];
|
||||||
@@ -504,7 +500,7 @@ export type FeedQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type FeedQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, cover_image: string | null, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, createdAt: any, body: string, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any } }> } | { __typename?: 'Story', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, cover_image: string | null, comments_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
|
export type FeedQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, cover_image: string | null, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Story', id: number, title: string, createdAt: any, excerpt: string, votes_count: number, type: string, cover_image: string | null, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
|
||||||
|
|
||||||
export type PostDetailsQueryVariables = Exact<{
|
export type PostDetailsQueryVariables = Exact<{
|
||||||
id: Scalars['Int'];
|
id: Scalars['Int'];
|
||||||
@@ -512,14 +508,14 @@ export type PostDetailsQueryVariables = Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, applications: Array<{ __typename?: 'BountyApplication', id: number, date: string, workplan: string, author: { __typename?: 'Author', id: number, name: string, avatar: string } }> } | { __typename?: 'Question', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, answers_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, createdAt: any, body: string, votes_count: number, parentId: number | null, author: { __typename?: 'Author', id: number, name: string, avatar: string } }> } | { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, is_published: boolean | null, comments_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, createdAt: any, body: string, votes_count: number, parentId: number | null, author: { __typename?: 'Author', id: number, name: string, avatar: string } }> } };
|
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, applications: Array<{ __typename?: 'BountyApplication', id: number, date: string, workplan: string, author: { __typename?: 'Author', id: number, name: string, avatar: string } }> } | { __typename?: 'Question', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string | null, is_published: boolean | null, author: { __typename?: 'Author', id: number, name: string, avatar: string, join_date: any }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
|
||||||
|
|
||||||
export type ProfileQueryVariables = Exact<{
|
export type ProfileQueryVariables = Exact<{
|
||||||
profileId: Scalars['Int'];
|
profileId: Scalars['Int'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type ProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: number, name: string, avatar: string, join_date: any, role: string | null, email: string | null, jobTitle: string | null, lightning_address: string | null, website: string | null, twitter: string | null, github: string | null, linkedin: string | null, bio: string | null, location: string | null, stories: Array<{ __typename?: 'Story', id: number, title: string, createdAt: any, tags: Array<{ __typename?: 'Tag', title: string, icon: string | null, id: number }> }> } | null };
|
export type ProfileQuery = { __typename?: 'Query', profile: { __typename?: 'User', id: number, name: string, avatar: string, join_date: any, role: string | null, email: string | null, jobTitle: string | null, lightning_address: string | null, website: string | null, twitter: string | null, github: string | null, linkedin: string | null, bio: string | null, location: string | null, stories: Array<{ __typename?: 'Story', id: number, title: string, createdAt: any, tags: Array<{ __typename?: 'Tag', id: number, title: string, icon: string | null }> }> } | null };
|
||||||
|
|
||||||
export type UpdateProfileAboutMutationVariables = Exact<{
|
export type UpdateProfileAboutMutationVariables = Exact<{
|
||||||
data: InputMaybe<UpdateProfileInput>;
|
data: InputMaybe<UpdateProfileInput>;
|
||||||
@@ -1005,7 +1001,6 @@ export const CreateStoryDocument = gql`
|
|||||||
is_published
|
is_published
|
||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
comments_count
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
@@ -1125,7 +1120,6 @@ export const FeedDocument = gql`
|
|||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
comments_count
|
|
||||||
}
|
}
|
||||||
... on Bounty {
|
... on Bounty {
|
||||||
id
|
id
|
||||||
@@ -1166,18 +1160,6 @@ export const FeedDocument = gql`
|
|||||||
}
|
}
|
||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
answers_count
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
createdAt
|
|
||||||
body
|
|
||||||
author {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
avatar
|
|
||||||
join_date
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1235,19 +1217,6 @@ export const PostDetailsDocument = gql`
|
|||||||
type
|
type
|
||||||
cover_image
|
cover_image
|
||||||
is_published
|
is_published
|
||||||
comments_count
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
createdAt
|
|
||||||
body
|
|
||||||
votes_count
|
|
||||||
parentId
|
|
||||||
author {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
avatar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
... on Bounty {
|
... on Bounty {
|
||||||
id
|
id
|
||||||
@@ -1298,19 +1267,6 @@ export const PostDetailsDocument = gql`
|
|||||||
}
|
}
|
||||||
votes_count
|
votes_count
|
||||||
type
|
type
|
||||||
answers_count
|
|
||||||
comments {
|
|
||||||
id
|
|
||||||
createdAt
|
|
||||||
body
|
|
||||||
votes_count
|
|
||||||
parentId
|
|
||||||
author {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
avatar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1366,9 +1322,9 @@ export const ProfileDocument = gql`
|
|||||||
title
|
title
|
||||||
createdAt
|
createdAt
|
||||||
tags {
|
tags {
|
||||||
|
id
|
||||||
title
|
title
|
||||||
icon
|
icon
|
||||||
id
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const getAuthor = () => ({
|
|||||||
join_date: getDate()
|
join_date: getDate()
|
||||||
})
|
})
|
||||||
|
|
||||||
export const generatePostComments = (cnt: number = 1): Story['comments'] => {
|
export const generatePostComments = (cnt: number = 1) => {
|
||||||
|
|
||||||
let comments = [];
|
let comments = [];
|
||||||
const rootCommentsIds: any[] = []
|
const rootCommentsIds: any[] = []
|
||||||
@@ -24,10 +24,12 @@ export const generatePostComments = (cnt: number = 1): Story['comments'] => {
|
|||||||
const comment = {
|
const comment = {
|
||||||
id: i + 1,
|
id: i + 1,
|
||||||
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nisi, at ut sit id. Vulputate aliquet aliquam penatibus ac, et dictum est etiam. Sagittis odio dui sed viverra donec rutrum iaculis vitae morbi.",
|
body: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nisi, at ut sit id. Vulputate aliquet aliquam penatibus ac, et dictum est etiam. Sagittis odio dui sed viverra donec rutrum iaculis vitae morbi.",
|
||||||
createdAt: getDate(),
|
created_at: Date.now(),
|
||||||
author: getAuthor(),
|
author: getAuthor(),
|
||||||
votes_count: 123,
|
votes_count: 123,
|
||||||
parentId
|
parentId,
|
||||||
|
pubkey: '123',
|
||||||
|
replies: [],
|
||||||
}
|
}
|
||||||
comments.push(comment);
|
comments.push(comment);
|
||||||
if (!parentId)
|
if (!parentId)
|
||||||
@@ -85,14 +87,17 @@ export let posts = {
|
|||||||
title: 'Digital Editor, Mars Review of Books',
|
title: 'Digital Editor, Mars Review of Books',
|
||||||
body: postBody,
|
body: postBody,
|
||||||
cover_image: getCoverImage(),
|
cover_image: getCoverImage(),
|
||||||
comments_count: 3,
|
// comments_count: 3,
|
||||||
createdAt: getDate(),
|
createdAt: getDate(),
|
||||||
|
updatedAt: getDate(),
|
||||||
votes_count: 120,
|
votes_count: 120,
|
||||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||||
type: "Story",
|
type: "Story",
|
||||||
tags: randomItems(3, ...tags),
|
tags: randomItems(3, ...tags),
|
||||||
author: getAuthor(),
|
author: getAuthor(),
|
||||||
comments: generatePostComments(3),
|
// comments: generatePostComments(3),
|
||||||
|
is_published: true,
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -100,15 +105,16 @@ export let posts = {
|
|||||||
title: 'The End Is Nigh',
|
title: 'The End Is Nigh',
|
||||||
body: postBody,
|
body: postBody,
|
||||||
cover_image: getCoverImage(),
|
cover_image: getCoverImage(),
|
||||||
comments_count: 3,
|
// comments_count: 3,
|
||||||
createdAt: getDate(),
|
createdAt: getDate(),
|
||||||
|
updatedAt: getDate(),
|
||||||
votes_count: 120,
|
votes_count: 120,
|
||||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||||
type: "Story",
|
type: "Story",
|
||||||
tags: randomItems(3, ...tags),
|
tags: randomItems(3, ...tags),
|
||||||
author: getAuthor(),
|
author: getAuthor(),
|
||||||
comments: generatePostComments(3),
|
// comments: generatePostComments(3),
|
||||||
|
is_published: true,
|
||||||
},
|
},
|
||||||
] as Story[],
|
] as Story[],
|
||||||
bounties: [
|
bounties: [
|
||||||
@@ -153,32 +159,36 @@ export let posts = {
|
|||||||
id: 33,
|
id: 33,
|
||||||
title: 'Digital Editor, Mars Review of Books',
|
title: 'Digital Editor, Mars Review of Books',
|
||||||
body: postBody,
|
body: postBody,
|
||||||
answers_count: 3,
|
// answers_count: 3,
|
||||||
createdAt: getDate(),
|
createdAt: getDate(),
|
||||||
|
updatedAt: getDate(),
|
||||||
votes_count: 70,
|
votes_count: 70,
|
||||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||||
tags: [
|
tags: [
|
||||||
{ id: 1, title: "lnurl" },
|
{ id: 1, title: "lnurl", description: '', isOfficial: false, icon: '' },
|
||||||
{ id: 2, title: "webln" },
|
{ id: 2, title: "webln", description: '', isOfficial: false, icon: '' },
|
||||||
],
|
],
|
||||||
author: getAuthor(),
|
author: getAuthor(),
|
||||||
comments: generatePostComments(3)
|
// comments: generatePostComments(3),
|
||||||
|
is_published: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "Question",
|
type: "Question",
|
||||||
id: 33,
|
id: 33,
|
||||||
title: 'What is a man but miserable pile of secrets?',
|
title: 'What is a man but miserable pile of secrets?',
|
||||||
body: postBody,
|
body: postBody,
|
||||||
answers_count: 3,
|
// answers_count: 3,
|
||||||
createdAt: getDate(),
|
createdAt: getDate(),
|
||||||
|
updatedAt: getDate(),
|
||||||
votes_count: 70,
|
votes_count: 70,
|
||||||
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
|
||||||
tags: [
|
tags: [
|
||||||
{ id: 1, title: "lnurl" },
|
{ id: 1, title: "lnurl", description: '', isOfficial: false, icon: '' },
|
||||||
{ id: 2, title: "webln" },
|
{ id: 2, title: "webln", description: '', isOfficial: false, icon: '' },
|
||||||
],
|
],
|
||||||
author: getAuthor(),
|
author: getAuthor(),
|
||||||
comments: generatePostComments(3)
|
// comments: generatePostComments(3),
|
||||||
|
is_published: true,
|
||||||
},
|
},
|
||||||
] as Question[]
|
] as Question[]
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/utils/types/nostr.d.ts
vendored
8
src/utils/types/nostr.d.ts
vendored
@@ -11,16 +11,16 @@ interface NostrEvent {
|
|||||||
|
|
||||||
|
|
||||||
declare module 'nostr-tools' {
|
declare module 'nostr-tools' {
|
||||||
declare function generatePrivateKey(): void
|
declare function generatePrivateKey(): string
|
||||||
declare function relayConnect(): void
|
declare function relayConnect(): void
|
||||||
declare function relayPool(): any
|
declare function relayPool(): any
|
||||||
declare function signEvent(event: NostrEvent, key: sting): string
|
declare function signEvent(event: NostrEvent, key: sting): string
|
||||||
declare function validateEvent(): void
|
declare function validateEvent(): void
|
||||||
declare function verifySignature(event: NostrEvent): bool
|
declare function verifySignature(event: NostrEvent): bool
|
||||||
declare function serializeEvent(): void
|
declare function serializeEvent(): string
|
||||||
declare function getEventHash(event: NostrEvent): string
|
declare function getEventHash(event: NostrEvent): string
|
||||||
declare function getPublicKey(event: NostrEvent): boolean
|
declare function getPublicKey(prvKey: string): string
|
||||||
declare function getBlankEvent(): void
|
declare function getBlankEvent(): NostrEvent
|
||||||
declare function matchFilter(): void
|
declare function matchFilter(): void
|
||||||
declare function matchFilters(): void
|
declare function matchFilters(): void
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"dom",
|
"dom",
|
||||||
"dom.iterable",
|
"dom.iterable",
|
||||||
"esnext"
|
"esnext"
|
||||||
],
|
],
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|||||||
Reference in New Issue
Block a user