Skip to content

Commit

Permalink
feat: detect user sign in and prepare listing address books
Browse files Browse the repository at this point in the history
  • Loading branch information
angelo-v committed Apr 17, 2024
1 parent db435fe commit d9fc8e7
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 55 deletions.
62 changes: 46 additions & 16 deletions contacts/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,15 @@ export namespace Components {
interface PosContactsGroupList {
"groups": Group[];
}
interface PosContactsListAddressBooks {
"webId": string;
}
interface PosContactsLoadingSpinner {
"defer": number;
}
interface PosContactsOpenAddressBook {
"webId": string | undefined;
}
interface PosContactsPhoneNumbers {
"phoneNumbers": PhoneNumber[];
}
Expand All @@ -72,13 +78,13 @@ export interface PosContactsGroupListCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLPosContactsGroupListElement;
}
export interface PosContactsRouterCustomEvent<T> extends CustomEvent<T> {
export interface PosContactsOpenAddressBookCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLPosContactsRouterElement;
target: HTMLPosContactsOpenAddressBookElement;
}
export interface PosContactsWelcomePageCustomEvent<T> extends CustomEvent<T> {
export interface PosContactsRouterCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLPosContactsWelcomePageElement;
target: HTMLPosContactsRouterElement;
}
declare global {
interface HTMLPosContactsAddressBookPageElement extends Components.PosContactsAddressBookPage, HTMLStencilElement {
Expand Down Expand Up @@ -193,12 +199,35 @@ declare global {
prototype: HTMLPosContactsGroupListElement;
new (): HTMLPosContactsGroupListElement;
};
interface HTMLPosContactsListAddressBooksElement extends Components.PosContactsListAddressBooks, HTMLStencilElement {
}
var HTMLPosContactsListAddressBooksElement: {
prototype: HTMLPosContactsListAddressBooksElement;
new (): HTMLPosContactsListAddressBooksElement;
};
interface HTMLPosContactsLoadingSpinnerElement extends Components.PosContactsLoadingSpinner, HTMLStencilElement {
}
var HTMLPosContactsLoadingSpinnerElement: {
prototype: HTMLPosContactsLoadingSpinnerElement;
new (): HTMLPosContactsLoadingSpinnerElement;
};
interface HTMLPosContactsOpenAddressBookElementEventMap {
"pod-os-contacts:open-address-book": string;
}
interface HTMLPosContactsOpenAddressBookElement extends Components.PosContactsOpenAddressBook, HTMLStencilElement {
addEventListener<K extends keyof HTMLPosContactsOpenAddressBookElementEventMap>(type: K, listener: (this: HTMLPosContactsOpenAddressBookElement, ev: PosContactsOpenAddressBookCustomEvent<HTMLPosContactsOpenAddressBookElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLPosContactsOpenAddressBookElementEventMap>(type: K, listener: (this: HTMLPosContactsOpenAddressBookElement, ev: PosContactsOpenAddressBookCustomEvent<HTMLPosContactsOpenAddressBookElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLPosContactsOpenAddressBookElement: {
prototype: HTMLPosContactsOpenAddressBookElement;
new (): HTMLPosContactsOpenAddressBookElement;
};
interface HTMLPosContactsPhoneNumbersElement extends Components.PosContactsPhoneNumbers, HTMLStencilElement {
}
var HTMLPosContactsPhoneNumbersElement: {
Expand All @@ -222,18 +251,7 @@ declare global {
prototype: HTMLPosContactsRouterElement;
new (): HTMLPosContactsRouterElement;
};
interface HTMLPosContactsWelcomePageElementEventMap {
"pod-os-contacts:open-address-book": string;
}
interface HTMLPosContactsWelcomePageElement extends Components.PosContactsWelcomePage, HTMLStencilElement {
addEventListener<K extends keyof HTMLPosContactsWelcomePageElementEventMap>(type: K, listener: (this: HTMLPosContactsWelcomePageElement, ev: PosContactsWelcomePageCustomEvent<HTMLPosContactsWelcomePageElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLPosContactsWelcomePageElementEventMap>(type: K, listener: (this: HTMLPosContactsWelcomePageElement, ev: PosContactsWelcomePageCustomEvent<HTMLPosContactsWelcomePageElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLPosContactsWelcomePageElement: {
prototype: HTMLPosContactsWelcomePageElement;
Expand All @@ -251,7 +269,9 @@ declare global {
"pos-contacts-group": HTMLPosContactsGroupElement;
"pos-contacts-group-details": HTMLPosContactsGroupDetailsElement;
"pos-contacts-group-list": HTMLPosContactsGroupListElement;
"pos-contacts-list-address-books": HTMLPosContactsListAddressBooksElement;
"pos-contacts-loading-spinner": HTMLPosContactsLoadingSpinnerElement;
"pos-contacts-open-address-book": HTMLPosContactsOpenAddressBookElement;
"pos-contacts-phone-numbers": HTMLPosContactsPhoneNumbersElement;
"pos-contacts-router": HTMLPosContactsRouterElement;
"pos-contacts-welcome-page": HTMLPosContactsWelcomePageElement;
Expand Down Expand Up @@ -301,17 +321,23 @@ declare namespace LocalJSX {
"groups"?: Group[];
"onPod-os-contacts:group-selected"?: (event: PosContactsGroupListCustomEvent<Group>) => void;
}
interface PosContactsListAddressBooks {
"webId": string;
}
interface PosContactsLoadingSpinner {
"defer"?: number;
}
interface PosContactsOpenAddressBook {
"onPod-os-contacts:open-address-book"?: (event: PosContactsOpenAddressBookCustomEvent<string>) => void;
"webId"?: string | undefined;
}
interface PosContactsPhoneNumbers {
"phoneNumbers": PhoneNumber[];
}
interface PosContactsRouter {
"onPod-os:init"?: (event: PosContactsRouterCustomEvent<any>) => void;
}
interface PosContactsWelcomePage {
"onPod-os-contacts:open-address-book"?: (event: PosContactsWelcomePageCustomEvent<string>) => void;
}
interface IntrinsicElements {
"pos-contacts-address-book-page": PosContactsAddressBookPage;
Expand All @@ -325,7 +351,9 @@ declare namespace LocalJSX {
"pos-contacts-group": PosContactsGroup;
"pos-contacts-group-details": PosContactsGroupDetails;
"pos-contacts-group-list": PosContactsGroupList;
"pos-contacts-list-address-books": PosContactsListAddressBooks;
"pos-contacts-loading-spinner": PosContactsLoadingSpinner;
"pos-contacts-open-address-book": PosContactsOpenAddressBook;
"pos-contacts-phone-numbers": PosContactsPhoneNumbers;
"pos-contacts-router": PosContactsRouter;
"pos-contacts-welcome-page": PosContactsWelcomePage;
Expand All @@ -346,7 +374,9 @@ declare module "@stencil/core" {
"pos-contacts-group": LocalJSX.PosContactsGroup & JSXBase.HTMLAttributes<HTMLPosContactsGroupElement>;
"pos-contacts-group-details": LocalJSX.PosContactsGroupDetails & JSXBase.HTMLAttributes<HTMLPosContactsGroupDetailsElement>;
"pos-contacts-group-list": LocalJSX.PosContactsGroupList & JSXBase.HTMLAttributes<HTMLPosContactsGroupListElement>;
"pos-contacts-list-address-books": LocalJSX.PosContactsListAddressBooks & JSXBase.HTMLAttributes<HTMLPosContactsListAddressBooksElement>;
"pos-contacts-loading-spinner": LocalJSX.PosContactsLoadingSpinner & JSXBase.HTMLAttributes<HTMLPosContactsLoadingSpinnerElement>;
"pos-contacts-open-address-book": LocalJSX.PosContactsOpenAddressBook & JSXBase.HTMLAttributes<HTMLPosContactsOpenAddressBookElement>;
"pos-contacts-phone-numbers": LocalJSX.PosContactsPhoneNumbers & JSXBase.HTMLAttributes<HTMLPosContactsPhoneNumbersElement>;
"pos-contacts-router": LocalJSX.PosContactsRouter & JSXBase.HTMLAttributes<HTMLPosContactsRouterElement>;
"pos-contacts-welcome-page": LocalJSX.PosContactsWelcomePage & JSXBase.HTMLAttributes<HTMLPosContactsWelcomePageElement>;
Expand Down
7 changes: 6 additions & 1 deletion contacts/src/components/app.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { Component, h } from '@stencil/core';
import { Component, h, Listen } from '@stencil/core';

import '@pod-os/elements';

@Component({
tag: 'pos-contacts-app',
})
export class App {
@Listen('pod-os:session-changed')
sessionChanged(ev) {
console.log('app session changed', ev.detail);
}

render() {
return (
<pos-app>
Expand Down
12 changes: 12 additions & 0 deletions contacts/src/components/list-address-books/list-address-books.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component, h, Prop } from '@stencil/core';

@Component({
tag: 'pos-contacts-list-address-books',
})
export class ListAddressBooks {
@Prop()
webId!: string;
render() {
return <div>TODO: list address books of {this.webId}</div>;
}
}
33 changes: 33 additions & 0 deletions contacts/src/components/open-address-book/open-address-book.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#container {
display: flex;
flex-direction: column;
gap: var(--size-5);
align-items: flex-start;
}

#sign-in {
display: flex;
gap: var(--size-1);
align-items: center;
color: var(--color-grey-800);
font-weight: var(--weight-light);
}

button.open {
white-space: nowrap;
font-size: var(--scale-1);
border-radius: var(--radius-xs);
padding: var(--size-2);
background-color: white;
color: var(--pos-primary-color);
border: 1px solid var(--color-blue-700);
display: flex;
align-items: center;
gap: var(--size-2);
}


button.open:hover {
background-color: var(--color-grey-50);
filter: brightness(90%);
}
48 changes: 48 additions & 0 deletions contacts/src/components/open-address-book/open-address-book.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { SessionInfo } from '@pod-os/core';
import { Component, Event, EventEmitter, h, Listen, Prop, State } from '@stencil/core';

@Component({
tag: 'pos-contacts-open-address-book',
shadow: true,
styleUrl: 'open-address-book.css',
})
export class OpenAddressBook {
@Event({ eventName: 'pod-os-contacts:open-address-book' }) openAddressBook: EventEmitter<string>;

@State()
sessionInfo: SessionInfo | undefined;

@Listen('pod-os:session-changed', { target: 'window' })
sessionChanged(event: CustomEvent<SessionInfo>) {
this.sessionInfo = event.detail;
}

@Prop()
webId: string | undefined;

promptAndOpen() {
const uri = prompt('Please enter URI of an address book', 'http://localhost:3000/alice/public-contacts/index.ttl#this');
if (uri) {
this.openAddressBook.emit(uri);
}
}

render() {
return (
<div id="container">
{this.sessionInfo?.isLoggedIn ? (
<pos-contacts-list-address-books webId={this.sessionInfo.webId} />
) : (
<div id="sign-in">
<pos-login></pos-login>
Sign in to list your address books.
</div>
)}
<button title="open any other address book by it's URI" class="open" onClick={() => this.promptAndOpen()}>
<ion-icon name="folder-open-outline"></ion-icon>
open other
</button>
</div>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { SessionInfo } from '@pod-os/core';
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { fireEvent } from '@testing-library/dom';
import { OpenAddressBook } from '../open-address-book';

describe('open address book', () => {
let page;
beforeEach(async () => {
page = await newSpecPage({
components: [OpenAddressBook],
template: () => <pos-contacts-open-address-book />,
supportsShadowDom: false,
});
});

it('renders', () => {
expect(page.root).toEqualHtml(`
<pos-contacts-open-address-book>
<div id="container">
<div id="sign-in">
<pos-login></pos-login>
Sign in to list your address books.
</div>
<button class="open" title="open any other address book by it's URI">
<ion-icon name="folder-open-outline"></ion-icon>
open other
</button>
</div>
</pos-contacts-open-address-book>`);
});

it('lists address books after login', async () => {
const sessionInfo: SessionInfo = {
isLoggedIn: true,
webId: 'https://alice.test/profile/card#me',
sessionId: 'test',
};
fireEvent(
window,
new CustomEvent('pod-os:session-changed', {
detail: sessionInfo,
}),
);
await page.waitForChanges();
expect(page.root).toEqualHtml(`
<pos-contacts-open-address-book>
<div id="container">
<pos-contacts-list-address-books webid="https://alice.test/profile/card#me"></pos-contacts-list-address-books>
<button class="open" title="open any other address book by it's URI">
<ion-icon name="folder-open-outline"></ion-icon>
open other
</button>
</div>
</pos-contacts-open-address-book>
`);
});
});
29 changes: 29 additions & 0 deletions contacts/src/components/welcome-page/test/welcome-page.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { h } from '@stencil/core';
import { newSpecPage } from '@stencil/core/testing';
import { WelcomePage } from '../welcome-page';

describe('welcome page', () => {
let page;
beforeEach(async () => {
page = await newSpecPage({
components: [WelcomePage],
template: () => <pos-contacts-welcome-page />,
supportsShadowDom: false,
});
});

it('allows to sign in and open address book before login', () => {
expect(page.root).toEqualHtml(`
<pos-contacts-welcome-page>
<header>
<h1>
PodOS contacts
</h1>
<pos-login></pos-login>
</header>
<main>
<pos-contacts-open-address-book></pos-contacts-open-address-book>
</main>
</pos-contacts-welcome-page>`);
});
});
21 changes: 0 additions & 21 deletions contacts/src/components/welcome-page/welcome-page.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ header {
padding: var(--size-10);
}


main {
grid-area: main;
margin: var(--size-10);
Expand All @@ -24,26 +23,6 @@ main {
padding: var(--size-4)
}

button.open {
color: white;
font-size: var(--scale-1);
border-radius: var(--radius-xs);
font-weight: var(--weight-bold);
padding: var(--size-4);
background-color: var(--color-blue-700);
border: 1px solid var(--color-blue-500);
box-shadow: var(--shadow-md);
display: flex;
align-items: center;
gap: var(--size-2);
}


button.open:hover {
cursor: pointer;
filter: brightness(110%);
}

.toolbar {
display: flex;
justify-items: center;
Expand Down
Loading

0 comments on commit d9fc8e7

Please sign in to comment.