kopia lustrzana https://github.com/learn-awesome/learndb
Combobox fix, map fix, tag search
rodzic
b420ed03ca
commit
7c1ab1afb7
|
@ -10,28 +10,27 @@
|
|||
let query = {
|
||||
text: "",
|
||||
topic: "",
|
||||
format: "",
|
||||
level: "",
|
||||
tags: "",
|
||||
tag: "",
|
||||
sortby: "rating"
|
||||
};
|
||||
|
||||
$: fetch(`/learn/items.json?_shape=array&links__contains=${format}|`)
|
||||
$: query && fetch(`/learn/items.json?_shape=array&_size=100&links__contains=${format}|&topics__contains=${query.topic}`)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
items = data;
|
||||
});
|
||||
|
||||
function handleQueryChanged(event){
|
||||
console.log("queryChanged: ", event.detail);
|
||||
// console.log("queryChanged: ", event.detail);
|
||||
query = event.detail;
|
||||
}
|
||||
|
||||
$: filteredItems = items.filter(item => {
|
||||
if(query.text && !item.name.toLowerCase().includes(query.text.toLowerCase())){ return false; }
|
||||
if(query.format && !item.links.includes(query.format)) { return false; }
|
||||
if(query.topic && !item.topics.includes(query.topic)){ return false; }
|
||||
if(query.level && item.difficulty != query.level){ return false; }
|
||||
// TODO Apply tags filter
|
||||
if(query.tag && !item.tags.includes(query.tag)){ return false; }
|
||||
return true;
|
||||
}).sort((a,b) => {
|
||||
if(query.sortby == 'rating') { return (a.rating - b.rating) };
|
||||
|
|
|
@ -3,16 +3,12 @@
|
|||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let alltopics;
|
||||
export let hideFormat = false;
|
||||
export let hideTopic = false;
|
||||
export let hideQuality = true;
|
||||
|
||||
let query = {
|
||||
text: "",
|
||||
topic: "",
|
||||
format: "",
|
||||
level: "",
|
||||
quality: "",
|
||||
sortby: "rating",
|
||||
tag: ""
|
||||
};
|
||||
|
@ -24,24 +20,19 @@
|
|||
</script>
|
||||
|
||||
<form class="w-full p-2 inline-flex flex-wrap" on:submit|preventDefault>
|
||||
<sl-input type="search" placeholder="Type something to search items by keywords" size="medium" clearable class="flex-1 border-0 p-0 focus:ring-0" value={query.text} on:sl-input="{e => query.text = e.target.value}">
|
||||
<sl-input type="search" placeholder="Search by keywords" size="medium" clearable class="flex-1 border-0 p-0 focus:ring-0" value={query.text} on:sl-input="{e => query.text = e.target.value}">
|
||||
<sl-icon name="search" slot="prefix"></sl-icon>
|
||||
</sl-input>
|
||||
|
||||
{#if !hideTopic}
|
||||
<ComboBox options={alltopics.map(t => { return {label: t.display_name, value: t.name}; }).sort((a,b) => a.label.localeCompare(b.label)).slice(0,10)} selected={null}/>
|
||||
<fluent-combobox autocomplete="both" placeholder="Any topic" class="ml-2 mt-1 outline-none border-2 border-grey-600" on:change="{e => query.topic = e.target.value}">
|
||||
{#each alltopics.sort((a,b) => a.display_name.localeCompare(b.display_name)) as topic}
|
||||
<fluent-option value={topic.name}>{topic.display_name}</fluent-option>
|
||||
{/each}
|
||||
</fluent-combobox>
|
||||
{/if}
|
||||
|
||||
{#if !hideFormat}
|
||||
<sl-select class="ml-2 w-44" on:sl-change="{e => query.format = e.target.value}" value={query.format}>
|
||||
<sl-menu-item value="">Any format</sl-menu-item>
|
||||
<sl-menu-item value="book">Books</sl-menu-item>
|
||||
<sl-menu-item value="video">Videos</sl-menu-item>
|
||||
<sl-menu-item value="audio">Podcasts</sl-menu-item>
|
||||
</sl-select>
|
||||
{/if}
|
||||
|
||||
<sl-select class="ml-2 w-44" on:sl-change="{e => query.tag = e.target.value}" value={query.tag}>
|
||||
<sl-select class="ml-2 w-52" on:sl-change="{e => query.tag = e.target.value}" value={query.tag}>
|
||||
<sl-menu-item value="">Any tag</sl-menu-item>
|
||||
<sl-menu-item value="inspirational">Inspirational</sl-menu-item>
|
||||
<sl-menu-item value="educational">Educational</sl-menu-item>
|
||||
|
@ -49,6 +40,7 @@
|
|||
<sl-menu-item value="entertaining">Entertaining</sl-menu-item>
|
||||
<sl-menu-item value="visual">Visual</sl-menu-item>
|
||||
<sl-menu-item value="interactive">Interactive</sl-menu-item>
|
||||
<sl-menu-item value="oer">Open (no login or pay)</sl-menu-item>
|
||||
</sl-select>
|
||||
|
||||
<sl-select class="ml-2 w-44" on:sl-change="{e => query.level = e.target.value}" value={query.level}>
|
||||
|
@ -60,15 +52,6 @@
|
|||
<sl-menu-item value="research">Research</sl-menu-item>
|
||||
</sl-select>
|
||||
|
||||
{#if !hideQuality}
|
||||
<sl-select class="ml-2 w-44" on:sl-change="{e => query.quality = e.target.value}" value={query.quality}>
|
||||
<sl-menu-item value="">Any quality</sl-menu-item>
|
||||
<sl-menu-item value="visual">Visual</sl-menu-item>
|
||||
<sl-menu-item value="interactive">Interactive</sl-menu-item>
|
||||
<sl-menu-item value="entertaining">Entertaining</sl-menu-item>
|
||||
</sl-select>
|
||||
{/if}
|
||||
|
||||
<sl-select class="ml-2 w-52" on:sl-change="{e => query.sortby = e.target.value}" value={query.sortby}>
|
||||
<sl-icon name="sort-down-alt" slot="prefix"></sl-icon>
|
||||
<sl-menu-item value="rating">Sort by Rating</sl-menu-item>
|
||||
|
|
|
@ -14,9 +14,8 @@
|
|||
let query = {
|
||||
text: "",
|
||||
topic: "",
|
||||
format: "",
|
||||
level: "",
|
||||
tags: "",
|
||||
tag: "",
|
||||
sortby: "rating"
|
||||
};
|
||||
|
||||
|
@ -28,15 +27,14 @@
|
|||
});
|
||||
|
||||
function handleQueryChanged(event){
|
||||
console.log("queryChanged: ", event.detail);
|
||||
// console.log("queryChanged: ", event.detail);
|
||||
query = event.detail;
|
||||
}
|
||||
|
||||
$: filteredItems = items.filter(item => {
|
||||
if(query.text && !item.name.toLowerCase().includes(query.text.toLowerCase())){ return false; }
|
||||
if(query.format && !item.links.includes(query.format)) { return false; }
|
||||
if(query.level && item.difficulty != query.level){ return false; }
|
||||
// TODO: apply tags filter
|
||||
if(query.tag && !item.tags.includes(query.tag)){ return false; }
|
||||
return true;
|
||||
}).sort((a,b) => {
|
||||
if(query.sortby == 'rating') { return (a.rating - b.rating) };
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
</script>
|
||||
|
||||
<div class="flex justify-end">
|
||||
<a href="#/map" class="underline hover:scale-110 px-3 py-2 hover:ease-in-out transition duration-200">Try mapview (beta)</a>
|
||||
<a href="#/map" class="font-semibold bg-lightTertiary text-lightBg rounded-lg hover:scale-110 px-3 py-2 hover:ease-in-out transition duration-200">Explore Map</a>
|
||||
</div>
|
||||
<TopicMasonryGrid {alltopics}/>
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
</sl-breadcrumb>
|
||||
</div>
|
||||
|
||||
<div class="gap-8 columns-1 sm:columns-2 lg:columns-3 xl:columns-4 2xl:columns-5 mb-8">
|
||||
<div class="gap-8 columns-1 sm:columns-2 lg:columns-3 xl:columns-4 3xl:columns-5 mb-8">
|
||||
{#each [...map.entries()].sort((t1,t2) => (t1[0].sort_index || 100) - (t2[0].sort_index || 100)) as parent}
|
||||
<a href={"#/topic/" + parent[0].name}>
|
||||
<div class="rounded-lg shadow-md p-4 break-inside-avoid mb-4 border-8 border-lightPrimCont dark:border-darkPrimCont hover:bg-lightPrimCont dark:bg-darkPrimCont ">
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
<script>
|
||||
export let options = [];
|
||||
let userInput = '3';
|
||||
export let userInput = '';
|
||||
$: filteredOptions = options.filter(x => x.label.startsWith(userInput))
|
||||
$: console.log(userInput)
|
||||
$: console.log({options})
|
||||
$: console.log(filteredOptions)
|
||||
$: console.log({userInput})
|
||||
</script>
|
||||
|
||||
<sl-dropdown>
|
||||
<sl-input slot="trigger" on:change="{e => userInput = e.target.value}" value={userInput}></sl-input>
|
||||
<sl-dropdown class="ml-2">
|
||||
<sl-input
|
||||
slot="trigger"
|
||||
class="p-0 m-0 border-0"
|
||||
on:sl-input="{e => userInput = e.target.value}"
|
||||
value={userInput}
|
||||
placeholder="select topic">
|
||||
</sl-input>
|
||||
|
||||
<sl-menu>
|
||||
{#each filteredOptions as opt (opt.value)}
|
||||
<sl-menu-item>{opt.label}</sl-menu-item>
|
||||
<sl-menu-item on:click="{e => userInput = opt.value}">{opt.label}</sl-menu-item>
|
||||
{/each}
|
||||
</sl-menu>
|
||||
</sl-dropdown>
|
||||
|
|
|
@ -23,6 +23,8 @@ body {
|
|||
|
||||
text {
|
||||
cursor: pointer;
|
||||
fill: #7a28cb;
|
||||
|
||||
}
|
||||
|
||||
.grandparent text {
|
||||
|
@ -40,11 +42,11 @@ rect.parent,
|
|||
}
|
||||
|
||||
.grandparent rect {
|
||||
fill: rgb(232, 255, 0);
|
||||
fill: #f4b393;
|
||||
}
|
||||
|
||||
.grandparent:hover rect {
|
||||
fill: rgb(202, 225, 0);
|
||||
fill: #f4d393;
|
||||
}
|
||||
|
||||
.children rect.parent,
|
||||
|
@ -54,21 +56,21 @@ rect.parent,
|
|||
|
||||
.leaf rect.parent {
|
||||
cursor: pointer;
|
||||
fill: #c9d9ff;
|
||||
fill: #ffdbd1;
|
||||
}
|
||||
|
||||
.leaf rect.parent:hover {
|
||||
cursor: pointer;
|
||||
fill: #d9e9ff;
|
||||
fill: #ffcfd4;
|
||||
}
|
||||
|
||||
.children rect.parent {
|
||||
fill: #99F6E4;
|
||||
fill: #ceec97;
|
||||
fill-opacity: .5;
|
||||
}
|
||||
|
||||
.children:hover rect.child {
|
||||
fill: #D7CBFA;
|
||||
fill: #deec97;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@ -88,8 +90,8 @@ function hierarchy(topic_array, parent_id){
|
|||
.map(item => ({ ...item, children: nest(items, item.name), value: 100 }))
|
||||
.map(item => {
|
||||
return item.children.length == 0 ?
|
||||
{id: item.name, name: item.name.split("/").reverse()[0], value: 100} :
|
||||
{id: item.name, name: item.name.split("/").reverse()[0], children: item.children}
|
||||
{id: item.name, name: item.name, value: 100} :
|
||||
{id: item.name, name: item.name, children: item.children}
|
||||
});
|
||||
|
||||
let topnodes = nest(topic_array, ''); // includes childless nodes
|
||||
|
@ -98,7 +100,7 @@ function hierarchy(topic_array, parent_id){
|
|||
let misc = {id: 'misc', name: 'Misc', children: topnodes.filter(t => t.value).slice(0,15)};
|
||||
|
||||
|
||||
return {name: "·", children: [...topnodes.filter(t => t.children), misc]};
|
||||
return {name: "", children: [...topnodes.filter(t => t.children), misc]};
|
||||
}
|
||||
|
||||
d3.json("/learn/topics.json?_shape=array&_size=5000", function(alltopics){
|
||||
|
@ -232,7 +234,7 @@ grandparent.append("text")
|
|||
g.append("text")
|
||||
.attr("dy", ".75em")
|
||||
.on("click", (n) => { window.parent.location.href = "/#/topic/" + n.name;})
|
||||
.text(function(d) { return d.name.split('{')[0].split('(')[0]
|
||||
.text(function(d) { return d.name.split('/').reverse()[0].split('{')[0].split('(')[0]
|
||||
.split('[')[0]; })
|
||||
.call(text);
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
<link href="/static/bundle.css" rel="stylesheet" />
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.73/dist/themes/light.css" />
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.0.0-beta.73/dist/shoelace.js"></script>
|
||||
<script type="module" src="https://unpkg.com/@fluentui/web-components"></script>
|
||||
<title>LearnAwesome</title>
|
||||
|
||||
<!-- fonts -->
|
||||
|
|
Ładowanie…
Reference in New Issue