diff --git a/WebApp/Endpoints/MessagesEndpoints.cs b/WebApp/Endpoints/MessagesEndpoints.cs new file mode 100644 index 0000000..b8cdcf8 --- /dev/null +++ b/WebApp/Endpoints/MessagesEndpoints.cs @@ -0,0 +1,113 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; +using WebApp.Data; +using WebApp.Entities; +using System.Linq; + +namespace WebApp.Endpoints +{ + public static class MessagesEndpoints + { + public static RouteGroupBuilder MapMessagesEndpoints(this WebApplication app) + { + Console.WriteLine("Registering MessagesEndpoints..."); + + var group = app.MapGroup("api/messages"); + + // Test endpoint to verify registration + group.MapGet("/test", () => Results.Ok("Messages endpoint is working")); + + // POST /api/messages/sendFromOrgToVolunteers + group.MapPost("/sendFromOrgToVolunteers", + async (SendMessageRequest request, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => + { + Console.WriteLine("Hit sendFromOrgToVolunteers endpoint."); + + // Get token and organization + var token = await guhf.GetTokenFromHTTPContext(httpContext); + var org = await guhf.GetOrganisationFromToken(token); + if (org == null) + return Results.Unauthorized(); + + // Verify event belongs to org + var ev = await dbContext.Events.FindAsync(request.EventId); + if (ev == null || ev.OrganisationId != org.OrganisationId) + return Results.BadRequest("Event not found or unauthorized."); + + // Get all volunteers (non-org users) + var volunteers = await dbContext.WebUsers + .Where(u => !u.IsOrganisation) + .ToListAsync(); + + // Create message entities + var messages = volunteers.Select(v => new Message + { + EventType = request.EventId, + VolunteerId = v.UserId, + OrganizationId = org.OrganisationId, + IsMsgFromVolunteer = false, + IsoDate = DateTime.UtcNow, + Content = request.Content + }).ToList(); + + dbContext.Messages.AddRange(messages); + await dbContext.SaveChangesAsync(); + + return Results.Ok(); + }); + + // GET /api/messages/my - get messages for current user + group.MapGet("/my", + async (ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => + { + var token = await guhf.GetTokenFromHTTPContext(httpContext); + var user = await guhf.GetUserFromToken(token); + + if (user == null) + return Results.Unauthorized(); + + var messages = await dbContext.Messages + .Where(m => + (user.IsOrganisation && m.OrganizationId == user.UserId) || + (!user.IsOrganisation && m.VolunteerId == user.UserId)) + .OrderByDescending(m => m.IsoDate) + .ToListAsync(); + + return Results.Ok(messages); + }); + // DELETE /api/messages/{id} + group.MapDelete("/{id:int}", async (int id, ApplicationDbContext dbContext, HttpContext httpContext, GeneralUseHelpers guhf) => + { + var token = await guhf.GetTokenFromHTTPContext(httpContext); + var user = await guhf.GetUserFromToken(token); + + if (user == null) + return Results.Unauthorized(); + + var message = await dbContext.Messages.FindAsync(id); + if (message == null) + return Results.NotFound(); + + // Only allow deleting if user is either the organization or volunteer in the message + if (user.IsOrganisation && message.OrganizationId != user.UserId) + return Results.Forbid(); + + if (!user.IsOrganisation && message.VolunteerId != user.UserId) + return Results.Forbid(); + + dbContext.Messages.Remove(message); + await dbContext.SaveChangesAsync(); + + return Results.NoContent(); + }); + + return group; + } + } + + public class SendMessageRequest + { + public int EventId { get; set; } + public string Content { get; set; } + } +} diff --git a/WebApp/Program.cs b/WebApp/Program.cs index 71e6c9d..e855ef3 100644 --- a/WebApp/Program.cs +++ b/WebApp/Program.cs @@ -55,5 +55,6 @@ app.MapOrganizationsEndpoints(); app.MapAuthEndpoints(); app.MapSkillsEndpoints(); app.MapEventsRegistrationEndpoints(); +app.MapMessagesEndpoints(); app.Run(); diff --git a/WebApp/ts/eventList.ts b/WebApp/ts/eventList.ts index f0d37cc..da1fe35 100644 --- a/WebApp/ts/eventList.ts +++ b/WebApp/ts/eventList.ts @@ -26,17 +26,15 @@ function toggleOptionsVisibility() { async function getEvents(titleOrDescription?: string, fDate?: Date, tDate?: Date) { var res: Response; - var searchbar = document.getElementById("searchbar") as HTMLInputElement; + var searchbar = document.getElementById("searchbar") as HTMLInputElement; var eventDateFrom = (document.getElementById('fDate') as HTMLInputElement).value; - var eventDateTo = (document.getElementById('tDate') as HTMLInputElement).value; - + var eventDateTo = (document.getElementById('tDate') as HTMLInputElement).value; if (titleOrDescription == null) { titleOrDescription = searchbar.value; } if (optionsVisibility) { - // Opcje widoczne var payload_visible = { titleOrDescription, eventDateFrom, @@ -64,6 +62,30 @@ async function getEvents(titleOrDescription?: string, fDate?: Date, tDate?: Date return events; } +async function sendMessageForEvent(eventId: number) { + const messageContent = `Help me with this event`; + + try { + const response = await fetch('/api/messages/sendFromOrgToVolunteers', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ eventId, content: messageContent }) + }); + + if (response.ok) { + alert('Message sent successfully to all volunteers!'); + } else { + let error = await response.text(); + if (!error) error = `Status code: ${response.status}`; + alert('Failed to send message: ' + error); + console.error('Send message failed', response.status, error); + } + } catch (error) { + alert('Error sending message: ' + error); + console.error('Fetch error:', error); + } +} + async function loadEvents(org_id: number, evs?: Promise) { const container = document.getElementById("eventList"); if (!container) return; @@ -82,39 +104,56 @@ async function loadEvents(org_id: number, evs?: Promise) { return; } - // Wyczyść kontener przed dodaniem nowych container.innerHTML = ''; - const styleDefault = "color: #2898BD"; - const styleHighlighted = "#2393BD"; - for (const ev of events) { const card = document.createElement("div"); card.className = "event-card filled"; let formattedDate: string = new Intl.DateTimeFormat('en-US', { - weekday: 'long', // "Monday" - year: 'numeric', // "2023" - month: 'long', // "December" - day: 'numeric' // "1" + weekday: 'long', + year: 'numeric', + month: 'long', + day: 'numeric' }).format(new Date(ev.eventDate)); - card.innerHTML = ` - - ${ev.title} -

👥 ${ev.organisation} | 📍 ${ev.location} | 📅 ${formattedDate}

-
` + const eventInfoSpan = document.createElement("span"); + eventInfoSpan.innerHTML = ` + ${ev.title} +

👥 ${ev.organisation} | 📍 ${ev.location} | 📅 ${formattedDate}

+ `; + card.appendChild(eventInfoSpan); if (org_id == ev.organisationId) { - card.innerHTML += ` -
- - -
`; + const buttonsDiv = document.createElement("div"); + buttonsDiv.className = "d-flex gap-2 mt-2"; + + const editBtn = document.createElement("button"); + editBtn.className = "edit-btn mod-btn"; + editBtn.setAttribute("data-id", ev.eventId); + editBtn.title = "Edit event"; + editBtn.innerHTML = ``; + + const removeBtn = document.createElement("button"); + removeBtn.className = "remove-btn mod-btn"; + removeBtn.setAttribute("data-id", ev.eventId); + removeBtn.title = "Remove event"; + removeBtn.innerHTML = ``; + + const sendMsgBtn = document.createElement("button"); + sendMsgBtn.className = "btn btn-sm btn-info"; + sendMsgBtn.textContent = "Send Message"; + sendMsgBtn.setAttribute("data-id", ev.eventId); + sendMsgBtn.title = "Send message about this event"; + sendMsgBtn.addEventListener("click", async () => { + await sendMessageForEvent(ev.eventId); + }); + + buttonsDiv.appendChild(editBtn); + buttonsDiv.appendChild(removeBtn); + buttonsDiv.appendChild(sendMsgBtn); + + card.appendChild(buttonsDiv); } container.appendChild(card); @@ -141,28 +180,27 @@ document.addEventListener("DOMContentLoaded", async () => { unhideElementById(document, "logout-btn"); } } catch { - // console.log("User not signed in. Failing gracefully."); unhideElementById(document, "joinnow-btn"); unhideElementById(document, "signin-btn"); } loadEvents(org_id); - // listen for clicks + const listSortToggleButton = document.getElementById("list-sort-btn"); if (listSortToggleButton) { listSortToggleButton.addEventListener("click", () => toggleListSortOrder(org_id)); } + const optionsToggleButton = document.getElementById("optionsbtn"); if (optionsToggleButton) { optionsToggleButton.addEventListener("click", () => toggleOptionsVisibility()); } - // and for enter in search bar + const searchBar = document.getElementById('searchbar') as HTMLInputElement; searchBar.addEventListener('keydown', (event) => { if (event.key === 'Enter') { - // console.log('Enter key pressed!'); var searchResults = getEvents(searchBar.value); loadEvents(org_id, searchResults); } - }) + }); }); diff --git a/WebApp/ts/messages.ts b/WebApp/ts/messages.ts new file mode 100644 index 0000000..65100d5 --- /dev/null +++ b/WebApp/ts/messages.ts @@ -0,0 +1,93 @@ +// messages.ts + +async function getMyMessages() { + const res = await fetch('/api/messages/my', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) throw new Error('Failed to load messages'); + return await res.json(); +} + +function formatDate(dateStr: string): string { + const date = new Date(dateStr); + return date.toLocaleString(undefined, { + year: 'numeric', month: 'short', day: 'numeric', + hour: '2-digit', minute: '2-digit' + }); +} + +function createMessageCard(msg: any) { + const card = document.createElement('div'); + card.className = 'messages-card'; + + const sender = msg.isMsgFromVolunteer + ? `Volunteer #${msg.volunteerId}` + : `Organization #${msg.organizationId}`; + + // Safely inject content as HTML because it contains links + const contentHtml = msg.content ?? ''; + + card.innerHTML = ` + +
${sender}
+
${formatDate(msg.isoDate)}
+
${contentHtml}
+ Regarding Event #${msg.eventType} + `; + + return card; +} + +async function deleteMessage(messageId: number) { + if (!confirm('Are you sure you want to delete this message?')) return; + + const res = await fetch(`/api/messages/${messageId}`, { + method: 'DELETE', + headers: { 'Content-Type': 'application/json' } + }); + + if (!res.ok) { + alert('Failed to delete message.'); + return; + } + + // Reload messages after delete + loadMessages(); +} + +async function loadMessages() { + const container = document.getElementById('messagesContainer'); + if (!container) return; + + try { + const messages = await getMyMessages(); + + container.innerHTML = ''; + if (messages.length === 0) { + container.innerHTML = `

No messages to display.

`; + return; + } + + messages.forEach((msg: any) => { + const card = createMessageCard(msg); + container.appendChild(card); + }); + + // Attach delete handlers + container.querySelectorAll('.delete-btn').forEach(btn => { + btn.addEventListener('click', () => { + const idStr = btn.getAttribute('data-id'); + if (idStr) deleteMessage(parseInt(idStr)); + }); + }); + + } catch (err) { + container.innerHTML = `

Failed to load messages.

`; + console.error(err); + } +} + +document.addEventListener('DOMContentLoaded', () => { + loadMessages(); +}); diff --git a/WebApp/ts/userSkills.ts b/WebApp/ts/userSkills.ts index 98d6057..d5c4053 100644 --- a/WebApp/ts/userSkills.ts +++ b/WebApp/ts/userSkills.ts @@ -1,10 +1,10 @@ import { getEvent, getMyAccount, unhideElementById, getMyRegisteredEventIds } from './generalUseHelpers.js'; -var redirected = false; +var redirected = false; document.addEventListener("DOMContentLoaded", async () => { - var container = document.getElementById("mainContainer"); + var container = document.getElementById("mainContainer"); const modifyBtn = document.getElementById("editBtn"); const removeBtn = document.getElementById("removeBtn"); const applyBtn = document.getElementById("applyBtn"); @@ -28,7 +28,7 @@ document.addEventListener("DOMContentLoaded", async () => { } else { unhideElementById(document, "orgno"); } - } catch { + } catch (e) { window.location.href = "login.html"; } @@ -40,15 +40,15 @@ document.addEventListener("DOMContentLoaded", async () => { if (container !== null) container.innerHTML = `

Błąd we wczytywaniu wydarzenia. Powrót ->

`; } else { - const nameText = document.getElementById("nameText") as HTMLElement; - const orgnameText = document.getElementById( "orgname") as HTMLElement; - const dateText = document.getElementById("dateText") as HTMLElement; + const nameText = document.getElementById("nameText") as HTMLElement; + const orgnameText = document.getElementById("orgname") as HTMLElement; + const dateText = document.getElementById("dateText") as HTMLElement; const newdateText = new Date(thisAccount.createdAt).toLocaleDateString('pl-PL'); const newtimeText = new Date(thisAccount.createdAt).toLocaleTimeString('pl-PL'); - nameText.innerHTML = thisAccount.firstName + " " + thisAccount.lastName + " (" + thisAccount.email + ")"; - dateText.innerHTML = "📅 Account creation date: " + newdateText + " " + newtimeText; + nameText.innerHTML = thisAccount.firstName + " " + thisAccount.lastName + " (" + thisAccount.email + ")"; + dateText.innerHTML = "📅 Account creation date: " + newdateText + " " + newtimeText; orgnameText.innerHTML = "👥 Organization: " + org_name; if (org_id == -1) { @@ -57,10 +57,10 @@ document.addEventListener("DOMContentLoaded", async () => { // Użytkownik jest wolontariuszem try { const registeredIds = await getMyRegisteredEventIds(); - } catch { + } catch (e) { } - + } unhideElementById(document, "mainContainer"); @@ -75,9 +75,9 @@ window.onload = () => { dropdown.addEventListener('change', () => { const skillName = dropdown.options[dropdown.selectedIndex].text; - const skillId = dropdown.options[dropdown.selectedIndex].value; + const skillId = dropdown.options[dropdown.selectedIndex].value; if (skillName) { - addSkill(skillName, skillId, false); + addSkill(skillName, Number(skillId), false); dropdown.value = ''; // Reset dropdown } }); diff --git a/WebApp/wwwroot/calendar.html b/WebApp/wwwroot/calendar.html index 179c3b2..c70dbcb 100644 --- a/WebApp/wwwroot/calendar.html +++ b/WebApp/wwwroot/calendar.html @@ -24,7 +24,7 @@
- +
Chats
diff --git a/WebApp/wwwroot/index.html b/WebApp/wwwroot/index.html index a956be9..d843885 100644 --- a/WebApp/wwwroot/index.html +++ b/WebApp/wwwroot/index.html @@ -22,7 +22,7 @@
- +
Chats
diff --git a/WebApp/wwwroot/js/eventList.js b/WebApp/wwwroot/js/eventList.js index 3e823bb..9394220 100644 --- a/WebApp/wwwroot/js/eventList.js +++ b/WebApp/wwwroot/js/eventList.js @@ -39,7 +39,6 @@ function getEvents(titleOrDescription, fDate, tDate) { titleOrDescription = searchbar.value; } if (optionsVisibility) { - // Opcje widoczne var payload_visible = { titleOrDescription, eventDateFrom, @@ -69,6 +68,32 @@ function getEvents(titleOrDescription, fDate, tDate) { return events; }); } +function sendMessageForEvent(eventId) { + return __awaiter(this, void 0, void 0, function* () { + const messageContent = `Help me with this event`; + try { + const response = yield fetch('/api/messages/sendFromOrgToVolunteers', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ eventId, content: messageContent }) + }); + if (response.ok) { + alert('Message sent successfully to all volunteers!'); + } + else { + let error = yield response.text(); + if (!error) + error = `Status code: ${response.status}`; + alert('Failed to send message: ' + error); + console.error('Send message failed', response.status, error); + } + } + catch (error) { + alert('Error sending message: ' + error); + console.error('Fetch error:', error); + } + }); +} function loadEvents(org_id, evs) { return __awaiter(this, void 0, void 0, function* () { const container = document.getElementById("eventList"); @@ -86,10 +111,7 @@ function loadEvents(org_id, evs) { container.innerHTML = "

No events to display at this moment.

"; return; } - // Wyczyść kontener przed dodaniem nowych container.innerHTML = ''; - const styleDefault = "color: #2898BD"; - const styleHighlighted = "#2393BD"; for (const ev of events) { const card = document.createElement("div"); card.className = "event-card filled"; @@ -97,23 +119,39 @@ function loadEvents(org_id, evs) { weekday: 'long', year: 'numeric', month: 'long', - day: 'numeric' // "1" + day: 'numeric' }).format(new Date(ev.eventDate)); - card.innerHTML = ` - - ${ev.title} -

👥 ${ev.organisation} | 📍 ${ev.location} | 📅 ${formattedDate}

-
`; + const eventInfoSpan = document.createElement("span"); + eventInfoSpan.innerHTML = ` + ${ev.title} +

👥 ${ev.organisation} | 📍 ${ev.location} | 📅 ${formattedDate}

+ `; + card.appendChild(eventInfoSpan); if (org_id == ev.organisationId) { - card.innerHTML += ` -
- - -
`; + const buttonsDiv = document.createElement("div"); + buttonsDiv.className = "d-flex gap-2 mt-2"; + const editBtn = document.createElement("button"); + editBtn.className = "edit-btn mod-btn"; + editBtn.setAttribute("data-id", ev.eventId); + editBtn.title = "Edit event"; + editBtn.innerHTML = ``; + const removeBtn = document.createElement("button"); + removeBtn.className = "remove-btn mod-btn"; + removeBtn.setAttribute("data-id", ev.eventId); + removeBtn.title = "Remove event"; + removeBtn.innerHTML = ``; + const sendMsgBtn = document.createElement("button"); + sendMsgBtn.className = "btn btn-sm btn-info"; + sendMsgBtn.textContent = "Send Message"; + sendMsgBtn.setAttribute("data-id", ev.eventId); + sendMsgBtn.title = "Send message about this event"; + sendMsgBtn.addEventListener("click", () => __awaiter(this, void 0, void 0, function* () { + yield sendMessageForEvent(ev.eventId); + })); + buttonsDiv.appendChild(editBtn); + buttonsDiv.appendChild(removeBtn); + buttonsDiv.appendChild(sendMsgBtn); + card.appendChild(buttonsDiv); } container.appendChild(card); } @@ -138,12 +176,10 @@ document.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, vo } } catch (_a) { - // console.log("User not signed in. Failing gracefully."); unhideElementById(document, "joinnow-btn"); unhideElementById(document, "signin-btn"); } loadEvents(org_id); - // listen for clicks const listSortToggleButton = document.getElementById("list-sort-btn"); if (listSortToggleButton) { listSortToggleButton.addEventListener("click", () => toggleListSortOrder(org_id)); @@ -152,11 +188,9 @@ document.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, vo if (optionsToggleButton) { optionsToggleButton.addEventListener("click", () => toggleOptionsVisibility()); } - // and for enter in search bar const searchBar = document.getElementById('searchbar'); searchBar.addEventListener('keydown', (event) => { if (event.key === 'Enter') { - // console.log('Enter key pressed!'); var searchResults = getEvents(searchBar.value); loadEvents(org_id, searchResults); } diff --git a/WebApp/wwwroot/js/messages.js b/WebApp/wwwroot/js/messages.js new file mode 100644 index 0000000..0ca5521 --- /dev/null +++ b/WebApp/wwwroot/js/messages.js @@ -0,0 +1,97 @@ +"use strict"; +// messages.ts +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +function getMyMessages() { + return __awaiter(this, void 0, void 0, function* () { + const res = yield fetch('/api/messages/my', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) + throw new Error('Failed to load messages'); + return yield res.json(); + }); +} +function formatDate(dateStr) { + const date = new Date(dateStr); + return date.toLocaleString(undefined, { + year: 'numeric', month: 'short', day: 'numeric', + hour: '2-digit', minute: '2-digit' + }); +} +function createMessageCard(msg) { + var _a; + const card = document.createElement('div'); + card.className = 'messages-card'; + const sender = msg.isMsgFromVolunteer + ? `Volunteer #${msg.volunteerId}` + : `Organization #${msg.organizationId}`; + // Safely inject content as HTML because it contains links + const contentHtml = (_a = msg.content) !== null && _a !== void 0 ? _a : ''; + card.innerHTML = ` + +
${sender}
+
${formatDate(msg.isoDate)}
+
${contentHtml}
+ Regarding Event #${msg.eventType} + `; + return card; +} +function deleteMessage(messageId) { + return __awaiter(this, void 0, void 0, function* () { + if (!confirm('Are you sure you want to delete this message?')) + return; + const res = yield fetch(`/api/messages/${messageId}`, { + method: 'DELETE', + headers: { 'Content-Type': 'application/json' } + }); + if (!res.ok) { + alert('Failed to delete message.'); + return; + } + // Reload messages after delete + loadMessages(); + }); +} +function loadMessages() { + return __awaiter(this, void 0, void 0, function* () { + const container = document.getElementById('messagesContainer'); + if (!container) + return; + try { + const messages = yield getMyMessages(); + container.innerHTML = ''; + if (messages.length === 0) { + container.innerHTML = `

No messages to display.

`; + return; + } + messages.forEach((msg) => { + const card = createMessageCard(msg); + container.appendChild(card); + }); + // Attach delete handlers + container.querySelectorAll('.delete-btn').forEach(btn => { + btn.addEventListener('click', () => { + const idStr = btn.getAttribute('data-id'); + if (idStr) + deleteMessage(parseInt(idStr)); + }); + }); + } + catch (err) { + container.innerHTML = `

Failed to load messages.

`; + console.error(err); + } + }); +} +document.addEventListener('DOMContentLoaded', () => { + loadMessages(); +}); diff --git a/WebApp/wwwroot/js/userSkills.js b/WebApp/wwwroot/js/userSkills.js index d227ad0..a06859e 100644 --- a/WebApp/wwwroot/js/userSkills.js +++ b/WebApp/wwwroot/js/userSkills.js @@ -35,7 +35,7 @@ document.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, vo unhideElementById(document, "orgno"); } } - catch (_a) { + catch (e) { window.location.href = "login.html"; } var thisAccount = null; @@ -63,7 +63,7 @@ document.addEventListener("DOMContentLoaded", () => __awaiter(void 0, void 0, vo try { const registeredIds = yield getMyRegisteredEventIds(); } - catch (_b) { + catch (e) { } } unhideElementById(document, "mainContainer"); @@ -76,7 +76,7 @@ window.onload = () => { const skillName = dropdown.options[dropdown.selectedIndex].text; const skillId = dropdown.options[dropdown.selectedIndex].value; if (skillName) { - addSkill(skillName, skillId, false); + addSkill(skillName, Number(skillId), false); dropdown.value = ''; // Reset dropdown } }); diff --git a/WebApp/wwwroot/login.html b/WebApp/wwwroot/login.html index 71c3a34..f3f7e82 100644 --- a/WebApp/wwwroot/login.html +++ b/WebApp/wwwroot/login.html @@ -37,7 +37,7 @@
- +
Settings
diff --git a/WebApp/wwwroot/messages.html b/WebApp/wwwroot/messages.html new file mode 100644 index 0000000..3452315 --- /dev/null +++ b/WebApp/wwwroot/messages.html @@ -0,0 +1,111 @@ + + + + + Messages Panel + + + + + + + +
+ + + + +
+ +
+ + + + +
+
+ + +
+

Messages

+
+

Loading messages... please wait.

+
+
+
+ + + + + diff --git a/WebApp/wwwroot/modify.html b/WebApp/wwwroot/modify.html index 6067d2a..02feb3c 100644 --- a/WebApp/wwwroot/modify.html +++ b/WebApp/wwwroot/modify.html @@ -25,7 +25,7 @@
- +
Chats
diff --git a/WebApp/wwwroot/user.html b/WebApp/wwwroot/user.html index 095bc5c..9f5368a 100644 --- a/WebApp/wwwroot/user.html +++ b/WebApp/wwwroot/user.html @@ -24,7 +24,7 @@
- +
Chats
diff --git a/WebApp/wwwroot/view.html b/WebApp/wwwroot/view.html index fba58cc..af8853c 100644 --- a/WebApp/wwwroot/view.html +++ b/WebApp/wwwroot/view.html @@ -24,7 +24,7 @@