Refactor codebase. Functioning item list
This commit is contained in:
parent
a9eaa5dbde
commit
37401a85c8
20
index.html
20
index.html
|
|
@ -8,8 +8,24 @@
|
||||||
<link rel="icon" href="./favicon.ico" type="image/x-icon">
|
<link rel="icon" href="./favicon.ico" type="image/x-icon">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module" src="src/main.js" defer></script>
|
<script type="module" src="src/components/app-base.js" defer></script>
|
||||||
<main id="root"></main>
|
<script type="module" src="src/components/main-window.js" defer></script>
|
||||||
|
<script type="module" src="src/components/custom-button.js" defer></script>
|
||||||
|
<script type="module" src="src/components/item-list.js" defer></script>
|
||||||
|
<style>
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
background: transparent linear-gradient(135deg, #A1C4FD 0%, #C2E9FB 100%) 0% 0% no-repeat padding-box;
|
||||||
|
opacity: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<app-base></app-base>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ import Store from '../modules/store.js';
|
||||||
import text from '../modules/text.js';
|
import text from '../modules/text.js';
|
||||||
|
|
||||||
class AppBase extends HTMLElement {
|
class AppBase extends HTMLElement {
|
||||||
static observedAttributes = ['title', 'description'];
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.attachShadow({ mode: 'open' });
|
this.attachShadow({ mode: 'open' });
|
||||||
|
|
@ -14,25 +12,18 @@ class AppBase extends HTMLElement {
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.store.subscribe(this.render.bind(this));
|
this.store.subscribe(this.render.bind(this));
|
||||||
this.render();
|
this.render();
|
||||||
|
|
||||||
console.log('Component constructed', this);
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnectedCallback() {
|
|
||||||
console.log('Component disconnected', this);
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeChangedCallback() {
|
|
||||||
this.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderText() {
|
renderText() {
|
||||||
const textList = this.store.getRecords();
|
const textList = this.store.getRecords();
|
||||||
const selected = this.store.getSelected();
|
return textList.map((item) => `<option value=${item.id}>${item.text}</option>`).join('\n');
|
||||||
return textList.map((item) => `<option value=${item.id} ${selected.includes(item.id) && "selected"}>${item.text}</option>`).join('\n');
|
}
|
||||||
|
|
||||||
|
render(action = 'INITIAL') {
|
||||||
|
if (![Store.actions.ADD_LINE, Store.actions.REMOVE_LINE, Store.actions.UNDO, 'INITIAL'].includes(action)) {
|
||||||
|
return; // Only render if content changed
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
|
||||||
this.shadowRoot.innerHTML = `
|
this.shadowRoot.innerHTML = `
|
||||||
<main-window title="${this.text.title}" description="${this.text.description}">
|
<main-window title="${this.text.title}" description="${this.text.description}">
|
||||||
<select multiple is="item-list">
|
<select multiple is="item-list">
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,10 @@ class CustomButton extends HTMLElement {
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.render();
|
this.render();
|
||||||
this.shadowRoot.getElementById('button').addEventListener('click', this.onClick.bind(this));
|
this.shadowRoot.getElementById('button').addEventListener('click', this.onClick.bind(this));
|
||||||
|
|
||||||
console.log('Component constructed', this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
this.shadowRoot.getElementById('button').removeEventListener('click', this.onClick);
|
this.shadowRoot.getElementById('button').removeEventListener('click', this.onClick);
|
||||||
|
|
||||||
console.log('Component disconnected', this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeChangedCallback() {
|
attributeChangedCallback() {
|
||||||
|
|
@ -52,7 +48,9 @@ class CustomButton extends HTMLElement {
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<button id="button"><slot></slot></button>
|
<button id="button">
|
||||||
|
<slot></slot>
|
||||||
|
</button>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,23 +9,15 @@ class ItemList extends HTMLSelectElement {
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.addEventListener('click', this.onChange.bind(this));
|
this.addEventListener('click', this.onChange.bind(this));
|
||||||
this.updateStyle();
|
this.updateStyle();
|
||||||
|
|
||||||
console.log('Component constructed', this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange() {
|
onChange() {
|
||||||
const selectedIds = Array.from(this.selectedOptions).map((option) => option.value);
|
const selectedIds = Array.from(this.selectedOptions).map((option) => +option.value);
|
||||||
this.publish(Store.actions.SELECT, selectedIds);
|
this.publish(Store.actions.SELECT, selectedIds);
|
||||||
}
|
}
|
||||||
|
|
||||||
disconnectedCallback() {
|
disconnectedCallback() {
|
||||||
this.removeEventListener('change', this.onChange.bind(this));
|
this.removeEventListener('click', this.onChange.bind(this));
|
||||||
|
|
||||||
console.log('Component disconnected', this);
|
|
||||||
}
|
|
||||||
|
|
||||||
attributeChangedCallback() {
|
|
||||||
this.updateStyle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateStyle() {
|
updateStyle() {
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,6 @@ class MainWindow extends HTMLElement {
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
this.render();
|
this.render();
|
||||||
console.log('Component constructed', this);
|
|
||||||
}
|
|
||||||
|
|
||||||
disconnectedCallback() {
|
|
||||||
console.log('Component disconnected', this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeChangedCallback() {
|
attributeChangedCallback() {
|
||||||
|
|
@ -25,7 +20,7 @@ class MainWindow extends HTMLElement {
|
||||||
|
|
||||||
this.shadowRoot.innerHTML = `
|
this.shadowRoot.innerHTML = `
|
||||||
<style>
|
<style>
|
||||||
div {
|
#window {
|
||||||
width: 900px;
|
width: 900px;
|
||||||
height: 577px;
|
height: 577px;
|
||||||
background: #FFFFFF 0% 0% no-repeat padding-box;
|
background: #FFFFFF 0% 0% no-repeat padding-box;
|
||||||
|
|
@ -33,12 +28,10 @@ class MainWindow extends HTMLElement {
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
#content {
|
||||||
span {
|
|
||||||
width: 800px;
|
width: 800px;
|
||||||
margin: 0 50px 13px 50px;
|
margin: 0 50px 13px 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
top: 221px;
|
top: 221px;
|
||||||
margin: 50px 50px 13px 50px;
|
margin: 50px 50px 13px 50px;
|
||||||
|
|
@ -66,14 +59,13 @@ class MainWindow extends HTMLElement {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
slot {
|
|
||||||
margin: 0 50px 0 50px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<div>
|
<div id="window">
|
||||||
<h1>${title}</h1>
|
<h1>${title}</h1>
|
||||||
<p>${description}</p>
|
<p>${description}</p>
|
||||||
<span><slot></slot></span>
|
<div id="content" >
|
||||||
|
<slot></slot>
|
||||||
|
<div/>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
29
src/main.js
29
src/main.js
|
|
@ -3,32 +3,3 @@ import './components/main-window.js';
|
||||||
import './components/custom-button.js';
|
import './components/custom-button.js';
|
||||||
import './components/item-list.js';
|
import './components/item-list.js';
|
||||||
|
|
||||||
class App {
|
|
||||||
constructor(root, text, store) {
|
|
||||||
this.root = root;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
this.root.innerHTML = `
|
|
||||||
<style>
|
|
||||||
html {
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
background: transparent linear-gradient(135deg, #A1C4FD 0%, #C2E9FB 100%) 0% 0% no-repeat padding-box;
|
|
||||||
opacity: 1;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<app-base></app-base>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const app = new App(document.getElementById('root'));
|
|
||||||
|
|
||||||
app.start();
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ export default class Store {
|
||||||
records: [],
|
records: [],
|
||||||
selected: [],
|
selected: [],
|
||||||
};
|
};
|
||||||
this.callbacks = [];
|
this.callbacks = [() => console.log(this.state)];
|
||||||
|
|
||||||
Object.values(this.constructor.actions).forEach(action => document.addEventListener(action, this.eventHandler.bind(this), false));
|
Object.values(this.constructor.actions).forEach(action => document.addEventListener(action, this.eventHandler.bind(this), false));
|
||||||
}
|
}
|
||||||
|
|
@ -48,12 +48,15 @@ export default class Store {
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case this.constructor.actions.REMOVE_LINE:
|
case this.constructor.actions.REMOVE_LINE:
|
||||||
|
const linesToRemove = this.state.selected.map((id, index) => ({
|
||||||
|
id: this.state.records.length + index,
|
||||||
|
targetId: id,
|
||||||
|
action: 'remove',
|
||||||
|
}));
|
||||||
this.state = {
|
this.state = {
|
||||||
...this.state,
|
...this.state,
|
||||||
records: this.records.concat({
|
records: [ ...this.state.records, ...linesToRemove],
|
||||||
id: this.state.records.length,
|
selected: [],
|
||||||
action: 'remove',
|
|
||||||
}),
|
|
||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
case this.constructor.actions.UNDO:
|
case this.constructor.actions.UNDO:
|
||||||
|
|
@ -73,11 +76,11 @@ export default class Store {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.callbacks.forEach((cb) => cb());
|
this.callbacks.forEach((cb) => cb(event.type));
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecords() {
|
getRecords() {
|
||||||
return this.state.records.reduce((acc, current) => {
|
const result = this.state.records.reduce((acc, current) => {
|
||||||
if (current.action === "add") {
|
if (current.action === "add") {
|
||||||
return acc.concat({id: current.id, text: current.text});
|
return acc.concat({id: current.id, text: current.text});
|
||||||
}
|
}
|
||||||
|
|
@ -86,6 +89,7 @@ export default class Store {
|
||||||
}
|
}
|
||||||
console.error(`Action ${current.action} not valid`);
|
console.error(`Action ${current.action} not valid`);
|
||||||
}, []);
|
}, []);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
getSelected() {
|
getSelected() {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue