mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-04-29 06:17:51 +00:00
Added search name and follow name general
This commit is contained in:
parent
226e1d3a09
commit
b6aae8b2f6
@ -1,4 +1,5 @@
|
|||||||
import { LitElement, html, css } from 'lit'
|
import { LitElement, html, css } from 'lit'
|
||||||
|
import { render } from 'lit/html.js'
|
||||||
import { connect } from 'pwa-helpers'
|
import { connect } from 'pwa-helpers'
|
||||||
import { store } from '../store.js'
|
import { store } from '../store.js'
|
||||||
import { Epml } from '../epml.js'
|
import { Epml } from '../epml.js'
|
||||||
@ -17,6 +18,11 @@ import '@material/mwc-button'
|
|||||||
import '@material/mwc-dialog'
|
import '@material/mwc-dialog'
|
||||||
import '@material/mwc-icon'
|
import '@material/mwc-icon'
|
||||||
import '@material/mwc-textfield'
|
import '@material/mwc-textfield'
|
||||||
|
import '@polymer/paper-icon-button/paper-icon-button.js'
|
||||||
|
import '@polymer/iron-icons/iron-icons.js'
|
||||||
|
import '@polymer/paper-dialog/paper-dialog.js'
|
||||||
|
import '@vaadin/grid'
|
||||||
|
import '@vaadin/text-field'
|
||||||
|
|
||||||
const chatLastSeen = localForage.createInstance({
|
const chatLastSeen = localForage.createInstance({
|
||||||
name: "chat-last-seen",
|
name: "chat-last-seen",
|
||||||
@ -727,7 +733,11 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
textFieldDisabled: { type: Boolean },
|
textFieldDisabled: { type: Boolean },
|
||||||
initialName: { type: String },
|
initialName: { type: String },
|
||||||
newId: { type: String },
|
newId: { type: String },
|
||||||
removeTitle: { type: String }
|
removeTitle: { type: String },
|
||||||
|
myFollowedNames: { type: Array },
|
||||||
|
myFollowedNamesList: { type: Array },
|
||||||
|
searchNameContentString: { type: String },
|
||||||
|
searchNameResources: { type: Array }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -891,9 +901,9 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.resetIcon {
|
.resetIcon {
|
||||||
position: absolute;
|
position: fixed;
|
||||||
right: 16px;
|
right: 16px;
|
||||||
top: 16px;
|
top: 116px;
|
||||||
color: #666;
|
color: #666;
|
||||||
--mdc-icon-size: 32px;
|
--mdc-icon-size: 32px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -903,7 +913,76 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
color: #03a9f4;
|
color: #03a9f4;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.searchIcon {
|
||||||
|
position: fixed;
|
||||||
|
left: 16px;
|
||||||
|
top: 116px;
|
||||||
|
color: #666;
|
||||||
|
--mdc-icon-size: 32px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchIcon:hover {
|
||||||
|
color: #03a9f4;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-dialog.searchSettings {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 550px;
|
||||||
|
height: auto;
|
||||||
|
max-height: 600px;
|
||||||
|
background-color: var(--white);
|
||||||
|
color: var(--black);
|
||||||
|
line-height: 1.6;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 1px solid var(--black);
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-dialog button {
|
||||||
|
padding: 5px 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
background-color: #03a9f4;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-dialog button:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search {
|
||||||
|
display: inline;
|
||||||
|
width: 50%;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divCard {
|
||||||
|
height: auto;
|
||||||
|
max-height: 500px;
|
||||||
|
border: 1px solid var(--border);
|
||||||
|
padding: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
border-radius: 25%;
|
||||||
|
max-width: 32px;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
vaadin-text-field[focused]::part(input-field) {
|
||||||
|
border-color: #03a9f4;
|
||||||
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super()
|
super()
|
||||||
this.menuList = []
|
this.menuList = []
|
||||||
@ -922,12 +1001,17 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
this.initialName = ''
|
this.initialName = ''
|
||||||
this.newId = ''
|
this.newId = ''
|
||||||
this.removeTitle = ''
|
this.removeTitle = ''
|
||||||
|
this.myFollowedNames = []
|
||||||
|
this.myFollowedNamesList = []
|
||||||
|
this.searchContentString = ''
|
||||||
|
this.searchNameResources = []
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return html`
|
return html`
|
||||||
<div class="parent">
|
<div class="parent">
|
||||||
<mwc-icon class="resetIcon" @click="${() => this.resetMenu()}" title="Reset Tab Menu">reset_tv</mwc-icon>
|
<mwc-icon class="resetIcon" @click="${() => this.resetMenu()}" title="${translate("tabmenu.tm29")}">reset_tv</mwc-icon>
|
||||||
|
<mwc-icon class="searchIcon" @click="${() => this.openNameSearch()}" title="${translate("tabmenu.tm30")}">person_search</mwc-icon>
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<input @keydown=${this._handleKeyDown} id="linkInput" type="text" placeholder="qortal://">
|
<input @keydown=${this._handleKeyDown} id="linkInput" type="text" placeholder="qortal://">
|
||||||
<button @click="${this.handlePasteLink}">${translate('general.open')}</button>
|
<button @click="${this.handlePasteLink}">${translate('general.open')}</button>
|
||||||
@ -1019,6 +1103,115 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
${translate("general.no")}
|
${translate("general.no")}
|
||||||
</mwc-button>
|
</mwc-button>
|
||||||
</mwc-dialog>
|
</mwc-dialog>
|
||||||
|
<paper-dialog id="searchNameDialog" class="searchSettings" vertical-align="top" horizontal-align="center" dynamic-align>
|
||||||
|
<div style="display: inline;">
|
||||||
|
<div class="search">
|
||||||
|
<vaadin-text-field
|
||||||
|
style="width: 350px"
|
||||||
|
id="searchNameContent"
|
||||||
|
placeholder="${translate("appspage.schange33")}"
|
||||||
|
value="${this.searchNameContentString}"
|
||||||
|
@keydown="${this.searchNameKeyListener}"
|
||||||
|
clear-button-visible
|
||||||
|
autofocus
|
||||||
|
>
|
||||||
|
</vaadin-text-field>
|
||||||
|
<paper-icon-button icon="icons:search" @click="${() => this.searchNameResult()}" title="${translate("websitespage.schange35")}"></paper-icon-button>
|
||||||
|
<paper-icon-button icon="icons:close" @click="${() => this.closeNameSearch()}" title="${translate("general.close")}"></paper-icon-button>
|
||||||
|
</div>
|
||||||
|
</div><br>
|
||||||
|
<div class="divCard">
|
||||||
|
<vaadin-grid
|
||||||
|
theme="wrap-cell-content"
|
||||||
|
id="searchNameGrid"
|
||||||
|
?hidden="${this.isEmptyArray(this.searchNameResources)}"
|
||||||
|
.items="${this.searchNameResources}"
|
||||||
|
aria-label="Search Name"
|
||||||
|
>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="6rem"
|
||||||
|
flex-grow="0" header="${translate("appspage.schange5")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${this.renderNameAvatar(data.item)}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="12rem"
|
||||||
|
flex-grow="0"
|
||||||
|
header="${translate("datapage.dchange5")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${data.item.name}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="10rem"
|
||||||
|
flex-grow="0"
|
||||||
|
header="${translate("appspage.schange8")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${this.renderMyFollowUnfollowButton(data.item)}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
</vaadin-grid>
|
||||||
|
${this.isEmptyArray(this.searchNameResources) ? html`
|
||||||
|
<span style="color: var(--black); text-align: center; font-size: 16px;">${translate("login.entername")}</span>
|
||||||
|
`: ''}
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<button @click="${this.openMyFollowedNames}">${translate("tabmenu.tm31")}</button>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
|
<paper-dialog id="myFollowedNamesDialog" class="searchSettings" vertical-align="top" horizontal-align="center" dynamic-align>
|
||||||
|
<div style="text-align:center">
|
||||||
|
<h2>${translate("tabmenu.tm31")}</h2>
|
||||||
|
<hr>
|
||||||
|
</div>
|
||||||
|
<div class="divCard">
|
||||||
|
<vaadin-grid
|
||||||
|
theme="wrap-cell-content"
|
||||||
|
id="followedNameGrid"
|
||||||
|
?hidden="${this.isEmptyArray(this.myFollowedNamesList)}"
|
||||||
|
.items="${this.myFollowedNamesList}"
|
||||||
|
aria-label="My Followed Bames"
|
||||||
|
>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="6rem"
|
||||||
|
flex-grow="0" header="${translate("appspage.schange5")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${this.renderNameAvatar(data.item)}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="12rem"
|
||||||
|
flex-grow="0"
|
||||||
|
header="${translate("datapage.dchange5")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${data.item.name}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
<vaadin-grid-column
|
||||||
|
width="10rem"
|
||||||
|
flex-grow="0"
|
||||||
|
header="${translate("appspage.schange8")}"
|
||||||
|
.renderer=${(root, column, data) => {
|
||||||
|
render(html`${this.renderMyFollowUnfollowButton(data.item)}`, root)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
</vaadin-grid-column>
|
||||||
|
</vaadin-grid>
|
||||||
|
${this.isEmptyArray(this.myFollowedNamesList) ? html`
|
||||||
|
<span style="color: var(--black); text-align: center; font-size: 16px;">${translate("tabmenu.tm32")}</span>
|
||||||
|
`: ''}
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; justify-content: space-between;">
|
||||||
|
<button @click="${this.openNameSearch}">${translate("websitespage.schange35")}</button>
|
||||||
|
<button style="background-color: red;" @click="${this.closeMyFollowedNames}">${translate("general.close")}</button>
|
||||||
|
</div>
|
||||||
|
</paper-dialog>
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,6 +1245,165 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
} else {
|
} else {
|
||||||
this.myMenuList = this.newMenuList
|
this.myMenuList = this.newMenuList
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.getMyFollowedNames()
|
||||||
|
await this.getMyFollowedNamesList()
|
||||||
|
}
|
||||||
|
|
||||||
|
openNameSearch() {
|
||||||
|
this.searchNameResources = []
|
||||||
|
this.shadowRoot.getElementById('searchNameContent').value = ''
|
||||||
|
this.shadowRoot.getElementById('myFollowedNamesDialog').close()
|
||||||
|
this.shadowRoot.getElementById('searchNameDialog').open()
|
||||||
|
}
|
||||||
|
|
||||||
|
closeNameSearch() {
|
||||||
|
this.shadowRoot.getElementById('searchNameDialog').close()
|
||||||
|
}
|
||||||
|
|
||||||
|
openMyFollowedNames() {
|
||||||
|
this.shadowRoot.getElementById('searchNameDialog').close()
|
||||||
|
this.shadowRoot.getElementById('myFollowedNamesDialog').open()
|
||||||
|
this.getMyFollowedNamesList()
|
||||||
|
}
|
||||||
|
|
||||||
|
closeMyFollowedNames() {
|
||||||
|
this.shadowRoot.getElementById('myFollowedNamesDialog').close()
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMyFollowedNames() {
|
||||||
|
let myFollowedNames = await parentEpml.request('apiCall', {
|
||||||
|
url: `/lists/followedNames?apiKey=${this.getApiKey()}`
|
||||||
|
})
|
||||||
|
|
||||||
|
this.myFollowedNames = myFollowedNames
|
||||||
|
}
|
||||||
|
|
||||||
|
searchNameKeyListener(e) {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
this.searchNameResult()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getMyFollowedNamesList() {
|
||||||
|
const myNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||||
|
const myNodeUrl = myNode.protocol + '://' + myNode.domain + ':' + myNode.port
|
||||||
|
const followedNamesUrl = `${myNodeUrl}/lists/followedNames?apiKey=${this.getApiKey()}`
|
||||||
|
|
||||||
|
var myFollowedNamesNew = []
|
||||||
|
|
||||||
|
this.myFollowedNamesList = []
|
||||||
|
|
||||||
|
await fetch(followedNamesUrl).then(response => {
|
||||||
|
return response.json()
|
||||||
|
}).then(data => {
|
||||||
|
return data.map(item => {
|
||||||
|
const addListName = {
|
||||||
|
name: item
|
||||||
|
}
|
||||||
|
myFollowedNamesNew.push(addListName)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
this.myFollowedNamesList = myFollowedNamesNew
|
||||||
|
if(this.shadowRoot.getElementById('myFollowedNamesDialog').opened) {
|
||||||
|
this.shadowRoot.getElementById('myFollowedNamesDialog').notifyResize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchNameResult() {
|
||||||
|
let searchMyName = this.shadowRoot.getElementById('searchNameContent').value
|
||||||
|
if (searchMyName.length === 0) {
|
||||||
|
let err1string = get("appspage.schange34")
|
||||||
|
parentEpml.request('showSnackBar', `${err1string}`)
|
||||||
|
} else {
|
||||||
|
let searchNameResources = await parentEpml.request('apiCall', {
|
||||||
|
url: `/names/search?query=${searchMyName}&prefix=true&limit=0&reverse=true`
|
||||||
|
})
|
||||||
|
if (this.isEmptyArray(searchNameResources)) {
|
||||||
|
let err2string = get("appspage.schange17")
|
||||||
|
parentEpml.request('showSnackBar', `${err2string}`)
|
||||||
|
} else {
|
||||||
|
this.searchNameResources = searchNameResources
|
||||||
|
if(this.shadowRoot.getElementById('searchNameDialog').opened) {
|
||||||
|
this.shadowRoot.getElementById('searchNameDialog').notifyResize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderNameAvatar(nameObj) {
|
||||||
|
let myName = nameObj.name
|
||||||
|
const myNameNode = window.parent.reduxStore.getState().app.nodeConfig.knownNodes[window.parent.reduxStore.getState().app.nodeConfig.node]
|
||||||
|
const myNodeUrl = myNameNode.protocol + '://' + myNameNode.domain + ':' + myNameNode.port
|
||||||
|
const nameUrl = `${myNodeUrl}/arbitrary/THUMBNAIL/${myName}/qortal_avatar?async=true`
|
||||||
|
return html`<img src="${nameUrl}" onerror="this.src='/img/incognito.png';">`
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMyFollowUnfollowButton(nameObj) {
|
||||||
|
let name = nameObj.name
|
||||||
|
|
||||||
|
if (this.myFollowedNames == null || !Array.isArray(this.myFollowedNames)) {
|
||||||
|
return html``
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.myFollowedNames.indexOf(name) === -1) {
|
||||||
|
return html`<mwc-button @click=${() => this.myFollowName(nameObj)}><mwc-icon>add_to_queue</mwc-icon> ${translate("appspage.schange29")}</mwc-button>`
|
||||||
|
} else {
|
||||||
|
return html`<mwc-button @click=${() => this.myUnfollowName(nameObj)}><mwc-icon>remove_from_queue</mwc-icon> ${translate("appspage.schange30")}</mwc-button>`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async myFollowName(nameObj) {
|
||||||
|
let name = nameObj.name
|
||||||
|
let items = [
|
||||||
|
name
|
||||||
|
]
|
||||||
|
let namesJsonString = JSON.stringify({ "items": items })
|
||||||
|
|
||||||
|
let ret = await parentEpml.request('apiCall', {
|
||||||
|
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: `${namesJsonString}`
|
||||||
|
})
|
||||||
|
|
||||||
|
if (ret === true) {
|
||||||
|
this.myFollowedNames = this.myFollowedNames.filter(item => item != name)
|
||||||
|
this.myFollowedNames.push(name)
|
||||||
|
} else {
|
||||||
|
let err3string = get("appspage.schange22")
|
||||||
|
parentEpml.request('showSnackBar', `${err3string}`)
|
||||||
|
}
|
||||||
|
this.getMyFollowedNamesList()
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
async myUnfollowName(nameObj) {
|
||||||
|
let name = nameObj.name
|
||||||
|
let items = [
|
||||||
|
name
|
||||||
|
]
|
||||||
|
let namesJsonString = JSON.stringify({ "items": items })
|
||||||
|
|
||||||
|
let ret = await parentEpml.request('apiCall', {
|
||||||
|
url: `/lists/followedNames?apiKey=${this.getApiKey()}`,
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: `${namesJsonString}`
|
||||||
|
})
|
||||||
|
|
||||||
|
if (ret === true) {
|
||||||
|
this.myFollowedNames = this.myFollowedNames.filter(item => item != name)
|
||||||
|
} else {
|
||||||
|
let err4string = get("appspage.schange23")
|
||||||
|
parentEpml.request('showSnackBar', `${err4string}`)
|
||||||
|
}
|
||||||
|
this.getMyFollowedNamesList()
|
||||||
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkMyMenuPlugins() {
|
async checkMyMenuPlugins() {
|
||||||
@ -1707,6 +2059,11 @@ class NavBar extends connect(store)(LitElement) {
|
|||||||
return apiKey
|
return apiKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEmptyArray(arr) {
|
||||||
|
if (!arr) { return true }
|
||||||
|
return arr.length === 0
|
||||||
|
}
|
||||||
|
|
||||||
stateChanged(state) {
|
stateChanged(state) {
|
||||||
this.menuList = state.app.registeredUrls
|
this.menuList = state.app.registeredUrls
|
||||||
this.addressInfo = state.app.accountInfo.addressInfo
|
this.addressInfo = state.app.accountInfo.addressInfo
|
||||||
|
Loading…
x
Reference in New Issue
Block a user