auto-populate link title
This commit is contained in:
parent
f523088531
commit
ce0e3dac45
@ -2,6 +2,8 @@ import { UserInputError, AuthenticationError } from 'apollo-server-micro'
|
|||||||
import { ensureProtocol } from '../../lib/url'
|
import { ensureProtocol } from '../../lib/url'
|
||||||
import serialize from './serial'
|
import serialize from './serial'
|
||||||
import { decodeCursor, LIMIT, nextCursorEncoded } from './cursor'
|
import { decodeCursor, LIMIT, nextCursorEncoded } from './cursor'
|
||||||
|
import { getMetadata, metadataRuleSets } from 'page-metadata-parser'
|
||||||
|
import domino from 'domino'
|
||||||
|
|
||||||
async function comments (models, id) {
|
async function comments (models, id) {
|
||||||
const flat = await models.$queryRaw(`
|
const flat = await models.$queryRaw(`
|
||||||
@ -96,6 +98,17 @@ export default {
|
|||||||
FROM "Item"
|
FROM "Item"
|
||||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||||
ORDER BY created_at DESC`, Number(userId))
|
ORDER BY created_at DESC`, Number(userId))
|
||||||
|
},
|
||||||
|
pageTitle: async (parent, { url }, { models }) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(ensureProtocol(url), { redirect: 'follow' })
|
||||||
|
const html = await response.text()
|
||||||
|
const doc = domino.createWindow(html).document
|
||||||
|
const metadata = getMetadata(doc, url, { title: metadataRuleSets.title })
|
||||||
|
return metadata?.title
|
||||||
|
} catch (e) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ export default gql`
|
|||||||
moreFlatComments(cursor: String, userId: ID): Comments
|
moreFlatComments(cursor: String, userId: ID): Comments
|
||||||
item(id: ID!): Item
|
item(id: ID!): Item
|
||||||
userComments(userId: ID!): [Item!]
|
userComments(userId: ID!): [Item!]
|
||||||
|
pageTitle(url: String!): String
|
||||||
}
|
}
|
||||||
|
|
||||||
extend type Mutation {
|
extend type Mutation {
|
||||||
|
@ -108,9 +108,16 @@ function FormGroup ({ className, label, children }) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function InputInner ({ prepend, append, hint, showValid, ...props }) {
|
function InputInner ({ prepend, append, hint, showValid, onChange, overrideValue, ...props }) {
|
||||||
const [field, meta] = props.readOnly ? [{}, {}] : useField(props)
|
const [field, meta, helpers] = props.readOnly ? [{}, {}, {}] : useField(props)
|
||||||
const formik = props.readOnly ? null : useFormikContext()
|
const formik = props.readOnly ? null : useFormikContext()
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (overrideValue) {
|
||||||
|
helpers.setValue(overrideValue)
|
||||||
|
}
|
||||||
|
}, [overrideValue])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<InputGroup hasValidation>
|
<InputGroup hasValidation>
|
||||||
@ -126,6 +133,12 @@ function InputInner ({ prepend, append, hint, showValid, ...props }) {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
{...field} {...props}
|
{...field} {...props}
|
||||||
|
onChange={(e) => {
|
||||||
|
field.onChange(e)
|
||||||
|
if (onChange) {
|
||||||
|
onChange(formik, e)
|
||||||
|
}
|
||||||
|
}}
|
||||||
isInvalid={meta.touched && meta.error}
|
isInvalid={meta.touched && meta.error}
|
||||||
isValid={showValid && meta.touched && !meta.error}
|
isValid={showValid && meta.touched && !meta.error}
|
||||||
/>
|
/>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Form, Input, SubmitButton } from '../components/form'
|
import { Form, Input, SubmitButton } from '../components/form'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import * as Yup from 'yup'
|
import * as Yup from 'yup'
|
||||||
import { gql, useMutation } from '@apollo/client'
|
import { gql, useLazyQuery, useMutation } from '@apollo/client'
|
||||||
import { ensureProtocol } from '../lib/url'
|
import { ensureProtocol } from '../lib/url'
|
||||||
import ActionTooltip from '../components/action-tooltip'
|
import ActionTooltip from '../components/action-tooltip'
|
||||||
import Countdown from './countdown'
|
import Countdown from './countdown'
|
||||||
@ -24,6 +24,10 @@ export const LinkSchema = Yup.object({
|
|||||||
})
|
})
|
||||||
|
|
||||||
export function LinkForm ({ item, editThreshold }) {
|
export function LinkForm ({ item, editThreshold }) {
|
||||||
|
const [getPageTitle, { data }] = useLazyQuery(gql`
|
||||||
|
query PageTitle($url: String!) {
|
||||||
|
pageTitle(url: $url)
|
||||||
|
}`)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [createLink] = useMutation(
|
const [createLink] = useMutation(
|
||||||
gql`
|
gql`
|
||||||
@ -81,6 +85,7 @@ export function LinkForm ({ item, editThreshold }) {
|
|||||||
<Input
|
<Input
|
||||||
label='title'
|
label='title'
|
||||||
name='title'
|
name='title'
|
||||||
|
overrideValue={data?.pageTitle}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
@ -91,6 +96,13 @@ export function LinkForm ({ item, editThreshold }) {
|
|||||||
hint={editThreshold
|
hint={editThreshold
|
||||||
? <Countdown date={editThreshold} />
|
? <Countdown date={editThreshold} />
|
||||||
: null}
|
: null}
|
||||||
|
onChange={async (formik, e) => {
|
||||||
|
if ((/^ *$/).test(formik?.values.title)) {
|
||||||
|
getPageTitle({
|
||||||
|
variables: { url: e.target.value }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<ActionTooltip>
|
<ActionTooltip>
|
||||||
<SubmitButton variant='secondary' className='mt-2'>{item ? 'save' : 'post'}</SubmitButton>
|
<SubmitButton variant='secondary' className='mt-2'>{item ? 'save' : 'post'}</SubmitButton>
|
||||||
|
22
package-lock.json
generated
22
package-lock.json
generated
@ -15,6 +15,7 @@
|
|||||||
"bech32": "^2.0.0",
|
"bech32": "^2.0.0",
|
||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
"clipboard-copy": "^4.0.1",
|
"clipboard-copy": "^4.0.1",
|
||||||
|
"domino": "^2.1.6",
|
||||||
"formik": "^2.2.6",
|
"formik": "^2.2.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"ln-service": "^51.7.0",
|
"ln-service": "^51.7.0",
|
||||||
@ -23,6 +24,7 @@
|
|||||||
"next-auth": "^3.13.3",
|
"next-auth": "^3.13.3",
|
||||||
"next-plausible": "^2.0.0",
|
"next-plausible": "^2.0.0",
|
||||||
"next-seo": "^4.24.0",
|
"next-seo": "^4.24.0",
|
||||||
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pageres": "^6.2.3",
|
"pageres": "^6.2.3",
|
||||||
"prisma": "^2.25.0",
|
"prisma": "^2.25.0",
|
||||||
"qrcode.react": "^1.0.1",
|
"qrcode.react": "^1.0.1",
|
||||||
@ -3287,6 +3289,11 @@
|
|||||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/domino": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||||
|
},
|
||||||
"node_modules/domutils": {
|
"node_modules/domutils": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||||
@ -7660,6 +7667,11 @@
|
|||||||
"node": ">=4"
|
"node": ">=4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/page-metadata-parser": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/page-metadata-parser/-/page-metadata-parser-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-TbPNw7GddbHs4c2DyYinFvh51BVsaMfdrweeylzGlg8qeuzALGxq2NF+6jbmeKc7DnU2BZRDOuWNnEjDwUSqRQ=="
|
||||||
|
},
|
||||||
"node_modules/pageres": {
|
"node_modules/pageres": {
|
||||||
"version": "6.2.3",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
||||||
@ -14030,6 +14042,11 @@
|
|||||||
"domelementtype": "^2.2.0"
|
"domelementtype": "^2.2.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"domino": {
|
||||||
|
"version": "2.1.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/domino/-/domino-2.1.6.tgz",
|
||||||
|
"integrity": "sha512-3VdM/SXBZX2omc9JF9nOPCtDaYQ67BGp5CoLpIQlO2KCAPETs8TcDHacF26jXadGbvUteZzRTeos2fhID5+ucQ=="
|
||||||
|
},
|
||||||
"domutils": {
|
"domutils": {
|
||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||||
@ -17312,6 +17329,11 @@
|
|||||||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"page-metadata-parser": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/page-metadata-parser/-/page-metadata-parser-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-TbPNw7GddbHs4c2DyYinFvh51BVsaMfdrweeylzGlg8qeuzALGxq2NF+6jbmeKc7DnU2BZRDOuWNnEjDwUSqRQ=="
|
||||||
|
},
|
||||||
"pageres": {
|
"pageres": {
|
||||||
"version": "6.2.3",
|
"version": "6.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
"bech32": "^2.0.0",
|
"bech32": "^2.0.0",
|
||||||
"bootstrap": "^4.6.0",
|
"bootstrap": "^4.6.0",
|
||||||
"clipboard-copy": "^4.0.1",
|
"clipboard-copy": "^4.0.1",
|
||||||
|
"domino": "^2.1.6",
|
||||||
"formik": "^2.2.6",
|
"formik": "^2.2.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"ln-service": "^51.7.0",
|
"ln-service": "^51.7.0",
|
||||||
@ -25,6 +26,7 @@
|
|||||||
"next-auth": "^3.13.3",
|
"next-auth": "^3.13.3",
|
||||||
"next-plausible": "^2.0.0",
|
"next-plausible": "^2.0.0",
|
||||||
"next-seo": "^4.24.0",
|
"next-seo": "^4.24.0",
|
||||||
|
"page-metadata-parser": "^1.1.4",
|
||||||
"pageres": "^6.2.3",
|
"pageres": "^6.2.3",
|
||||||
"prisma": "^2.25.0",
|
"prisma": "^2.25.0",
|
||||||
"qrcode.react": "^1.0.1",
|
"qrcode.react": "^1.0.1",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user