Skip to content

Commit d820068

Browse files
authored
Update API Configuration to store known page types and collection keys (#9)
* feat(search content): Ability to store known page types & collection keys in API Configuration, then have toggles to enable which scope to search * feat(search content): Improve UI * fix(search content): Persist chosen scopes correctly to localstorage * feat: Update what's new
1 parent 8a1cf71 commit d820068

7 files changed

Lines changed: 533 additions & 1322 deletions

File tree

src/App.vue

Lines changed: 176 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,82 @@
3535
</div>
3636

3737
<label class="app__checkbox-label">
38-
<input type="checkbox" v-model="store.includePreview" class="app__checkbox-input" />
38+
<input
39+
type="checkbox"
40+
v-model="store.includePreview"
41+
class="app__checkbox-input"
42+
aria-label="Include preview content in API requests"
43+
/>
3944
<span>Include draft content in search results</span>
4045
</label>
46+
47+
<!-- Page Types Section -->
48+
<div class="app__config-section">
49+
<h3 class="app__config-title">Page Types</h3>
50+
<form @submit.prevent="addPageType" class="app__config-form">
51+
<TextInput
52+
id="page-type-input"
53+
type="text"
54+
v-model="pageTypeInput"
55+
root-class="app__config-input"
56+
>
57+
<template v-slot:label>Add Page Type</template>
58+
</TextInput>
59+
<Btn v-if="pageTypeInput" type="submit" status="secondary" class="app__form-button"
60+
>Add</Btn
61+
>
62+
</form>
63+
<ul v-if="store.pageTypes.length > 0" class="app__items-list">
64+
<li v-for="pageType in store.pageTypes" :key="pageType">
65+
<Chip class="app__item-chip">
66+
{{ pageType }}
67+
<button
68+
type="button"
69+
@click="removePageType(pageType)"
70+
class="app__chip-remove"
71+
:aria-label="`Remove ${pageType}`"
72+
>
73+
74+
</button>
75+
</Chip>
76+
</li>
77+
</ul>
78+
<p v-else class="app__empty-message">No page types configured</p>
79+
</div>
80+
81+
<!-- Collection Keys Section -->
82+
<div class="app__config-section">
83+
<h3 class="app__config-title">Collection Keys</h3>
84+
<form @submit.prevent="addCollectionKey" class="app__config-form">
85+
<TextInput
86+
id="collection-key-input"
87+
type="text"
88+
v-model="collectionKeyInput"
89+
root-class="app__config-input"
90+
>
91+
<template v-slot:label>Add Collection Key</template>
92+
</TextInput>
93+
<Btn v-if="collectionKeyInput" type="submit" status="secondary" class="app__form-button"
94+
>Add</Btn
95+
>
96+
</form>
97+
<ul v-if="store.collectionKeys.length > 0" class="app__items-list">
98+
<li v-for="collectionKey in store.collectionKeys" :key="collectionKey">
99+
<Chip class="app__item-chip">
100+
{{ collectionKey }}
101+
<button
102+
type="button"
103+
@click="removeCollectionKey(collectionKey)"
104+
class="app__chip-remove"
105+
:aria-label="`Remove ${collectionKey}`"
106+
>
107+
108+
</button>
109+
</Chip>
110+
</li>
111+
</ul>
112+
<p v-else class="app__empty-message">No collection keys configured</p>
113+
</div>
41114
</UtilitySection>
42115

43116
<h2 style="font-weight: 500">Utilities</h2>
@@ -52,21 +125,50 @@
52125
</template>
53126

54127
<script setup lang="ts">
128+
import { ref } from 'vue'
55129
import { useStore } from './stores/index'
56130
import Header from './components/Header.vue'
57131
import Footer from './components/Footer.vue'
58132
import WhatsNew from './components/WhatsNew.vue'
59133
import InfoBanner from './components/InfoBanner.vue'
60134
import UtilitySection from './components/UtilitySection.vue'
61135
import TextInput from './components/TextInput.vue'
136+
import Btn from './components/Btn.vue'
137+
import Chip from './components/Chip.vue'
62138
import SearchContent from './components/Features/SearchContent.vue'
63139
import ComingSoon from './components/ComingSoon.vue'
64140
65141
const store = useStore()
142+
const pageTypeInput = ref('')
143+
const collectionKeyInput = ref('')
66144
67145
function toggleTokenLock(): void {
68146
store.lockToken = !store.lockToken
69147
}
148+
149+
function addPageType(): void {
150+
const trimmed = pageTypeInput.value.trim()
151+
if (trimmed && !store.pageTypes.includes(trimmed)) {
152+
store.pageTypes = [...store.pageTypes, trimmed]
153+
pageTypeInput.value = ''
154+
}
155+
}
156+
157+
function removePageType(pageType: string): void {
158+
store.pageTypes = store.pageTypes.filter((p: string) => p !== pageType)
159+
}
160+
161+
function addCollectionKey(): void {
162+
const trimmed = collectionKeyInput.value.trim()
163+
if (trimmed && !store.collectionKeys.includes(trimmed)) {
164+
store.collectionKeys = [...store.collectionKeys, trimmed]
165+
collectionKeyInput.value = ''
166+
}
167+
}
168+
169+
function removeCollectionKey(collectionKey: string): void {
170+
store.collectionKeys = store.collectionKeys.filter((c: string) => c !== collectionKey)
171+
}
70172
</script>
71173

72174
<style lang="scss" scoped>
@@ -81,7 +183,7 @@ main {
81183
max-width: 1200px;
82184
width: 100%;
83185
margin: 0 auto;
84-
padding: 2rem 1.5rem;
186+
padding: 2rem 1rem;
85187
}
86188
87189
.app {
@@ -136,5 +238,77 @@ main {
136238
height: 1.25rem;
137239
flex-shrink: 0;
138240
}
241+
242+
&__config-section {
243+
margin-top: 1.5rem;
244+
padding: 1rem;
245+
background-color: var(--butter-light-gray);
246+
border-radius: 6px;
247+
border-left: 3px solid var(--butter-border);
248+
}
249+
250+
&__config-title {
251+
font-size: 0.875rem;
252+
font-weight: 600;
253+
text-transform: uppercase;
254+
color: var(--text-secondary);
255+
margin: 0 0 0.75rem 0;
256+
}
257+
258+
&__items-list {
259+
display: flex;
260+
flex-wrap: wrap;
261+
gap: 0.5rem;
262+
margin-bottom: 0.75rem;
263+
padding: 0;
264+
list-style: none;
265+
}
266+
267+
&__empty-message {
268+
font-size: 0.875rem;
269+
color: var(--text-secondary);
270+
margin: 0 0 0.5rem 0;
271+
font-style: italic;
272+
}
273+
274+
&__config-form {
275+
display: flex;
276+
gap: 0.75rem;
277+
margin-bottom: 1rem;
278+
flex-direction: column;
279+
280+
@media (min-width: 450px) {
281+
flex-direction: row;
282+
align-items: flex-end;
283+
}
284+
}
285+
286+
&__config-input {
287+
flex: 1;
288+
min-width: 200px;
289+
}
290+
291+
&__form-button {
292+
min-width: unset;
293+
}
294+
295+
&__item-chip {
296+
padding-right: 0.25rem;
297+
}
298+
299+
&__chip-remove {
300+
margin-left: 0.5rem;
301+
background: none;
302+
border: none;
303+
color: inherit;
304+
cursor: pointer;
305+
padding: 0 0.25rem;
306+
opacity: 0.6;
307+
transition: opacity 0.2s;
308+
309+
&:hover {
310+
opacity: 1;
311+
}
312+
}
139313
}
140314
</style>

src/components/Btn.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ withDefaults(
3030
*/
3131
href?: string
3232
disabled?: boolean
33-
status?: 'secondary'
33+
status?: 'secondary' | 'tertiary'
3434
}>(),
3535
{
3636
tag: 'button',
@@ -56,7 +56,7 @@ withDefaults(
5656
color: var(--btn-color);
5757
text-decoration: none;
5858
padding: 0.75rem 1rem;
59-
border-radius: 0.5rem;
59+
border-radius: 0.3125rem;
6060
cursor: pointer;
6161
outline-offset: 4px;
6262
height: var(--btn-height);
@@ -73,6 +73,14 @@ withDefaults(
7373
position: relative;
7474
7575
&--secondary {
76+
--btn-background-color: var(--text-primary);
77+
--btn-border-color: var(--text-primary);
78+
--btn-color: #fff;
79+
--btn-hover-background-color: var(--butter-dark);
80+
--btn-hover-border-color: var(--butter-dark);
81+
}
82+
83+
&--tertiary {
7684
--btn-background-color: #fff;
7785
--btn-border-color: var(--butter-yellow);
7886
--btn-color: var(--butter-dark);

0 commit comments

Comments
 (0)