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 serialize from './serial'
|
||||
import { decodeCursor, LIMIT, nextCursorEncoded } from './cursor'
|
||||
import { getMetadata, metadataRuleSets } from 'page-metadata-parser'
|
||||
import domino from 'domino'
|
||||
|
||||
async function comments (models, id) {
|
||||
const flat = await models.$queryRaw(`
|
||||
|
@ -96,6 +98,17 @@ export default {
|
|||
FROM "Item"
|
||||
WHERE "userId" = $1 AND "parentId" IS NOT NULL
|
||||
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
|
||||
item(id: ID!): Item
|
||||
userComments(userId: ID!): [Item!]
|
||||
pageTitle(url: String!): String
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
|
|
|
@ -108,9 +108,16 @@ function FormGroup ({ className, label, children }) {
|
|||
)
|
||||
}
|
||||
|
||||
function InputInner ({ prepend, append, hint, showValid, ...props }) {
|
||||
const [field, meta] = props.readOnly ? [{}, {}] : useField(props)
|
||||
function InputInner ({ prepend, append, hint, showValid, onChange, overrideValue, ...props }) {
|
||||
const [field, meta, helpers] = props.readOnly ? [{}, {}, {}] : useField(props)
|
||||
const formik = props.readOnly ? null : useFormikContext()
|
||||
|
||||
useEffect(() => {
|
||||
if (overrideValue) {
|
||||
helpers.setValue(overrideValue)
|
||||
}
|
||||
}, [overrideValue])
|
||||
|
||||
return (
|
||||
<>
|
||||
<InputGroup hasValidation>
|
||||
|
@ -126,6 +133,12 @@ function InputInner ({ prepend, append, hint, showValid, ...props }) {
|
|||
}
|
||||
}}
|
||||
{...field} {...props}
|
||||
onChange={(e) => {
|
||||
field.onChange(e)
|
||||
if (onChange) {
|
||||
onChange(formik, e)
|
||||
}
|
||||
}}
|
||||
isInvalid={meta.touched && meta.error}
|
||||
isValid={showValid && meta.touched && !meta.error}
|
||||
/>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Form, Input, SubmitButton } from '../components/form'
|
||||
import { useRouter } from 'next/router'
|
||||
import * as Yup from 'yup'
|
||||
import { gql, useMutation } from '@apollo/client'
|
||||
import { gql, useLazyQuery, useMutation } from '@apollo/client'
|
||||
import { ensureProtocol } from '../lib/url'
|
||||
import ActionTooltip from '../components/action-tooltip'
|
||||
import Countdown from './countdown'
|
||||
|
@ -24,6 +24,10 @@ export const LinkSchema = Yup.object({
|
|||
})
|
||||
|
||||
export function LinkForm ({ item, editThreshold }) {
|
||||
const [getPageTitle, { data }] = useLazyQuery(gql`
|
||||
query PageTitle($url: String!) {
|
||||
pageTitle(url: $url)
|
||||
}`)
|
||||
const router = useRouter()
|
||||
const [createLink] = useMutation(
|
||||
gql`
|
||||
|
@ -81,6 +85,7 @@ export function LinkForm ({ item, editThreshold }) {
|
|||
<Input
|
||||
label='title'
|
||||
name='title'
|
||||
overrideValue={data?.pageTitle}
|
||||
required
|
||||
autoFocus
|
||||
/>
|
||||
|
@ -91,6 +96,13 @@ export function LinkForm ({ item, editThreshold }) {
|
|||
hint={editThreshold
|
||||
? <Countdown date={editThreshold} />
|
||||
: null}
|
||||
onChange={async (formik, e) => {
|
||||
if ((/^ *$/).test(formik?.values.title)) {
|
||||
getPageTitle({
|
||||
variables: { url: e.target.value }
|
||||
})
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ActionTooltip>
|
||||
<SubmitButton variant='secondary' className='mt-2'>{item ? 'save' : 'post'}</SubmitButton>
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
"bech32": "^2.0.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"clipboard-copy": "^4.0.1",
|
||||
"domino": "^2.1.6",
|
||||
"formik": "^2.2.6",
|
||||
"graphql": "^15.5.0",
|
||||
"ln-service": "^51.7.0",
|
||||
|
@ -23,6 +24,7 @@
|
|||
"next-auth": "^3.13.3",
|
||||
"next-plausible": "^2.0.0",
|
||||
"next-seo": "^4.24.0",
|
||||
"page-metadata-parser": "^1.1.4",
|
||||
"pageres": "^6.2.3",
|
||||
"prisma": "^2.25.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
|
@ -3287,6 +3289,11 @@
|
|||
"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": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||
|
@ -7660,6 +7667,11 @@
|
|||
"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": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
||||
|
@ -14030,6 +14042,11 @@
|
|||
"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": {
|
||||
"version": "2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz",
|
||||
|
@ -17312,6 +17329,11 @@
|
|||
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
|
||||
"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": {
|
||||
"version": "6.2.3",
|
||||
"resolved": "https://registry.npmjs.org/pageres/-/pageres-6.2.3.tgz",
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
"bech32": "^2.0.0",
|
||||
"bootstrap": "^4.6.0",
|
||||
"clipboard-copy": "^4.0.1",
|
||||
"domino": "^2.1.6",
|
||||
"formik": "^2.2.6",
|
||||
"graphql": "^15.5.0",
|
||||
"ln-service": "^51.7.0",
|
||||
|
@ -25,6 +26,7 @@
|
|||
"next-auth": "^3.13.3",
|
||||
"next-plausible": "^2.0.0",
|
||||
"next-seo": "^4.24.0",
|
||||
"page-metadata-parser": "^1.1.4",
|
||||
"pageres": "^6.2.3",
|
||||
"prisma": "^2.25.0",
|
||||
"qrcode.react": "^1.0.1",
|
||||
|
@ -63,4 +65,4 @@
|
|||
"eslint-plugin-compat": "^3.9.0",
|
||||
"standard": "^16.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue