diff --git a/packages/api/src/jobs/ai-summarize.ts b/packages/api/src/jobs/ai-summarize.ts
index 64cef703c..974a6b347 100644
--- a/packages/api/src/jobs/ai-summarize.ts
+++ b/packages/api/src/jobs/ai-summarize.ts
@@ -7,6 +7,7 @@ import { libraryItemRepository } from '../repository/library_item'
import { htmlToMarkdown } from '../utils/parser'
import { AISummary } from '../entity/AISummary'
import { LibraryItemState } from '../entity/library_item'
+import { getAISummary } from '../services/ai-summaries'
export interface AISummarizeJobData {
userId: string
@@ -35,6 +36,19 @@ export const aiSummarize = async (jobData: AISummarizeJobData) => {
return
}
+ const existingSummary = await getAISummary({
+ userId: jobData.userId,
+ idx: 'latest',
+ libraryItemId: jobData.libraryItemId,
+ })
+
+ if (existingSummary) {
+ logger.info(
+ `Library item already has a summary: ${jobData.libraryItemId}`
+ )
+ return
+ }
+
const llm = new ChatOpenAI({
configuration: {
apiKey: process.env.OPENAI_API_KEY,
diff --git a/packages/web/components/elements/FormElements.tsx b/packages/web/components/elements/FormElements.tsx
index d2e3c7691..b672989bf 100644
--- a/packages/web/components/elements/FormElements.tsx
+++ b/packages/web/components/elements/FormElements.tsx
@@ -41,6 +41,9 @@ export const FormInput = styled('input', {
'&:focus': {
outline: 'none',
},
+ '@mdDown': {
+ pl: '5px',
+ },
})
export const FormLabel = styled('label', {
diff --git a/packages/web/components/patterns/LibraryCards/LibraryGridCard.tsx b/packages/web/components/patterns/LibraryCards/LibraryGridCard.tsx
index e2dc59569..c824c82e9 100644
--- a/packages/web/components/patterns/LibraryCards/LibraryGridCard.tsx
+++ b/packages/web/components/patterns/LibraryCards/LibraryGridCard.tsx
@@ -74,9 +74,11 @@ export function LibraryGridCard(props: LinkedItemCardProps): JSX.Element {
overflow: 'hidden',
cursor: 'pointer',
'@media (max-width: 930px)': {
- // m: '15px',
width: 'calc(100% - 30px)',
},
+ '@mdDown': {
+ width: '100%',
+ },
}}
alignment="start"
distribution="start"
diff --git a/packages/web/components/templates/homeFeed/FetchItemsError.tsx b/packages/web/components/templates/homeFeed/FetchItemsError.tsx
index 7a6f1c2d9..d96c7f8b5 100644
--- a/packages/web/components/templates/homeFeed/FetchItemsError.tsx
+++ b/packages/web/components/templates/homeFeed/FetchItemsError.tsx
@@ -1,4 +1,4 @@
-import { VStack } from '../../elements/LayoutPrimitives'
+import { Box, SpanBox, VStack } from '../../elements/LayoutPrimitives'
import { StyledText } from '../../elements/StyledText'
import { ErrorSlothIcon } from '../../elements/icons/ErrorSlothIcon'
import { DEFAULT_HEADER_HEIGHT } from './HeaderSpacer'
@@ -13,6 +13,7 @@ export const FetchItemsError = (): JSX.Element => {
width: '100%',
height: '100%',
pb: '100px',
+ px: '30px',
minHeight: `calc(100vh - ${DEFAULT_HEADER_HEIGHT})`,
}}
>
@@ -30,16 +31,15 @@ export const FetchItemsError = (): JSX.Element => {
>
Something has gone wrong.
-
We have encountered unexpected problems.{' '}
@@ -50,7 +50,7 @@ export const FetchItemsError = (): JSX.Element => {
>
Get help
-
+
)
}
diff --git a/packages/web/components/templates/homeFeed/LibraryHeader.tsx b/packages/web/components/templates/homeFeed/LibraryHeader.tsx
index 93e97ba97..26efa348b 100644
--- a/packages/web/components/templates/homeFeed/LibraryHeader.tsx
+++ b/packages/web/components/templates/homeFeed/LibraryHeader.tsx
@@ -49,7 +49,6 @@ export const headerControlWidths = (
return {
width: '95%',
'@mdDown': {
- padding: '15px',
width: '100%',
},
'@media (min-width: 930px)': {
@@ -135,18 +134,26 @@ function LargeHeaderLayout(props: LibraryHeaderProps): JSX.Element {
}
const HeaderControls = (props: LibraryHeaderProps): JSX.Element => {
+ const [searchBoxFocused, setSearchBoxFocused] = useState(false)
+
return (
<>
-
-
-
+ {!searchBoxFocused && (
+
+
+
+ )}
-
+
{userHasFeature(props.viewer, 'ai-summaries') && (
@@ -243,9 +250,13 @@ export function MenuHeaderButton(props: MenuHeaderButtonProps): JSX.Element {
)
}
-export function SearchBox(props: LibraryHeaderProps): JSX.Element {
+type SearchBoxProps = LibraryHeaderProps & {
+ searchBoxFocused: boolean
+ setSearchBoxFocused: (show: boolean) => void
+}
+
+export function SearchBox(props: SearchBoxProps): JSX.Element {
const inputRef = useRef(null)
- const [focused, setFocused] = useState(false)
const [searchTerm, setSearchTerm] = useState(props.searchTerm ?? '')
useEffect(() => {
@@ -272,7 +283,7 @@ export function SearchBox(props: LibraryHeaderProps): JSX.Element {
maxWidth: '521px',
bg: '$thLibrarySearchbox',
borderRadius: '6px',
- boxShadow: focused
+ boxShadow: props.searchBoxFocused
? 'none'
: '0 1px 3px 0 rgba(0, 0, 0, 0.1),0 1px 2px 0 rgba(0, 0, 0, 0.06);',
}}
@@ -306,7 +317,7 @@ export function SearchBox(props: LibraryHeaderProps): JSX.Element {
alignment="center"
distribution="start"
css={{
- border: focused
+ border: props.searchBoxFocused
? '2px solid $searchActiveOutline'
: '2px solid transparent',
borderTopRightRadius: '6px',
@@ -331,10 +342,10 @@ export function SearchBox(props: LibraryHeaderProps): JSX.Element {
placeholder="Search keywords or labels"
onFocus={(event) => {
event.target.select()
- setFocused(true)
+ props.setSearchBoxFocused(true)
}}
onBlur={() => {
- setFocused(false)
+ props.setSearchBoxFocused(false)
}}
onChange={(event) => {
setSearchTerm(event.target.value)
diff --git a/packages/web/components/templates/homeFeed/MultiSelectControls.tsx b/packages/web/components/templates/homeFeed/MultiSelectControls.tsx
index 4361bef88..987889182 100644
--- a/packages/web/components/templates/homeFeed/MultiSelectControls.tsx
+++ b/packages/web/components/templates/homeFeed/MultiSelectControls.tsx
@@ -21,7 +21,6 @@ export const MultiSelectControls = (props: LibraryHeaderProps): JSX.Element => {
const [hoverColor, setHoverColor] = useState(
theme.colors.thTextContrast2.toString()
)
- const compact = false
return (
{
css={{
width: '100%',
height: '100%',
- pr: compact ? '5px' : '10px',
+ pr: '10px',
}}
onClick={(e) => {
e.preventDefault()
@@ -81,17 +80,37 @@ export const MultiSelectControls = (props: LibraryHeaderProps): JSX.Element => {
border: '2px solid transparent',
width: '100%',
height: '100%',
+ '@mdDown': {
+ pl: '5px',
+ },
}}
>
{props.numItemsSelected} items selected
+
+ {props.numItemsSelected} items
+
diff --git a/packages/web/components/templates/homeFeed/TLDRLayout.tsx b/packages/web/components/templates/homeFeed/TLDRLayout.tsx
index 53eafdc00..29a3a26cc 100644
--- a/packages/web/components/templates/homeFeed/TLDRLayout.tsx
+++ b/packages/web/components/templates/homeFeed/TLDRLayout.tsx
@@ -58,11 +58,14 @@ export function TLDRLayout(props: TLDRLayoutProps): JSX.Element {
{props.isValidating && props.items.length == 0 && }
{props.items.map((item) => {
- const source = siteName(
+ const sourceName = siteName(
item.node.originalArticleUrl,
item.node.url,
item.node.siteName
)
+ const source =
+ sourceName == item.node.author ? undefined : item.node.author
+
return (
{item.node.siteName}
@@ -104,9 +113,14 @@ export function TLDRLayout(props: TLDRLayoutProps): JSX.Element {
{source && item.node.author && (
•
@@ -118,6 +132,12 @@ export function TLDRLayout(props: TLDRLayoutProps): JSX.Element {
display: 'flex',
fontFamily: '$inter',
fontSize: '16px',
+ maxWidth: '120px',
+ maxLines: '1',
+ textOverflow: 'ellipsis',
+ '@mdDown': {
+ fontSize: '12px',
+ },
}}
>
{item.node.author}
@@ -145,6 +165,7 @@ export function TLDRLayout(props: TLDRLayoutProps): JSX.Element {
fontFamily: '$inter',
fontWeight: '700',
fontSize: '20px',
+ wordBreak: 'break-all',
textDecoration: 'underline',
a: {
color: '$thTLDRText',