Compare commits
8 Commits
9e6675b8d2
...
d41b2e14f1
Author | SHA1 | Date | |
---|---|---|---|
|
d41b2e14f1 | ||
|
15c6843d80 | ||
|
ecedbd1527 | ||
|
fbd3f8efed | ||
|
fa5adac297 | ||
|
01de4e7ba7 | ||
|
d7ecbbae3a | ||
|
0552736dc7 |
31
.github/pull_request_template.md
vendored
31
.github/pull_request_template.md
vendored
@ -1,58 +1,37 @@
|
|||||||
## Description
|
## Description
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
A clear and concise description of what you changed and why.
|
A clear and concise description of what you changed and why.
|
||||||
|
|
||||||
Bullet points can be enough.
|
|
||||||
|
|
||||||
You can use the following PRs as inspiration:
|
|
||||||
- https://github.com/stackernews/stacker.news/pull/227 (feature)
|
|
||||||
- https://github.com/stackernews/stacker.news/pull/915 (feature)
|
|
||||||
- https://github.com/stackernews/stacker.news/pull/871 (fix)
|
|
||||||
- <your PR could be here>
|
|
||||||
|
|
||||||
Don't forget to mention which tickets this closes (if any).
|
Don't forget to mention which tickets this closes (if any).
|
||||||
Use following syntax to close them automatically on merge: closes #<NUMBER>
|
Use following syntax to close them automatically on merge: closes #<number>
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Screenshots
|
## Screenshots
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
If your changes are user facing, please add screenshots of the new UI.
|
If your changes are user facing, please add screenshots of the new UI.
|
||||||
|
|
||||||
You can also create a video to showcase your changes (useful to show UX).
|
You can also create a video to showcase your changes (useful to show UX).
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Additional Context
|
## Additional Context
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
You can mention here anything that you think is relevant for this PR. Some examples:
|
You can mention here anything that you think is relevant for this PR. Some examples:
|
||||||
|
|
||||||
* You encountered something that you didn't understand while working on this PR
|
* You encountered something that you didn't understand while working on this PR
|
||||||
* You were not sure about something you did but did not find a better way
|
* You were not sure about something you did but did not find a better way
|
||||||
* You initially had a different approach but went with a different approach for some reason
|
* You initially had a different approach but went with a different approach for some reason
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Checklist
|
## Checklist
|
||||||
|
|
||||||
<!-- Examples for backwards incompatible changes:
|
|
||||||
- dropping database columns
|
|
||||||
- changing GraphQL type definitions to make a field mandatory -->
|
|
||||||
- [ ] Are your changes backwards compatible?
|
- [ ] Are your changes backwards compatible?
|
||||||
|
|
||||||
<!-- If your PR is not ready for review yet, please mark your PR as a draft.
|
<!--
|
||||||
If changes were requested, request a new review when you incorporated the feedback. -->
|
If your PR is not ready for review yet, please mark your PR as a draft.
|
||||||
|
If changes were requested, request a new review when you incorporated the feedback.
|
||||||
|
-->
|
||||||
- [ ] Did you QA this? Could we deploy this straight to production?
|
- [ ] Did you QA this? Could we deploy this straight to production?
|
||||||
|
|
||||||
<!-- You should be able to use the mobile browser emulator in your browser to test this. -->
|
|
||||||
- [ ] For frontend changes: Tested on mobile?
|
- [ ] For frontend changes: Tested on mobile?
|
||||||
|
|
||||||
<!-- New env vars need to be called out
|
|
||||||
so they can be properly configured for prod. -->
|
|
||||||
- [ ] Did you introduce any new environment variables? If so, call them out explicitly in the PR description.
|
- [ ] Did you introduce any new environment variables? If so, call them out explicitly in the PR description.
|
||||||
|
@ -176,7 +176,10 @@ export default {
|
|||||||
let sitems = null
|
let sitems = null
|
||||||
let termQueries = []
|
let termQueries = []
|
||||||
|
|
||||||
if (!q) {
|
// short circuit: return empty result if either:
|
||||||
|
// 1. no query provided, or
|
||||||
|
// 2. searching bookmarks without being authed
|
||||||
|
if (!q || (what === 'bookmarks' && !me)) {
|
||||||
return {
|
return {
|
||||||
items: [],
|
items: [],
|
||||||
cursor: null
|
cursor: null
|
||||||
@ -191,6 +194,11 @@ export default {
|
|||||||
case 'comments':
|
case 'comments':
|
||||||
whatArr.push({ bool: { must: { exists: { field: 'parentId' } } } })
|
whatArr.push({ bool: { must: { exists: { field: 'parentId' } } } })
|
||||||
break
|
break
|
||||||
|
case 'bookmarks':
|
||||||
|
if (me?.id) {
|
||||||
|
whatArr.push({ match: { bookmarkedBy: me?.id } })
|
||||||
|
}
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -55,3 +55,10 @@ benalleng,pr,#1068,#1067,good-first-issue,,,,20k,???,???
|
|||||||
abhiShandy,helpfulness,#1068,#1067,good-first-issue,,,,2k,abhishandy@stacker.news,2024-04-14
|
abhiShandy,helpfulness,#1068,#1067,good-first-issue,,,,2k,abhishandy@stacker.news,2024-04-14
|
||||||
bumi,pr,#1076,,,,,,20k,bumi@getalby.com,2024-04-16
|
bumi,pr,#1076,,,,,,20k,bumi@getalby.com,2024-04-16
|
||||||
benalleng,pr,#1079,#977,easy,,,,100k,???,???
|
benalleng,pr,#1079,#977,easy,,,,100k,???,???
|
||||||
|
felipebueno,pr,#1024,,,,,,20k,felipe@stacker.news,2024-04-21
|
||||||
|
SatsAllDay,pr,#1075,#1064,medium-hard,,1,,450k,weareallsatoshi@getalby.com,2024-04-21
|
||||||
|
aChrisYouKnow,issue,#1075,#1064,medium-hard,,1,,45k,ACYK@stacker.news,2024-04-22
|
||||||
|
SatsAllDay,pr,#1098,,,,,,20k,weareallsatoshi@getalby.com,2024-04-21
|
||||||
|
SatsAllDay,pr,#1095,#728,medium,,,,250k,weareallsatoshi@getalby.com,2024-04-21
|
||||||
|
benalleng,pr,#1090,#1077,good-first-issue,,,,20k,???,???
|
||||||
|
benalleng,helpfulness,#1087,,,,,informed fix,20k,???,???
|
||||||
|
|
@ -29,6 +29,8 @@ import { AWS_S3_URL_REGEXP } from '@/lib/constants'
|
|||||||
import { whenRange } from '@/lib/time'
|
import { whenRange } from '@/lib/time'
|
||||||
import { useFeeButton } from './fee-button'
|
import { useFeeButton } from './fee-button'
|
||||||
import Thumb from '@/svgs/thumb-up-fill.svg'
|
import Thumb from '@/svgs/thumb-up-fill.svg'
|
||||||
|
import Eye from '@/svgs/eye-fill.svg'
|
||||||
|
import EyeClose from '@/svgs/eye-close-line.svg'
|
||||||
import Info from './info'
|
import Info from './info'
|
||||||
|
|
||||||
export function SubmitButton ({
|
export function SubmitButton ({
|
||||||
@ -1052,5 +1054,35 @@ function Client (Component) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function PasswordHider ({ onClick, showPass }) {
|
||||||
|
return (
|
||||||
|
<InputGroup.Text
|
||||||
|
style={{ cursor: 'pointer' }}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{!showPass
|
||||||
|
? <EyeClose
|
||||||
|
fill='var(--bs-body-color)' height={20} width={20}
|
||||||
|
/>
|
||||||
|
: <Eye
|
||||||
|
fill='var(--bs-body-color)' height={20} width={20}
|
||||||
|
/>}
|
||||||
|
</InputGroup.Text>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PasswordInput ({ newPass, ...props }) {
|
||||||
|
const [showPass, setShowPass] = useState(false)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ClientInput
|
||||||
|
{...props}
|
||||||
|
type={showPass ? 'text' : 'password'}
|
||||||
|
autoComplete={newPass ? 'new-password' : 'current-password'}
|
||||||
|
append={<PasswordHider showPass={showPass} onClick={() => setShowPass(!showPass)} />}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const ClientInput = Client(Input)
|
export const ClientInput = Client(Input)
|
||||||
export const ClientCheckbox = Client(Checkbox)
|
export const ClientCheckbox = Client(Checkbox)
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import Container from 'react-bootstrap/Container'
|
import Container from 'react-bootstrap/Container'
|
||||||
import styles from './search.module.css'
|
import styles from './search.module.css'
|
||||||
import SearchIcon from '@/svgs/search-line.svg'
|
import SearchIcon from '@/svgs/search-line.svg'
|
||||||
import { useEffect, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { Form, Input, Select, DatePicker, SubmitButton } from './form'
|
import { Form, Input, Select, DatePicker, SubmitButton } from './form'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { whenToFrom } from '@/lib/time'
|
import { whenToFrom } from '@/lib/time'
|
||||||
|
import { useMe } from './me'
|
||||||
|
|
||||||
export default function Search ({ sub }) {
|
export default function Search ({ sub }) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [q, setQ] = useState(router.query.q || '')
|
const [q, setQ] = useState(router.query.q || '')
|
||||||
const inputRef = useRef(null)
|
const inputRef = useRef(null)
|
||||||
|
const me = useMe()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
inputRef.current?.focus()
|
inputRef.current?.focus()
|
||||||
@ -50,6 +52,7 @@ export default function Search ({ sub }) {
|
|||||||
const what = router.pathname.startsWith('/stackers') ? 'stackers' : router.query.what || 'all'
|
const what = router.pathname.startsWith('/stackers') ? 'stackers' : router.query.what || 'all'
|
||||||
const sort = router.query.sort || 'zaprank'
|
const sort = router.query.sort || 'zaprank'
|
||||||
const when = router.query.when || 'forever'
|
const when = router.query.when || 'forever'
|
||||||
|
const whatItemOptions = useMemo(() => (['all', 'posts', 'comments', me ? 'bookmarks' : undefined, 'stackers'].filter(item => !!item)), [me])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -86,7 +89,7 @@ export default function Search ({ sub }) {
|
|||||||
name='what'
|
name='what'
|
||||||
size='sm'
|
size='sm'
|
||||||
overrideValue={what}
|
overrideValue={what}
|
||||||
items={['all', 'posts', 'comments', 'stackers']}
|
items={whatItemOptions}
|
||||||
/>
|
/>
|
||||||
{what !== 'stackers' &&
|
{what !== 'stackers' &&
|
||||||
<>
|
<>
|
||||||
|
@ -110,7 +110,7 @@ export const ToastProvider = ({ children }) => {
|
|||||||
// Only clear toasts with no cancel function on page navigation
|
// Only clear toasts with no cancel function on page navigation
|
||||||
// since navigation should not interfere with being able to cancel an action.
|
// since navigation should not interfere with being able to cancel an action.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleRouteChangeStart = () => setToasts(toasts => toasts.length > 0 ? toasts.filter(({ onCancel, onUndo }) => onCancel || onUndo) : toasts)
|
const handleRouteChangeStart = () => setToasts(toasts => toasts.length > 0 ? toasts.filter(({ onCancel, onUndo, persistOnNavigate }) => onCancel || onUndo || persistOnNavigate) : toasts)
|
||||||
router.events.on('routeChangeStart', handleRouteChangeStart)
|
router.events.on('routeChangeStart', handleRouteChangeStart)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -40,6 +40,7 @@ export const toastDeleteScheduled = (toaster, upsertResponseData, dataKey, isEdi
|
|||||||
}[dataKey] ?? 'item'
|
}[dataKey] ?? 'item'
|
||||||
|
|
||||||
const message = `${itemType === 'comment' ? 'your comment' : isEdit ? `this ${itemType}` : `your new ${itemType}`} will be deleted at ${deleteScheduledAt.toLocaleString()}`
|
const message = `${itemType === 'comment' ? 'your comment' : isEdit ? `this ${itemType}` : `your new ${itemType}`} will be deleted at ${deleteScheduledAt.toLocaleString()}`
|
||||||
toaster.success(message)
|
// only persist this on navigation for posts, not comments
|
||||||
|
toaster.success(message, { persistOnNavigate: itemType !== 'comment' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getGetServerSideProps } from '@/api/ssrApollo'
|
import { getGetServerSideProps } from '@/api/ssrApollo'
|
||||||
import { Form, ClientInput, ClientCheckbox } from '@/components/form'
|
import { Form, ClientInput, ClientCheckbox, PasswordInput } from '@/components/form'
|
||||||
import { CenterLayout } from '@/components/layout'
|
import { CenterLayout } from '@/components/layout'
|
||||||
import { WalletButtonBar, WalletCard } from '@/components/wallet-card'
|
import { WalletButtonBar, WalletCard } from '@/components/wallet-card'
|
||||||
import { lnbitsSchema } from '@/lib/validate'
|
import { lnbitsSchema } from '@/lib/validate'
|
||||||
@ -51,12 +51,12 @@ export default function LNbits () {
|
|||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
<ClientInput
|
<PasswordInput
|
||||||
initialValue={adminKey}
|
initialValue={adminKey}
|
||||||
type='password'
|
|
||||||
autoComplete='false'
|
|
||||||
label='admin key'
|
label='admin key'
|
||||||
name='adminKey'
|
name='adminKey'
|
||||||
|
newPass
|
||||||
|
required
|
||||||
/>
|
/>
|
||||||
<ClientCheckbox
|
<ClientCheckbox
|
||||||
disabled={!enabled || isDefault || enabledProviders.length === 1}
|
disabled={!enabled || isDefault || enabledProviders.length === 1}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { getGetServerSideProps } from '@/api/ssrApollo'
|
import { getGetServerSideProps } from '@/api/ssrApollo'
|
||||||
import { Form, ClientInput, ClientCheckbox } from '@/components/form'
|
import { Form, ClientCheckbox, PasswordInput } from '@/components/form'
|
||||||
import { CenterLayout } from '@/components/layout'
|
import { CenterLayout } from '@/components/layout'
|
||||||
import { WalletButtonBar, WalletCard } from '@/components/wallet-card'
|
import { WalletButtonBar, WalletCard } from '@/components/wallet-card'
|
||||||
import { nwcSchema } from '@/lib/validate'
|
import { nwcSchema } from '@/lib/validate'
|
||||||
@ -43,12 +43,11 @@ export default function NWC () {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ClientInput
|
<PasswordInput
|
||||||
initialValue={nwcUrl}
|
initialValue={nwcUrl}
|
||||||
label='connection'
|
label='connection'
|
||||||
name='nwcUrl'
|
name='nwcUrl'
|
||||||
type='password'
|
newPass
|
||||||
autoComplete='new-password'
|
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
@ -0,0 +1,46 @@
|
|||||||
|
CREATE OR REPLACE FUNCTION index_bookmarked_item() RETURNS TRIGGER AS $$
|
||||||
|
BEGIN
|
||||||
|
-- if a bookmark was created or updated, `NEW` will be used
|
||||||
|
IF NEW IS NOT NULL THEN
|
||||||
|
INSERT INTO pgboss.job (name, data) VALUES ('indexItem', jsonb_build_object('id', NEW."itemId"));
|
||||||
|
RETURN NEW;
|
||||||
|
END IF;
|
||||||
|
-- if a bookmark was deleted, `OLD` will be used
|
||||||
|
IF OLD IS NOT NULL THEN
|
||||||
|
-- include `updatedAt` in the `indexItem` job as `now()` to indicate when the indexed item should think it was updated
|
||||||
|
-- this is to facilitate the fact that deleted bookmarks do not show up when re-indexing the item, and therefore
|
||||||
|
-- we don't have a reliable way to calculate a more recent index version, to displace the prior version
|
||||||
|
INSERT INTO pgboss.job (name, data) VALUES ('indexItem', jsonb_build_object('id', OLD."itemId", 'updatedAt', now()));
|
||||||
|
RETURN OLD;
|
||||||
|
END IF;
|
||||||
|
-- This should never be reached
|
||||||
|
RETURN NULL;
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- Re-index the bookmarked item when a bookmark changes, so new bookmarks are searchable
|
||||||
|
DROP TRIGGER IF EXISTS index_bookmarked_item ON "Bookmark";
|
||||||
|
CREATE TRIGGER index_bookmarked_item
|
||||||
|
AFTER INSERT OR UPDATE OR DELETE ON "Bookmark"
|
||||||
|
FOR EACH ROW
|
||||||
|
EXECUTE PROCEDURE index_bookmarked_item();
|
||||||
|
|
||||||
|
-- hack ... prisma doesn't know about our other schemas (e.g. pgboss)
|
||||||
|
-- and this is only really a problem on their "shadow database"
|
||||||
|
-- so we catch the exception it throws and ignore it
|
||||||
|
CREATE OR REPLACE FUNCTION reindex_all_current_bookmarked_items() RETURNS void AS $$
|
||||||
|
BEGIN
|
||||||
|
-- Re-index all existing bookmarked items so these bookmarks are searchable
|
||||||
|
INSERT INTO pgboss.job (name, data, priority, startafter, expirein)
|
||||||
|
SELECT 'indexItem', jsonb_build_object('id', "itemId"), -100, now() + interval '10 minutes', interval '1 day'
|
||||||
|
FROM "Bookmark"
|
||||||
|
GROUP BY "itemId";
|
||||||
|
EXCEPTION WHEN OTHERS THEN
|
||||||
|
-- catch the exception for prisma dev execution, but do nothing with it
|
||||||
|
END;
|
||||||
|
$$ LANGUAGE plpgsql;
|
||||||
|
|
||||||
|
-- execute the function once
|
||||||
|
SELECT reindex_all_current_bookmarked_items();
|
||||||
|
-- then drop it since we don't need it anymore
|
||||||
|
DROP FUNCTION reindex_all_current_bookmarked_items();
|
@ -171,9 +171,8 @@ Have a great weekend!
|
|||||||
|
|
||||||
##### Top Posts
|
##### Top Posts
|
||||||
${top.data.items.items.slice(0, 10).map((item, i) =>
|
${top.data.items.items.slice(0, 10).map((item, i) =>
|
||||||
`${i + 1}. [@${item.user.name}](https://stacker.news/${item.user.name}) [${item.title}](https://stacker.news/items/${item.id})
|
`${i + 1}. [${item.title}](https://stacker.news/items/${item.id})
|
||||||
- [${item.title}](https://stacker.news/items/${item.id})
|
- ${abbrNum(item.sats)} sats${item.boost ? ` \\ ${abbrNum(item.boost)} boost` : ''} \\ ${item.ncomments} comments \\ [@${item.user.name}](https://stacker.news/${item.user.name})\n`).join('')}
|
||||||
- ${abbrNum(item.sats)} sats${item.boost ? ` \\ ${abbrNum(item.boost)} boost` : ''} \\ ${item.ncomments} comments \\ [@${item.user.name}](https://stacker.news/${item.user.name})\n`).join('')}
|
|
||||||
|
|
||||||
##### Don't miss
|
##### Don't miss
|
||||||
${top.data.items.items.map((item, i) =>
|
${top.data.items.items.map((item, i) =>
|
||||||
|
7
sndev
7
sndev
@ -13,7 +13,12 @@ docker__compose() {
|
|||||||
COMPOSE_PROFILES="images,search,payments,email,capture"
|
COMPOSE_PROFILES="images,search,payments,email,capture"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
CURRENT_UID=$(id -u) CURRENT_GID=$(id -g) COMPOSE_PROFILES=$COMPOSE_PROFILES command docker compose --env-file .env.development --env-file .env.local "$@"
|
ENV_LOCAL=
|
||||||
|
if [ -f .env.local ]; then
|
||||||
|
ENV_LOCAL='--env-file .env.local'
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT_UID=$(id -u) CURRENT_GID=$(id -g) COMPOSE_PROFILES=$COMPOSE_PROFILES command docker compose --env-file .env.development $ENV_LOCAL "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
docker__exec() {
|
docker__exec() {
|
||||||
|
@ -35,7 +35,7 @@ const ITEM_SEARCH_FIELDS = gql`
|
|||||||
ncomments
|
ncomments
|
||||||
}`
|
}`
|
||||||
|
|
||||||
async function _indexItem (item, { models }) {
|
async function _indexItem (item, { models, updatedAt }) {
|
||||||
console.log('indexing item', item.id)
|
console.log('indexing item', item.id)
|
||||||
// HACK: modify the title for jobs so that company/location are searchable
|
// HACK: modify the title for jobs so that company/location are searchable
|
||||||
// and highlighted without further modification
|
// and highlighted without further modification
|
||||||
@ -60,11 +60,33 @@ async function _indexItem (item, { models }) {
|
|||||||
|
|
||||||
itemcp.wvotes = itemdb.weightedVotes - itemdb.weightedDownVotes
|
itemcp.wvotes = itemdb.weightedVotes - itemdb.weightedDownVotes
|
||||||
|
|
||||||
|
const bookmarkedBy = await models.bookmark.findMany({
|
||||||
|
where: { itemId: Number(item.id) },
|
||||||
|
select: { userId: true, createdAt: true },
|
||||||
|
orderBy: [
|
||||||
|
{
|
||||||
|
createdAt: 'desc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
itemcp.bookmarkedBy = bookmarkedBy.map(bookmark => bookmark.userId)
|
||||||
|
|
||||||
|
// use the latest of:
|
||||||
|
// 1. an explicitly-supplied updatedAt value, used when a bookmark to this item was removed
|
||||||
|
// 2. when the item itself was updated
|
||||||
|
// 3. or when it was last bookmarked
|
||||||
|
// to determine the latest version of the indexed version
|
||||||
|
const latestUpdatedAt = Math.max(
|
||||||
|
updatedAt ? new Date(updatedAt).getTime() : 0,
|
||||||
|
new Date(item.updatedAt).getTime(),
|
||||||
|
bookmarkedBy[0] ? new Date(bookmarkedBy[0].createdAt).getTime() : 0
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await search.index({
|
await search.index({
|
||||||
id: item.id,
|
id: item.id,
|
||||||
index: process.env.OPENSEARCH_INDEX,
|
index: process.env.OPENSEARCH_INDEX,
|
||||||
version: new Date(item.updatedAt).getTime(),
|
version: new Date(latestUpdatedAt).getTime(),
|
||||||
versionType: 'external_gte',
|
versionType: 'external_gte',
|
||||||
body: itemcp
|
body: itemcp
|
||||||
})
|
})
|
||||||
@ -79,7 +101,9 @@ async function _indexItem (item, { models }) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function indexItem ({ data: { id }, apollo, models }) {
|
// `data.updatedAt` is an explicit updatedAt value for the use case of a bookmark being removed
|
||||||
|
// this is consulted to generate the index version
|
||||||
|
export async function indexItem ({ data: { id, updatedAt }, apollo, models }) {
|
||||||
// 1. grab item from database
|
// 1. grab item from database
|
||||||
// could use apollo to avoid duping logic
|
// could use apollo to avoid duping logic
|
||||||
// when grabbing sats and user name, etc
|
// when grabbing sats and user name, etc
|
||||||
@ -94,7 +118,7 @@ export async function indexItem ({ data: { id }, apollo, models }) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 2. index it with external version based on updatedAt
|
// 2. index it with external version based on updatedAt
|
||||||
await _indexItem(item, { models })
|
await _indexItem(item, { models, updatedAt })
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function indexAllItems ({ apollo, models }) {
|
export async function indexAllItems ({ apollo, models }) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user