Authenticated with GitHub
@@ -15,7 +15,7 @@
diff --git a/modules/gui/src/components/SearchPackages/SearchPackages.svelte b/modules/gui/src/components/SearchPackages/SearchPackages.svelte
index 7b1cbca..f18230b 100644
--- a/modules/gui/src/components/SearchPackages/SearchPackages.svelte
+++ b/modules/gui/src/components/SearchPackages/SearchPackages.svelte
@@ -1,21 +1,16 @@
diff --git a/modules/gui/src/components/SearchPopupResults/SearchPopupResults.svelte b/modules/gui/src/components/SearchPopupResults/SearchPopupResults.svelte
new file mode 100644
index 0000000..2444caa
--- /dev/null
+++ b/modules/gui/src/components/SearchPopupResults/SearchPopupResults.svelte
@@ -0,0 +1,160 @@
+
+
+
+
+
+
+
+
+
+ Top Package Results ({packages.length})
+
+
+ {#if packages.length > 0}
+ {#each packages as pkg}
+
+
{
+ try {
+ pkg.state = PackageStates.INSTALLING;
+ await installPackage(pkg.full_name);
+ pkg.state = PackageStates.INSTALLED;
+ } catch (error) {
+ console.error(error);
+ }
+ }}
+ />
+
+ {/each}
+ {:else if loading}
+ {#each Array(12) as _}
+
+ {/each}
+ {/if}
+
+
+ Top Article Results ({articles.length})
+
+ {#if articles.length}
+
+ {:else if loading}
+
+ {/if}
+
+ Top Workshop Results ({workshops.length})
+
+ {#if workshops.length}
+
+ {:else if loading}
+
+ {/if}
+
+
+
+
diff --git a/modules/gui/src/libs/api/tauri.ts b/modules/gui/src/libs/api/tauri.ts
index 3747ae1..af8e6d3 100644
--- a/modules/gui/src/libs/api/tauri.ts
+++ b/modules/gui/src/libs/api/tauri.ts
@@ -26,7 +26,8 @@ async function get
(path: string, query?: { [key: string]: string }) {
const uri = join(base, path);
const { data } = await client.get(uri.toString(), {
headers: {
- Authorization: 'public' // TODO: figure out why req w/o Authorization does not work
+ Authorization: 'public', // TODO: figure out why req w/o Authorization does not work
+ 'cache-control': 'no-cache'
},
query: query || {}
});
@@ -151,9 +152,9 @@ export async function getTopPackages(): Promise {
return packages;
}
-export async function getAllPosts(tag: string): Promise {
+export async function getAllPosts(tag?: string): Promise {
// add filter here someday: tag = news | course
- const posts = await get('posts', { tag });
+ const posts = await get('posts', tag ? { tag } : {});
return posts;
}
diff --git a/modules/gui/src/libs/stores.ts b/modules/gui/src/libs/stores.ts
index 60dbe7b..8abb466 100644
--- a/modules/gui/src/libs/stores.ts
+++ b/modules/gui/src/libs/stores.ts
@@ -1,21 +1,49 @@
import { writable } from 'svelte/store';
-import type { Package, Review } from '@tea/ui/types';
+import Fuse from 'fuse.js';
+
+import type { Package, Review, AirtablePost } from '@tea/ui/types';
import type { GUIPackage } from '$libs/types';
// TODO: figure out a better structure for managing states maybe turn them into models?
-import { getPackages, getFeaturedPackages, getPackageReviews } from '@api';
+import { getPackages, getFeaturedPackages, getPackageReviews, getAllPosts } from '@api';
export const backLink = writable('/');
-export const packages = writable([]);
-
export const featuredPackages = writable([]);
-export const initializePackages = async () => {
- console.log('initialize packages');
- const newPackages = await getPackages();
- packages.set(newPackages);
-};
+function initPackagesStore() {
+ let initialized = false;
+ const { subscribe, set } = writable([]);
+ const packages: GUIPackage[] = [];
+ let packagesIndex: Fuse;
+
+ if (!initialized) {
+ initialized = true;
+ getPackages().then((pkgs) => {
+ set(pkgs);
+ packagesIndex = new Fuse(pkgs, {
+ keys: ['name', 'full_name', 'desc']
+ });
+ });
+ }
+
+ subscribe((v) => packages.push(...v));
+
+ return {
+ packages,
+ subscribe,
+ search: async (term: string, limit = 5): Promise => {
+ if (!term || !packagesIndex) return [];
+ // TODO: if online, use algolia else use Fuse
+
+ const res = packagesIndex.search(term, { limit });
+ const matchingPackages: GUIPackage[] = res.map((v) => v.item);
+ return matchingPackages;
+ }
+ };
+}
+
+export const packagesStore = initPackagesStore();
export const initializeFeaturedPackages = async () => {
console.log('initialzie featured packages');
@@ -60,3 +88,81 @@ function initPackagesReviewStore() {
}
export const packagesReviewStore = initPackagesReviewStore();
+
+function initPosts() {
+ let initialized = false;
+ const { subscribe, set } = writable([]);
+ const posts: AirtablePost[] = [];
+ let postsIndex: Fuse;
+
+ if (!initialized) {
+ initialized = true;
+ getAllPosts().then(set);
+ }
+
+ subscribe((v) => {
+ posts.push(...v);
+ postsIndex = new Fuse(posts, {
+ keys: ['title', 'sub_title', 'short_description', 'tags']
+ });
+ });
+
+ return {
+ subscribe,
+ search: async (term: string, limit = 10) => {
+ const res = postsIndex.search(term, { limit });
+ const matchingPosts: AirtablePost[] = res.map((v) => v.item);
+ return matchingPosts;
+ }
+ };
+}
+export const postsStore = initPosts();
+
+function initSearchStore() {
+ const searching = writable(false);
+ const { subscribe, set } = writable('');
+ const packagesSearch = writable([]);
+ const postsSearch = writable([]);
+
+ // TODO:
+ // add fuse.js index here: packages, articles/posts, etc
+ // define fuse.js shape { tags:[], desc:string, title: string, thumb_image_url: string }
+ // should use algolia if user is somehow online
+
+ const packagesFound: GUIPackage[] = [];
+
+ let term = '';
+
+ subscribe((v) => (term = v));
+ packagesSearch.subscribe((v) => packagesFound.push(...v));
+
+ return {
+ term,
+ searching,
+ packagesSearch,
+ postsSearch,
+ packagesFound,
+ subscribe,
+ search: async (term: string) => {
+ searching.set(true);
+ try {
+ if (term) {
+ const [resultPkgs, resultPosts] = await Promise.all([
+ packagesStore.search(term, 5),
+ postsStore.search(term, 10)
+ ]);
+ packagesSearch.set(resultPkgs);
+ postsSearch.set(resultPosts);
+ } else {
+ packagesSearch.set([]);
+ postsSearch.set([]);
+ }
+ set(term);
+ } finally {
+ searching.set(false);
+ }
+ }
+ };
+}
+
+export const searchStore = initSearchStore();
diff --git a/modules/gui/src/routes/+layout.svelte b/modules/gui/src/routes/+layout.svelte
index 9ebd22d..fa7a693 100644
--- a/modules/gui/src/routes/+layout.svelte
+++ b/modules/gui/src/routes/+layout.svelte
@@ -6,6 +6,7 @@
import FooterLinks from '$components/FooterLinks/FooterLinks.svelte';
import { backLink as backLinkStore } from '$libs/stores';
+ import SearchPopupResults from '$components/SearchPopupResults/SearchPopupResults.svelte';
let view: HTMLElement;
@@ -36,6 +37,7 @@
+
@@ -56,15 +58,17 @@
overflow-y: scroll;
}
+ figure {
+ z-index: 0;
+ position: fixed;
+ top: 220px;
+ left: 240px;
+ right: 0px;
+ bottom: 0px;
+ background-image: url('/images/gui-background-grid.svg');
+ }
@media screen and (min-width: 1440px) {
figure {
- position: fixed;
- z-index: 0;
- top: 220px;
- left: 240px;
- right: 0px;
- bottom: 0px;
- background-image: url('/images/gui-background-grid.svg');
background-size: cover;
background-repeat: repeat-y;
}
@@ -74,13 +78,6 @@
}
@media screen and (max-width: 1440px) {
figure {
- position: fixed;
- z-index: 0;
- top: 220px;
- left: 240px;
- right: 0px;
- bottom: 0px;
- background-image: url('/images/gui-background-grid.svg');
background-size: contain;
background-repeat: repeat;
}
diff --git a/modules/gui/src/routes/packages/[slug]/+page.svelte b/modules/gui/src/routes/packages/[slug]/+page.svelte
index 710c62e..d6bc051 100644
--- a/modules/gui/src/routes/packages/[slug]/+page.svelte
+++ b/modules/gui/src/routes/packages/[slug]/+page.svelte
@@ -9,7 +9,7 @@
/** @type {import('./$types').PageData} */
export let data;
- import { packages, featuredPackages } from '$libs/stores';
+ import { packagesStore, featuredPackages } from '$libs/stores';
import type { Package } from '@tea/ui/types';
@@ -30,7 +30,7 @@
// }
};
- packages.subscribe(setPkg);
+ packagesStore.subscribe(setPkg);
featuredPackages.subscribe(setPkg);