-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from theRealImy/add-me-to-your-friends
implemneted feature 'add me to your friends' #8
- Loading branch information
Showing
12 changed files
with
329 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
lib | ||
node_modules | ||
node_modules | ||
.history | ||
.vscode |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
import { html, TemplateResult } from "lit-html"; | ||
import { styleMap } from "lit-html/directives/style-map"; | ||
import { DataBrowserContext, LiveStore } from "pane-registry"; | ||
import { rdf, widgets, authn, ns } from "solid-ui"; | ||
import { complain, mention, clearPreviousMessage } from "./addMeToYourFriendsHelper"; | ||
import { padding, textCenter } from "./baseStyles"; | ||
import { | ||
logInAddMeToYourFriendsButtonText, | ||
friendExistsAlreadyButtonText, | ||
addMeToYourFriendsButtonText, | ||
friendWasAddedSuccesMessage, | ||
userNotLoggedInErrorMessage, | ||
friendExistsMessage, | ||
internalErrorMessage, | ||
} from "./texts"; | ||
|
||
let buttonContainer = <HTMLDivElement>document.createElement("div"); | ||
|
||
//panel local style | ||
const styles = { | ||
button: styleMap({ ...textCenter(), ...padding() }), | ||
}; | ||
|
||
const addMeToYourFriendsDiv = ( | ||
subject: rdf.NamedNode, | ||
context: DataBrowserContext | ||
): TemplateResult => { | ||
buttonContainer = context.dom.createElement("div"); | ||
const button = createAddMeToYourFriendsButton(subject, context); | ||
buttonContainer.appendChild(button); | ||
return html` <div style="${styles.button}">${buttonContainer}</div> `; | ||
}; | ||
|
||
const createAddMeToYourFriendsButton = ( | ||
subject: rdf.NamedNode, | ||
context: DataBrowserContext | ||
): HTMLButtonElement => { | ||
const button = widgets.button( | ||
context.dom, | ||
undefined, | ||
logInAddMeToYourFriendsButtonText, | ||
setButtonHandler, //sets an onclick event listener | ||
{ | ||
needsBorder: true, | ||
} | ||
); | ||
|
||
function setButtonHandler(event) { | ||
event.preventDefault(); | ||
saveNewFriend(subject, context) | ||
.then(() => { | ||
clearPreviousMessage(buttonContainer); | ||
mention(buttonContainer, friendWasAddedSuccesMessage); | ||
refreshButton(); | ||
}) | ||
.catch((error) => { | ||
clearPreviousMessage(buttonContainer); | ||
//else UI.widgets.complain(buttonContainer, message); //displays an error message at the top of the window | ||
complain(buttonContainer, context, error); | ||
}); | ||
} | ||
|
||
button.refresh = refreshButton(); | ||
|
||
function refreshButton() { | ||
const me = authn.currentUser(); | ||
const store = context.session.store; | ||
|
||
if (checkIfAnyUserLoggedIn(me)) { | ||
checkIfFriendExists(store, me, subject).then((friendExists) => { | ||
if (friendExists) { | ||
//logged in and friend exists or friend was just added | ||
button.innerHTML = friendExistsAlreadyButtonText.toUpperCase(); | ||
button.setAttribute("class", "textButton-0-1-3"); //style of 'Primary' UI button with needsBorder=true | ||
} else { | ||
//logged in and friend does not exist yet | ||
button.innerHTML = addMeToYourFriendsButtonText.toUpperCase(); | ||
button.setAttribute("class", "textButton-0-1-2"); //style of 'Primary' UI button with needsBorder=false | ||
} | ||
}); | ||
} else { | ||
//not logged in | ||
button.innerHTML = logInAddMeToYourFriendsButtonText.toUpperCase(); | ||
button.setAttribute("class", "textButton-0-1-3"); //style of 'Primary' UI button with needsBorder=false | ||
} | ||
} | ||
|
||
return button; | ||
}; | ||
|
||
async function saveNewFriend(subject: rdf.NamedNode, context: DataBrowserContext): Promise<void> { | ||
const me = authn.currentUser(); | ||
const store = context.session.store; | ||
|
||
if (checkIfAnyUserLoggedIn(me)) { | ||
if (!(await checkIfFriendExists(store, me, subject))) { | ||
//if friend does not exist, we add her/him | ||
await store.fetcher.load(me); | ||
const updater = store.updater; | ||
const toBeInserted = [rdf.st(me, ns.foaf("knows"), subject, me.doc())]; | ||
try { | ||
await updater.update([], toBeInserted); | ||
} catch (error) { | ||
let errorMessage = error; | ||
if (errorMessage.toString().includes("Unauthenticated")) | ||
errorMessage = userNotLoggedInErrorMessage; | ||
throw new Error(errorMessage); | ||
} | ||
} else throw new Error(friendExistsMessage); | ||
} else throw new Error(userNotLoggedInErrorMessage); | ||
} | ||
|
||
function checkIfAnyUserLoggedIn(me: rdf.NamedNode): boolean { | ||
if (me) return true; | ||
else return false; | ||
} | ||
|
||
async function checkIfFriendExists( | ||
store: LiveStore, | ||
me: rdf.NamedNode, | ||
subject: rdf.NamedNode | ||
): Promise<boolean> { | ||
await store.fetcher.load(me); | ||
if (store.whether(me, ns.foaf("knows"), subject, me.doc()) === 0) return false; | ||
else return true; | ||
} | ||
|
||
//Because the code has unhandled Promises we still want to signal the user a message. | ||
//Console will contain actual error. | ||
window.addEventListener("unhandledrejection", function () { | ||
clearPreviousMessage(buttonContainer); | ||
buttonContainer.appendChild(widgets.errorMessageBlock(window.document, internalErrorMessage)); | ||
}); | ||
|
||
export { | ||
addMeToYourFriendsDiv, | ||
createAddMeToYourFriendsButton, | ||
saveNewFriend, | ||
checkIfAnyUserLoggedIn, | ||
checkIfFriendExists, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { DataBrowserContext } from "pane-registry"; | ||
import { widgets } from "solid-ui"; | ||
|
||
function complain( | ||
buttonContainer: HTMLDivElement, | ||
context: DataBrowserContext, | ||
error: string | ||
): void { | ||
buttonContainer.appendChild(widgets.errorMessageBlock(context.dom, error)); | ||
} | ||
|
||
//TODO create positive frontend message component on UI | ||
function mention(buttonContainer: HTMLDivElement, message: string): void { | ||
const positiveFrontendMessageDiv = <HTMLDivElement>document.createElement("div"); | ||
positiveFrontendMessageDiv.setAttribute( | ||
"style", | ||
"margin: 0.1em; padding: 0.5em; border: 0.05em solid gray; background-color: #efe; color:black;" | ||
); | ||
//positiveFrontendMessageDiv.setAttribute('style', UI.style.messageBodyStyle) -> using UI but missing green backgroung color | ||
positiveFrontendMessageDiv.innerHTML = message; | ||
buttonContainer.appendChild(positiveFrontendMessageDiv); | ||
} | ||
|
||
function clearPreviousMessage(buttonContainer: HTMLDivElement): void { | ||
while (buttonContainer.childNodes.length > 1) { | ||
buttonContainer.removeChild(buttonContainer.lastChild); | ||
} | ||
} | ||
|
||
export { complain, mention, clearPreviousMessage }; |
2 changes: 1 addition & 1 deletion
2
src/CVPresenter.spec.ts → src/integration-tests/CVPresenter.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
src/integration-tests/add-me-to-your-friends-functions.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { context, subject } from "./setup"; | ||
import { addMeToYourFriendsDiv, checkIfAnyUserLoggedIn, checkIfFriendExists, createAddMeToYourFriendsButton, saveNewFriend } from "../addMeToYourFriends"; | ||
|
||
describe("add-me-to-your-friends functions", () => { | ||
describe("addMeToYourFriendsDiv", () => { | ||
it("exists", () => { | ||
expect(addMeToYourFriendsDiv).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(addMeToYourFriendsDiv(subject, context)).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe("createAddMeToYourFriendsButton", () => { | ||
it("exists", () => { | ||
expect(createAddMeToYourFriendsButton).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(createAddMeToYourFriendsButton(subject, context)).toBeTruthy(); | ||
}); | ||
}); | ||
|
||
describe("saveNewFriend", () => { | ||
it("exists", () => { | ||
expect(saveNewFriend).toBeInstanceOf(Function); | ||
}); | ||
|
||
}); | ||
|
||
describe("checkIfAnyUserLoggedIn", () => { | ||
it("exists", () => { | ||
expect(checkIfAnyUserLoggedIn).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(checkIfAnyUserLoggedIn(subject)).toBe(true); | ||
expect(checkIfAnyUserLoggedIn(null)).toBe(false); | ||
expect(checkIfAnyUserLoggedIn(undefined)).toBe(false); | ||
}); | ||
}); | ||
|
||
describe("checkIfFriendExists", () => { | ||
it("exists", () => { | ||
expect(checkIfFriendExists).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(checkIfFriendExists(context.session.store, subject, subject)).toBeTruthy(); | ||
expect(checkIfFriendExists(context.session.store, subject, subject)).toBeInstanceOf(Promise); | ||
}); | ||
}); | ||
|
||
}); | ||
|
||
|
46 changes: 46 additions & 0 deletions
46
src/integration-tests/add-me-to-your-friends-helper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { clearPreviousMessage, complain, mention } from "../addMeToYourFriendsHelper"; | ||
import { context } from "./setup"; | ||
|
||
describe("add me to your friends helper functions", () => { | ||
let buttonContainer: HTMLDivElement; | ||
let error: string; | ||
|
||
beforeAll(() => { | ||
buttonContainer = context.dom.createElement("div"); | ||
const button = context.dom.createElement("button"); | ||
buttonContainer.appendChild(button); | ||
error = "error"; | ||
}); | ||
describe("complain", () => { | ||
it("exists", () => { | ||
expect(complain).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(complain(buttonContainer, context, error)).toEqual(undefined); | ||
expect(buttonContainer.childNodes.length).toBe(2); | ||
}); | ||
}); | ||
|
||
describe("mention", () => { | ||
it("exists", () => { | ||
expect(mention).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(mention(buttonContainer, error)).toEqual(undefined); | ||
expect(buttonContainer.childNodes.length).toBe(3); | ||
}); | ||
}); | ||
|
||
describe("clearPreviousMessage", () => { | ||
it("exists", () => { | ||
expect(clearPreviousMessage).toBeInstanceOf(Function); | ||
}); | ||
|
||
it("runs", () => { | ||
expect(clearPreviousMessage(buttonContainer)).toEqual(undefined); | ||
expect(buttonContainer.childNodes.length).toBe(1); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { context, subject } from "./setup"; | ||
import pane from "../"; | ||
import { findByText, fireEvent } from "@testing-library/dom"; | ||
import { logInAddMeToYourFriendsButtonText, userNotLoggedInErrorMessage } from "../texts"; | ||
|
||
describe("add-me-to-your-friends pane", () => { | ||
describe("saveNewFriend with NO logged in user", () => { | ||
let result; | ||
beforeAll(() => { | ||
result = pane.render(subject, context); | ||
}); | ||
|
||
it("renders the Add me to friends button", async () => { | ||
const button = await findByText(result, logInAddMeToYourFriendsButtonText.toUpperCase()); | ||
expect(button).not.toBeNull(); | ||
}); | ||
|
||
it("saveNewFriend with user NOT logged in", async () => { | ||
const button = await findByText(result, logInAddMeToYourFriendsButtonText.toUpperCase()); | ||
fireEvent.click(button); | ||
const errorMessage = await findByText(result, userNotLoggedInErrorMessage); | ||
expect(errorMessage).not.toBeNull(); | ||
expect(button).toThrowError; | ||
}); | ||
}); | ||
}); | ||
|
2 changes: 1 addition & 1 deletion
2
src/presenter.spec.ts → src/integration-tests/presenter.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
//ERRORS & SUCCESS | ||
//Same 'not logged in' error message like on 'Chat with me' button | ||
export const userNotLoggedInErrorMessage = "Current user not found! Not logged in?"; | ||
export const internalErrorMessage = "An internal error occured!"; | ||
export const friendWasAddedSuccesMessage = "Friend was added!"; | ||
|
||
//OTHER | ||
export const friendExistsMessage = "Friend already exists"; | ||
export const loadingMessage = "Loading..."; | ||
|
||
//BUTTONS | ||
export const addMeToYourFriendsButtonText = "Add me to your friend list"; | ||
export const logInAddMeToYourFriendsButtonText = "Login to add me to your friend list"; | ||
export const friendExistsAlreadyButtonText = "Already part of friend list"; | ||
export const chatWithMeButtonText = "Chat with me"; | ||
|
||
|