Merge pull request #34 from cssbubble/main

issue #33 closed
pull/35/head^2
Nilesh 2022-06-09 12:28:22 +01:00 zatwierdzone przez GitHub
commit 23cd0a3115
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
9 zmienionych plików z 252 dodań i 296 usunięć

Wyświetl plik

@ -13,13 +13,13 @@
var saturation = randint(0,100)
var lightness = randint(0,100)
tailwind.config.theme.extend.colors.lightPrimary = `hsl(${hues[0]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightSecondary = `hsl(${hues[1]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightTertiary = `hsl(${hues[2]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightBg = `hsl(${hues[3]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightPrimCont = `hsl(${hues[4]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightButtonBg = `hsl(${hues[5]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.light = `hsl(${hues[6]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.primary = `hsl(${hues[0]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.primary_light = `hsl(${hues[1]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.neutral_light = `hsl(${hues[2]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.neutral_dark = `hsl(${hues[3]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.secondary = `hsl(${hues[4]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightGradOne = `hsl(${hues[5]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.lightGradTwo = `hsl(${hues[6]}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.darkPrimary = `hsl(${(hues[0] + 180) % 360}, ${saturation}%, ${lightness}%)`;
tailwind.config.theme.extend.colors.darkSecondary = `hsl(${(hues[1] + 180) % 360}, ${saturation}%, ${lightness}%)`;
@ -34,43 +34,44 @@
</script>
<div >
<div class="md:pl-64 flex flex-col flex-1">
<div class="sticky top-0 z-10 flex-shrink-0 flex text-primary_light bg-primary shadow">
{#if isNavDrawerOpen == false}
<button on:click={e => isNavDrawerOpen = true} type="button" class="px-4 border-r border-primary_light text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Open sidebar</span>
<Icon kind="menu"/>
</button>
{/if}
<!-- sticky top bar -->
<div class="sticky top-0 z-10 flex-shrink-0 flex text-primary_light bg-primary shadow">
{#if isNavDrawerOpen == false}
<button on:click={e => isNavDrawerOpen = true} type="button" class="px-4 border-r border-primary_light text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Open sidebar</span>
<Icon kind="menu"/>
</button>
{/if}
{#if isNavDrawerOpen}
<button on:click={e => isNavDrawerOpen = false} type="button" class="px-4 border-r border-primary_light text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Close sidebar</span>
<Icon kind="close"/>
</button>
{/if}
{#if isNavDrawerOpen}
<button on:click={e => isNavDrawerOpen = false} type="button" class="px-4 border-r border-primary_light text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Close sidebar</span>
<Icon kind="close"/>
</button>
{/if}
<div class="md:hidden py-3 flex flex-col items-center flex-shrink-0 px-4 tracking-wider font-bold group">
<a href="/" class="">LearnAwesome</a>
<div class="w-1/5 mt-0.25 h-0.5 bg-primary group-hover:w-full ease-in-out duration-300"></div>
</div>
<div class="flex-1 flex justify-between">
{#if showNotificationBell || showProfileMenu}
<div class="ml-4 flex items-center md:ml-6">
{#if showNotificationBell}
<button type="button" class="bg-white p-1 rounded-full text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<span class="sr-only">View notifications</span>
<Icon kind="bell"/>
</button>
{/if}
</div>
{/if}
</div>
<div class=" py-3 flex flex-col items-center flex-shrink-0 px-4 tracking-wider font-bold group">
<a href="/" class="">LearnAwesome</a>
<div class="w-1/5 mt-0.25 h-0.5 bg-primary group-hover:w-full ease-in-out duration-300"></div>
</div>
<div class="flex-1 flex justify-between">
{#if showNotificationBell || showProfileMenu}
<div class="ml-4 flex items-center md:ml-6">
{#if showNotificationBell}
<button type="button" class="bg-white p-1 rounded-full text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<span class="sr-only">View notifications</span>
<Icon kind="bell"/>
</button>
{/if}
</div>
{/if}
</div>
</div>
<!-- main container -->
<div class="md:pl-64 flex flex-col flex-1">
<!-- content -->
<main class="">
<div class="py-6">
@ -87,20 +88,6 @@
<div class="fixed inset-y-0 left-0 flex z-50 mt-12">
<div class="relative flex-1 flex flex-col w-64 w-full pt-5 pb-4 bg-primary_light text-primary dark:bg-neutral_dark dark:text-primary_light">
<!-- <div class="absolute top-0 right-0 -mr-12 pt-2"> -->
<!-- <button on:click={e => isNavDrawerOpen = false} type="button" class="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
<span class="sr-only">Close sidebar</span> -->
<!-- Heroicon name: outline/x -->
<!-- <svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button> -->
<!-- </div> -->
<!-- <div class="flex-shrink-0 flex items-center tracking-wider font-bold text-lightPrimCont">
<a href="#/" class="">LearnAwesome</a>
</div> -->
<div class="md:ml-6 flex-1 h-0 overflow-y-auto">
<nav class="px-4 space-y-1" on:click={e => isNavDrawerOpen = false}>
<slot name="nav"></slot>
@ -110,24 +97,20 @@
</nav>
</div>
</div>
<!-- <div class="flex-shrink-0 w-14" aria-hidden="true"> -->
<!-- Dummy element to force sidebar to shrink to fit close icon -->
<!-- </div> -->
</div>
</div>
{/if}
<!-- Static sidebar for desktop -->
<div class="hidden md:flex md:w-64 md:flex-col md:fixed md:inset-y-0">
<!-- Sidebar component, swap this element with another sidebar if you like -->
<div class="flex flex-col flex-grow pt-5 border-r-8 overflow-y-auto">
<div class="flex flex-col items-center flex-shrink-0 px-4 tracking-wider font-bold text-primary">
<!-- Sidebar component -->
<div class="flex flex-col flex-grow border-r-8 overflow-y-auto">
<!-- <div class="flex flex-col items-center flex-shrink-0 px-4 tracking-wider font-bold text-primary">
<a href="/" class="">LearnAwesome</a>
<div class="w-1/5 mt-0.25 h-0.5 bg-primary group-hover:w-full ease-in-out duration-300"></div>
</div>
<div class="mt-5 flex-1 flex flex-col bg-primary_light text-primary">
<nav class="flex-1 pb-4 space-y-1">
</div> -->
<div class="mt-12 flex-1 flex flex-col bg-primary_light text-primary">
<nav class="flex-1 pb-4 space-y-1 pt-5">
<slot name="nav"></slot>
{#if window.location.href.startsWith('http://127.0.0.1')}
<button class="" on:click={themeRandomize}>Randomize</button>

Wyświetl plik

@ -2,8 +2,8 @@
export let item;
</script>
<a class="relative flex flex-col sm:w-44 items-center mb-4 rounded-md overflow-hidden transform transition ease-out duration-300 hover:bg-lightSecondary2 drop-shadow-lg hover:drop-shadow-2xl hover:scale-105 break-inside-avoid dark:bg-darkSecondaryBg dark:text-darkSecondary2" href="#/item/{item.rowid}">
<img class="object-cover sm:h-64 sm:w-44" src={item.image || '/static/book-cover.png'} alt="{item.name}"/>
<a class="relative flex flex-col lg:w-44 items-center mb-4 rounded-md overflow-hidden transform transition ease-out duration-300 drop-shadow-lg hover:drop-shadow-2xl hover:scale-105 break-inside-avoid" href="#/item/{item.rowid}">
<img class="object-cover h-36 w-24 lg:h-64 lg:w-44" src={item.image || '/static/book-cover.png'} alt="{item.name}"/>
{#if item.rating}
<h1 class="text-lg font-semibold p-2 text-white tracking-wider">
@ -13,8 +13,8 @@
{#if !item.image}
<div class="absolute inset-y-0 px-2 py-4 break-inside-avoid">
<p class="font-bold text-sm sm:font-extrabold text-white sm:text-xl">{item.name}</p>
<p class="text-sm text-white mt-3">{item.creators}</p>
<p class="font-bold text-xs lg:font-extrabold text-primary_light lg:text-xl">{item.name}</p>
<p class="text-xs text-primary_light mt-3">{item.creators}</p>
</div>
{/if}
</a>

Wyświetl plik

@ -56,7 +56,7 @@ import { fix_and_destroy_block } from "svelte/internal";
{/each}
</div>
{:else}
<div class="mt-12 mx-auto gap-5 flex flex-wrap">
<div class="mt-12 mx-auto gap-5 flex flex-wrap justify-center">
{#each filteredItems as item}
<ItemCard {item} displayType={format}/>
{/each}

Wyświetl plik

@ -5,10 +5,10 @@
<div class=" mx-auto flex flex-wrap gap-3 justify-center items-center">
{#each formats as format}
<a href="#/format/{format.id}" class="w-32 h-28 relative sm:w-64 flex flex-col rounded-lg shadow-md overflow-hidden transform transition ease-out duration-300 hover:scale-105 ">
<a href="#/format/{format.id}" class="w-32 h-28 relative flex flex-col rounded-lg shadow-md overflow-hidden transform transition ease-out duration-300 hover:scale-105 ">
<div class="flex-shrink-0">
<img class="w-32 h-28 object-cover" src={format.image} alt="">
<div class="absolute inset-0 bg-neutral_Light mix-blend-multiply"></div>
<div class="absolute inset-0 bg-neutral_light mix-blend-multiply"></div>
</div>
<div class="absolute flex justify-center items-center inset-0">
<h1 class="text-sm text-center md:text-lg font-semibold p-2 tracking-wider text-lightGradOne">{format.name}</h1>

Wyświetl plik

@ -2,6 +2,7 @@
import ButtonGroup from "./ButtonGroup.svelte";
import { bookmarks } from "./stores.js"
import Review from "./Review.svelte"
import AdvancedSearch from "./AdvancedSearch.svelte";
export let itemid;
let item;
@ -57,20 +58,6 @@
return wikiurl.replace('simple.wikipedia.org/','simple.m.wikipedia.org/').replace('en.wikipedia.org/','en.m.wikipedia.org/');
}
// function youtube_parser(url){
// var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
// var match = url.match(regExp);
// return (match&&match[7].length==11)? match[7] : false;
// }
// function get_thumbnail_image_url(item){
// let youtubeformat = item.links.split(";").find(s => s.startsWith('video|') && (s.includes('youtube.com') || s.includes('youtu.be')));
// let youtubeurl = youtubeformat && youtubeformat.split('|')[1];
// let ytid = youtubeurl && youtube_parser(youtubeurl);
// let thumbnail_image_url = ytid && `https://img.youtube.com/vi/${ytid}/mqdefault.jpg`
// return thumbnail_image_url
// }
</script>
<style>
@ -96,7 +83,7 @@
{#if item}
<div class="w-full px-6 py-4 mt-10 md:max-w-4xl mx-auto border shadow-2xl md:px-20 md:py-8 rounded-xl md:mt-20 bg-white font-sans">
<div class="w-full px-6 py-4 mt-10 lg:max-w-4xl mx-auto border shadow-2xl lg:px-20 lg:py-8 rounded-xl lg:mt-20 bg-primary_light font-sans">
<h3 class="my-2">
{#each item.topics.split(";") as topicname}
<div class="group inline-flex">
@ -108,103 +95,101 @@
</h3>
<div class="mt-10">
{#if !item.links.includes('video|') && oembed_iframe}
<div class="mb-10 flex flex-col sm:flex-row md:flex-col lg:flex-row">
<div class="flex-nowrap">
{#if item.image}
<div class="sm:mr-10">
<img class="mr-28 mb-6 sm:w-44 sm:h-64 transform rounded-md shadow-lg transition duration-300 ease-out hover:scale-105 md:shadow-xl " src="{item.image}" alt="{item.name}" />
</div>
<!-- {:else if item.links.includes('book')}
<img class="mr-6 mb-6 w-44 h-64 transform rounded-md shadow-md transition duration-300 ease-out hover:scale-105 md:shadow-xl" src="/static/book-cover.png" alt="{item.name}" /> -->
{:else if item.links.includes('video') }
<div class="relative mr-5 rounded-lg overflow-hidden shadow-lg">
<div class="w-80 h-60 bg-lightPrimary">
<img class="h-auto w-80 flex justify-center items-center border-r border-gray-500 relative" src="{oEmded_image_ytb_url}" alt="{item.name}">
<div class="mb-10 flex flex-wrap justify-start">
<div class="w-full">
{#if item.links.includes('wiki|')}
<iframe src={wikiUrlForEmbed(item)} class="w-full h-[48rem]" title="embedded wiki"></iframe>
{:else if item.links.includes('video|') && oembed_iframe}
{@html oembed_iframe.replace('width="200"','width="100%"').replace('height="113"','height="400"')}
{:else if item.image}
<div class="">
<img class="mr-5 mb-6 sm:w-44 sm:h-64 transform rounded-md shadow-lg transition duration-300 ease-out hover:scale-105 md:shadow-xl " src="{item.image}" alt="{item.name}" />
</div>
<div class="absolute inset-0 w-full h-full flex items-center justify-center" aria-hidden="true">
<svg class="h-12 w-12 text-indigo-500" fill="currentColor" viewBox="0 0 84 84"><circle opacity="0.9" cx="42" cy="42" r="42" fill="white"></circle><path d="M55.5039 40.3359L37.1094 28.0729C35.7803 27.1869 34 28.1396 34 29.737V54.263C34 55.8604 35.7803 56.8131 37.1094 55.9271L55.5038 43.6641C56.6913 42.8725 56.6913 41.1275 55.5039 40.3359Z"></path></svg>
{:else if item.links.includes('video') }
<div class="relative mr-5 rounded-lg overflow-hidden shadow-lg">
<div class="w-80 h-60">
<img class="h-auto w-80 flex justify-center items-center border-r border-gray-500 relative" src="{oEmded_image_ytb_url}" alt="{item.name}">
</div>
<div class="absolute inset-0 w-full h-full flex items-center justify-center" aria-hidden="true">
<svg class="h-12 w-12 text-indigo-500" fill="currentColor" viewBox="0 0 84 84"><circle opacity="0.9" cx="42" cy="42" r="42" fill="white"></circle><path d="M55.5039 40.3359L37.1094 28.0729C35.7803 27.1869 34 28.1396 34 29.737V54.263C34 55.8604 35.7803 56.8131 37.1094 55.9271L55.5038 43.6641C56.6913 42.8725 56.6913 41.1275 55.5039 40.3359Z"></path></svg>
</div>
</div>
</div>
{:else if !item.links.includes('video') && item.links.includes('book')}
<div class="sm:mr-10 relative">
<img class="mr-28 mb-6 h-auto transform rounded-md shadow-md transition duration-300 ease-out hover:scale-105 md:shadow-xl" src="/static/book-cover.png" alt="{item.name}" />
{:else if !item.links.includes('video') && item.links.includes('book')}
<div class="sm:mr-10 w-44 h-64 relative">
<img class="w-44 h-64 mr-28 mb-6 h-auto transform rounded-md shadow-md transition duration-300 ease-out hover:scale-105 md:shadow-xl" src="/static/book-cover.png" alt="{item.name}" />
<div class="absolute inset-y-0 pl-4 pr-6 py-4 break-inside-avoid">
<p class="font-bold text-white text-2xl">{item.name}</p>
<p class="text-sm text-white mt-3">{item.creators}</p>
<div class="absolute inset-y-0 pl-4 pr-6 py-4 break-inside-avoid">
<p class="font-bold text-white text-2xl">{item.name}</p>
<p class="text-sm text-white mt-3">{item.creators}</p>
</div>
</div>
{/if}
</div>
{/if}
<!-- <img class="mr-6 mb-6 w-44 h-64 transform rounded-md shadow-md transition duration-300 ease-out hover:scale-105 md:shadow-xl" src="{item.image || '/static/book-cover.png'}" alt="" /> -->
</div>
<!-- book details -->
<div class="flex w-full flex-col justify-between">
<!-- title, sub title, author -->
<section>
<h1 class="text-xl md:text-4xl font-extrabold">{item.name}</h1>
<span class="text-sm mt-5">{item.creators}</span>
<div class="mt-5">
<sl-rating readonly precision="0.1" value={item.rating}></sl-rating>
</div>
</section>
<!-- ratings and upload buttons -->
<div class="mt-2 mb-6 flex flex-col justify-between">
<div class="flex flex-wrap items-center justify-start gap-3 mt-5">
{#each item.links.split(";") as type}
<sl-button-group>
<sl-button size="small" href={type.split("|")[1]} target="_blank" class="linkButton">{type.split("|")[0]} at {get_tld(type.split("|")[1])} <sl-icon name="link-45deg"></sl-icon></sl-button>
{#if type.split("|")[2] || type.split("|")[0] === 'book'}
<sl-dropdown placement="bottom-end" on:sl-select="{e => window.open(e.detail.item.value, '_blank')}">
<sl-button slot="trigger" size="small" caret>
<sl-icon name="cloud-download"></sl-icon>
</sl-button>
<sl-menu style="width: 200px;">
{#if type.split("|")[2] && type.split("|")[2].startsWith('ipfs:')}
<sl-menu-label>Download via IPFS:</sl-menu-label>
<sl-menu-item value={'https://cloudflare-ipfs.com/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Cloudflare</sl-menu-item>
<sl-menu-item value={'https://ipfs.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>IPFS.io</sl-menu-item>
<sl-menu-item value={'https://ipfs.infura.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Infura</sl-menu-item>
<sl-menu-item value={'https://gateway.pinata.cloud/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Pinata</sl-menu-item>
{/if}
{#if type.split("|")[2] && type.split("|")[2].startsWith('doi:')}
<sl-menu-item value={'https://sci-hub.se/' + type.split("|")[2].replace('doi:','')}>On SciHub</sl-menu-item>
{/if}
{#if type.split("|")[0] === 'book'}
<sl-divider></sl-divider>
<sl-menu-label>Look up on:</sl-menu-label>
<sl-menu-item value={'http://libgen.rs/search.php?req=' + encodeURIComponent(item.name)}>LibGen</sl-menu-item>
<sl-menu-item value={'https://openlibrary.org/search?q=' + encodeURIComponent(item.name)}>OpenLibrary</sl-menu-item>
<sl-menu-item value={'https://www.goodreads.com/search?q=' + encodeURIComponent(item.name)}>GoodReads</sl-menu-item>
{/if}
</sl-menu>
</sl-dropdown>
{/if}
</sl-button-group>
{/each}
<!-- item details -->
<div class="w-full mt-10 flex flex-col justify-between flex-1">
<!-- title, sub title, author -->
<section>
<h1 class="text-xl md:text-4xl font-extrabold">{item.name}</h1>
<span class="text-sm mt-5">{item.creators}</span>
<div class="mt-5">
<sl-rating readonly precision="0.1" value={item.rating}></sl-rating>
</div>
</section>
<!-- ratings and upload buttons -->
<div class="mt-2 mb-6 flex flex-col justify-between">
<div class="flex flex-wrap items-center justify-start gap-3 mt-5">
{#each item.links.split(";") as type}
<sl-button-group>
<sl-button size="small" href={type.split("|")[1]} target="_blank" class="linkButton">{type.split("|")[0]} at {get_tld(type.split("|")[1])} <sl-icon name="link-45deg"></sl-icon></sl-button>
{#if type.split("|")[2] || type.split("|")[0] === 'book'}
<sl-dropdown placement="bottom-end" on:sl-select="{e => window.open(e.detail.item.value, '_blank')}">
<sl-button slot="trigger" size="small" caret>
<sl-icon name="cloud-download"></sl-icon>
</sl-button>
<sl-menu style="width: 200px;">
{#if type.split("|")[2] && type.split("|")[2].startsWith('ipfs:')}
<sl-menu-label>Download via IPFS:</sl-menu-label>
<sl-menu-item value={'https://cloudflare-ipfs.com/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Cloudflare</sl-menu-item>
<sl-menu-item value={'https://ipfs.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>IPFS.io</sl-menu-item>
<sl-menu-item value={'https://ipfs.infura.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Infura</sl-menu-item>
<sl-menu-item value={'https://gateway.pinata.cloud/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Pinata</sl-menu-item>
{/if}
{#if type.split("|")[2] && type.split("|")[2].startsWith('doi:')}
<sl-menu-item value={'https://sci-hub.se/' + type.split("|")[2].replace('doi:','')}>On SciHub</sl-menu-item>
{/if}
{#if type.split("|")[0] === 'book'}
<sl-divider></sl-divider>
<sl-menu-label>Look up on:</sl-menu-label>
<sl-menu-item value={'http://libgen.rs/search.php?req=' + encodeURIComponent(item.name)}>LibGen</sl-menu-item>
<sl-menu-item value={'https://openlibrary.org/search?q=' + encodeURIComponent(item.name)}>OpenLibrary</sl-menu-item>
<sl-menu-item value={'https://www.goodreads.com/search?q=' + encodeURIComponent(item.name)}>GoodReads</sl-menu-item>
{/if}
</sl-menu>
</sl-dropdown>
{/if}
</sl-button-group>
{/each}
</div>
<ButtonGroup tabs={['Want to learn','Finished']} currentlySelected={$bookmarks[itemid]} on:change={saveStatusToLocalStorage}/>
</div>
<ButtonGroup tabs={['Want to learn','Finished']} currentlySelected={$bookmarks[itemid]} on:change={saveStatusToLocalStorage}/>
</div>
</div>
</div>
<hr class="bg-lightPrimary"/>
<!-- Description -->
{#if item.description}
<section class="my-8">
<h2 class="font-bold text-lg">Description</h2>
<p class="mt-4 tracking-wide">{item.description}</p>
</section>
{/if}
{/if}
<hr class="bg-neutral_light"/>
<!-- Description -->
{#if item.description}
<section class="my-8">
<h2 class="font-bold text-lg">Description</h2>
<p class="mt-4 tracking-wide">{item.description}</p>
</section>
{/if}
<!-- details -->
<!-- item fields -->
<div class="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6">
{#if item.genre}
@ -288,72 +273,9 @@
</section>
{/if}
<div>
{#if item.links.includes('wiki|')}
<iframe src={wikiUrlForEmbed(item)} class="w-full h-[48rem]" title="embedded wiki"></iframe>
{:else if item.links.includes('video|') && oembed_iframe}
{@html oembed_iframe.replace('width="200"','width="100%"').replace('height="113"','height="400"')}
{/if}
<div class="mt-10 flex w-full flex-col justify-between">
<!-- title, sub title, author -->
<section>
<h1 class="text-xl md:text-4xl font-extrabold">{item.name}</h1>
<span class="text-sm mt-5">{item.creators}</span>
<div class="mt-5">
<sl-rating readonly precision="0.1" value={item.rating}></sl-rating>
</div>
</section>
<!-- Description -->
{#if item.description}
<section class="my-8">
<h2 class="font-bold text-lg">Description</h2>
<p class="mt-4 tracking-wide">{item.description}</p>
</section>
{/if}
<!-- ratings and upload buttons -->
<div class="mt-2 mb-6 flex flex-col justify-between">
<div class="flex flex-wrap items-center justify-start gap-3 mt-5">
{#each item.links.split(";") as type}
<sl-button-group>
<sl-button size="small" href={type.split("|")[1]} target="_blank" class="linkButton">{type.split("|")[0]} at {get_tld(type.split("|")[1])} <sl-icon name="link-45deg"></sl-icon></sl-button>
{#if type.split("|")[2] || type.split("|")[0] === 'book'}
<sl-dropdown placement="bottom-end" on:sl-select="{e => window.open(e.detail.item.value, '_blank')}">
<sl-button slot="trigger" size="small" caret>
<sl-icon name="cloud-download"></sl-icon>
</sl-button>
<sl-menu style="width: 200px;">
{#if type.split("|")[2] && type.split("|")[2].startsWith('ipfs:')}
<sl-menu-label>Download via IPFS:</sl-menu-label>
<sl-menu-item value={'https://cloudflare-ipfs.com/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Cloudflare</sl-menu-item>
<sl-menu-item value={'https://ipfs.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>IPFS.io</sl-menu-item>
<sl-menu-item value={'https://ipfs.infura.io/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Infura</sl-menu-item>
<sl-menu-item value={'https://gateway.pinata.cloud/ipfs/' + type.split("|")[2].replace('ipfs:','')}>Pinata</sl-menu-item>
{/if}
{#if type.split("|")[2] && type.split("|")[2].startsWith('doi:')}
<sl-menu-item value={'https://sci-hub.se/' + type.split("|")[2].replace('doi:','')}>On SciHub</sl-menu-item>
{/if}
{#if type.split("|")[0] === 'book'}
<sl-divider></sl-divider>
<sl-menu-label>Look up on:</sl-menu-label>
<sl-menu-item value={'http://libgen.rs/search.php?req=' + encodeURIComponent(item.name)}>LibGen</sl-menu-item>
<sl-menu-item value={'https://openlibrary.org/search?q=' + encodeURIComponent(item.name)}>OpenLibrary</sl-menu-item>
<sl-menu-item value={'https://www.goodreads.com/search?q=' + encodeURIComponent(item.name)}>GoodReads</sl-menu-item>
{/if}
</sl-menu>
</sl-dropdown>
{/if}
</sl-button-group>
{/each}
</div>
<ButtonGroup tabs={['Want to learn','Finished']} currentlySelected={$bookmarks[itemid]} on:change={saveStatusToLocalStorage}/>
</div>
</div>
</div>
</div>
</div>
{:else}
<p class="loading">loading...</p>

Wyświetl plik

@ -15,7 +15,8 @@
<div class="mt-10">
<div class="">
<!-- desktop view -->
<div class="hidden md:block">
<sl-tab-group placement="start">
{#each formats.filter(f => items.filter(x => x.links.includes(f.id + '|')).length > 0) as format, i}
@ -23,7 +24,7 @@
{#if format.id == 'book'}
<sl-tab-panel name={format.id} active={i == 0}>
<div class="grid gap-5 grid-cols-1 sm:grid-cols-2 md:grid-cols-1 lg:grid-cols-3 xl:grid-cols-4 justify-items-center">
<div class="grid gap-5 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 justify-items-center">
{#each items.filter(x => x.links.includes(format.id + '|')) as item}
<BookCard {item}/>
{/each}
@ -52,6 +53,43 @@
</sl-tab-group>
</div>
<!-- mobile view -->
<div class="md:hidden">
<sl-tab-group>
{#each formats.filter(f => items.filter(x => x.links.includes(f.id + '|')).length > 0) as format, i}
<sl-tab slot="nav" panel={format.id} active={i == 0}>{getFormatDisplayName(format.name)} </sl-tab>
{#if format.id == 'book'}
<sl-tab-panel name={format.id} active={i == 0}>
<div class="grid gap-5 grid-cols-2 justify-items-center">
{#each items.filter(x => x.links.includes(format.id + '|')) as item}
<BookCard {item}/>
{/each}
</div>
</sl-tab-panel>
{:else if format.id == 'video'}
<sl-tab-panel name={format.id} active={i == 0}>
<div class="mx-auto gap-5 flex flex-wrap">
{#each items.filter(x => x.links.includes(format.id + '|')) as item}
<VideoCard {item}/>
{/each}
</div>
</sl-tab-panel>
{:else}
<sl-tab-panel name={format.id} active={i == 0}>
<div class="mx-auto gap-5 flex flex-wrap">
{#each items.filter(x => x.links.includes(format.id + '|')) as item}
<GenericCard {item}/>
{/each}
</div>
</sl-tab-panel>
{/if}
{/each}
</sl-tab-group>
</div>
</div>

Wyświetl plik

@ -1,9 +1,12 @@
<script>
import { createEventDispatcher } from 'svelte';
import Icon from "./Icon.svelte"
export let alltopics;
export let hideTopic = false;
let showForm = true;
let query = {
text: "",
topic: "",
@ -18,46 +21,70 @@
</script>
<form class="w-full p-2 gap-3 mt-10 flex flex-col xl:flex-row sticky top-14 z-10 bg-gradient-to-r from-lightGradOne to-lightGradTwo" on:submit|preventDefault>
<sl-input type="search" placeholder="Search by keywords" size="medium" clearable class="w-full 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}
<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}
<div class="flex flex-col md:flex-row justify-center items-center gap-3 w-full">
<sl-select class="w-full" 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>
<sl-menu-item value="challenging">Challenging</sl-menu-item>
<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="w-full" on:sl-change="{e => query.level = e.target.value}" value={query.level}>
<sl-menu-item value="">Any level</sl-menu-item>
<sl-menu-item value="childlike">Childlike</sl-menu-item>
<sl-menu-item value="beginner">Beginner</sl-menu-item>
<sl-menu-item value="intermediate">Intermediate</sl-menu-item>
<sl-menu-item value="advanced">Advanced</sl-menu-item>
<sl-menu-item value="research">Research</sl-menu-item>
</sl-select>
<div class="sticky top-24 z-10 md:top-12 bg-primary md:bg-gradient-to-r from-lightGradOne to-lightGradTwo rounded">
{#if showForm == false}
<div class="bg-primary rounded absolute -top-8 right-0">
<button on:click={e => showForm = true} type="button" class=" p-2 text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Open search form</span>
<Icon kind="search"/>
</button>
</div>
{/if}
<sl-select class="w-full md:w-2/5" 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>
<sl-menu-item value="year">Sort by Year</sl-menu-item>
<sl-menu-item value="name">Sort by Name</sl-menu-item>
</sl-select>
</form>
{#if showForm}
<div class="bg-primary rounded absolute -top-8 right-0">
<button on:click={e => showForm = false} type="button" class="p-2 text-primary_light focus:outline-none focus:ring-2 focus:ring-inset focus:ring-primary md:hidden">
<span class="sr-only">Close search form</span>
<Icon kind="close"/>
</button>
</div>
{/if}
{#if showForm}
<form class="w-full p-2 gap-3 mt-10 flex flex-col xl:flex-row" on:submit|preventDefault>
<sl-input type="search" placeholder="Search by keywords" size="medium" clearable class="w-full 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}
<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}
<div class="flex flex-col md:flex-row justify-center items-center gap-3 w-full">
<sl-select class="w-full" 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>
<sl-menu-item value="challenging">Challenging</sl-menu-item>
<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="w-full" on:sl-change="{e => query.level = e.target.value}" value={query.level}>
<sl-menu-item value="">Any level</sl-menu-item>
<sl-menu-item value="childlike">Childlike</sl-menu-item>
<sl-menu-item value="beginner">Beginner</sl-menu-item>
<sl-menu-item value="intermediate">Intermediate</sl-menu-item>
<sl-menu-item value="advanced">Advanced</sl-menu-item>
<sl-menu-item value="research">Research</sl-menu-item>
</sl-select>
</div>
<sl-select class="w-full md:w-2/5" 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>
<sl-menu-item value="year">Sort by Year</sl-menu-item>
<sl-menu-item value="name">Sort by Name</sl-menu-item>
</sl-select>
</form>
{/if}
</div>

Wyświetl plik

@ -18,25 +18,11 @@
.then(data => {
oEmded_image_ytb_url = data.thumbnail_url
});
// function youtube_parser(url){
// var regExp = /^.*((youtu.be\/)|(v\/)|(\/u\/\w\/)|(embed\/)|(watch\?))\??v?=?([^#&?]*).*/;
// var match = url.match(regExp);
// return (match&&match[7].length==11)? match[7] : false;
// }
// function get_thumbnail_image_url(item){
// let youtubeformat = item.links.split(";").find(s => s.startsWith('video|') && (s.includes('youtube.com') || s.includes('youtu.be')));
// let youtubeurl = youtubeformat && youtubeformat.split('|')[1];
// let ytid = youtubeurl && youtube_parser(youtubeurl);
// let thumbnail_image_url = ytid && `https://img.youtube.com/vi/${ytid}/mqdefault.jpg`
// return thumbnail_image_url
// }
</script>
<a class="flex flex-wrap justify-between overflow-hidden w-full rounded-lg duration-300 break-inside-avoid max-w-lg bg-lightPrimCont text-lightPrimary dark:bg-darkPrimCont dark:text-darkPrimary hover:bg-lightPrimary hover:bg-darkPrimary border-secondary" href="#/item/{item.rowid}">
<a class="flex flex-wrap overflow-hidden rounded-lg duration-300 break-inside-avoid max-w-lg border-secondary" href="#/item/{item.rowid}">
<div class="relative w-full max-w-sm w-full md:w-64 ring-black/5 rounded-xl flex flex-col items-start">
<div class="h-36 w-full md:w-64 flex justify-center items-center relative ">

Wyświetl plik

@ -11,10 +11,10 @@
colors: {
primary: '#1E3A8A', //blue-900
primary_light: '#FAFAFA', //neutral-50
neutral_Light: '#737373', // neutral-400
neutral_light: '#737373', // neutral-400
neutral_dark: '#262626', // neutral-800
secondary: '#6B21A8', // purple-800
white: '#ffffff',
//white: '#ffffff',
lightGradOne: '#DBEAFE', //blue-100
lightGradTwo: '#F3E8FF', //purple-100
},