kopia lustrzana https://github.com/Stopka/fedisearch
Fixed Matomo, preparations for parentFeed
rodzic
c96890b435
commit
7b43914b4c
|
@ -1,7 +1,7 @@
|
||||||
FROM node:16-bullseye AS build
|
FROM node:16-bullseye AS build
|
||||||
ENV POSTGRES_URL='postgresql://fedisearch:passwd@postgres:5432/fedisearch?schema=public' \
|
ENV POSTGRES_URL='postgresql://fedisearch:passwd@postgres:5432/fedisearch?schema=public' \
|
||||||
NEXT_PUBLIC_MATOMO_URL='' \
|
MATOMO_URL='' \
|
||||||
NEXT_PUBLIC_MATOMO_SITE_ID='' \
|
MATOMO_SITE_ID='' \
|
||||||
TZ='UTC'
|
TZ='UTC'
|
||||||
WORKDIR /srv
|
WORKDIR /srv
|
||||||
COPY application/package*.json ./
|
COPY application/package*.json ./
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { FeedResponseItem } from '../types/FeedResponse'
|
|
||||||
|
|
||||||
const Avatar:React.FC<{feed:FeedResponseItem}> = ({ feed }) => {
|
const Avatar:React.FC<{url:string|null|undefined}> = ({ url }) => {
|
||||||
const fallbackImage = '/avatar.svg'
|
const fallbackImage = '/avatar.svg'
|
||||||
|
|
||||||
const handleAvatarImageError = (event) => {
|
const handleAvatarImageError = (event) => {
|
||||||
|
@ -11,7 +10,7 @@ const Avatar:React.FC<{feed:FeedResponseItem}> = ({ feed }) => {
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
className={'avatar'}
|
className={'avatar'}
|
||||||
src={feed.avatar ?? fallbackImage}
|
src={url ?? fallbackImage}
|
||||||
alt={'Avatar'}
|
alt={'Avatar'}
|
||||||
onError={handleAvatarImageError}
|
onError={handleAvatarImageError}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { tracker } from '../lib/matomo'
|
|
||||||
import Footer from './Footer'
|
import Footer from './Footer'
|
||||||
|
import getMatomo from '../lib/getMatomo'
|
||||||
|
import { UserOptions } from '@datapunt/matomo-tracker-js/es/types'
|
||||||
|
|
||||||
export const siteTitle = 'FediSearch'
|
export const siteTitle = 'FediSearch'
|
||||||
|
|
||||||
const Layout:React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
const Layout:React.FC<{ matomoConfig:UserOptions, children: React.ReactNode }> = ({ matomoConfig, children }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
tracker.trackPageView()
|
getMatomo(matomoConfig).trackPageView()
|
||||||
})
|
})
|
||||||
return (
|
return (
|
||||||
<div className={'container'}>
|
<div className={'container'}>
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import React from 'react'
|
||||||
|
import Avatar from './Avatar'
|
||||||
|
import { FeedResponseParent } from '../types/FeedResponse'
|
||||||
|
|
||||||
|
const ParentFeed: React.FC<{feed:FeedResponseParent|null}> = ({ feed }) => {
|
||||||
|
if (feed === null) {
|
||||||
|
return (<></>)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className={'parent-feed'}>
|
||||||
|
<Avatar url={feed.avatar}/>
|
||||||
|
<div className={'display-name'}>
|
||||||
|
<a href={feed.url}>{feed.displayName}</a>
|
||||||
|
</div>
|
||||||
|
<div className={'address'}>{feed.name}@{feed.domain}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ParentFeed
|
|
@ -8,6 +8,7 @@ import CreatedAtBadge from './badges/CreatedAtBadge'
|
||||||
import LastPostAtBadge from './badges/LastPostAtBadge'
|
import LastPostAtBadge from './badges/LastPostAtBadge'
|
||||||
import BotBadge from './badges/BotBadge'
|
import BotBadge from './badges/BotBadge'
|
||||||
import { FeedResponseField, FeedResponseItem } from '../types/FeedResponse'
|
import { FeedResponseField, FeedResponseItem } from '../types/FeedResponse'
|
||||||
|
import ParentFeed from './ParentFeed'
|
||||||
|
|
||||||
const Result:React.FC<{ feed:FeedResponseItem }> = ({ feed }) => {
|
const Result:React.FC<{ feed:FeedResponseItem }> = ({ feed }) => {
|
||||||
const fallbackEmojiImage = '/emoji.svg'
|
const fallbackEmojiImage = '/emoji.svg'
|
||||||
|
@ -33,9 +34,10 @@ const Result:React.FC<{ feed:FeedResponseItem }> = ({ feed }) => {
|
||||||
dangerouslySetInnerHTML={{ __html: striptags(feed.displayName, ['img']) }}
|
dangerouslySetInnerHTML={{ __html: striptags(feed.displayName, ['img']) }}
|
||||||
/>
|
/>
|
||||||
</h3>
|
</h3>
|
||||||
<Avatar feed={feed}/>
|
<Avatar url={feed.avatar}/>
|
||||||
<div className={'address'}>
|
<div className={'address'}>
|
||||||
<span>{feed.name}@{feed.node.domain}</span>
|
<span>{feed.name}@{feed.node.domain}</span>
|
||||||
|
<ParentFeed feed={feed.parentFeed}/>
|
||||||
</div>
|
</div>
|
||||||
<div className={'badges'}>
|
<div className={'badges'}>
|
||||||
<SoftwareBadge softwareName={feed.node.softwareName}/>
|
<SoftwareBadge softwareName={feed.node.softwareName}/>
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import { UserOptions } from '@datapunt/matomo-tracker-js/es/types'
|
||||||
|
import MatomoTracker from '@datapunt/matomo-tracker-js'
|
||||||
|
|
||||||
|
let matomo:MatomoTracker|undefined
|
||||||
|
|
||||||
|
const getMatomo = (config:UserOptions):MatomoTracker => {
|
||||||
|
if (!matomo) {
|
||||||
|
console.info('Starting Matomo', config)
|
||||||
|
matomo = new MatomoTracker(config)
|
||||||
|
}
|
||||||
|
return matomo
|
||||||
|
}
|
||||||
|
|
||||||
|
export default getMatomo
|
|
@ -1,12 +0,0 @@
|
||||||
import MatomoTracker from '@datapunt/matomo-tracker-js'
|
|
||||||
|
|
||||||
export const tracker = new MatomoTracker({
|
|
||||||
urlBase: typeof process.env.NEXT_PUBLIC_MATOMO_URL === 'string' && process.env.NEXT_PUBLIC_MATOMO_URL !== ''
|
|
||||||
? process.env.NEXT_PUBLIC_MATOMO_URL
|
|
||||||
: 'https://dummy.url',
|
|
||||||
siteId: parseInt(typeof process.env.NEXT_PUBLIC_MATOMO_SITE_ID === 'string' && process.env.NEXT_PUBLIC_MATOMO_SITE_ID !== ''
|
|
||||||
? process.env.NEXT_PUBLIC_MATOMO_SITE_ID
|
|
||||||
: '1'
|
|
||||||
),
|
|
||||||
disabled: !process.env.NEXT_PUBLIC_MATOMO_URL || !process.env.NEXT_PUBLIC_MATOMO_SITE_ID
|
|
||||||
})
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export const matomoConfig = {
|
||||||
|
urlBase: typeof process.env.MATOMO_URL === 'string' && process.env.MATOMO_URL !== ''
|
||||||
|
? process.env.MATOMO_URL
|
||||||
|
: 'https://domain.tld',
|
||||||
|
siteId: parseInt(typeof process.env.MATOMO_SITE_ID === 'string' && process.env.MATOMO_SITE_ID !== ''
|
||||||
|
? process.env.MATOMO_SITE_ID
|
||||||
|
: '1'
|
||||||
|
),
|
||||||
|
disabled: !process.env.MATOMO_URL || !process.env.MATOMO_SITE_ID
|
||||||
|
}
|
|
@ -65,7 +65,8 @@ const handleFeedSearch = async (req:NextApiRequest, res:NextApiResponse<FeedResp
|
||||||
softwareName: feed.node.softwareName
|
softwareName: feed.node.softwareName
|
||||||
},
|
},
|
||||||
type: feed.type,
|
type: feed.type,
|
||||||
url: feed.url
|
url: feed.url,
|
||||||
|
parentFeed: null // TODO find parent data
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,14 +2,16 @@ import Head from 'next/head'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { feedResponseSchema } from '../types/FeedResponse'
|
import { feedResponseSchema } from '../types/FeedResponse'
|
||||||
import { tracker } from '../lib/matomo'
|
|
||||||
import Loader from '../components/Loader'
|
import Loader from '../components/Loader'
|
||||||
import Results from '../components/Results'
|
import Results from '../components/Results'
|
||||||
import Layout, { siteTitle } from '../components/Layout'
|
import Layout, { siteTitle } from '../components/Layout'
|
||||||
|
import { matomoConfig } from '../lib/matomoConfig'
|
||||||
|
import getMatomo from '../lib/getMatomo'
|
||||||
|
import { GetServerSideProps, InferGetServerSidePropsType } from 'next'
|
||||||
|
|
||||||
let source = axios.CancelToken.source()
|
let source = axios.CancelToken.source()
|
||||||
|
|
||||||
const Home:React.FC = () => {
|
const Home:React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => {
|
||||||
const [query, setQuery] = useState('')
|
const [query, setQuery] = useState('')
|
||||||
const [submitted, setSubmitted] = useState(null)
|
const [submitted, setSubmitted] = useState(null)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
@ -54,7 +56,7 @@ const Home:React.FC = () => {
|
||||||
console.info('Loading new query search', { query, page })
|
console.info('Loading new query search', { query, page })
|
||||||
setLoading(true)
|
setLoading(true)
|
||||||
setTimeout(search)
|
setTimeout(search)
|
||||||
tracker.trackEvent({
|
getMatomo(matomoConfig).trackEvent({
|
||||||
category: 'feeds',
|
category: 'feeds',
|
||||||
action: 'new-search'
|
action: 'new-search'
|
||||||
})
|
})
|
||||||
|
@ -67,7 +69,7 @@ const Home:React.FC = () => {
|
||||||
}
|
}
|
||||||
console.info('Loading next page', { query, page })
|
console.info('Loading next page', { query, page })
|
||||||
setTimeout(search)
|
setTimeout(search)
|
||||||
tracker.trackEvent({
|
getMatomo(matomoConfig).trackEvent({
|
||||||
category: 'feeds',
|
category: 'feeds',
|
||||||
action: 'next-page',
|
action: 'next-page',
|
||||||
customDimensions: [
|
customDimensions: [
|
||||||
|
@ -102,7 +104,7 @@ const Home:React.FC = () => {
|
||||||
useEffect(loadNextPageResults, [page])
|
useEffect(loadNextPageResults, [page])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout>
|
<Layout matomoConfig={matomoConfig}>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{siteTitle}</title>
|
<title>{siteTitle}</title>
|
||||||
</Head>
|
</Head>
|
||||||
|
@ -154,4 +156,13 @@ const Home:React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getServerSideProps:GetServerSideProps = async (context) => {
|
||||||
|
console.info('Loading matomo config', matomoConfig)
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
matomoConfig
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default Home
|
export default Home
|
||||||
|
|
|
@ -5,6 +5,14 @@ export const feedResponseFieldSchema = z.object({
|
||||||
value: z.string()
|
value: z.string()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const feedResponseParentSchema = z.object({
|
||||||
|
name: z.string(),
|
||||||
|
domain: z.string(),
|
||||||
|
displayName: z.string().nullable(),
|
||||||
|
avatar: z.string().nullable(),
|
||||||
|
url: z.string()
|
||||||
|
})
|
||||||
|
|
||||||
export const feedResponseItemSchema = z.object({
|
export const feedResponseItemSchema = z.object({
|
||||||
avatar: z.string().url().nullable(),
|
avatar: z.string().url().nullable(),
|
||||||
bot: z.boolean().nullable(),
|
bot: z.boolean().nullable(),
|
||||||
|
@ -22,7 +30,8 @@ export const feedResponseItemSchema = z.object({
|
||||||
softwareName: z.string()
|
softwareName: z.string()
|
||||||
}),
|
}),
|
||||||
type: z.enum(['account', 'channel']),
|
type: z.enum(['account', 'channel']),
|
||||||
url: z.string().url()
|
url: z.string().url(),
|
||||||
|
parentFeed: z.nullable(feedResponseParentSchema)
|
||||||
})
|
})
|
||||||
|
|
||||||
export const feedResponseSchema = z.object({
|
export const feedResponseSchema = z.object({
|
||||||
|
@ -33,3 +42,4 @@ export const feedResponseSchema = z.object({
|
||||||
export type FeedResponse = z.infer<typeof feedResponseSchema>
|
export type FeedResponse = z.infer<typeof feedResponseSchema>
|
||||||
export type FeedResponseItem = z.infer<typeof feedResponseItemSchema>
|
export type FeedResponseItem = z.infer<typeof feedResponseItemSchema>
|
||||||
export type FeedResponseField = z.infer<typeof feedResponseFieldSchema>
|
export type FeedResponseField = z.infer<typeof feedResponseFieldSchema>
|
||||||
|
export type FeedResponseParent = z.infer<typeof feedResponseParentSchema>
|
||||||
|
|
Ładowanie…
Reference in New Issue