Skip to content

Commit

Permalink
implement generates notes and save notes
Browse files Browse the repository at this point in the history
implemention to show toast components for messages
  • Loading branch information
krmanik committed Feb 10, 2023
1 parent 7ae1194 commit 634b2a2
Show file tree
Hide file tree
Showing 2 changed files with 215 additions and 0 deletions.
61 changes: 61 additions & 0 deletions ts/image-occlusion/Toast.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="ts">
import IconButton from "../components/IconButton.svelte";
import { mdiClose } from "./icons";
export let type: "success" | "error" = "success";
export let message;
export let showToast = false;
const closeToast = () => {
showToast = false;
};
</script>

{#if showToast}
<div class="toast-container">
<div class="toast {type === 'success' ? 'success' : 'error'}">
{message}
<IconButton iconSize={96} on:click={closeToast} class="toast-icon">
{@html mdiClose}</IconButton
>
</div>
</div>
{/if}

<style>
.toast-container {
position: fixed;
bottom: 3rem;
z-index: 100;
width: 100%;
text-align: center;
display: flex;
justify-content: center;
}
.toast {
display: flex;
align-items: center;
padding: 1rem;
background-color: #fff;
border-radius: 0.5rem;
box-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.1);
width: 60%;
justify-content: space-between;
}
.success {
background: #66bb6a;
color: white;
}
.error {
background: #ef5350;
color: white;
}
:global(.toast-icon) {
background: unset !important;
color: white !important;
border: none !important;
}
</style>
154 changes: 154 additions & 0 deletions ts/image-occlusion/generate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

import * as tr from "@tslib/ftl";
import { get } from "svelte/store";

import type { Collection } from "../lib/proto";
import { addImageOcclusionNotes } from "./lib";
import { noteFieldsData, tagsWritable } from "./store";
import Toast from "./Toast.svelte";
import { getQuestionMaskColor } from "./tools/lib";

const divData = [
"angle",
"fill",
"height",
"left",
"points",
"rx",
"ry",
"top",
"type",
"width",
];

export function generate(): { occlusionCloze: string; noteCount: number } {
const canvas = globalThis.canvas;
const canvasObjects = canvas.getObjects();
if (canvasObjects.length < 1) {
return { occlusionCloze: "", noteCount: 0 };
}

let occlusionCloze = "";
let clozeData = "";
let noteCount = 0;

canvasObjects.forEach((object, index) => {
const obJson = object.toJSON();
noteCount++;
if (obJson.type === "group") {
clozeData += getGroupCloze(object, index);
} else {
clozeData += getCloze(object, index, null);
}
});

occlusionCloze += clozeData;
console.log(occlusionCloze);
return { occlusionCloze, noteCount };
}

const getCloze = (object, index, relativePos): string => {
const obJson = object.toJSON();
let clozeData = "";

// generate cloze data in form of
// {{c1::image-occlusion:rect:top=100:left=100:width=100:height=100}}
Object.keys(obJson).forEach(function(key) {
if (divData.includes(key)) {
if (key === "type") {
clozeData += `:${obJson[key]}`;
} else if (key === "points") {
const points = obJson[key];
let pnts = "";
points.forEach((point: { x: number; y: number }) => {
pnts += point.x.toFixed(2) + "," + point.y.toFixed(2) + " ";
});
clozeData += `:${key}=${pnts.trim()}`;
} else if (relativePos && key === "top") {
clozeData += `:top=${relativePos.top}`;
} else if (relativePos && key === "left") {
clozeData += `:left=${relativePos.left}`;
} else {
clozeData += `:${key}=${obJson[key]}`;
}
}
});

// question mask color, on front side asking for cloze
clozeData += `:quesmaskcolor=${getQuestionMaskColor()}`;
clozeData = `{{c${index + 1}::image-occlusion${clozeData}}}\n`;
return clozeData;
};

const getGroupCloze = (group, index): string => {
let clozeData = "";
const objects = group._objects;

objects.forEach((object) => {
const { top, left } = getObjectPositionInGroup(group, object);
clozeData += getCloze(object, index, { top, left });
});

return clozeData;
};

const getObjectPositionInGroup = (group, object): { top: number; left: number } => {
let left = object.left + group.left + group.width / 2;
let top = object.top + group.top + group.height / 2;
left = left.toFixed(2);
top = top.toFixed(2);
return { top, left };
};

export const saveImageNotes = async function(
imagePath: string,
deckId: number,
hideAll: boolean,
): Promise<void> {
const { occlusionCloze, noteCount } = generate();
if (noteCount === 0) {
return;
}

const fieldsData = get(noteFieldsData);
const tags = get(tagsWritable);
let header = fieldsData["header"];
let notes = fieldsData["back-extra"];

if (header === undefined) {
const textArea = document.getElementById("img-occ-html-header")! as HTMLTextAreaElement;
header = textArea.value;
}

if (notes === undefined) {
const textArea = document.getElementById("img-occ-html-back-extra")! as HTMLTextAreaElement;
notes = textArea.value;
}

header = `<div>${header}</div>`;
notes = `<div">${notes}</div>`;

const result = await addImageOcclusionNotes(imagePath, deckId, occlusionCloze, header, notes, tags, hideAll);
showResult(result, noteCount);
};

// show toast message
const showResult = (result: Collection.OpChanges, count: number) => {
const toastComponent = new Toast({
target: document.body,
props: {
message: "",
type: "error",
},
});

if (result.note) {
const msg = tr.importingNoteAdded({ count: count });
toastComponent.$set({ message: msg, type: "success", showToast: true });
} else {
const msg = tr.notetypesErrorGeneratingCloze();
toastComponent.$set({ message: msg, showToast: true });
}
};

0 comments on commit 634b2a2

Please sign in to comment.