![Image of {this.state.name}]()
`,
style: `
- a {
- text-decoration: none;
- color: inherit;
- }
-
- a:hover {
- text-decoration: underline;
- }
-
.product-listing {
display: flex;
flex-direction: column;
margin: 7px;
max-width: 320px;
}
+
.product-listing-image {
display: block;
margin: 0 auto;
max-width: 100%;
}
+
+ .product-image:hover {
+ cursor: hand;
+ }
+
.product-listing-info {
display: flex;
align-items: flex-start;
flex-direction: column;
max-width: 100%;
}
+
.product-listing-name {
font-size: 1.2em;
font-weight: bold;
}
+ .product-listing-name:hover {
+ cursor: hand;
+ text-decoration: underline;
+ }
+
.product-listing-price {
font-size: 1.1em;
}
@@ -90,8 +92,29 @@ class CompactProductListing extends Component {
};
}
- OnceRendered() {
+ OpenProductListing() {
+ const location = document.querySelector('#current-open-listing');
+ // Make sure there is not already a product listing open
+ if (window.getComputedStyle(location).display !== 'none') {
+ return;
+ }
+ // Open the product listing
+ const productListing = document.createElement('product-listing-component');
+ productListing.setAttribute('id', this.state.id);
+ productListing.setAttribute('type', this.state.type);
+ location.appendChild(productListing);
+ location.style.display = 'block';
+ }
+ OnRender() {
+ const image = this.root.querySelector('.product-image');
+ const name = this.root.querySelector('.product-listing-name');
+ image.addEventListener('click', () => {
+ this.OpenProductListing(Object.bind(this));
+ });
+ name.addEventListener('click', () => {
+ this.OpenProductListing(Object.bind(this));
+ });
}
}
diff --git a/client/public/components/components.mjs b/client/public/components/components.mjs
index 394bdc2..10ce1fb 100644
--- a/client/public/components/components.mjs
+++ b/client/public/components/components.mjs
@@ -28,10 +28,10 @@ export class Component extends HTMLElement {
}
// Override these
- PostLoad() { }
+ OnMount() { }
Update() { }
Render() { Component.__WARN('Render'); }
- OnceRendered() { Component.__WARN('Render'); }
+ OnRender() { Component.__WARN('Render'); }
static __IDENTIFY() { Component.__WARN('identify'); }
connectedCallback() {
@@ -45,12 +45,14 @@ export class Component extends HTMLElement {
for (const attribute of this.attributes) {
stateUpdateQueue = { ...stateUpdateQueue, [attribute.name]: attribute.value };
}
- this.setState(stateUpdateQueue);
+ this.state = stateUpdateQueue;
- this.PostLoad(Object.bind(this));
+ this.OnMount(Object.bind(this));
this.Update(Object.bind(this));
+ this.setState(this.state);
+
if (this.attributes.length === 0) {
this.__INVOKE_RENDER(Object.bind(this));
}
@@ -141,7 +143,7 @@ export class Component extends HTMLElement {
style.textContent = res.style;
this.root.appendChild(style);
- this.OnceRendered();
+ this.OnRender();
}
static __WARN(caller) {
diff --git a/src/__test/.eslintignore b/client/public/components/css/product-listing.css
similarity index 100%
rename from src/__test/.eslintignore
rename to client/public/components/css/product-listing.css
diff --git a/client/public/components/navbar.mjs b/client/public/components/navbar.mjs
index d18cd25..02174fa 100644
--- a/client/public/components/navbar.mjs
+++ b/client/public/components/navbar.mjs
@@ -14,7 +14,7 @@ class NavBar extends Component {
};
}
- OnceRendered() {
+ OnRender() {
const menuToggler = document.querySelector('navbar-component').shadowRoot.querySelector('#menu-toggler');
const navMenu = document.querySelector('navbar-component').shadowRoot.querySelector('.navbar');
diff --git a/client/public/components/notificationbar.mjs b/client/public/components/notificationbar.mjs
index 69d8dca..a83e84b 100644
--- a/client/public/components/notificationbar.mjs
+++ b/client/public/components/notificationbar.mjs
@@ -23,7 +23,7 @@ class NotificationBar extends Component {
};
}
- async PostLoad() {
+ async OnMount() {
const data = await fetch('/api/special').then(response => response.json());
const { days, hours, minutes, seconds } = this.daysHoursMinutesSecondsUntil(data.data.end);
@@ -51,12 +51,17 @@ class NotificationBar extends Component {
};
}
- OnceRendered() {
+ OnRender() {
// expect only one notification bar on the dom (otherwise this won't work)
const notificationToggler = document.querySelector('notificationbar-component').shadowRoot.querySelector('.notification-toggler');
const notificationBar = document.querySelector('notificationbar-component').shadowRoot.querySelector('.notification-bar');
notificationToggler.addEventListener('click', () => {
+ this.setState({
+ ...this.getState,
+ isOpen: !this.getState.isOpen,
+ });
+
notificationBar.classList.add('notification-toggled');
});
}
diff --git a/client/public/components/product-list.mjs b/client/public/components/product-list.mjs
index 243ff7f..6cca3ab 100644
--- a/client/public/components/product-list.mjs
+++ b/client/public/components/product-list.mjs
@@ -21,6 +21,7 @@ class ProductList extends Component {
listing="${product.listing}"
image="${product.image}"
price="${product.price}"
+ type="${product.type}"
discount="${product.discount || ''}">
`;
}).join('')}
@@ -133,7 +134,7 @@ class ProductList extends Component {
}
- OnceRendered() {
+ OnRender() {
}
diff --git a/client/public/components/product-listing.mjs b/client/public/components/product-listing.mjs
index 114c884..d6c4f69 100644
--- a/client/public/components/product-listing.mjs
+++ b/client/public/components/product-listing.mjs
@@ -1,4 +1,4 @@
-import { RegisterComponent, Component } from './components.mjs';
+import { RegisterComponent, Component, SideLoad } from './components.mjs';
class ProductListing extends Component {
static __IDENTIFY() { return 'product-listing'; }
@@ -7,14 +7,21 @@ class ProductListing extends Component {
super(ProductListing);
}
- async Render() {
- const route = this.state.getroute;
- const productDetails = await fetch(route).then(response => response.json());
+ OnMount() {
+ console.log(this.state);
}
+ async Render() {
+ const route = this.getState.getroute;
+ // const productDetails = await fetch(route).then(response => response.json());
- OnceRendered() {
+ return {
+ template: SideLoad('./components/templates/product-listing.html'),
+ style: SideLoad('./components/css/product-listing.css'),
+ };
+ }
+ OnRender() {
}
}
diff --git a/client/public/components/storefront.mjs b/client/public/components/storefront.mjs
index 4f3b6c6..afb39e6 100644
--- a/client/public/components/storefront.mjs
+++ b/client/public/components/storefront.mjs
@@ -12,7 +12,8 @@ class StoreFront extends Component {
template: `
+ getroute="/api/sets/featured"
+ type="set">
`,
style: `
@@ -23,7 +24,7 @@ class StoreFront extends Component {
};
}
- OnceRendered() {
+ OnRender() {
}
}
diff --git a/client/public/components/templates/product-listing.html b/client/public/components/templates/product-listing.html
new file mode 100644
index 0000000..e69de29
diff --git a/client/public/index.html b/client/public/index.html
index 50759e8..7f10098 100644
--- a/client/public/index.html
+++ b/client/public/index.html
@@ -26,6 +26,8 @@
+
+
diff --git a/docs/CLIENT-FRAMEWORK.md b/docs/CLIENT-FRAMEWORK.md
index 63a627c..10e5cca 100644
--- a/docs/CLIENT-FRAMEWORK.md
+++ b/docs/CLIENT-FRAMEWORK.md
@@ -90,7 +90,7 @@ State is updated with `setState()`.
Within the HTML, any instance of `{this.state.}` will be replaced with
the internal state of the component.
-The `PostLoad` method is called once the component has been loaded and
+The `OnMount` method is called once the component has been loaded and
attatched to the DOM. This is where you can do any post-load setup.
It is only called once and it's return value becomes the state of the
component.
diff --git a/package.json b/package.json
index 43516f4..277bcae 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"description": "",
"main": "index.js",
"scripts": {
- "test": "jest src/__test",
+ "test": "jest src/__test client/public/__test",
"start": "node src/index.js",
"dev": "nodemon src/index.js --watch src",
"lint": "eslint src --ext .js && eslint client --ext .js",
diff --git a/src/__test/tests.test.js b/src/__test/tests.test.js
index c1752a1..e316da6 100644
--- a/src/__test/tests.test.js
+++ b/src/__test/tests.test.js
@@ -1,3 +1,4 @@
+/* eslint-disable */
test('Sanity Check', () => {
expect(1 + 1).toBe(2);
diff --git a/src/routes/sets-router.js b/src/routes/sets-router.js
index 655440c..a44015e 100644
--- a/src/routes/sets-router.js
+++ b/src/routes/sets-router.js
@@ -10,12 +10,14 @@ function Featured(req, res, next) {
name: 'Tail 4 x 1 x 3',
price: '1.00',
discount: '0.50',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '2',
name: 'Mini Doll Hips and Skirt Full Length with Stars Pattern (Ariel)',
price: '2.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
@@ -23,36 +25,42 @@ function Featured(req, res, next) {
name: 'Minecraft Polar Bear Baby - Brick Built',
price: '3.00',
discount: '0.50',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '3',
name: 'Cardboard Sleeve 46931 with Contents',
price: '3.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '3',
name: 'Train Wheel RC, Holder with 2 Black Train Wheel and Chrome Silver Train Wheel, Metal Axle with Slots (2878 / 2879 / bb0837)',
price: '3.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '3',
name: 'Minifigure, Weapon Bazooka, Mini Blaster / Shooter',
price: '3.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '3',
name: 'Minifigure, Weapon Bazooka, Mini Blaster / Shooter',
price: '3.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
{
id: '3',
name: 'Minifigure, Weapon Bazooka, Mini Blaster / Shooter',
price: '3.00',
+ type: 'set',
image: 'https://via.placeholder.com/320x320',
},
],