all repos — artbound-python @ b5720f74b0147985267c3c962c494ae983e25190

A client-server reimplementation of the administration panel for ArtBound.

artbound_python/static/script.js (view raw)

  1const BS_COL_WIDTH = 4,
  2	MAX_WIDTH = MAX_HEIGHT = 1000,
  3	WATERMARK_SRC = "/static/res/wm.png",
  4	WATERMARK_WIDTH = 325,
  5	WATERMARK_HEIGHT = 98,
  6
  7	WATERMARK = new Image(),
  8	date = new Date(),
  9	month_input = document.getElementById("month_input"),
 10	month_div = document.getElementById("month_div"),
 11	authorize_button = document.getElementById("authorize_button"),
 12	selectall_button = document.getElementById("selectall_button"),
 13	selectnone_button = document.getElementById("selectnone_button"),
 14	togglecolor_button = document.getElementById("togglecolor_button"),
 15	controls_div = document.getElementById("controls"),
 16	opacity_range = document.getElementById("opacity_range"),
 17	main_container_div = document.getElementById("main_container"),
 18	content_div = document.getElementById("content"),
 19	canvas_link = document.getElementById("canvas-download");
 20
 21let	fanarts = new Array(),
 22	watermark_invert = '';
 23
 24WATERMARK.src = WATERMARK_SRC;
 25month_input.value = `${date.getFullYear()}-${("0" + (date.getMonth() + 1)).slice(-2)}`;
 26
 27function addCanvasEvents(img, canvas, ctx){
 28	function abc(e) {
 29		if (e.button == 0) addWatermark(e, img, canvas, ctx);
 30	}
 31
 32	canvas.addEventListener('mousemove', abc);
 33	canvas.addEventListener('mousedown', function(e) {
 34		canvas.removeEventListener('mousemove', abc);
 35		canvas.addEventListener('mousedown', abc);
 36	});
 37}
 38
 39function getNewCardHtml(element) {
 40	element.div = document.createElement("div");
 41	element.canvas = document.createElement("canvas");
 42	const div1 = document.createElement("div"),
 43		div2 = document.createElement("div"),
 44		a = document.createElement("a"),
 45		div3 = document.createElement("div"),
 46		div4 = document.createElement("div"),
 47		button1 = document.createElement("button"),
 48		button2 = document.createElement("button"),
 49		button3 = document.createElement("button"),
 50		button4 = document.createElement("button"),
 51		button5 = document.createElement("button"),
 52		filename = `${('0' + element.index).slice(-2)} - ${element.name}.png`;
 53	
 54	element.div.className = `col-md-${BS_COL_WIDTH} entry${element.enabled == 0 ? " entry-disabled" : ""}`;
 55	element.div.id = `div-${element.id}`;
 56	element.div.setAttribute("data-index", element.index);
 57	div1.className = `card mb-${BS_COL_WIDTH} box-shadow my-card`;
 58	element.canvas.className = "card-img-top entry-img";
 59	element.canvas.id = element.id;
 60	element.canvas.setAttribute("data-name", element.name);
 61	element.canvas.setAttribute("data-content", element.content);
 62	element.canvas.setAttribute("data-filename", filename)
 63	div2.className = "card-body";
 64	a.className = "card-text";
 65	a.innerText = filename;
 66	a.title = "Clicca per copiare."
 67	a.addEventListener("click", function() { navigator.clipboard.writeText(a.innerText); }, false)
 68	div3.className = "d-flex justify-content-between align-items-center card-controls";
 69	div4.className = "btn-group";
 70
 71	button1.className = button2.className = button3.className = button4.className = button5.className = "btn btn-sm btn-outline-secondary";
 72	button1.innerText = "⬅️";
 73	button2.innerText = "*️⃣";
 74	button3.innerText = "🔄";
 75	button5.innerText = "➡️";
 76	button4.innerText = "💾";
 77	button1.addEventListener("click", function() { moveUpDown(element.id, -1); }, false);
 78	button2.addEventListener("click", function() { toggleEntry(element.id); }, false);
 79	button3.addEventListener("click", function() { reloadEntry(element.id); }, false);
 80	button4.addEventListener("click", function() { saveCanvas(element.id); }, false);
 81	button5.addEventListener("click", function() { moveUpDown(element.id, 1); }, false);
 82
 83	div4.appendChild(button1);
 84	div4.appendChild(button2);
 85	div4.appendChild(button3);
 86	div4.appendChild(button4);
 87	div4.appendChild(button5);
 88	div3.appendChild(div4);
 89	div2.appendChild(a);
 90	div2.appendChild(div3);
 91	div1.appendChild(element.canvas);
 92	div1.appendChild(div2);
 93	element.div.appendChild(div1);
 94
 95	const ctx = element.canvas.getContext("2d");
 96
 97	element.image = new Image();
 98	element.image.addEventListener("load", () => {
 99		console.warn("loaded " + element.content);
100		setBaseImage(element.image, element.canvas, ctx);
101		addCanvasEvents(element.image, element.canvas, ctx);
102	});
103	console.warn("loading " + element.content);
104	element.image.src = element.content;
105
106	return element.div;
107}
108
109async function updateFanartList() {
110	main_container_div.hidden = false;
111	content_div.innerHTML = ""
112	
113	let i = 0;
114	for (fanart of fanarts) {
115		if(fanart.enabled){
116			i++;
117			fanart.index = i;
118			content_div.appendChild(getNewCardHtml(fanart));
119		}
120	}
121
122	for (fanart of fanarts) {
123		if(!fanart.enabled){
124			fanart.index = 0;
125			content_div.appendChild(getNewCardHtml(fanart));
126		}
127	}
128}
129
130function getFanart(id){
131	return fanarts.find(element => element.id == id)
132}
133
134function toggleEntry(id) {
135	entry = getFanart(id);
136	if (!entry) return;
137
138	entry.enabled = !entry.enabled;
139	updateFanartList()
140}
141
142function saveCanvas(id) {
143	entry = getFanart(id);
144	if (!entry) return;
145
146	const image = entry.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
147	canvas_link.href = image;
148	canvas_link.setAttribute("download", entry.canvas.getAttribute("data-filename"));
149	canvas_link.click()
150}
151
152function reloadEntry(id){
153	const fanart = getFanart(id);
154	if (!fanart) return;
155
156	const old_div = fanart.div;
157	content_div.replaceChild(getNewCardHtml(fanart), old_div);
158	old_div.remove();
159}
160
161function selectAllNone(toggle) {
162	fanarts.map(x => x.enabled = toggle)
163	updateFanartList()
164}
165
166function debugFn(){
167	fanarts = JSON.parse('[{"id":"1dE8L7w2DuOfQSJwf5oRjAeJ-VZfy5o-6","date":["03","08","2022"],"name":"Saro","content":"/static/res/wm.png","enabled":1,"index":1,"div":{}},{"id":"1ZO2poqaylmh7_FkEjRthozVXFpcP1Edx","date":["18","08","2022"],"name":"suchetto","content":"https://drive.google.com/uc?id=1ZO2poqaylmh7_FkEjRthozVXFpcP1Edx","enabled":1,"index":2,"div":{}},{"id":"1jkpZzqnQUdXv7QiW1khuwnSsdnjudBt-","date":["18","08","2022"],"name":"suca","content":"https://drive.google.com/uc?id=1clZbi1QzJQo_c7PGWx-nmLgfPhXqHdZR","enabled":1,"index":3,"div":{}}]');
168	controls_div.hidden = false;
169	updateOpacity();
170	updateFanartList();
171}
172
173function toggleColor() {
174	watermark_invert = watermark_invert == '' ? 'invert(1)' : '';
175	updateColorDisplay();
176}
177
178function updateColorDisplay() {
179	togglecolor_button.innerText = watermark_invert ? "⚫" : "⚪";
180}
181
182function addWatermark(event, img, c, ctx) {
183	setBaseImage(img, c, ctx);
184
185	const rect = c.getBoundingClientRect();
186	const x = (event.clientX - rect.left) * c.width / c.clientWidth;
187	const y = (event.clientY - rect.top) * c.height / c.clientHeight;
188
189	ctx.globalAlpha = opacity_range.value;
190	ctx.filter = watermark_invert;
191	ctx.drawImage(WATERMARK, x - (WATERMARK_WIDTH / 2), y - (WATERMARK_HEIGHT / 2), WATERMARK_WIDTH, WATERMARK_HEIGHT);
192}
193
194function updateOpacity() {
195	opacity_label.innerHTML = Math.round(opacity_range.value * 100) + '%';
196}
197
198function setBaseImage(img, c, ctx) {
199	const f = Math.min(MAX_WIDTH / img.width, MAX_HEIGHT / img.height);
200
201	const new_width = c.width = Math.ceil(img.width * f);
202	const new_height = c.height = Math.ceil(img.height * f)
203
204	ctx.imageSmoothingEnabled = (f < 1);
205	ctx.drawImage(img, 0, 0, new_width, new_height);
206}
207
208function moveUpDown(id, amount) {
209	const pos = fanarts.indexOf(fanarts.find(element => element.id == id));
210	const new_pos = pos + amount;
211
212	if (new_pos <= -1 || new_pos >= fanarts.length) {
213		return;
214	}
215
216	[fanarts[pos], fanarts[new_pos]] = [fanarts[new_pos], fanarts[pos]];
217
218	updateFanartList();
219}
220
221async function postData(url = "", data = {}, contentType = "application/x-www-form-urlencoded") {
222    // Default options are marked with *
223    const response = await fetch(url, { method: "POST", headers: { "Content-Type": contentType },
224      //redirect: "follow", // manual, *follow, error
225      //referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
226      body: JSON.stringify(data), // body data type must match "Content-Type" header
227    });
228    return response.json();
229}
230
231function getArtworks() {
232    postData("/", { month: month_input.value }, "application/json").then((data) => {
233        console.log(data);
234        fanarts = fanarts.concat(data);
235        controls_div.hidden = false;
236	    updateOpacity();
237	    updateFanartList();
238    });
239}
240
241