mirror of
https://github.com/LukeHagar/sveltesociety.dev.git
synced 2025-12-10 12:47:45 +00:00
Refactoring + cleanup
This commit is contained in:
@@ -55,7 +55,7 @@
|
||||
configurations as Configuration<string, string, string>
|
||||
);
|
||||
|
||||
export function search() {
|
||||
export function search(): void {
|
||||
const results = searcher.search({
|
||||
per_page: 100000,
|
||||
query,
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import { compare } from './sort';
|
||||
|
||||
describe('sort', () => {
|
||||
const mock = [
|
||||
{
|
||||
addedOn: '2019-09-29T14:39:13Z',
|
||||
category: 'Svelte',
|
||||
description:
|
||||
'Boilerplate with TypeScript, Webpack, Storybook, Travis CI, SCSS, Babel, EsLint, Prettier, Jest',
|
||||
stars: 51,
|
||||
tags: [],
|
||||
title: 'agusID/boilerplate-svelte',
|
||||
url: 'https://github.com/agusID/boilerplate-svelte'
|
||||
},
|
||||
{
|
||||
addedOn: '2020-09-29T14:39:13Z',
|
||||
category: 'Svelte',
|
||||
description: 'An example repo of a Svelte app that is IE11 compatible',
|
||||
stars: 27,
|
||||
tags: [],
|
||||
title: 'angelozehr/svelte-example-museums',
|
||||
url: 'https://github.com/angelozehr/svelte-example-museums'
|
||||
}
|
||||
];
|
||||
|
||||
it('should sort by added_desc', () => {
|
||||
mock.sort(compare('added_desc'));
|
||||
expect(mock[0].title).toEqual('angelozehr/svelte-example-museums');
|
||||
expect(mock[1].title).toEqual('agusID/boilerplate-svelte');
|
||||
});
|
||||
|
||||
it('should sort by added_asc', () => {
|
||||
mock.sort(compare('added_asc'));
|
||||
expect(mock[0].title).toEqual('agusID/boilerplate-svelte');
|
||||
expect(mock[1].title).toEqual('angelozehr/svelte-example-museums');
|
||||
});
|
||||
|
||||
it('should sort by name_asc', () => {
|
||||
mock.sort(compare('name_asc'));
|
||||
expect(mock[0].title).toEqual('agusID/boilerplate-svelte');
|
||||
expect(mock[1].title).toEqual('angelozehr/svelte-example-museums');
|
||||
});
|
||||
|
||||
it('should sort by name_desc', () => {
|
||||
mock.sort(compare('name_desc'));
|
||||
expect(mock[0].title).toEqual('angelozehr/svelte-example-museums');
|
||||
expect(mock[1].title).toEqual('agusID/boilerplate-svelte');
|
||||
});
|
||||
|
||||
it('should sort by stars_asc', () => {
|
||||
mock.sort(compare('stars_asc'));
|
||||
expect(mock[0].title).toEqual('angelozehr/svelte-example-museums');
|
||||
expect(mock[1].title).toEqual('agusID/boilerplate-svelte');
|
||||
});
|
||||
|
||||
it('should sort by stars_desc', () => {
|
||||
mock.sort(compare('stars_desc'));
|
||||
expect(mock[0].title).toEqual('agusID/boilerplate-svelte');
|
||||
expect(mock[1].title).toEqual('angelozehr/svelte-example-museums');
|
||||
});
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
type SortableEntity = {
|
||||
title: string;
|
||||
addedOn?: string;
|
||||
stars?: number;
|
||||
};
|
||||
|
||||
export const compare = (sorting: string) => {
|
||||
return (sortableEntityA: SortableEntity, sortableEntityB: SortableEntity): number => {
|
||||
switch (sorting) {
|
||||
case 'added_desc':
|
||||
return (
|
||||
new Date(sortableEntityB.addedOn || '').getTime() -
|
||||
new Date(sortableEntityA.addedOn || '').getTime()
|
||||
);
|
||||
case 'added_asc':
|
||||
return (
|
||||
new Date(sortableEntityA.addedOn || '').getTime() -
|
||||
new Date(sortableEntityB.addedOn || '').getTime()
|
||||
);
|
||||
case 'name_asc':
|
||||
return sortableEntityA.title
|
||||
.toLowerCase()
|
||||
.localeCompare(sortableEntityB.title.toLowerCase());
|
||||
case 'name_desc':
|
||||
return sortableEntityB.title
|
||||
.toLowerCase()
|
||||
.localeCompare(sortableEntityA.title.toLowerCase());
|
||||
case 'stars_desc':
|
||||
return (sortableEntityB.stars || 0) - (sortableEntityA.stars || 0);
|
||||
case 'stars_asc':
|
||||
return (sortableEntityA.stars || 0) - (sortableEntityB.stars || 0);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
export const sortMap = {
|
||||
added_desc: 'Added Desc',
|
||||
added_asc: 'Added Asc',
|
||||
name_asc: 'Name Asc',
|
||||
name_desc: 'Name Desc',
|
||||
stars_desc: 'Stars Desc',
|
||||
stars_asc: 'Stars Asc'
|
||||
};
|
||||
|
||||
export const selectSortItems = Object.entries(sortMap).map(([value, label]) => ({ label, value }));
|
||||
100
src/routes/_searchableJson.svelte
Normal file
100
src/routes/_searchableJson.svelte
Normal file
@@ -0,0 +1,100 @@
|
||||
<script>
|
||||
import ComponentCard from '$lib/components/ComponentIndex/Card.svelte';
|
||||
import List from '$lib/components/ComponentIndex/CardList.svelte';
|
||||
import SearchLayout from '$layouts/SearchLayout.svelte';
|
||||
import { extractUnique } from '$lib/utils/extractUnique';
|
||||
import Seo from '$lib/components/Seo.svelte';
|
||||
import Search from '$lib/components/Search.svelte';
|
||||
import Select from '../lib/components/Select.svelte';
|
||||
import { localStorage, persist } from '@macfja/svelte-persistent-store';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
export let data;
|
||||
export let displayTitle = '';
|
||||
export let displayTitleSingular = '';
|
||||
export let submittingType = '';
|
||||
|
||||
let selectedPackageManager = { value: 'npm' };
|
||||
const packageManager = persist(writable('npm'), localStorage(), 'packageManager');
|
||||
let searchValue;
|
||||
let dataToDisplay = [];
|
||||
|
||||
$: $packageManager = selectedPackageManager.value;
|
||||
$: categories = extractUnique(dataToDisplay, 'category');
|
||||
|
||||
export let categoryId = {};
|
||||
</script>
|
||||
|
||||
<Seo title={displayTitle} />
|
||||
|
||||
<SearchLayout title={displayTitle}>
|
||||
<section slot="controls" class="controls">
|
||||
<div class="inputs">
|
||||
<Search
|
||||
{data}
|
||||
dataDefault={{ category: '' }}
|
||||
bind:query={searchValue}
|
||||
sortableFields={[
|
||||
{ identifier: 'addedOn', title: 'Last added first', ascending: false },
|
||||
{ identifier: 'addedOn', title: 'Oldest first', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (A-Z)', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (Z-A)', ascending: false },
|
||||
{ identifier: 'stars', title: 'Most stars first', ascending: false }
|
||||
]}
|
||||
searchableFields={['title', 'description']}
|
||||
facetsConfig={[
|
||||
{
|
||||
title: 'Category',
|
||||
identifier: 'category',
|
||||
isClearable: true,
|
||||
showIndicator: true
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
identifier: 'tags',
|
||||
isMulti: true
|
||||
}
|
||||
]}
|
||||
on:search={(a) => (dataToDisplay = a.detail.data.items)}
|
||||
/>
|
||||
<Select
|
||||
label="Package manager"
|
||||
isClearable={false}
|
||||
showIndicator
|
||||
bind:value={selectedPackageManager}
|
||||
items={[
|
||||
{ label: 'NPM', value: 'npm' },
|
||||
{ label: 'PNPM', value: 'pnpm' },
|
||||
{ label: 'Yarn', value: 'yarn' }
|
||||
]}
|
||||
/>
|
||||
<a href="/help/submitting?type={submittingType}" class="submit"
|
||||
>Submit a {displayTitleSingular}</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<input
|
||||
class="searchbar"
|
||||
type="text"
|
||||
placeholder="Search for {displayTitle.toLowerCase()}..."
|
||||
bind:value={searchValue}
|
||||
/>
|
||||
<span class="searchbar-count"
|
||||
>{dataToDisplay.length} result{#if dataToDisplay.length !== 1}s{/if}</span
|
||||
>
|
||||
</section>
|
||||
<section slot="items">
|
||||
{#each categories as category}
|
||||
<List
|
||||
title={category.label || 'Unclassified'}
|
||||
id={categoryId[category.label] || category.label || 'unclassified'}
|
||||
>
|
||||
{#each dataToDisplay.filter((d) => d.category === category.value || (!categories
|
||||
.map((v) => v.value)
|
||||
.includes(d.category) && category.value === '')) as cardData}
|
||||
<ComponentCard {...cardData} />
|
||||
{/each}
|
||||
</List>
|
||||
{/each}
|
||||
</section>
|
||||
</SearchLayout>
|
||||
@@ -1,26 +1,6 @@
|
||||
<script>
|
||||
import { persist, localStorage } from '@macfja/svelte-persistent-store';
|
||||
import { onMount } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
|
||||
import components from './components.json';
|
||||
import List from '$components/ComponentIndex/CardList.svelte';
|
||||
import Select from '$components/Select.svelte';
|
||||
import SearchLayout from '$layouts/SearchLayout.svelte';
|
||||
import ComponentCard from '$lib/components/ComponentIndex/Card.svelte';
|
||||
import { extractUnique } from '$lib/utils/extractUnique';
|
||||
import Seo from '$lib/components/Seo.svelte';
|
||||
import Search from '$lib/components/Search.svelte';
|
||||
|
||||
let searchValue;
|
||||
let selectedPackageManager = { value: 'npm' };
|
||||
let packageManager = writable('npm');
|
||||
let dataToDisplay = [];
|
||||
onMount(() => {
|
||||
packageManager = persist(writable('npm'), localStorage(), 'packageManager');
|
||||
});
|
||||
$: $packageManager = selectedPackageManager.value;
|
||||
$: categories = extractUnique(dataToDisplay, 'category');
|
||||
import SearchableJson from '../_searchableJson.svelte';
|
||||
|
||||
const categoryId = {
|
||||
Animations: 'animations',
|
||||
@@ -39,74 +19,10 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<Seo title="Components" />
|
||||
|
||||
<SearchLayout title="Components">
|
||||
<section class="controls" slot="controls">
|
||||
<div class="inputs">
|
||||
<Search
|
||||
data={components}
|
||||
dataDefault={{ category: '' }}
|
||||
bind:query={searchValue}
|
||||
sortableFields={[
|
||||
{ identifier: 'addedOn', title: 'Last added first', ascending: false },
|
||||
{ identifier: 'addedOn', title: 'Oldest first', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (A-Z)', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (Z-A)', ascending: false },
|
||||
{ identifier: 'stars', title: 'Most star first', ascending: false }
|
||||
]}
|
||||
searchableFields={['title', 'description']}
|
||||
facetsConfig={[
|
||||
{
|
||||
title: 'Category',
|
||||
identifier: 'category',
|
||||
isClearable: true,
|
||||
showIndicator: true
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
identifier: 'tags',
|
||||
isMulti: true
|
||||
}
|
||||
]}
|
||||
on:search={(a) => (dataToDisplay = a.detail.data.items)}
|
||||
/>
|
||||
<Select
|
||||
label="Package manager"
|
||||
isClearable={false}
|
||||
showIndicator
|
||||
bind:value={selectedPackageManager}
|
||||
items={[
|
||||
{ label: 'NPM', value: 'npm' },
|
||||
{ label: 'PNPM', value: 'pnpm' },
|
||||
{ label: 'Yarn', value: 'yarn' }
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<a href="/help/submitting?type=component" class="submit">Submit a component</a>
|
||||
<input
|
||||
class="searchbar"
|
||||
type="text"
|
||||
placeholder="Search for components..."
|
||||
bind:value={searchValue}
|
||||
/>
|
||||
<span class="searchbar-count"
|
||||
>{dataToDisplay.length} result{#if dataToDisplay.length !== 1}s{/if}</span
|
||||
>
|
||||
</section>
|
||||
<section slot="items">
|
||||
{#each categories as category}
|
||||
<List
|
||||
title={category.label || 'Unclassified'}
|
||||
id={categoryId[category.label] || category.label || 'unclassified'}
|
||||
>
|
||||
{#each dataToDisplay.filter((d) => d.category === category.value || (!categories
|
||||
.map((v) => v.value)
|
||||
.includes(d.category) && category.value === '')) as data}
|
||||
<ComponentCard {...data} manager={$packageManager} />
|
||||
{/each}
|
||||
</List>
|
||||
{/each}
|
||||
</section>
|
||||
</SearchLayout>
|
||||
<SearchableJson
|
||||
{categoryId}
|
||||
data={components}
|
||||
displayTitle="Components"
|
||||
displayTitleSingular="component"
|
||||
submittingType="component"
|
||||
/>
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
<script>
|
||||
import ComponentCard from '$lib/components/ComponentIndex/Card.svelte';
|
||||
import List from '$lib/components/ComponentIndex/CardList.svelte';
|
||||
import templates from './templates.json';
|
||||
import { extractUnique } from '$lib/utils/extractUnique';
|
||||
import SearchLayout from '$lib/layouts/SearchLayout.svelte';
|
||||
import Seo from '$lib/components/Seo.svelte';
|
||||
import Search from '$lib/components/Search.svelte';
|
||||
|
||||
let searchValue;
|
||||
let dataToDisplay = [];
|
||||
$: categories = extractUnique(dataToDisplay, 'category');
|
||||
import SearchableJson from '../_searchableJson.svelte';
|
||||
|
||||
const categoryId = {
|
||||
Sapper: 'sapper',
|
||||
@@ -19,64 +10,10 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<Seo title="Templates" />
|
||||
|
||||
<SearchLayout title="Templates">
|
||||
<section class="controls" slot="controls">
|
||||
<div class="inputs">
|
||||
<Search
|
||||
data={templates}
|
||||
dataDefault={{ category: '' }}
|
||||
bind:query={searchValue}
|
||||
sortableFields={[
|
||||
{ identifier: 'addedOn', title: 'Last added first', ascending: false },
|
||||
{ identifier: 'addedOn', title: 'Oldest first', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (A-Z)', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (Z-A)', ascending: false },
|
||||
{ identifier: 'stars', title: 'Most star first', ascending: false }
|
||||
]}
|
||||
searchableFields={['title', 'description']}
|
||||
facetsConfig={[
|
||||
{
|
||||
title: 'Category',
|
||||
identifier: 'category',
|
||||
isClearable: true,
|
||||
showIndicator: true
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
identifier: 'tags',
|
||||
isMulti: true
|
||||
}
|
||||
]}
|
||||
on:search={(a) => (dataToDisplay = a.detail.data.items)}
|
||||
/>
|
||||
|
||||
<a href="/help/submitting?type=template" class="submit">Submit a template</a>
|
||||
</div>
|
||||
|
||||
<input
|
||||
class="searchbar"
|
||||
type="text"
|
||||
placeholder="Search for templates..."
|
||||
bind:value={searchValue}
|
||||
/>
|
||||
<span class="searchbar-count"
|
||||
>{dataToDisplay.length} result{#if dataToDisplay.length !== 1}s{/if}</span
|
||||
>
|
||||
</section>
|
||||
<section slot="items">
|
||||
{#each categories as category}
|
||||
<List
|
||||
title={category.label || 'Unclassified'}
|
||||
id={categoryId[category.label] || category.label || 'unclassified'}
|
||||
>
|
||||
{#each dataToDisplay.filter((d) => d.category === category.value || (!categories
|
||||
.map((v) => v.value)
|
||||
.includes(d.category) && category.value === '')) as data}
|
||||
<ComponentCard {...data} />
|
||||
{/each}
|
||||
</List>
|
||||
{/each}
|
||||
</section>
|
||||
</SearchLayout>
|
||||
<SearchableJson
|
||||
{categoryId}
|
||||
data={templates}
|
||||
displayTitle="Template"
|
||||
displayTitleSingular="template"
|
||||
submittingType="template"
|
||||
/>
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
<script>
|
||||
import ComponentCard from '$lib/components/ComponentIndex/Card.svelte';
|
||||
import List from '$lib/components/ComponentIndex/CardList.svelte';
|
||||
import SearchLayout from '$layouts/SearchLayout.svelte';
|
||||
import { extractUnique } from '$lib/utils/extractUnique';
|
||||
import tools from '../tools/tools.json';
|
||||
import Seo from '$lib/components/Seo.svelte';
|
||||
import Search from '$lib/components/Search.svelte';
|
||||
|
||||
let searchValue;
|
||||
let dataToDisplay = [];
|
||||
|
||||
$: categories = extractUnique(dataToDisplay, 'category');
|
||||
import SearchableJson from '../_searchableJson.svelte';
|
||||
|
||||
const categoryId = {
|
||||
'Bundler Plugins': 'bundling',
|
||||
@@ -21,63 +11,10 @@
|
||||
};
|
||||
</script>
|
||||
|
||||
<Seo title="Tools" />
|
||||
|
||||
<SearchLayout title="Tools">
|
||||
<section slot="controls" class="controls">
|
||||
<div class="inputs">
|
||||
<Search
|
||||
data={tools}
|
||||
dataDefault={{ category: '' }}
|
||||
bind:query={searchValue}
|
||||
sortableFields={[
|
||||
{ identifier: 'addedOn', title: 'Last added first', ascending: false },
|
||||
{ identifier: 'addedOn', title: 'Oldest first', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (A-Z)', ascending: true },
|
||||
{ identifier: 'title', title: 'Name (Z-A)', ascending: false },
|
||||
{ identifier: 'stars', title: 'Most stars first', ascending: false }
|
||||
]}
|
||||
searchableFields={['title', 'description']}
|
||||
facetsConfig={[
|
||||
{
|
||||
title: 'Category',
|
||||
identifier: 'category',
|
||||
isClearable: true,
|
||||
showIndicator: true
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
identifier: 'tags',
|
||||
isMulti: true
|
||||
}
|
||||
]}
|
||||
on:search={(a) => (dataToDisplay = a.detail.data.items)}
|
||||
/>
|
||||
<a href="/help/submitting?type=tool" class="submit">Submit a tool</a>
|
||||
</div>
|
||||
|
||||
<input
|
||||
class="searchbar"
|
||||
type="text"
|
||||
placeholder="Search for tools..."
|
||||
bind:value={searchValue}
|
||||
/>
|
||||
<span class="searchbar-count"
|
||||
>{dataToDisplay.length} result{#if dataToDisplay.length !== 1}s{/if}</span
|
||||
>
|
||||
</section>
|
||||
<section slot="items">
|
||||
{#each categories as category}
|
||||
<List
|
||||
title={category.label || 'Unclassified'}
|
||||
id={categoryId[category.label] || category.label || 'unclassified'}
|
||||
>
|
||||
{#each dataToDisplay.filter((d) => d.category === category.value || (!categories
|
||||
.map((v) => v.value)
|
||||
.includes(d.category) && category.value === '')) as data}
|
||||
<ComponentCard {...data} />
|
||||
{/each}
|
||||
</List>
|
||||
{/each}
|
||||
</section>
|
||||
</SearchLayout>
|
||||
<SearchableJson
|
||||
{categoryId}
|
||||
data={tools}
|
||||
displayTitle="Tools"
|
||||
displayTitleSingular="tool"
|
||||
submittingType="tool"
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user