Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
24da354
first push
MeezaanD Aug 14, 2023
f3ec479
update to search
MeezaanD Aug 14, 2023
a1270ce
update on how I display records on the load up page
MeezaanD Aug 15, 2023
77728c9
fixed the filtering issues and displaying on the large screen
MeezaanD Aug 16, 2023
fc0e2d9
fixed the issue where I can do the next page on the last page
MeezaanD Aug 17, 2023
7c0db77
updates on resizing not completely functional yet
MeezaanD Aug 17, 2023
0614c90
upadtes on resizing according to the searchResults
MeezaanD Aug 18, 2023
93d1277
add page number out total pages display on the dom
MeezaanD Aug 18, 2023
320c076
changed the page to update according to the first record to always ch…
MeezaanD Aug 22, 2023
f6ae00b
added a background-color to search results
MeezaanD Aug 22, 2023
fba4223
first record on different page update
MeezaanD Aug 24, 2023
e1ea02b
updates to last page
MeezaanD Aug 24, 2023
504dabe
new changes with the resize
MeezaanD Aug 25, 2023
f7d63df
upadtes
MeezaanD Aug 28, 2023
4e33773
working search after resizing issue
MeezaanD Aug 29, 2023
7eb6cf8
updates 30 Aug
MeezaanD Aug 30, 2023
0b79c4a
updates
MeezaanD Aug 30, 2023
55e4984
updates Aug 30
MeezaanD Aug 30, 2023
df6f87d
worked on navigations with buttons regarding to first and last page
MeezaanD Aug 31, 2023
e188ba6
first pull request changes
MeezaanD Sep 1, 2023
56968ae
reduced global variables and other pull request changes
MeezaanD Sep 4, 2023
9033e9c
first round of pull request changes made
MeezaanD Sep 6, 2023
1297016
updates
MeezaanD Sep 7, 2023
5bea166
updates 8 Sep
MeezaanD Sep 8, 2023
9c91a08
updates 11 Sep
MeezaanD Sep 11, 2023
6d189b1
updates 12 Sep
MeezaanD Sep 12, 2023
ca099e1
switching to class
MeezaanD Sep 12, 2023
d41e2f4
updated async functions to normal with adjustments and added javadoc …
MeezaanD Sep 13, 2023
b0e10fb
chnages 14 Sep
MeezaanD Sep 14, 2023
4b1bb4b
small updates
MeezaanD Sep 14, 2023
3211f9e
removed unnecessary spaces
MeezaanD Sep 14, 2023
5fb8789
a few type adjustments
MeezaanD Sep 15, 2023
581729c
updates 15 Sep
MeezaanD Sep 15, 2023
8663db3
updates Wed 20 morning
MeezaanD Sep 20, 2023
b578caa
request for pr review
MeezaanD Sep 21, 2023
510571e
removed the unnecessary return of the displayData on the updateScreen…
MeezaanD Sep 21, 2023
c9d1b4c
update
MeezaanD Sep 22, 2023
3649ab6
css updates
MeezaanD Sep 22, 2023
042d9ac
removed unnecessary returns
MeezaanD Sep 22, 2023
a00ccbc
small changes
MeezaanD Sep 26, 2023
966ea03
removed unnecessary brackets
MeezaanD Sep 28, 2023
f0fb7a2
update
MeezaanD Sep 28, 2023
65fb57b
update Oct 9
MeezaanD Oct 9, 2023
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
18 changes: 18 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:2050",
"webRoot": "${workspaceFolder}",
"sourceMapPathOverrides": {
"webpack:///./*": "${webRoot}/*"
}
}
]
}
5 changes: 5 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"cSpell.words": [
"IMQS"
]
}
353 changes: 353 additions & 0 deletions app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,353 @@
class InitializeApp {
IMQS: string = "http://localhost:2050";
/** Current value of the first record being displayed */
currentValueOfFirstRecord: number = 0;
/** Index of the first record currently displayed on the page */
currentFirstRecordIndex: number = 0;
/** Current page number (changes dynamically) */
currentPage: number = 1;
/** Total number of pages available (changes dynamically) */
totalPages: number = 1;
/** Default number of records to display per page (changes on screen size) */
recordsPerPage: number = 16;
/** Index of the record being searched for (null if not searching) */
searchedIndex: number | null = null;
/** Actual value of the record being searched for (null if not searching) */
searchedValue: number | null = null;
/** Checks if the button is enabled/disabled */
isButtonDisabled: boolean = false;

constructor() {
$(window).on(
"resize",
this.debounce(() => {
this.updateScreen();
}, 250)
);
this.fetchColumns();
this.updateScreen();
this.eventHandlers();
}

/** Fetch the total number of records from the server */
totalRecords(): Promise<number> {
return fetch(`${this.IMQS}/recordCount`)
.then(recordCountResponse => {
if (!recordCountResponse.ok) {
throw new Error("Error trying to get recordCount");
}
return recordCountResponse.text();
})
.then(recordCountData => {
return parseInt(recordCountData);
})
.catch(error => {
throw error;
});
}

/** Fetch column names and create them as table headings */
fetchColumns(): Promise<string[]> {
return fetch(`${this.IMQS}/columns`)
.then((columnsResponse) => {
if (!columnsResponse.ok) {
throw new Error("Error trying to fetch the columns");
}
return columnsResponse.json();
})
.then((columns: string[]) => {
const tableHeaderRow = $("#tableHeaderRow");
for (const columnName of columns) {
const th = $("<th>").text(columnName);
tableHeaderRow.append(th);
}
return columns;
})
.catch((error) => {
throw error;
});
}

/** Fetch records within a specified range */
fetchRecords(fromRecord: number, toRecord: number): Promise<string[]> {
if (fromRecord > toRecord) {
return Promise.reject(
new Error(
"Invalid arguments: fromRecord cannot be greater than toRecord"
)
);
}
return fetch(`${this.IMQS}/records?from=${fromRecord}&to=${toRecord}`).then(
(response) => {
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
}
);
}

displayData(fromRecord: number, recordsDisplayed: number): void {
$("#loader").show();
$("#tableWrapper").hide();
const adjustedFromRecord = Math.max(fromRecord, 0);
let recordCount: number;
this.totalRecords()
.then(count => {
recordCount = count;
this.totalPages = Math.ceil(recordCount / this.recordsPerPage);
if (this.currentPage > this.totalPages) {
this.currentPage = this.totalPages;
this.currentFirstRecordIndex =
Math.max(0, (this.currentPage - 1) * this.recordsPerPage);
}
const maxToRecord =
Math.min(adjustedFromRecord + recordsDisplayed - 1, recordCount - 1);
// Check if the calculated range exceeds the total records
if (maxToRecord < adjustedFromRecord) {
throw new Error("Error trying to display the data");
}
return this.fetchRecords(adjustedFromRecord, maxToRecord).then(
(data) => {
return { data, maxToRecord };
}
);
})
.then(({ data, maxToRecord }) => {
let tableData = "";
if (data && data.length > 0) {
this.currentValueOfFirstRecord = parseInt(data[0][0]);
this.currentFirstRecordIndex = adjustedFromRecord;
for (const record of data) {
tableData += "<tr>";
for (const value of record) {
tableData += `<td>${value}</td>`;
}
tableData += "</tr>";
}
}
// Hide the "Next Page" button if maxToRecord is the last record
if (maxToRecord >= recordCount - 1) {
$("#nextPageButton").hide();
} else {
$("#nextPageButton").show();
}
if (this.searchedIndex !== null) {
this.currentPage = Math.ceil(
(this.searchedIndex + 1) / this.recordsPerPage
);
this.currentFirstRecordIndex = Math.max(
this.searchedIndex - this.recordsPerPage + 1, 0
);
this.searchedIndex = null;
}
$("#tableBody").html(tableData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

$("#loader").hide();
$("#tableWrapper").show();
})
.catch(error => {
throw new Error("An error occurred while fetching and displaying data." + error);
});
}

/** Handle the search method */
async searchMethod(searchValue: number): Promise<void> {
const totalRecCount = await this.totalRecords()
.catch(error => {
throw new Error("No valid records found" + error);
});
if (searchValue < 0 || searchValue >= totalRecCount) {
window.alert("Record not found on this database");
return;
}
const lastRecordIndex = totalRecCount - 1;
const targetPage = Math.ceil((searchValue + 1) / this.recordsPerPage);
const fromRecord = (targetPage - 1) * this.recordsPerPage;
const toRecord = Math.min(
fromRecord + this.recordsPerPage,
lastRecordIndex
);
this.currentPage = targetPage;
this.searchedValue = searchValue;
this.currentFirstRecordIndex = fromRecord;
this.displayData(fromRecord, this.recordsPerPage);
}

/** Update the screen layout and data display */
updateScreen(): void {
const newScreenHeight = window.innerHeight;
this.recordsPerPage = this.windowAdjustments(newScreenHeight);
this.totalRecords()
.then(totalRecCount => {
let fromRecord: number;
if (this.searchedValue !== null) {
const searchIndex = Math.min(this.searchedValue, totalRecCount - 1);
const targetPage = Math.ceil((searchIndex + 1) / this.recordsPerPage);
fromRecord = (targetPage - 1) * this.recordsPerPage;
} else {
const previousFirstRecordIndex = this.currentFirstRecordIndex;
this.currentPage = Math.ceil(
(previousFirstRecordIndex + 1) / this.recordsPerPage
);
fromRecord = this.currentFirstRecordIndex;
}
if (this.currentPage * this.recordsPerPage > totalRecCount - 1) {
const lastPage = Math.ceil(totalRecCount / this.recordsPerPage);
this.currentPage = lastPage;
fromRecord = (lastPage - 1) * this.recordsPerPage;
}
this.displayData(fromRecord, this.recordsPerPage);
})
.catch(error => {
throw new Error("Error updating screen:" + error);
});
}

/** Adjust the number of records displayed based on screen height */
windowAdjustments(screenHeight: number): number {
const estimatedRowHeightFactor = 1;
const estimatedRowHeight = estimatedRowHeightFactor * 50;
const availableScreenHeight = screenHeight - 140;
this.recordsPerPage = Math.floor(
availableScreenHeight / estimatedRowHeight
);
// This ensures that will at least be 1 record on display
return Math.max(this.recordsPerPage, 1);
}

/** Create a debounce function to delay function execution */
debounce(func: any, delay: number) {
let timeoutId: any;
return function (...args: any) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func(...args);
}, delay);
};
}

/** Handles the events such as pagination buttons, input handling and search form */
eventHandlers(): void {
/* Ensures that only positive numbers is accepted */
$("#searchInput").on("input", (e) => {
const inputElement = e.target as HTMLInputElement;
const inputValue = inputElement.value;
const validInputRegex = /^[0-9]+$/;
if (!validInputRegex.test(inputValue)) {
const sanitizedInput = inputValue.replace(/[^0-9]/g, "");
inputElement.value = sanitizedInput;
}
});

/* Handle form submission for searching */
$("#searchForm").submit((e) => {
e.preventDefault();
const searchInputValue = <string>$("#searchInput").val();
const searchValue = Number(searchInputValue);
this.searchedIndex = null;
this.searchMethod(searchValue)
.catch(error => {
window.alert("An error occurred during search. Please try again." + error);
});
});

/* Handle previous page button click */
$("#prevPageButton").on("click", () => {
if ($("#prevPageButton").hasClass("hidden")) {
return;
}
if (this.currentFirstRecordIndex <= 0) {
const errorMessage = "Already on the first page";
window.alert(errorMessage);
return;
}
$("#prevPageButton").addClass("hidden");
this.searchedIndex = null;
this.searchedValue = null;
const firstRecordOfCurrentPage =
(this.currentPage - 1) * this.recordsPerPage;
let fromRecord = firstRecordOfCurrentPage;
$("#nextPageButton").hide();
$("#prevPageButton").hide();
$("#tableWrapper").hide();
$("#loader").show();
this.totalRecords()
.then(() => {
$("#prevPageButton").removeClass("hidden");
$("#loader").hide();
$("#tableWrapper").show();
$("#nextPageButton").show();
$("#prevPageButton").show();
if (this.currentPage < this.totalPages) {
$("#nextPageButton").show();
}
})
.then(() => {
if (this.currentValueOfFirstRecord <= this.recordsPerPage) {
this.currentPage = 1;
this.currentFirstRecordIndex = 0;
} else {
this.currentPage--;
this.currentFirstRecordIndex -= this.recordsPerPage;
}
fromRecord = this.currentFirstRecordIndex;
this.displayData(fromRecord, this.recordsPerPage);
})
.catch(error => {
throw new Error("Error while trying go to the previous page" + error);
});
});

/* Handle next page button click */
$("#nextPageButton").on("click", () => {
if ($("#nextPageButton").hasClass("hidden")) {
return;
}
if (this.currentPage >= this.totalPages) {
const errorMessage = "Already on the last page";
window.alert(errorMessage);
return;
}
$("#nextPageButton").addClass("hidden");
this.searchedIndex = null;
this.searchedValue = null;
let fromRecord = this.currentFirstRecordIndex;
$("#nextPageButton").hide();
$("#prevPageButton").hide();
$("#tableWrapper").hide();
$("#loader").show();
this.totalRecords()
.then((totalRecCount: number) => {
$("#nextPageButton").removeClass("hidden");
$("#loader").hide();
$("#tableWrapper").show();
$("#nextPageButton").show();
$("#prevPageButton").show();
if (
typeof totalRecCount === "number" &&
this.currentFirstRecordIndex >= totalRecCount
) {
$("#nextPageButton").hide();
}
})
.then(() => {
if (this.currentPage < this.totalPages) {
this.currentPage++;
this.currentFirstRecordIndex += this.recordsPerPage;
} else {
this.currentPage = this.totalPages;
}
fromRecord = this.currentFirstRecordIndex;
this.displayData(fromRecord, this.recordsPerPage);
})
.catch(() => {
throw new Error("Error while trying go to the next page");
});
});
}
}

window.onload = () => {
$("#loader").hide();
new InitializeApp();
};
Loading