mirror of
https://github.com/LukeHagar/sveltesociety.dev.git
synced 2025-12-10 04:21:49 +00:00
Refactoring + cleanup
This commit is contained in:
@@ -55,7 +55,7 @@
|
|||||||
configurations as Configuration<string, string, string>
|
configurations as Configuration<string, string, string>
|
||||||
);
|
);
|
||||||
|
|
||||||
export function search() {
|
export function search(): void {
|
||||||
const results = searcher.search({
|
const results = searcher.search({
|
||||||
per_page: 100000,
|
per_page: 100000,
|
||||||
query,
|
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>
|
<script>
|
||||||
import { persist, localStorage } from '@macfja/svelte-persistent-store';
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { writable } from 'svelte/store';
|
|
||||||
|
|
||||||
import components from './components.json';
|
import components from './components.json';
|
||||||
import List from '$components/ComponentIndex/CardList.svelte';
|
import SearchableJson from '../_searchableJson.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');
|
|
||||||
|
|
||||||
const categoryId = {
|
const categoryId = {
|
||||||
Animations: 'animations',
|
Animations: 'animations',
|
||||||
@@ -39,74 +19,10 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Seo title="Components" />
|
<SearchableJson
|
||||||
|
{categoryId}
|
||||||
<SearchLayout title="Components">
|
|
||||||
<section class="controls" slot="controls">
|
|
||||||
<div class="inputs">
|
|
||||||
<Search
|
|
||||||
data={components}
|
data={components}
|
||||||
dataDefault={{ category: '' }}
|
displayTitle="Components"
|
||||||
bind:query={searchValue}
|
displayTitleSingular="component"
|
||||||
sortableFields={[
|
submittingType="component"
|
||||||
{ 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>
|
|
||||||
|
|||||||
@@ -1,15 +1,6 @@
|
|||||||
<script>
|
<script>
|
||||||
import ComponentCard from '$lib/components/ComponentIndex/Card.svelte';
|
|
||||||
import List from '$lib/components/ComponentIndex/CardList.svelte';
|
|
||||||
import templates from './templates.json';
|
import templates from './templates.json';
|
||||||
import { extractUnique } from '$lib/utils/extractUnique';
|
import SearchableJson from '../_searchableJson.svelte';
|
||||||
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');
|
|
||||||
|
|
||||||
const categoryId = {
|
const categoryId = {
|
||||||
Sapper: 'sapper',
|
Sapper: 'sapper',
|
||||||
@@ -19,64 +10,10 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Seo title="Templates" />
|
<SearchableJson
|
||||||
|
{categoryId}
|
||||||
<SearchLayout title="Templates">
|
|
||||||
<section class="controls" slot="controls">
|
|
||||||
<div class="inputs">
|
|
||||||
<Search
|
|
||||||
data={templates}
|
data={templates}
|
||||||
dataDefault={{ category: '' }}
|
displayTitle="Template"
|
||||||
bind:query={searchValue}
|
displayTitleSingular="template"
|
||||||
sortableFields={[
|
submittingType="template"
|
||||||
{ 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>
|
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
<script>
|
<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 tools from '../tools/tools.json';
|
||||||
import Seo from '$lib/components/Seo.svelte';
|
import SearchableJson from '../_searchableJson.svelte';
|
||||||
import Search from '$lib/components/Search.svelte';
|
|
||||||
|
|
||||||
let searchValue;
|
|
||||||
let dataToDisplay = [];
|
|
||||||
|
|
||||||
$: categories = extractUnique(dataToDisplay, 'category');
|
|
||||||
|
|
||||||
const categoryId = {
|
const categoryId = {
|
||||||
'Bundler Plugins': 'bundling',
|
'Bundler Plugins': 'bundling',
|
||||||
@@ -21,63 +11,10 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Seo title="Tools" />
|
<SearchableJson
|
||||||
|
{categoryId}
|
||||||
<SearchLayout title="Tools">
|
|
||||||
<section slot="controls" class="controls">
|
|
||||||
<div class="inputs">
|
|
||||||
<Search
|
|
||||||
data={tools}
|
data={tools}
|
||||||
dataDefault={{ category: '' }}
|
displayTitle="Tools"
|
||||||
bind:query={searchValue}
|
displayTitleSingular="tool"
|
||||||
sortableFields={[
|
submittingType="tool"
|
||||||
{ 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>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user