Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better Task Creation Page (#151) #301

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions components/CodingChallenge/EditableList.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<template>
<section>
<InputBtn class="my-7" full @click="openDialogAndAddNew()">{{
t("Buttons.AddNew")
}}</InputBtn>
<InputBtn class="my-7" full @click="openDialogAndAddNew()">
<PlusCircleIcon class="h-5 w-5" />
{{ t("Buttons.AddNew", { item: t("Buttons.Challenge") }) }}
</InputBtn>

<div v-if="codingChallenges.length">
<section
Expand Down Expand Up @@ -77,6 +78,7 @@ import {
LockOpenIcon,
EyeIcon,
PencilSquareIcon,
PlusCircleIcon,
} from "@heroicons/vue/24/outline";
import type { PropType } from "vue";
import { useDialogSlot } from "../../composables/dialogSlot";
Expand Down Expand Up @@ -155,6 +157,7 @@ export default {
LockOpenIcon,
EyeIcon,
PencilSquareIcon,
PlusCircleIcon,
},
};
</script>
Expand Down
1 change: 1 addition & 0 deletions components/input/Btn.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export default defineComponent({
icon: { type: Object, default: null },
iconRight: { type: Boolean, default: false },
iconColor: { type: String, default: "" },
item: { type: String, default: "" },
},
emits: ["click"],
setup(props, { emit }) {
Expand Down
9 changes: 7 additions & 2 deletions components/matching/EditableList.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<template>
<div>
<InputBtn class="my-7" full @click="openDialogAndAddNew()">
{{ t("Buttons.AddNew") }}
<PlusCircleIcon class="h-5 w-5" />
{{ t("Buttons.AddNew", { item: t("Buttons.Matching") }) }}
</InputBtn>
<section v-if="matchings?.length">
<div
Expand Down Expand Up @@ -51,7 +52,11 @@
<script lang="ts" setup>
import { useDialogSlot } from "~~/composables/dialogSlot";
import { useI18n } from "vue-i18n";
import { TrashIcon, EyeIcon } from "@heroicons/vue/24/outline";
import {
TrashIcon,
EyeIcon,
PlusCircleIcon,
} from "@heroicons/vue/24/outline";
import type { matching } from "~/types/matching";

const props = defineProps({
Expand Down
96 changes: 92 additions & 4 deletions components/quiz/SubTaskListEditable.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,48 @@
<template>
<div>
<InputBtn class="my-7" full @click="openDialogAndAddNew()">
{{ t("Buttons.AddNew") }}
<PlusCircleIcon class="h-5 w-5" />
{{ t("Buttons.AddNew", { item: t("Buttons.Quiz") }) }}
</InputBtn>
<section v-if="quizzes?.length">
<div
v-if="quizzes?.length"
class="pb-4 pr-4 pl-4 xl:pb-5 xl:pr-5 xl:pl-5">
<article class="flex justify-between">
<div>
<p class="text-sm text-accent clamp line-1 tight">
{{ t("Headings.Total") }}: {{ filteredQuizzes?.length }}
{{ filteredQuizzes.length === 1 ? t("Headings.Quiz") : t("Headings.Quizzes") }}
</p>
<p class="text-sm clamp line-1 tight">
{{ t("Headings.QuizCreated", {
count: userQuizCount,
quizText: userQuizCount === 1 ? t("Headings.Quiz") : t("Headings.Quizzes")
}) }}
</p>
</div>
<div class="flex gap-4 mb-4">
<InputSelect
id="select_user"
sm
:options="formattedUsers"
btn-type
v-model="selectedUser"
@change="filterQuizzes"
/>
<InputSelect
id="select_quiz_type"
sm
:options="availableTypes"
btn-type
v-model="selectedType"
@change="filterQuizzes"
/>
</div>
</article>
</div>
<section v-if="filteredQuizzes?.length">
<div
v-for="(quiz, i) of quizzes"
v-for="(quiz, i) of filteredQuizzes"
:key="i"
class="p-4 xl:p-5 bg-secondary mb-4 rounded-md"
>
Expand All @@ -16,11 +53,12 @@

<div class="flex gap-3 items-center">
<TrashIcon
v-if="!!user?.admin || quiz?.creator === user?.id"
@click="fnDeleteQuiz(quiz?.id)"
class="h-5 w-5 cursor-pointer text-accent"
/>
<PencilSquareIcon
v-if="!!user?.admin"
v-if="!!user?.admin || quiz?.creator === user?.id"
@click="openDialogCreate(quiz)"
class="h-5 w-5 cursor-pointer text-accent"
/>
Expand All @@ -31,6 +69,14 @@
/>
</div>
</article>
<div class="flex flex-col sm:flex-row items-start gap-1">
<p class="text-xs text-accent clamp line-1 tight sm:pr-3 md:pr-53">
{{ quiz?.creator === user?.id ? t("Headings.QuizCreatedByYou") : t("Body.CreatedBy", { user: quiz?.creator}) }}
</p>
<p class="text-xs text-subheading clamp line-1 tight sm:pr-3 md:pr-5">
{{ quiz?.type }}
</p>
</div>
</div>
</section>
<p
Expand Down Expand Up @@ -60,7 +106,9 @@ import {
TrashIcon,
EyeIcon,
PencilSquareIcon,
PlusCircleIcon,
} from "@heroicons/vue/24/outline";
import type { Quiz } from "~/types/courseTypes";

const props = defineProps({
quizzes: { type: Array as PropType<any>, default: [] },
Expand All @@ -69,9 +117,49 @@ const props = defineProps({
const { t } = useI18n();
const dialog = useDialogSlot();
const dialogCreateQiuz = useDialogCreateSubtask();
const selectedUser = ref();
const selectedType = ref();
const quizzes = ref(props.quizzes);
const filteredQuizzes = ref([...quizzes.value]);
const propData = ref();
const user: any = useUser();

const userQuizCount = computed(() => filteredQuizzes.value.filter((quiz) => quiz.creator === user.id).length);

const formattedUsers = computed<{ label: string; value: string }[]>(() => {
const creatorsSet = new Set<string>(quizzes.value.map((quiz: Quiz) => quiz.creator));
const creatorOptions = Array.from(creatorsSet).map(creatorId => {
const creatorDisplayName = quizzes.value.find((quiz: Quiz) => quiz.creator === creatorId)?.creator || "Unknown";
return {
label: `${creatorDisplayName}${creatorId === user.id ? ' (You)' : ''}`,
value: creatorId,
};
});

return [{ label: t("List.Filter.AllUsers"), value: "" }, ...creatorOptions];
});

const availableTypes = computed<{ label: string; value: string }[]>(() => {
const typesSet = new Set(quizzes.value.map((quiz: Quiz) => quiz.type));
const typeOptions = Array.from(typesSet).map(type => ({ label: String(type), value: String(type) }));

return [{ label: t("List.Filter.AllTypes"), value: "" }, ...typeOptions];
});

onMounted(() => {
selectedUser.value = "";
selectedType.value = "";
});

function filterQuizzes() {
filteredQuizzes.value = quizzes.value.filter((quiz: Quiz) => {
const userMatches = selectedUser.value ? quiz.creator === selectedUser.value : true;
const typeMatches = selectedType.value ? quiz.type === selectedType.value : true;

return userMatches && typeMatches;
});
}

function openDialogCreate(quiz: any) {
propData.value = quiz;
dialog.value = true;
Expand Down
10 changes: 7 additions & 3 deletions locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@
"EmptyCodingChallenge": "Für diese Vorlesung wurde keine Programmieraufgabe gefunden",
"DeleteQuiz": "Quiz löschen",
"Quiz": "Quiz",
"QuizCreated": "{count} {quizText} von dir erstellt",
"QuizCreatedByYou": "Dieses Quiz wurde von dir erstellt",
"Output": "Ausgang",
"FEE": "Gebühr",
"Fee": "Gebühr",
Expand Down Expand Up @@ -452,7 +454,7 @@
"MyCertificates": "Die Zertifikate, die du aus Prüfungen bekommen hast! Vielleicht sind es ja schon genügend um einen Job zu bekommen? Oder solltest du mehr sammeln?",
"GetMorphcoins": "Du willst kein Geld bezahlen? Die Coins kannst du auch auf andere Weise erhalten",
"MoreComingSoon": "Mehr folgt bald...",
"CreatedBy": "Erstellt von",
"CreatedBy": "Erstellt von {user}",
"And": "und",
"LastUpdated": "Zuletzt aktualisiert",
"VerifyCertificate": "Bitte gib das Zertifikatspasswort ein, um das Zertifikat anzuzeigen.",
Expand Down Expand Up @@ -655,7 +657,9 @@
"Any": "Egal",
"All": "Alle",
"Booked": "Gebucht",
"Mine": "Eigene Ereignisse"
"Mine": "Eigene Ereignisse",
"AllUsers": "Alle Benutzer",
"AllTypes": "Alle Typen"
},
"Sort": {
"Any": "@:List.Filter.Any",
Expand Down Expand Up @@ -792,7 +796,7 @@
"CreateCodingChallenge": "Erstelle eine Coding Challenge",
"UpdateCodingChallenge": "Coding Challenge aktualisieren",
"Delete": "Beschreibung",
"AddNew": "Neue hinzufügen",
"AddNew": "Neue {item} hinzufügen",
"AddTask": "Aufgabe hinzufügen",
"SaveDescription": "Beschreibung speichern",
"DeleteDescription": "Beschreibung löschen",
Expand Down
10 changes: 7 additions & 3 deletions locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@
"EmptyCodingChallenge": "No Coding Challenge Found For This Lecture",
"DeleteQuiz": "Delete Quiz",
"Quiz": "Quiz",
"QuizCreated": "{count} {quizText} created by you",
"QuizCreatedByYou": "This quiz was created by you",
"FEE": "Fee",
"Output": "Output",
"NoCodingChallengeCreated": "No Coding Challenge For This Challenge",
Expand Down Expand Up @@ -450,7 +452,7 @@
"MyCertificates": "The certificates you got by doing an exam! Maybe they are already good to get a job? Or should you get more?",
"GetMorphcoins": "Don't want to pay? You can get coins by other ways",
"MoreComingSoon": "More coming soon...",
"CreatedBy": "Created by",
"CreatedBy": "Created by {user}",
"And": "and",
"LastUpdated": "Last Updated",
"VerifyCertificate": "Please enter certificate password in order to view certificate.",
Expand Down Expand Up @@ -653,7 +655,9 @@
"Any": "Any",
"All": "All",
"Booked": "Booked",
"Mine": "Mine"
"Mine": "Mine",
"AllUsers": "All Users",
"AllTypes": "All Types"
},
"Sort": {
"Any": "@:List.Filter.Any",
Expand Down Expand Up @@ -787,7 +791,7 @@
"UpdateQuiz": "Update Quiz",
"CreateCodingChallenge": "Create Coding Challenge",
"UpdateCodingChallenge": "Update Coding Challenge",
"AddNew": "Add New",
"AddNew": "Add New {item}",
"SaveOutput": "Save Output",
"SaveInput": "Save Input",
"Save": "Save",
Expand Down