From fff560b2f7a458cc6afd02f371b5640a14cf051f Mon Sep 17 00:00:00 2001
From: AlphaX-Projects <77661270+AlphaX-Projects@users.noreply.github.com>
Date: Sat, 29 Jan 2022 05:22:51 -0800
Subject: [PATCH] Pagination
---
.../data-management/data-management.src.js | 448 +++++++++++-------
1 file changed, 270 insertions(+), 178 deletions(-)
diff --git a/qortal-ui-plugins/plugins/core/qdn/data-management/data-management.src.js b/qortal-ui-plugins/plugins/core/qdn/data-management/data-management.src.js
index f76c2882..1f2618be 100644
--- a/qortal-ui-plugins/plugins/core/qdn/data-management/data-management.src.js
+++ b/qortal-ui-plugins/plugins/core/qdn/data-management/data-management.src.js
@@ -11,25 +11,58 @@ import '@vaadin/vaadin-grid/theme/material/all-imports.js'
const parentEpml = new Epml({ type: 'WINDOW', source: window.parent })
class DataManagement extends LitElement {
- static get properties() {
- return {
+ static get properties() {
+ return {
loading: { type: Boolean },
- resources: { type: Array },
blockedNames: { type: Array },
- followedNames: { type: Array },
- }
- }
+ followedNames: { type: Array },
+ datres: { type: Array }
+ }
+ }
- static get observers() {
- return ['_kmxKeyUp(amount)']
- }
-
- static get styles() {
+ static get styles() {
return css`
- * {
- --mdc-theme-primary: rgb(3, 169, 244);
+ * {
+ --mdc-theme-primary: rgb(3, 169, 244);
--paper-input-container-focus-color: var(--mdc-theme-primary);
}
+
+ #pages {
+ display: flex;
+ flex-wrap: wrap;
+ padding: 10px 5px 5px 5px;
+ margin: 0px 20px 20px 20px;
+ }
+
+ #pages > button {
+ user-select: none;
+ padding: 5px;
+ margin: 0 5px;
+ border-radius: 10%;
+ border: 0;
+ background: transparent;
+ font: inherit;
+ outline: none;
+ cursor: pointer;
+ }
+
+ #pages > button:not([disabled]):hover,
+ #pages > button:focus {
+ color: #ccc;
+ background-color: #eee;
+ }
+
+ #pages > button[selected] {
+ font-weight: bold;
+ color: white;
+ background-color: #ccc;
+ }
+
+ #pages > button[disabled] {
+ opacity: 0.5;
+ cursor: default;
+ }
+
#websites-list-page {
background: #fff;
padding: 12px 24px;
@@ -38,7 +71,6 @@ class DataManagement extends LitElement {
.divCard {
border: 1px solid #eee;
padding: 1em;
- /** box-shadow: 0 1px 1px 0 rgba(0,0,0,0.14), 0 2px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20); **/
box-shadow: 0 .3px 1px 0 rgba(0,0,0,0.14), 0 1px 1px -1px rgba(0,0,0,0.12), 0 1px 2px 0 rgba(0,0,0,0.20);
margin-bottom: 2em;
}
@@ -61,14 +93,17 @@ class DataManagement extends LitElement {
display: hidden !important;
visibility: none !important;
}
+
.details {
display: flex;
font-size: 18px;
}
+
span {
font-size: 18px;
word-break: break-all;
}
+
select {
padding: 13px 20px;
width: 100%;
@@ -76,15 +111,18 @@ class DataManagement extends LitElement {
color: #555;
font-weight: 400;
}
+
.title {
font-weight:600;
font-size:12px;
line-height: 32px;
opacity: 0.66;
}
+
.itemList {
padding:0;
}
+
.default-identifier {
font-size: 14px;
font-style: italic;
@@ -92,85 +130,123 @@ class DataManagement extends LitElement {
`
}
- render() {
+ constructor() {
+ super()
+ this.selectedAddress = {}
+ this.blockedNames = []
+ this.followedNames = []
+ this.datres = []
+ this.isLoading = false
+ }
+
+ render() {
return html`
Data Management
-
Data hosted by this node
-
-
- {
- render(html`${this.renderName(data.item)}`, root)
- }}>
- {
- render(html`${this.renderService(data.item)}`, root)
- }}>
- {
- render(html`${this.renderIdentifier(data.item)}`, root)
- }}>
- {
- render(html`${this.renderDeleteButton(data.item)}`, root);
- }}>
- {
- render(html`${this.renderBlockUnblockButton(data.item)}`, root);
- }}>
+
+
+
+ {
+ render(html`${this.renderIdentifier(data.item)}`, root)
+ }}>
+ {
+ render(html`${this.renderDeleteButton(data.item)}`, root);
+ }}>
+ {
+ render(html`${this.renderBlockUnblockButton(data.item)}`, root);
+ }}>
- ${this.renderDefaultText()}
+
+ ${this.renderDefaultText()}
`
}
- goBack() {
- window.history.back();
+ firstUpdated() {
+
+ window.addEventListener('contextmenu', (event) => {
+ event.preventDefault()
+ this._textMenu(event)
+ })
+
+ window.addEventListener('click', () => {
+ parentEpml.request('closeCopyTextMenu', null)
+ })
+
+ window.onkeyup = (e) => {
+ if (e.keyCode === 27) {
+ parentEpml.request('closeCopyTextMenu', null)
+ }
+ }
+
+ let configLoaded = false
+
+ parentEpml.ready().then(() => {
+ parentEpml.subscribe('selected_address', async selectedAddress => {
+ this.selectedAddress = {}
+ selectedAddress = JSON.parse(selectedAddress)
+ if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
+ this.selectedAddress = selectedAddress
+ })
+ parentEpml.subscribe('config', c => {
+ this.config = JSON.parse(c)
+ if (!configLoaded) {
+ setTimeout(this.getFollowedNames, 1)
+ setTimeout(this.getBlockedNames, 1)
+ setInterval(this.showManagement(), 30 * 1000)
+ setInterval(this.getFollowedNames, 30 * 1000)
+ setInterval(this.getBlockedNames, 30 * 1000)
+ configLoaded = true
+ }
+ })
+ parentEpml.subscribe('copy_menu_switch', async value => {
+
+ if (value === 'false' && window.getSelection().toString().length !== 0) {
+
+ this.clearSelection()
+ }
+ })
+ })
+ parentEpml.imReady()
}
- renderDefaultText() {
- if (this.resources == null || !Array.isArray(this.resources)) {
+ renderDefaultText() {
+ if (this.datres == null || !Array.isArray(this.datres)) {
return html`
Couldn't fetch hosted data list from node`
}
- if (this.isEmptyArray(this.resources)) {
- return html`
This node isn't hosting any data`;
- }
- return '';
- }
-
- renderName(resource) {
- let name = resource.name
- return html`${name}`
+ if (this.isEmptyArray(this.datres)) {
+ return html`
This node isn't hosting any data`;
+ }
+ return '';
}
- renderService(resource) {
- let service = resource.service
- return html`${service}`
- }
-
- renderIdentifier(resource) {
+ renderIdentifier(resource) {
return resource.identifier == null ? html`default` : html`${resource.identifier}`
}
- renderDeleteButton(resource) {
+ renderDeleteButton(resource) {
let name = resource.name
// Only show the block/unblock button if we have permission to modify the list on this node
- // We can use the blocked names list for this, as it won't be a valid array if we have no access
+ // We can use the blocked names list for this, as it won't be a valid array if we have no access
if (this.blockedNames == null || !Array.isArray(this.blockedNames)) {
return html``
}
- // We need to check if we are following this name, as if we are, there is no point in deleting anything
- // as it will be re-fetched immediately. In these cases we should show an UNFOLLOW button.
- if (this.followedNames.indexOf(name) != -1) {
+ // We need to check if we are following this name, as if we are, there is no point in deleting anything
+ // as it will be re-fetched immediately. In these cases we should show an UNFOLLOW button.
+ if (this.followedNames.indexOf(name) != -1) {
// render unfollow button
return html` this.unfollowName(resource)}>remove_from_queue Unfollow`
}
- // render delete button
- return html` this.deleteResource(resource)} onclick="this.blur();">delete Delete`
+ // render delete button
+ return html` this.deleteResource(resource)} onclick="this.blur();">delete Delete`
}
renderBlockUnblockButton(resource) {
@@ -191,12 +267,12 @@ class DataManagement extends LitElement {
}
}
- async blockName(resource) {
+ async blockName(resource) {
let name = resource.name
let items = [
name
]
- let namesJsonString = JSON.stringify({"items": items})
+ let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
@@ -211,7 +287,7 @@ class DataManagement extends LitElement {
// Successfully blocked - add to local list
// Remove it first by filtering the list - doing it this way ensures the UI updates
// immediately, as apposed to only adding if it doesn't already exist
- this.blockedNames = this.blockedNames.filter(item => item != name);
+ this.blockedNames = this.blockedNames.filter(item => item != name);
this.blockedNames.push(name)
}
else {
@@ -221,12 +297,12 @@ class DataManagement extends LitElement {
return ret
}
- async unfollowName(websiteObj) {
- let name = websiteObj.name
+ async unfollowName(resource) {
+ let name = resource.name
let items = [
name
]
- let namesJsonString = JSON.stringify({"items": items})
+ let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
@@ -239,7 +315,7 @@ class DataManagement extends LitElement {
if (ret === true) {
// Successfully unfollowed - remove from local list
- this.followedNames = this.followedNames.filter(item => item != name);
+ this.followedNames = this.followedNames.filter(item => item != name);
}
else {
parentEpml.request('showSnackBar', 'Error occurred when trying to unfollow this registered name. Please try again')
@@ -253,7 +329,7 @@ class DataManagement extends LitElement {
let items = [
name
]
- let namesJsonString = JSON.stringify({"items": items})
+ let namesJsonString = JSON.stringify({ "items": items })
let ret = await parentEpml.request('apiCall', {
url: `/lists/blockedNames?apiKey=${this.getApiKey()}`,
@@ -266,7 +342,7 @@ class DataManagement extends LitElement {
if (ret === true) {
// Successfully unblocked - remove from local list
- this.blockedNames = this.blockedNames.filter(item => item != name);
+ this.blockedNames = this.blockedNames.filter(item => item != name);
}
else {
parentEpml.request('showSnackBar', 'Error occurred when trying to unblock this registered name. Please try again')
@@ -275,8 +351,8 @@ class DataManagement extends LitElement {
return ret
}
- async deleteResource(resource) {
- let identifier = resource.identifier == null ? "default" : resource.identifier;
+ async deleteResource(resource) {
+ let identifier = resource.identifier == null ? "default" : resource.identifier;
let ret = await parentEpml.request('apiCall', {
url: `/arbitrary/resource/${resource.service}/${resource.name}/${identifier}?apiKey=${this.getApiKey()}`,
@@ -285,7 +361,7 @@ class DataManagement extends LitElement {
if (ret === true) {
// Successfully deleted - so refresh the page
- this.getArbitraryResources();
+ this.getArbitraryResources();
}
else {
parentEpml.request('showSnackBar', 'Error occurred when trying to delete this resource. Please try again')
@@ -295,124 +371,140 @@ class DataManagement extends LitElement {
}
- // Helper Functions (Re-Used in Most part of the UI )
+ textColor(color) {
+ return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
+ }
- textColor(color) {
- return color == 'light' ? 'rgba(255,255,255,0.7)' : 'rgba(0,0,0,0.87)'
- }
+ _textMenu(event) {
+ const getSelectedText = () => {
+ var text = ''
+ if (typeof window.getSelection != 'undefined') {
+ text = window.getSelection().toString()
+ } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
+ text = this.shadowRoot.selection.createRange().text
+ }
+ return text
+ }
- _textMenu(event) {
- const getSelectedText = () => {
- var text = ''
- if (typeof window.getSelection != 'undefined') {
- text = window.getSelection().toString()
- } else if (typeof this.shadowRoot.selection != 'undefined' && this.shadowRoot.selection.type == 'Text') {
- text = this.shadowRoot.selection.createRange().text
- }
- return text
- }
+ const checkSelectedTextAndShowMenu = () => {
+ let selectedText = getSelectedText()
+ if (selectedText && typeof selectedText === 'string') {
+ let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
- const checkSelectedTextAndShowMenu = () => {
- let selectedText = getSelectedText()
- if (selectedText && typeof selectedText === 'string') {
- let _eve = { pageX: event.pageX, pageY: event.pageY, clientX: event.clientX, clientY: event.clientY }
+ let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
- let textMenuObject = { selectedText: selectedText, eventObject: _eve, isFrame: true }
+ parentEpml.request('openCopyTextMenu', textMenuObject)
+ }
+ }
- parentEpml.request('openCopyTextMenu', textMenuObject)
- }
- }
+ checkSelectedTextAndShowMenu()
+ }
- checkSelectedTextAndShowMenu()
- }
+ async getResourcesGrid() {
+ this.resourcesGrid = this.shadowRoot.querySelector(`#resourcesGrid`)
+ this.pagesControl = this.shadowRoot.querySelector('#pages')
+ this.pages = undefined
+ }
- constructor() {
- super()
- this.selectedAddress = {}
- this.resources = []
- this.blockedNames = []
- this.followedNames = []
- this.isLoading = false
- }
+ async fetchManagementDetails() {
+ const myDat = await parentEpml.request('apiCall', {
+ url: `/arbitrary/hosted/resources?apiKey=${this.getApiKey()}`
+ })
+ this.datres = myDat;
+ }
- getArbitraryResources = async () => {
- // this.resources = []
+ async updateItemsFromPage(page) {
+ if (page === undefined) {
+ return
+ }
- let resources = await parentEpml.request('apiCall', {
- url: `/arbitrary/hosted/resources?apiKey=${this.getApiKey()}`
- })
-
- this.resources = resources
- }
-
- getBlockedNames = async () => {
- // this.blockedNames = []
-
- let blockedNames = await parentEpml.request('apiCall', {
- url: `/lists/blockedNames?apiKey=${this.getApiKey()}`
- })
-
- this.blockedNames = blockedNames
- }
-
- getFollowedNames = async () => {
- // this.followedNames = []
-
- let followedNames = await parentEpml.request('apiCall', {
- url: `/lists/followedNames?apiKey=${this.getApiKey()}`
- })
-
- this.followedNames = followedNames
- }
-
- firstUpdated() {
-
- window.addEventListener('contextmenu', (event) => {
- event.preventDefault()
- this._textMenu(event)
- })
-
- window.addEventListener('click', () => {
- parentEpml.request('closeCopyTextMenu', null)
- })
-
- window.onkeyup = (e) => {
- if (e.keyCode === 27) {
- parentEpml.request('closeCopyTextMenu', null)
- }
- }
-
- let configLoaded = false
- parentEpml.ready().then(() => {
- parentEpml.subscribe('selected_address', async selectedAddress => {
- this.selectedAddress = {}
- selectedAddress = JSON.parse(selectedAddress)
- if (!selectedAddress || Object.entries(selectedAddress).length === 0) return
- this.selectedAddress = selectedAddress
+ if (!this.pages) {
+ this.pages = Array.apply(null, { length: Math.ceil(this.datres.length / this.resourcesGrid.pageSize) }).map((item, index) => {
+ return index + 1
})
- parentEpml.subscribe('config', c => {
- this.config = JSON.parse(c)
- if (!configLoaded) {
- setTimeout(this.getArbitraryResources, 1)
- setTimeout(this.getFollowedNames, 1)
- setTimeout(this.getBlockedNames, 1)
- setInterval(this.getArbitraryResources, 30*1000)
- setInterval(this.getFollowedNames, 30*1000)
- setInterval(this.getBlockedNames, 30*1000)
- configLoaded = true
+
+ const prevBtn = document.createElement('button')
+ prevBtn.textContent = '<'
+ prevBtn.addEventListener('click', () => {
+ const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
+ this.updateItemsFromPage(selectedPage - 1)
+ })
+ this.pagesControl.appendChild(prevBtn)
+
+ this.pages.forEach((pageNumber) => {
+ const pageBtn = document.createElement('button')
+ pageBtn.textContent = pageNumber
+ pageBtn.addEventListener('click', (e) => {
+ this.updateItemsFromPage(parseInt(e.target.textContent))
+ })
+ if (pageNumber === page) {
+ pageBtn.setAttribute('selected', true)
}
+ this.pagesControl.appendChild(pageBtn)
})
- parentEpml.subscribe('copy_menu_switch', async value => {
- if (value === 'false' && window.getSelection().toString().length !== 0) {
+ const nextBtn = window.document.createElement('button')
+ nextBtn.textContent = '>'
+ nextBtn.addEventListener('click', () => {
+ const selectedPage = parseInt(this.pagesControl.querySelector('[selected]').textContent)
+ this.updateItemsFromPage(selectedPage + 1)
+ })
+ this.pagesControl.appendChild(nextBtn)
+ }
- this.clearSelection()
+ const buttons = Array.from(this.pagesControl.children)
+ buttons.forEach((btn, index) => {
+ if (parseInt(btn.textContent) === page) {
+ btn.setAttribute('selected', true)
+ } else {
+ btn.removeAttribute('selected')
+ }
+ if (index === 0) {
+ if (page === 1) {
+ btn.setAttribute('disabled', '')
+ } else {
+ btn.removeAttribute('disabled')
}
- })
+ }
+ if (index === buttons.length - 1) {
+ if (page === this.pages.length) {
+ btn.setAttribute('disabled', '')
+ } else {
+ btn.removeAttribute('disabled')
+ }
+ }
+ })
+ let start = (page - 1) * this.resourcesGrid.pageSize
+ let end = page * this.resourcesGrid.pageSize
+
+ this.resourcesGrid.items = this.datres.slice(start, end)
+ }
+
+ async showManagement() {
+ await this.fetchManagementDetails()
+ await this.getResourcesGrid()
+ await this.updateItemsFromPage(1, true)
+ }
+
+
+
+ getBlockedNames = async () => {
+
+ let blockedNames = await parentEpml.request('apiCall', {
+ url: `/lists/blockedNames?apiKey=${this.getApiKey()}`
})
- parentEpml.imReady()
- }
+ this.blockedNames = blockedNames
+ }
+
+ getFollowedNames = async () => {
+
+ let followedNames = await parentEpml.request('apiCall', {
+ url: `/lists/followedNames?apiKey=${this.getApiKey()}`
+ })
+
+ this.followedNames = followedNames
+ }
getApiKey() {
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node];
@@ -420,12 +512,12 @@ class DataManagement extends LitElement {
return apiKey;
}
- clearSelection() {
- window.getSelection().removeAllRanges()
- window.parent.getSelection().removeAllRanges()
- }
+ clearSelection() {
+ window.getSelection().removeAllRanges()
+ window.parent.getSelection().removeAllRanges()
+ }
- isEmptyArray(arr) {
+ isEmptyArray(arr) {
if (!arr) { return true }
return arr.length === 0
}