Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion src/lib/components/AdditionalContext.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,19 @@ let { additionalContext = $bindable(''), expanded = $bindable(false) } = $props(
bind:value={additionalContext}
placeholder="anything else we should know about?"
></textarea>
{#if additionalContext.trim() !== ''}
<div class="button-container">
<button
type="button"
class="clear-button"
onclick={() => {
additionalContext = ''
}}
>
clear
</button>
</div>
{/if}
</details>

<style>
Expand Down Expand Up @@ -39,5 +52,25 @@ let { additionalContext = $bindable(''), expanded = $bindable(false) } = $props(
resize: vertical;
min-height: 80px;
color: var(--primary-dark);
}
}

.clear-button {
border: none;
background-color: var(--light);
color: var(--primary-dark);
border-radius: var(--border-radius);
padding: 0.25rem 0.75rem;
cursor: pointer;
}

.clear-button:hover {
background-color: var(--primary-dark);
color: var(--white);
}

.button-container {
display: flex;
justify-content: flex-end;
margin-top: 0.5rem;
}
</style>
39 changes: 19 additions & 20 deletions src/lib/components/ControlBar.svelte
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@
<script lang="ts">
// biome-ignore lint/style/useConst: Svelte 5 $props() pattern
let {
lookBackHours = $bindable(''),
lookBackAmount = $bindable(''),
lookBackUnit = $bindable('hours'),
messageCount,
onclick,
canGenerate,
isLoading,
}: {
lookBackHours?: string
lookBackAmount?: string
lookBackUnit?: string
messageCount: number
onclick: () => void
canGenerate: boolean
isLoading: boolean
} = $props()

const lookBackOptions = [
{ value: '1', label: 'hour' },
{ value: '2', label: '2 hours' },
{ value: '3', label: '3 hours' },
{ value: '4', label: '4 hours' },
{ value: '5', label: '5 hours' },
{ value: '6', label: '6 hours' },
{ value: '12', label: '12 hours' },
{ value: '24', label: '24 hours' },
]
const amountOptions = ['1', '2', '3', '4', '5', '6', '12', '24']
const unitOptions = ['minutes', 'hours', 'days']
</script>

<section class="control-bar">
<div class="timeframe-controls">
<label for="window-back">summarize last:</label>
<select id="window-back" bind:value={lookBackHours}>
{#each lookBackOptions as option (option.value)}
<option value={option.value}>{option.label}</option>
{/each}
</select>
<button type="button" class="go-button" { onclick } disabled={!canGenerate}>
<div class="timeframe-controls">
<label for="window-amount">summarize last:</label>
<select id="window-amount" bind:value={lookBackAmount}>
{#each amountOptions as val}
<option value={val}>{val}</option>
{/each}
</select>
<select id="window-unit" bind:value={lookBackUnit}>
{#each unitOptions as val}
<option value={val}>{val}</option>
{/each}
</select>
<button type="button" class="go-button" { onclick } disabled={!canGenerate}>
{#if isLoading}
<span class="loading-spinner"></span>
{:else}
Expand Down
10 changes: 7 additions & 3 deletions src/routes/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@ import type { Actions, PageServerLoad } from './$types'

const DEFAULT_TONE = 'gentle'
const DEFAULT_PROVIDER = 'openai'
const ONE_HOUR = 60 * 60 * 1000
const MINUTE = 60 * 1000
const HOUR = 60 * MINUTE
const DAY = 24 * HOUR

export const load: PageServerLoad = async ({ url }) => {
const lookBack = Number.parseInt(url.searchParams.get('lookBackHours') || '1')
const amount = Number.parseInt(url.searchParams.get('lookBackAmount') || '1')
const unit = url.searchParams.get('lookBackUnit') || 'hours'
const multiplier = unit === 'minutes' ? MINUTE : unit === 'days' ? DAY : HOUR
const end = new Date()
const start = new Date(end.getTime() - lookBack * ONE_HOUR)
const start = new Date(end.getTime() - amount * multiplier)
const { messages } = await queryMessagesDb(start.toISOString(), end.toISOString())

return { messages }
Expand Down
38 changes: 20 additions & 18 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const formState = $state({
loading: false,
},
form: {
lookBackHours: '1',
lookBackAmount: '1',
lookBackUnit: 'hours',
additionalContext: '',
tone: 'gentle' as ToneType,
messages: [] as Message[],
Expand Down Expand Up @@ -49,22 +50,22 @@ $effect(() => {
}
})

// Watch for changes to lookBackHours and navigate to the new URL
// Watch for changes to lookBackAmount/unit and navigate to the new URL
$effect(() => {
if (!browser) return

const lookBack = formState.form.lookBackHours
if (lookBack) {

const amount = formState.form.lookBackAmount
const unit = formState.form.lookBackUnit
if (amount && unit) {
const url = new URL(window.location.href)
const current = url.searchParams.get('lookBackHours')
const currentAmt = url.searchParams.get('lookBackAmount')
const currentUnit = url.searchParams.get('lookBackUnit')

if (current === lookBack) return
if (currentAmt === amount && currentUnit === unit) return

// Update the URL with the new lookBackHours parameter
url.searchParams.set('lookBackHours', lookBack)
url.searchParams.set('lookBackAmount', amount)
url.searchParams.set('lookBackUnit', unit)

// Use SvelteKit's goto to navigate to the new URL
// This will trigger a new page load with the updated parameter
goto(url.toString(), { keepFocus: true, noScroll: true })
}
})
Expand Down Expand Up @@ -176,13 +177,14 @@ async function onclick() {
<div class="content-container">
<form onsubmit={handleSubmit}>

<ControlBar
bind:lookBackHours={formState.form.lookBackHours}
messageCount={formState.form.messages.length}
onclick={onclick}
canGenerate={canGenerateReplies}
isLoading={showLoadingIndicators}
/>
<ControlBar
bind:lookBackAmount={formState.form.lookBackAmount}
bind:lookBackUnit={formState.form.lookBackUnit}
messageCount={formState.form.messages.length}
onclick={onclick}
canGenerate={canGenerateReplies}
isLoading={showLoadingIndicators}
/>

<!-- Additional context (collapsible) -->
<AdditionalContext bind:additionalContext={formState.form.additionalContext} bind:expanded={additionalContextExpanded} />
Expand Down
11 changes: 11 additions & 0 deletions tests/lib/components/AdditionalContext.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class AdditionalContextModel {
expanded: boolean
changeContext: (newContext: string) => void
toggleExpanded: () => void
clearContext: () => void

constructor(initialContext = '', initialExpanded = false) {
this.additionalContext = initialContext
Expand All @@ -15,6 +16,10 @@ class AdditionalContextModel {
this.additionalContext = newContext
}

this.clearContext = () => {
this.additionalContext = ''
}

this.toggleExpanded = () => {
this.expanded = !this.expanded
}
Expand Down Expand Up @@ -50,4 +55,10 @@ describe('AdditionalContext Component', () => {
component.toggleExpanded()
expect(component.expanded).toBe(false)
})

it('should clear additionalContext', () => {
const component = new AdditionalContextModel('hey')
component.clearContext()
expect(component.additionalContext).toBe('')
})
})
Loading