Add drag and drop + all exercise page
This commit is contained in:
Generated
+6
-16
@@ -1702,16 +1702,6 @@
|
|||||||
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
|
"integrity": "sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"carbon-components-svelte": {
|
|
||||||
"version": "0.39.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/carbon-components-svelte/-/carbon-components-svelte-0.39.0.tgz",
|
|
||||||
"integrity": "sha512-pz6P8JwU959YyrjJ9TUxM4O9uVjj51htGFWHAXyH2ou2TcY2t2u8DgRQMAXImAqVpwOKgwTNJ5HhnEzNyFhiSw==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"carbon-icons-svelte": "^10.27.0",
|
|
||||||
"flatpickr": "4.6.9"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"carbon-icons-svelte": {
|
"carbon-icons-svelte": {
|
||||||
"version": "10.28.0",
|
"version": "10.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/carbon-icons-svelte/-/carbon-icons-svelte-10.28.0.tgz",
|
||||||
@@ -2224,12 +2214,6 @@
|
|||||||
"pinkie-promise": "^2.0.0"
|
"pinkie-promise": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"flatpickr": {
|
|
||||||
"version": "4.6.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.9.tgz",
|
|
||||||
"integrity": "sha512-F0azNNi8foVWKSF+8X+ZJzz8r9sE1G4hl06RyceIaLvyltKvDl6vqk9Lm/6AUUCi5HWaIjiUbk7UpeE/fOXOpw==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"forever-agent": {
|
"forever-agent": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||||
@@ -4088,6 +4072,12 @@
|
|||||||
"svelte": "^3.15.0"
|
"svelte": "^3.15.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"svelte-dnd-action": {
|
||||||
|
"version": "0.9.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-dnd-action/-/svelte-dnd-action-0.9.9.tgz",
|
||||||
|
"integrity": "sha512-DuSfie7xukV3AXlA9vFnIkit97LYNSDpKFmUBgL0RansnBrFvJoFpnsnuUW2ULfsYR1NpqZGmHAsgKQUeBf6Lg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"svelte-preprocess": {
|
"svelte-preprocess": {
|
||||||
"version": "4.7.3",
|
"version": "4.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-4.7.3.tgz",
|
||||||
|
|||||||
+1
-1
@@ -31,7 +31,6 @@
|
|||||||
"@rollup/plugin-node-resolve": "^8.0.0",
|
"@rollup/plugin-node-resolve": "^8.0.0",
|
||||||
"@rollup/plugin-replace": "^2.2.0",
|
"@rollup/plugin-replace": "^2.2.0",
|
||||||
"@tailwindcss/typography": "^0.3.1",
|
"@tailwindcss/typography": "^0.3.1",
|
||||||
"carbon-components-svelte": "^0.39.0",
|
|
||||||
"carbon-icons-svelte": "^10.21.0",
|
"carbon-icons-svelte": "^10.21.0",
|
||||||
"postcss": "^8.0.9",
|
"postcss": "^8.0.9",
|
||||||
"postcss-load-config": "^2.1.0",
|
"postcss-load-config": "^2.1.0",
|
||||||
@@ -42,6 +41,7 @@
|
|||||||
"sass": "^1.32.13",
|
"sass": "^1.32.13",
|
||||||
"svelte": "^3.17.3",
|
"svelte": "^3.17.3",
|
||||||
"svelte-awesome": "^2.3.1",
|
"svelte-awesome": "^2.3.1",
|
||||||
|
"svelte-dnd-action": "^0.9.9",
|
||||||
"svelte-preprocess": "^4.7.3",
|
"svelte-preprocess": "^4.7.3",
|
||||||
"tailwindcss": "^2.1.2",
|
"tailwindcss": "^2.1.2",
|
||||||
"typescript": "^4.1.3"
|
"typescript": "^4.1.3"
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,5 @@
|
|||||||
import "carbon-components-svelte/css/all.css";
|
import * as sapper from '@sapper/app';
|
||||||
import * as sapper from "@sapper/app";
|
|
||||||
|
|
||||||
sapper.start({
|
sapper.start({
|
||||||
target: document.querySelector("#sapper"),
|
target: document.querySelector('#sapper'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { Modal } from 'carbon-components-svelte';
|
|
||||||
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
|
import PrimaryButton from '../../../../PrimaryButton/index.svelte';
|
||||||
import PageBody from '../../../../PageBody/index.svelte';
|
import PageBody from '../../../../PageBody/index.svelte';
|
||||||
|
import Modal from '../../../../Modal/index.svelte';
|
||||||
import TextField from '../../../../Form/TextField.svelte';
|
import TextField from '../../../../Form/TextField.svelte';
|
||||||
import Exercise from '../Exercise/index.svelte';
|
import Exercise from '../Exercise/index.svelte';
|
||||||
|
|
||||||
@@ -46,22 +46,23 @@
|
|||||||
<Exercise {exerciseId} />
|
<Exercise {exerciseId} />
|
||||||
{:else}
|
{:else}
|
||||||
<Modal
|
<Modal
|
||||||
size="xs"
|
onClose={handleCancelAddExercise}
|
||||||
bind:open
|
bind:open
|
||||||
modalHeading="Create an Exercise"
|
modalHeading="Create an Exercise"
|
||||||
primaryButtonText="Confirm"
|
|
||||||
secondaryButtonText="Cancel"
|
|
||||||
on:click:button--primary={handleAddExercise}
|
|
||||||
on:click:button--secondary={handleCancelAddExercise}
|
|
||||||
on:open
|
|
||||||
on:close
|
|
||||||
on:submit
|
|
||||||
>
|
>
|
||||||
<TextField
|
<TextField
|
||||||
bind:value={newExercise.title}
|
bind:value={newExercise.title}
|
||||||
autofocus={true}
|
autofocus={true}
|
||||||
placeholder="Exercise name"
|
placeholder="Exercise name"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="mt-5 flex items-center">
|
||||||
|
<PrimaryButton
|
||||||
|
className="px-6 py-2"
|
||||||
|
label="Submit"
|
||||||
|
onClick={handleAddExercise}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<PageBody width="w-11/12 m-auto">
|
<PageBody width="w-11/12 m-auto">
|
||||||
|
|||||||
@@ -1,28 +1,47 @@
|
|||||||
<script>
|
<script>
|
||||||
import { Tabs, Tab, TabContent } from 'carbon-components-svelte';
|
import Tabs from '../../../../Tabs/index.svelte';
|
||||||
|
import TabContent from '../../../../Tabs/index.svelte';
|
||||||
import EditContent from '../../../../EditContent/index.svelte';
|
import EditContent from '../../../../EditContent/index.svelte';
|
||||||
import TextField from '../../../../Form/TextField.svelte';
|
import TextField from '../../../../Form/TextField.svelte';
|
||||||
import { lesson } from '../store/lessons';
|
import { lesson } from '../store/lessons';
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
label: 'Note',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Slide',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Video',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let currentTab = tabs[0].value;
|
||||||
|
|
||||||
|
function onChange(tabValue) {
|
||||||
|
return () => {
|
||||||
|
currentTab = tabValue;
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Tabs class="flex justify-center" type="container">
|
<Tabs {tabs} {currentTab} {onChange}>
|
||||||
<Tab label="Note" />
|
<slot:fragment slot="content">
|
||||||
<Tab label="Slide" />
|
<TabContent value={tabs[0].value} index={currentTab}>
|
||||||
<Tab label="Video" />
|
|
||||||
|
|
||||||
<div slot="content">
|
|
||||||
<TabContent>
|
|
||||||
<EditContent
|
<EditContent
|
||||||
writeLabel="Note"
|
writeLabel="Note"
|
||||||
bind:value={$lesson.materials.note}
|
bind:value={$lesson.materials.note}
|
||||||
placeholder="Start typing your lesson"
|
placeholder="Start typing your lesson"
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent>
|
<TabContent value={tabs[1].value} index={currentTab}>
|
||||||
<TextField label="Slide link" bind:value={$lesson.materials.slide} />
|
<TextField label="Slide link" bind:value={$lesson.materials.slide} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent>
|
<TabContent value={tabs[2].value} index={currentTab}>
|
||||||
<TextField label="Youtube link" bind:value={$lesson.materials.video} />
|
<TextField label="Youtube link" bind:value={$lesson.materials.video} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</div>
|
</slot:fragment>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|||||||
@@ -1,19 +1,38 @@
|
|||||||
<script>
|
<script>
|
||||||
import { Tabs, Tab, TabContent } from 'carbon-components-svelte';
|
import Tabs from '../../../../Tabs/index.svelte';
|
||||||
|
import TabContent from '../../../../Tabs/index.svelte';
|
||||||
import MarkdownRender from '../../../../MarkdownRender/index.svelte';
|
import MarkdownRender from '../../../../MarkdownRender/index.svelte';
|
||||||
import { lesson } from '../store/lessons';
|
import { lesson } from '../store/lessons';
|
||||||
|
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
label: 'Note',
|
||||||
|
value: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Slide',
|
||||||
|
value: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Video',
|
||||||
|
value: 3,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let currentTab = tabs[0].value;
|
||||||
|
|
||||||
|
function onChange(tabValue) {
|
||||||
|
return () => {
|
||||||
|
currentTab = tabValue;
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Tabs class="flex justify-center" type="container">
|
<Tabs {tabs} {currentTab} {onChange}>
|
||||||
<Tab label="Note" />
|
<slot:fragment slot="content">
|
||||||
<Tab label="Slide" />
|
<TabContent value={tabs[0].value} index={currentTab}>
|
||||||
<Tab label="Video" />
|
|
||||||
|
|
||||||
<div slot="content">
|
|
||||||
<TabContent>
|
|
||||||
<MarkdownRender content={$lesson.materials.note} />
|
<MarkdownRender content={$lesson.materials.note} />
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent>
|
<TabContent value={tabs[1].value} index={currentTab}>
|
||||||
<iframe
|
<iframe
|
||||||
title="Embeded Slides"
|
title="Embeded Slides"
|
||||||
src={$lesson.materials.slide}
|
src={$lesson.materials.slide}
|
||||||
@@ -25,7 +44,7 @@
|
|||||||
webkitallowfullscreen="true"
|
webkitallowfullscreen="true"
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
<TabContent>
|
<TabContent value={tabs[2].value} index={currentTab}>
|
||||||
<iframe
|
<iframe
|
||||||
width="100%"
|
width="100%"
|
||||||
height="569"
|
height="569"
|
||||||
@@ -36,61 +55,5 @@
|
|||||||
allowfullscreen
|
allowfullscreen
|
||||||
/>
|
/>
|
||||||
</TabContent>
|
</TabContent>
|
||||||
</div>
|
</slot:fragment>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<!-- <div class="flex mb-2">
|
|
||||||
<button
|
|
||||||
on:click={handleTabClick(0)}
|
|
||||||
class="focus:outline-none text-lg font-bold border-b-2 border-transparent {currentTab ===
|
|
||||||
0 && `${activeClassName}`}"
|
|
||||||
>
|
|
||||||
Note
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={handleTabClick(1)}
|
|
||||||
class="focus:outline-none text-lg font-bold border-b-2 border-transparent {currentTab ===
|
|
||||||
1 && `${activeClassName}`}"
|
|
||||||
>
|
|
||||||
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={handleTabClick(2)}
|
|
||||||
class="focus:outline-none text-lg font-bold border-b-2 border-transparent {currentTab ===
|
|
||||||
2 && `${activeClassName}`}"
|
|
||||||
>
|
|
||||||
Video
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="m-2 mb-0 p-0">
|
|
||||||
{#if currentTab === 0}
|
|
||||||
<MarkdownRender content={$lesson.materials.note} />
|
|
||||||
{:else if currentTab === 1}
|
|
||||||
<iframe
|
|
||||||
title="Embeded Slides"
|
|
||||||
src={$lesson.materials.slide}
|
|
||||||
frameborder="0"
|
|
||||||
width="100%"
|
|
||||||
height="569"
|
|
||||||
allowfullscreen="true"
|
|
||||||
mozallowfullscreen="true"
|
|
||||||
webkitallowfullscreen="true"
|
|
||||||
/>
|
|
||||||
{:else if currentTab === 2}
|
|
||||||
<iframe
|
|
||||||
width="100%"
|
|
||||||
height="569"
|
|
||||||
src={$lesson.materials.video}
|
|
||||||
title="YouTube video player"
|
|
||||||
frameborder="0"
|
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
allowfullscreen
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
</div> -->
|
|
||||||
<style>
|
|
||||||
button {
|
|
||||||
padding: 12px 12px 8px 12px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script>
|
||||||
|
import CloseButton from '../Buttons/Close/index.svelte';
|
||||||
|
|
||||||
|
export let open;
|
||||||
|
export let onClose;
|
||||||
|
export let modalHeading;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div
|
||||||
|
class="dialog fixed overflow-x-hidden overflow-y-auto inset-0 flex justify-center items-center z-50 bg-gray-100 bg-opacity-50"
|
||||||
|
>
|
||||||
|
<div aria-hidden="true" class="backdrop" />
|
||||||
|
<div class="bg-white mx-auto w-3xl shadow-lg p-5 pt-2 rounded-md">
|
||||||
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
<h3 class="text-xl m-0">
|
||||||
|
{modalHeading}
|
||||||
|
</h3>
|
||||||
|
<CloseButton onClick={onClose} contained={true} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dialog {
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
<script>
|
<script>
|
||||||
import { CodeSnippet } from "carbon-components-svelte";
|
import CodeSnippet from '../../CodeSnippet/index.svelte';
|
||||||
import PrimaryButton from "../../PrimaryButton/index.svelte";
|
import PrimaryButton from '../../PrimaryButton/index.svelte';
|
||||||
import { VARIANTS } from "../../PrimaryButton/constants";
|
import { VARIANTS } from '../../PrimaryButton/constants';
|
||||||
import Checkbox from "../../Form/Checkbox.svelte";
|
import Checkbox from '../../Form/Checkbox.svelte';
|
||||||
|
|
||||||
export let title = "";
|
export let title = '';
|
||||||
export let code;
|
export let code;
|
||||||
export let name = "";
|
export let name = '';
|
||||||
export let options = [];
|
export let options = [];
|
||||||
export let answers = [];
|
export let answers = [];
|
||||||
export let onSubmit = () => {};
|
export let onSubmit = () => {};
|
||||||
@@ -45,13 +45,13 @@
|
|||||||
function getValidationClassName(option) {
|
function getValidationClassName(option) {
|
||||||
if (defaultValue.includes(option.id)) {
|
if (defaultValue.includes(option.id)) {
|
||||||
if (answers.includes(option.id)) {
|
if (answers.includes(option.id)) {
|
||||||
return "border-green-700";
|
return 'border-green-700';
|
||||||
} else {
|
} else {
|
||||||
return "border-red-700";
|
return 'border-red-700';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
|
|
||||||
{#if code}
|
{#if code}
|
||||||
<CodeSnippet {code} type="multi" />
|
<CodeSnippet {code} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<script>
|
<script>
|
||||||
import { CodeSnippet } from "carbon-components-svelte";
|
import CodeSnippet from '../../CodeSnippet/index.svelte';
|
||||||
import PrimaryButton from "../../PrimaryButton/index.svelte";
|
import PrimaryButton from '../../PrimaryButton/index.svelte';
|
||||||
import { VARIANTS } from "../../PrimaryButton/constants";
|
import { VARIANTS } from '../../PrimaryButton/constants';
|
||||||
import RadioItem from "../../Form/RadioItem.svelte";
|
import RadioItem from '../../Form/RadioItem.svelte';
|
||||||
|
|
||||||
export let title = "";
|
export let title = '';
|
||||||
export let code;
|
export let code;
|
||||||
export let name = "";
|
export let name = '';
|
||||||
export let options = [];
|
export let options = [];
|
||||||
export let answers = [];
|
export let answers = [];
|
||||||
export let onSubmit = () => {};
|
export let onSubmit = () => {};
|
||||||
export let onPrevious = () => {};
|
export let onPrevious = () => {};
|
||||||
export let defaultValue = "";
|
export let defaultValue = '';
|
||||||
export let disablePreviousButton = false;
|
export let disablePreviousButton = false;
|
||||||
export let disabled = false;
|
export let disabled = false;
|
||||||
export let isPreview = false;
|
export let isPreview = false;
|
||||||
@@ -45,13 +45,13 @@
|
|||||||
function getValidationClassName(option) {
|
function getValidationClassName(option) {
|
||||||
if (defaultValue.includes(option.id)) {
|
if (defaultValue.includes(option.id)) {
|
||||||
if (answers.includes(option.id)) {
|
if (answers.includes(option.id)) {
|
||||||
return "border-green-700";
|
return 'border-green-700';
|
||||||
} else {
|
} else {
|
||||||
return "border-red-700";
|
return 'border-red-700';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return "";
|
return '';
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
|
|
||||||
{#if code}
|
{#if code}
|
||||||
<CodeSnippet {code} type="multi" />
|
<CodeSnippet {code} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
<script>
|
<script>
|
||||||
import { CodeSnippet } from "carbon-components-svelte";
|
import CodeSnippet from '../../CodeSnippet/index.svelte';
|
||||||
import marked from "marked";
|
import marked from 'marked';
|
||||||
import PrimaryButton from "../../PrimaryButton/index.svelte";
|
import PrimaryButton from '../../PrimaryButton/index.svelte';
|
||||||
import { VARIANTS } from "../../PrimaryButton/constants";
|
import { VARIANTS } from '../../PrimaryButton/constants';
|
||||||
import TextArea from "../../Form/TextArea.svelte";
|
import TextArea from '../../Form/TextArea.svelte';
|
||||||
|
|
||||||
export let title = "";
|
export let title = '';
|
||||||
export let code;
|
export let code;
|
||||||
export let name = "";
|
export let name = '';
|
||||||
export let onSubmit = () => {};
|
export let onSubmit = () => {};
|
||||||
export let onPrevious = () => {};
|
export let onPrevious = () => {};
|
||||||
export let defaultValue = "";
|
export let defaultValue = '';
|
||||||
export let disablePreviousButton = false;
|
export let disablePreviousButton = false;
|
||||||
export let isLast = false;
|
export let isLast = false;
|
||||||
export let isPreview = false;
|
export let isPreview = false;
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<h2>{title}</h2>
|
<h2>{title}</h2>
|
||||||
|
|
||||||
{#if code}
|
{#if code}
|
||||||
<CodeSnippet {code} type="multi" />
|
<CodeSnippet {code} />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<PrimaryButton
|
<PrimaryButton
|
||||||
variant={VARIANTS.OUTLINED}
|
variant={VARIANTS.OUTLINED}
|
||||||
type="submit"
|
type="submit"
|
||||||
label={isLast ? "Finish" : "Next"}
|
label={isLast ? 'Finish' : 'Next'}
|
||||||
{name}
|
{name}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<script>
|
||||||
|
export let value;
|
||||||
|
export let index;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if value === index}
|
||||||
|
<slot />
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<script>
|
||||||
|
export let tabs = [];
|
||||||
|
export let currentTab;
|
||||||
|
export let onChange;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="w-full flex justify-center">
|
||||||
|
<div class="flex items-center">
|
||||||
|
{#each tabs as tab}
|
||||||
|
<button
|
||||||
|
class="relative border-r-1 border-t-0 border-b-0 border-l-0 rounded-none {currentTab ===
|
||||||
|
tab.value
|
||||||
|
? 'text-black font-bold bg-gray-100'
|
||||||
|
: 'bg-gray-200 text-gray'} focus:outline-none w-40 text-left p-3"
|
||||||
|
on:click={onChange(tab.value)}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
|
||||||
|
{#if currentTab === tab.value}
|
||||||
|
<span class="absolute w-full top-0 left-0 h-1 bg-blue-500" />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<slot name="content" />
|
||||||
|
</div>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar {
|
*::-webkit-scrollbar {
|
||||||
width: 11px;
|
width: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
*::-webkit-scrollbar-track {
|
*::-webkit-scrollbar-track {
|
||||||
|
|||||||
@@ -13,12 +13,110 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PageNav from "../../../components/PageNav/index.svelte";
|
import { flip } from 'svelte/animate';
|
||||||
import CourseContainer from "../../../components/CourseContainer/index.svelte";
|
import { dndzone } from 'svelte-dnd-action';
|
||||||
|
import PageNav from '../../../components/PageNav/index.svelte';
|
||||||
|
import Chip from '../../../components/Chip/index.svelte';
|
||||||
|
import PageBody from '../../../components/PageBody/index.svelte';
|
||||||
|
import CourseContainer from '../../../components/CourseContainer/index.svelte';
|
||||||
|
const flipDurationMs = 300;
|
||||||
|
|
||||||
export let courseData = {};
|
export let courseData = {};
|
||||||
|
|
||||||
|
let sections = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: 'Submitted',
|
||||||
|
value: 5,
|
||||||
|
items: [
|
||||||
|
{ id: 41, name: 'item41' },
|
||||||
|
{ id: 42, name: 'item42' },
|
||||||
|
{ id: 43, name: 'item43' },
|
||||||
|
{ id: 44, name: 'item44' },
|
||||||
|
{ id: 45, name: 'item45' },
|
||||||
|
{ id: 46, name: 'item46' },
|
||||||
|
{ id: 47, name: 'item47' },
|
||||||
|
{ id: 48, name: 'item48' },
|
||||||
|
{ id: 49, name: 'item49' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: 'In Progress',
|
||||||
|
value: 0,
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: 'Graded',
|
||||||
|
value: 10,
|
||||||
|
items: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function handleItemFinalize(columnIdx, newItems) {
|
||||||
|
sections[columnIdx].items = newItems;
|
||||||
|
// onFinalUpdate([...sections]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDndConsiderCards(columnIdx) {
|
||||||
|
return (e) => {
|
||||||
|
console.warn('got consider');
|
||||||
|
sections[columnIdx].items = e.detail.items;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleDndFinalizeCards(columnIdx) {
|
||||||
|
return (e) => handleItemFinalize(columnIdx, e.detail.items);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<CourseContainer {courseData}>
|
<CourseContainer {courseData}>
|
||||||
<PageNav title="All Exercises" />
|
<PageNav title="All Exercises" />
|
||||||
|
|
||||||
|
<PageBody width="w-11/12 overflow-x-auto overflow-y-hidden h-3/4">
|
||||||
|
<div class="flex items-center justify-between h-full w-full">
|
||||||
|
{#each sections as { id, title, value, items }, idx (id)}
|
||||||
|
<div
|
||||||
|
class="section rounded-md bg-gray-100 border border-gray-50 p-3 h-full mr-3 overflow-hidden"
|
||||||
|
animate:flip={{ duration: flipDurationMs }}
|
||||||
|
>
|
||||||
|
<div class="flex items-center mb-2">
|
||||||
|
<Chip {value} />
|
||||||
|
<p class="ml-2 font-bold">{title}</p>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="content pr-2 overflow-y-auto mb-3"
|
||||||
|
use:dndzone={{
|
||||||
|
items,
|
||||||
|
flipDurationMs,
|
||||||
|
dropTargetStyle: { outline: 'blue' },
|
||||||
|
}}
|
||||||
|
on:consider={handleDndConsiderCards(idx)}
|
||||||
|
on:finalize={handleDndFinalizeCards(idx)}
|
||||||
|
>
|
||||||
|
{#each items as item (item.id)}
|
||||||
|
<div
|
||||||
|
class="w-full h-16 my-2 mx-0 rounded-md bg-white p-2"
|
||||||
|
animate:flip={{ duration: flipDurationMs }}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</PageBody>
|
||||||
</CourseContainer>
|
</CourseContainer>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.section {
|
||||||
|
max-width: 355px;
|
||||||
|
min-width: 355px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
height: 90%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user