kopia lustrzana https://github.com/learn-awesome/learndb
hierarchy fix
rodzic
22fba5454d
commit
f8d72b7607
2970
db/topics.csv
2970
db/topics.csv
Plik diff jest za duży
Load Diff
BIN
learn.db
BIN
learn.db
Plik binarny nie jest wyświetlany.
|
@ -4,5 +4,6 @@
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"license_url": "",
|
"license_url": "",
|
||||||
"source": "LearnAwesome.org",
|
"source": "LearnAwesome.org",
|
||||||
"source_url": "https://learnawesome.org/"
|
"source_url": "https://learnawesome.org/",
|
||||||
|
"max_returned_rows": 20000
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"max_returned_rows": 20000
|
||||||
|
}
|
|
@ -57,7 +57,7 @@
|
||||||
{:else if currentView === "/topics"}
|
{:else if currentView === "/topics"}
|
||||||
<TopicList/>
|
<TopicList/>
|
||||||
{:else if currentView.startsWith("/topic/")}
|
{:else if currentView.startsWith("/topic/")}
|
||||||
<TopicDetail topicid={currentView.split("/")[2]}/>
|
<TopicDetail topicname={currentView.split("/")[2]}/>
|
||||||
{:else if currentView === "/formats"}
|
{:else if currentView === "/formats"}
|
||||||
<FormatList/>
|
<FormatList/>
|
||||||
{:else if currentView.startsWith("/format/")}
|
{:else if currentView.startsWith("/format/")}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
item = data[itemid];
|
item = data[itemid];
|
||||||
console.log(item)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
import ItemCard from "./ItemCard.svelte"
|
import ItemCard from "./ItemCard.svelte"
|
||||||
import TopicMasonryGrid from "./TopicMasonryGrid.svelte"
|
import TopicMasonryGrid from "./TopicMasonryGrid.svelte"
|
||||||
|
|
||||||
export let topicid;
|
export let topicname;
|
||||||
let items = [];
|
let items = [];
|
||||||
|
|
||||||
$: fetch(`/learn/items.json?_shape=array&topics__contains=${topicid}`)
|
$: fetch(`/learn/items.json?_shape=array&topics__contains=${topicname}`)
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
items = data;
|
items = data;
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<TopicMasonryGrid {topicid}/>
|
<TopicMasonryGrid {topicname}/>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
<div class="grid grid-cols-1 gap-6 lg:grid-cols-2">
|
||||||
{#each items as item}
|
{#each items as item}
|
||||||
|
|
|
@ -1,52 +1,97 @@
|
||||||
<script>
|
<script>
|
||||||
import Masonry from './Masonry.svelte'
|
import Masonry from './Masonry.svelte'
|
||||||
export let topicid; // undefined for top level
|
export let topicname; // undefined for top level
|
||||||
let topic;
|
let topic;
|
||||||
let alltopics = [];
|
let alltopics = [];
|
||||||
let tree = new Map();
|
let map = new Map();
|
||||||
|
|
||||||
function hierarchy(topics, rootid){
|
function capitalize(str){
|
||||||
// rootid can be null
|
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||||
let hier = topics.reduce((map, topic) => {
|
|
||||||
if(topic.first_parent_topic_id == rootid) {
|
|
||||||
map.set(topic, []);
|
|
||||||
} else {
|
|
||||||
let parent = [...map.keys()].find(t => t.id == topic.first_parent_topic_id)
|
|
||||||
if(parent) map.set(parent, [...map.get(parent), topic])
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}, new Map())
|
|
||||||
|
|
||||||
return hier
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$: fetch(`/learn/topics.json?_shape=array`)
|
function format_topic_name(topic){
|
||||||
|
if(topic.display_name == undefined){
|
||||||
|
return capitalize(topic);
|
||||||
|
}
|
||||||
|
if(topic.display_name.includes("/")){
|
||||||
|
return capitalize(topic.display_name.split("/")[1]);
|
||||||
|
} else {
|
||||||
|
return capitalize(topic.display_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function hierarchy(topic_array, parent_id){
|
||||||
|
let tempmap = new Map();
|
||||||
|
// first pass to find all top-level objects
|
||||||
|
let parentids = [];
|
||||||
|
for(let i = 0; i < topic_array.length; i++){
|
||||||
|
if(topic_array[i].parent_id == parent_id){
|
||||||
|
tempmap.set(topic_array[i], []);
|
||||||
|
parentids.push(topic_array[i].id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(tempmap);
|
||||||
|
|
||||||
|
// second pass for their children
|
||||||
|
for(let i = 0; i < topic_array.length; i++){
|
||||||
|
if(parentids.includes(topic_array[i].parent_id)){
|
||||||
|
tempmap.get(topic_array.find(t => t.id == topic_array[i].parent_id)).push(topic_array[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// console.log(tempmap);
|
||||||
|
|
||||||
|
// Now move child-less top-level objects under Misc
|
||||||
|
let count = [...tempmap.keys()].filter(k => tempmap.get(k).length == 0).length;
|
||||||
|
console.log({count}, tempmap.size);
|
||||||
|
if(count > 15){
|
||||||
|
console.log("pruning")
|
||||||
|
let misc = [];
|
||||||
|
[...tempmap.keys()].forEach(key => {
|
||||||
|
if(tempmap.get(key).length == 0) {
|
||||||
|
console.log({key});
|
||||||
|
misc.push(key);
|
||||||
|
tempmap.delete(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tempmap.set('Misc', misc.slice(0,15));
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log(tempmap);
|
||||||
|
return tempmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
$: fetch(`/learn/topics.json?_shape=array&_size=5000`)
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
topic = data.find(t => t.id == topicid)
|
topic = data.find(t => t.name == topicname)
|
||||||
alltopics = data;
|
alltopics = data;
|
||||||
});
|
});
|
||||||
|
|
||||||
$: tree = hierarchy(alltopics, topic?.id || "")
|
$: map = hierarchy(alltopics, topic?.id || "")
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if topic}
|
|
||||||
<h1 class="text-2xl font-bold">{topic.display_name}</h1>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if [...tree.keys()].length > 0}
|
<h1 class="text-2xl font-bold">
|
||||||
|
{#if topic}
|
||||||
|
{capitalize(topic.display_name)}
|
||||||
|
{:else}
|
||||||
|
All Topics
|
||||||
|
{/if}
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
|
||||||
<Masonry gridGap={'0.75rem'}>
|
<Masonry gridGap={'0.75rem'}>
|
||||||
{#each [...tree.keys()] as parent}
|
{#each [...map.entries()] as parent}
|
||||||
<div class="bg-white rounded-lg px-4 py-4 shadow-lg focus:outline-none">
|
<div class="bg-white rounded-lg px-4 py-4 shadow-lg focus:outline-none">
|
||||||
<a href={"#/topic/" + parent.id}><span class="mt-1 p-1 text-gray-900 font-semibold text-lg">{ parent.display_name }</span></a>
|
<a href={"#/topic/" + parent[0]?.name || parent}><span class="mt-1 p-1 text-gray-900 font-semibold text-lg">{ format_topic_name(parent[0]) }</span></a>
|
||||||
|
|
||||||
<div class="mt-2 flex flex-wrap text-sm text-gray-900">
|
<div class="mt-2 flex flex-wrap text-sm text-gray-900">
|
||||||
{#each tree.get(parent) as child}
|
{#each parent[1] as child}
|
||||||
<a href={"#/topic/" + child.id} class="text-purple-600 no-underline hover:underline hover:text-purple-900 px-2">{child.display_name}</a>
|
<a href={"#/topic/" + child.name} class="text-purple-600 no-underline hover:underline hover:text-purple-900 px-2">{format_topic_name(child)}</a>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</Masonry>
|
</Masonry>
|
||||||
{/if}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
export default alltopics = {
|
||||||
|
science: {
|
||||||
|
name: "Science",
|
||||||
|
physics: {
|
||||||
|
name: "Physics"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
maths: {
|
||||||
|
name: "Maths",
|
||||||
|
algebra: {}
|
||||||
|
},
|
||||||
|
|
||||||
|
humanities: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Ładowanie…
Reference in New Issue