From b0c2893ea3e88cf8477102ccb1845407989c98d6 Mon Sep 17 00:00:00 2001
From: syke9p3
Date: Sun, 21 Jul 2024 11:22:06 +0800
Subject: [PATCH] date generation
---
app.js | 62 +++++++++++++++++++++++++++++++------
index.html | 21 ++++++++++---
javascript/events.js | 74 ++++++++++++++++++++++++++++++++++++++++++++
javascript/modal.js | 0
javascript/output.js | 0
javascript/state.js | 50 ++++++++++++++++++++++++++++++
javascript/utils.js | 27 +++++++++++++++-
7 files changed, 219 insertions(+), 15 deletions(-)
create mode 100644 javascript/events.js
create mode 100644 javascript/modal.js
create mode 100644 javascript/output.js
create mode 100644 javascript/state.js
diff --git a/app.js b/app.js
index 4bed099..4ee3236 100644
--- a/app.js
+++ b/app.js
@@ -1,5 +1,5 @@
import { classify, modelStatus } from "./javascript/classifier.js"
-import { countCharacters, isValidCharacterCount, typeWriter, updateLabelsContainer } from "./javascript/utils.js"
+import { countCharacters, generateDate, getDate, getTime, isValidCharacterCount, typeWriter, updateLabelsContainer } from "./javascript/utils.js"
export const globalState = {
prevInput: '',
@@ -15,9 +15,13 @@ const clearButton = document.getElementById("clear-btn");
const exampleSelector = document.getElementById("sample-hate-speech");
const wordCountDisplay = document.getElementById("word-count");
const labelsContainer = document.getElementById("labels-container");
+const outputContainer = document.getElementById("output-container");
const inputDisplayContainer = document.getElementById("input-display-container");
const inputDisplay = document.getElementById("input-display");
const inputDisplayText = document.getElementById("input-display-text");
+const inputDisplayDate = document.getElementById("input-display-date");
+const tweetTime = document.getElementById("tweet-time");
+const tweetDate = document.getElementById("tweet-date");
const outputDisplay = document.getElementById("output-display");
const loadingDisplay = document.getElementById("loading-display");
const modelStatusDisplay = document.getElementById("model-status");
@@ -153,18 +157,28 @@ const setInputFieldValue = (text) => {
}
const updateSubmitButtonState = () => {
- const wordCount = globalState.wordCount;
- const prevInput = globalState.prevInput;
- console.group("updateSubmitButtonState: ")
- console.log("wordcount: ", wordCount)
- console.log("prevInput: ", prevInput)
- console.groupEnd()
+ // console.group("updateSubmitButtonState: ")
+ // console.log("wordcount: ", wordCount)
+ // console.log("prevInput: ", prevInput)
+ // console.groupEnd()
// Disable the submit button if input is invalid or data is being fetched
- submitButton.disabled = !isValidCharacterCount(wordCount) || globalState.isLoading || globalState.prevInput === inputField.value;
+ submitButton.disabled = !isValidCharacterCount(globalState.wordCount) || globalState.isLoading || globalState.prevInput === inputField.value;
};
+const displayDateToInputDisplay = () => {
+ const newDate = generateDate();
+ const time = getTime(newDate);
+ const date = getDate(newDate);
+
+ tweetTime.textContent = time;
+ tweetDate.textContent = date;
+
+ inputDisplayDate.style.display = "flex";
+
+}
+
/**
* Takes a string and displays it to the input display in output UI.
* @param {string | {label: string, score: number}[]} output an array of labels and scores sorted by descending scores
@@ -175,6 +189,9 @@ const updateInputDisplay = (inputText) => {
inputDisplayContainer.style.display = "grid"
// inputDisplayText.textContent = inputText
typeWriter(inputDisplayText, inputText);
+ displayDateToInputDisplay();
+
+
}
/**
@@ -230,7 +247,6 @@ const updateLoadingDisplay = (isLoading) => {
labelsContainer.classList.remove("fade-out");
- } else {
}
}
@@ -257,6 +273,8 @@ clearButton.onclick = (e) => {
// TEST: should reset the exampleOptions to default
// TEST: should reset word count
+ inputField.scrollIntoView({ behavior: "smooth" });
+
inputField.value = "";
updateInput()
exampleSelector.selectedIndex = 0;
@@ -270,6 +288,8 @@ clearButton.onclick = (e) => {
*/
const handleSubmitInput = async (input) => {
+ outputContainer.scrollIntoView({ behavior: "smooth" });
+
// TEST: should get output from the classifier if successful
// TEST: should display output to the UI
@@ -335,3 +355,27 @@ exampleSelector.oninput = () => {
handleInputChange()
debugGlobalState()
}
+
+
+/** TODO
+ * @TODO set title attribute to analyzeBtn on hover when same prevInput and input
+ * @TODO date and time to post
+ * @TODO save results to local storage
+ * @TODO retrieve from local storage and display to UI
+ * @TODO filter results
+ * @TODO pagination
+ * @TODO count and graph results
+ * @TODO export as csv
+ * @TODO dark mode
+ * @TODO guide below as an article
+ * @TODO description for the labels with icons/emoji (take from github readme)
+ */
+
+/** FEATURES
+ * @FEAT input text
+ * @FEAT hate speech examples
+ * @FEAT word counter
+ * @FEAT clear input field
+ * @FEAT post like display
+ * @FEAT hate speech categories display
+ */
\ No newline at end of file
diff --git a/index.html b/index.html
index 0ac6542..14357e5 100644
--- a/index.html
+++ b/index.html
@@ -55,9 +55,15 @@
the system requires a minimum of 3 characters and accepts up to a
maximum of 280 characters.
-
+
@@ -146,6 +152,11 @@ MLTHSC
Let's analyze Tagalog hate speech tweet according to Age, Gender, Physical, Race, Religion
and Others.
+
+
+
+
+
@@ -248,14 +259,14 @@ Saved Posts
-
+
-
+
diff --git a/javascript/events.js b/javascript/events.js
new file mode 100644
index 0000000..88bf4af
--- /dev/null
+++ b/javascript/events.js
@@ -0,0 +1,74 @@
+import { classify } from "./classifier.js";
+import { setGlobalInput, setGlobalWordCount, setGlobalOutput, globalState } from './state.js';
+import { updateWordCountDisplay, updateOutputDisplay, setInputFieldValue, getWordCountFromInputField } from './ui.js';
+import { isValidWordCount, countWords } from './utils.js';
+
+const inputField = document.getElementById("input-text");
+const submitButton = document.getElementById("analyze-btn");
+const clearButton = document.getElementById("clear-btn");
+const exampleSelector = document.getElementById("sample-hate-speech");
+
+const initializeGlobalState = () => {
+ setGlobalInput(inputField.value);
+ setGlobalWordCount(getWordCountFromInputField());
+};
+
+const updateWordCount = () => {
+ const wordCount = getWordCountFromInputField();
+ setGlobalWordCount(wordCount);
+ updateWordCountDisplay(wordCount);
+};
+
+const updateInput = () => {
+ setGlobalInput(inputField.value);
+};
+
+document.addEventListener("DOMContentLoaded", function () {
+ initializeGlobalState();
+ debug('globalState.input:', globalState.input);
+ debug('globalState.wordCount:', globalState.wordCount);
+ updateWordCountDisplay(globalState.wordCount);
+
+ inputField.oninput = () => {
+ updateInput();
+ updateWordCount();
+ debugGlobalState();
+ };
+
+ clearButton.onclick = () => {
+ inputField.value = "";
+ updateInput();
+ exampleSelector.selectedIndex = 0;
+ updateWordCount();
+ debugGlobalState();
+ };
+
+ submitButton.onclick = async () => {
+ const wordCount = globalState.wordCount;
+
+ if (!isValidWordCount(wordCount)) {
+ debug('Invalid word count, not submitting input.');
+ return;
+ }
+
+ debug('Submitting input...');
+ globalState.isLoading = true;
+
+ try {
+ const output = await classify(globalState.input);
+ setGlobalOutput(output);
+ updateOutputDisplay(globalState.output);
+ } finally {
+ globalState.isLoading = false;
+ }
+
+ debugGlobalState();
+ };
+
+ exampleSelector.oninput = () => {
+ setInputFieldValue(exampleSelector.value);
+ updateWordCount();
+ updateInput();
+ debugGlobalState();
+ };
+});
diff --git a/javascript/modal.js b/javascript/modal.js
new file mode 100644
index 0000000..e69de29
diff --git a/javascript/output.js b/javascript/output.js
new file mode 100644
index 0000000..e69de29
diff --git a/javascript/state.js b/javascript/state.js
new file mode 100644
index 0000000..9a98cc4
--- /dev/null
+++ b/javascript/state.js
@@ -0,0 +1,50 @@
+class GlobalState {
+ constructor() {
+ this._input = '';
+ this._output = [];
+ this._isLoading = false;
+ this._wordCount = 0;
+ }
+
+ get input() {
+ return this._input;
+ }
+
+ set input(value) {
+ this._input = value;
+ }
+
+ get output() {
+ return this._output;
+ }
+
+ set output(value) {
+ this._output = value;
+ }
+
+ get isLoading() {
+ return this._isLoading;
+ }
+
+ set isLoading(value) {
+ this._isLoading = value;
+ }
+
+ get wordCount() {
+ return this._wordCount;
+ }
+
+ set wordCount(value) {
+ this._wordCount = value;
+ }
+
+ debugGlobalState() {
+ console.group('Global State Debug:');
+ console.log(`Global Input: ${this._input}`);
+ console.log(`Global Word Count: ${this._wordCount}`);
+ console.log('Global Output:', this._output);
+ console.groupEnd();
+ }
+}
+
+export const globalState = new GlobalState();
diff --git a/javascript/utils.js b/javascript/utils.js
index 833cc79..151f46c 100644
--- a/javascript/utils.js
+++ b/javascript/utils.js
@@ -8,7 +8,6 @@ export function countCharacters(text) {
return count;
}
-
/**
* Takes a number and returns true if number is between 3 and 280
* @param {number} count number of words
@@ -18,6 +17,32 @@ export const isValidCharacterCount = (count) => {
return count >= 3 && count <= 280;
}
+
+export const generateDate = () => {
+ console.log(new Date())
+ return new Date()
+}
+
+export const getTime = (date) => {
+ const time = date.toLocaleTimeString();
+ console.log(time)
+ return time;
+}
+
+export const getDate = (date) => {
+ const monthNames = [
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ ];
+
+ const day = date.getDate();
+ const monthIndex = date.getMonth();
+ const year = date.getFullYear();
+
+ return `${day} ${monthNames[monthIndex]} ${year}`;
+}
+
+
debug("output.js")
const labelsContainer = document.getElementById("labels-container");