Browse Source

Merge pull request #151 from Philreact/q-apps

list modals
q-apps
AlphaX-Projects 1 year ago committed by GitHub
parent
commit
0f8cd2c03f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      qortal-ui-core/language/us.json
  2. 6
      qortal-ui-core/src/components/login-view/login-view.js
  3. 15
      qortal-ui-core/src/components/settings-view/security-view.js
  4. 15
      qortal-ui-core/src/redux/app/actions/app-core.js
  5. 2
      qortal-ui-core/src/redux/app/app-action-types.js
  6. 18
      qortal-ui-core/src/redux/app/app-reducer.js
  7. 11
      qortal-ui-plugins/plugins/core/components/qdn-action-types.js
  8. 240
      qortal-ui-plugins/plugins/core/qdn/browser/browser.src.js

8
qortal-ui-core/language/us.json

@ -638,7 +638,13 @@
"bchange35": "Do you give this application permission to send coins?",
"bchange36": "Do you want to publish instant to QDN without computing proof-of-work?",
"bchange37": "Enter Fullscreen",
"bchange38": "Exit Fullscreen"
"bchange38": "Exit Fullscreen",
"bchange39": "Always allow lists to be retrieved automatically",
"bchange40": "List",
"bchange41": "Do you give this application permission to access this list?",
"bchange42": "Items",
"bchange43": "Do you give this application permission to add to this list?",
"bchange44": "Do you give this application permission to delete from this list?"
},
"datapage": {
"dchange1": "Data Management",

6
qortal-ui-core/src/components/login-view/login-view.js

@ -14,7 +14,7 @@ import './login-section.js'
import '../qort-theme-toggle.js'
import settings from '../../functional-components/settings-page.js'
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth } from '../../redux/app/app-actions.js'
import { addAutoLoadImageChat, removeAutoLoadImageChat, addChatLastSeen, allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists } from '../../redux/app/app-actions.js'
window.reduxStore = store
window.reduxAction = {
@ -22,7 +22,9 @@ window.reduxAction = {
removeAutoLoadImageChat: removeAutoLoadImageChat,
addChatLastSeen: addChatLastSeen,
allowQAPPAutoAuth: allowQAPPAutoAuth,
removeQAPPAutoAuth: removeQAPPAutoAuth
removeQAPPAutoAuth: removeQAPPAutoAuth,
allowQAPPAutoLists: allowQAPPAutoLists,
removeQAPPAutoLists: removeQAPPAutoLists
}
const animationDuration = 0.7 // Seconds

15
qortal-ui-core/src/components/settings-view/security-view.js

@ -1,7 +1,7 @@
import { LitElement, html, css } from 'lit'
import { connect } from 'pwa-helpers'
import { store } from '../../store.js'
import { allowQAPPAutoAuth, removeQAPPAutoAuth } from '../../redux/app/app-actions.js'
import { allowQAPPAutoAuth, removeQAPPAutoAuth, removeQAPPAutoLists, allowQAPPAutoLists } from '../../redux/app/app-actions.js'
import { use, get, translate, translateUnsafeHTML, registerTranslateConfig } from 'lit-translate'
import '@material/mwc-checkbox'
@ -115,6 +115,12 @@ class SecurityView extends connect(store)(LitElement) {
</label>
<mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.checkForAuth(e)} ?checked=${store.getState().app.qAPPAutoAuth}></mwc-checkbox>
</div>
<div class="checkbox-row">
<label for="authButton" id="authButtonLabel" style="color: var(--black);">
${get('browserpage.bchange39')}
</label>
<mwc-checkbox style="margin-right: -15px;" id="authButton" @click=${(e) => this.checkForLists(e)} ?checked=${store.getState().app.qAPPAutoLists}></mwc-checkbox>
</div>
</div>
`
}
@ -129,6 +135,13 @@ class SecurityView extends connect(store)(LitElement) {
store.dispatch(allowQAPPAutoAuth(true))
}
}
checkForLists(e) {
if (e.target.checked) {
store.dispatch(removeQAPPAutoLists(false))
} else {
store.dispatch(allowQAPPAutoLists(true))
}
}
checkForDownload() {
const checkPass = this.shadowRoot.getElementById('downloadBackupPassword').value

15
qortal-ui-core/src/redux/app/actions/app-core.js

@ -1,5 +1,5 @@
// Core App Actions here...
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN } from '../app-action-types.js'
import { UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, CHAT_HEADS, ACCOUNT_INFO, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS } from '../app-action-types.js'
export const doUpdateBlockInfo = (blockObj) => {
return (dispatch, getState) => {
@ -133,6 +133,19 @@ export const removeQAPPAutoAuth = (payload) => {
payload
}
}
export const allowQAPPAutoLists = (payload) => {
return {
type: ALLOW_QAPP_AUTO_LISTS,
payload
}
}
export const removeQAPPAutoLists = (payload) => {
return {
type: REMOVE_QAPP_AUTO_LISTS,
payload
}
}
export const setChatLastSeen = (payload) => {
return {

2
qortal-ui-core/src/redux/app/app-action-types.js

@ -24,5 +24,7 @@ export const ADD_AUTO_LOAD_IMAGES_CHAT = 'ADD_AUTO_LOAD_IMAGES_CHAT'
export const REMOVE_AUTO_LOAD_IMAGES_CHAT = 'REMOVE_AUTO_LOAD_IMAGES_CHAT'
export const ALLOW_QAPP_AUTO_AUTH = 'ALLOW_QAPP_AUTO_AUTH'
export const REMOVE_QAPP_AUTO_AUTH = 'REMOVE_QAPP_AUTO_AUTH'
export const ALLOW_QAPP_AUTO_LISTS = 'ALLOW_QAPP_AUTO_LISTS'
export const REMOVE_QAPP_AUTO_LISTS = 'REMOVE_QAPP_AUTO_LISTS'
export const SET_CHAT_LAST_SEEN = 'SET_CHAT_LAST_SEEN'
export const ADD_CHAT_LAST_SEEN = 'ADD_CHAT_LAST_SEEN'

18
qortal-ui-core/src/redux/app/app-reducer.js

@ -1,6 +1,6 @@
// Loading state, login state, isNavDrawOpen state etc. None of this needs to be saved to localstorage.
import { loadStateFromLocalStorage, saveStateToLocalStorage } from '../../localStorageHelpers.js'
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN } from './app-action-types.js'
import { LOG_IN, LOG_OUT, NETWORK_CONNECTION_STATUS, INIT_WORKERS, ADD_PLUGIN_URL, ADD_PLUGIN, ADD_NEW_PLUGIN_URL, NAVIGATE, SELECT_ADDRESS, ACCOUNT_INFO, CHAT_HEADS, UPDATE_BLOCK_INFO, UPDATE_NODE_STATUS, UPDATE_NODE_INFO, LOAD_NODE_CONFIG, SET_NODE, ADD_NODE, PAGE_URL, COPY_MENU_SWITCH, PASTE_MENU_SWITCH, FRAME_PASTE_MENU_SWITCH, ADD_AUTO_LOAD_IMAGES_CHAT, REMOVE_AUTO_LOAD_IMAGES_CHAT, ALLOW_QAPP_AUTO_AUTH, REMOVE_QAPP_AUTO_AUTH, SET_CHAT_LAST_SEEN, ADD_CHAT_LAST_SEEN, ALLOW_QAPP_AUTO_LISTS, REMOVE_QAPP_AUTO_LISTS } from './app-action-types.js'
import { initWorkersReducer } from './reducers/init-workers.js'
import { loginReducer } from './reducers/login-reducer.js'
import { setNode, addNode } from './reducers/manage-node.js'
@ -51,6 +51,7 @@ const INITIAL_STATE = {
},
autoLoadImageChats: loadStateFromLocalStorage('autoLoadImageChats') || [],
qAPPAutoAuth: loadStateFromLocalStorage('qAPPAutoAuth') || false,
qAPPAutoLists: loadStateFromLocalStorage('qAPPAutoLists') || false,
chatLastSeen: []
}
@ -192,6 +193,21 @@ export default (state = INITIAL_STATE, action) => {
qAPPAutoAuth: action.payload
}
}
case ALLOW_QAPP_AUTO_LISTS: {
saveStateToLocalStorage("qAPPAutoLists", true)
return {
...state,
qAPPAutoLists: action.payload
}
}
case REMOVE_QAPP_AUTO_LISTS: {
saveStateToLocalStorage("qAPPAutoLists", false)
return {
...state,
qAPPAutoLists: action.payload
}
}
case SET_CHAT_LAST_SEEN: {
return {

11
qortal-ui-plugins/plugins/core/components/qdn-action-types.js

@ -26,4 +26,13 @@ export const GET_WALLET_BALANCE = 'GET_WALLET_BALANCE';
export const SEND_COIN = 'SEND_COIN';
// PUBLISH_MULTIPLE_QDN_RESOURCES
export const PUBLISH_MULTIPLE_QDN_RESOURCES = 'PUBLISH_MULTIPLE_QDN_RESOURCES'
export const PUBLISH_MULTIPLE_QDN_RESOURCES = 'PUBLISH_MULTIPLE_QDN_RESOURCES'
// GET_LIST_ITEMS
export const GET_LIST_ITEMS = 'GET_LIST_ITEMS'
// ADD_LIST_ITEMS
export const ADD_LIST_ITEMS = 'ADD_LIST_ITEMS'
// DELETE_LIST_ITEM
export const DELETE_LIST_ITEM = 'DELETE_LIST_ITEM'

240
qortal-ui-plugins/plugins/core/qdn/browser/browser.src.js

@ -258,7 +258,7 @@ class WebBrowser extends LitElement {
${this.renderFollowUnfollowButton()}
</div>
<div class="iframe-container">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-forms allow-downloads allow-modals" allow="fullscreen">
<iframe id="browser-iframe" src="${this.url}" sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen">
<span style="color: var(--black);">${translate('browserpage.bchange6')}</span>
</iframe>
</div>
@ -526,7 +526,8 @@ class WebBrowser extends LitElement {
let data = event.data;
switch (data.action) {
case actions.GET_USER_ACCOUNT:
case actions.GET_USER_ACCOUNT: {
let skip = false;
if (window.parent.reduxStore.getState().app.qAPPAutoAuth) {
skip = true;
@ -555,11 +556,199 @@ class WebBrowser extends LitElement {
response = JSON.stringify(data);
break;
}
}
case actions.GET_LIST_ITEMS: {
const requiredFields = ['list_name'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
let skip = false;
if (window.parent.reduxStore.getState().app.qAPPAutoLists) {
skip = true;
}
let res1;
if (!skip) {
res1 = await showModalAndWait(
actions.GET_LIST_ITEMS,
{
list_name: data.list_name
}
);
};
if (res1 && res1.action === 'accept' || skip) {
try {
const list = await parentEpml.request('apiCall', {
type: 'api',
url: `/lists/${data.list_name}?apiKey=${this.getApiKey()}`,
});
response = JSON.stringify(list);
} catch (error) {
const data = {};
const errorMsg = "Error in retrieving list"
data['error'] = errorMsg;
response = JSON.stringify(data);
} finally {
break;
}
} else {
const data = {};
const errorMsg = "User declined to share list"
data['error'] = errorMsg;
response = JSON.stringify(data);
break;
}
};
case actions.ADD_LIST_ITEMS: {
const requiredFields = ['list_name', 'items'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
const items = data.items
const list_name = data.list_name
const res = await showModalAndWait(
actions.ADD_LIST_ITEMS,
{
list_name: list_name,
items: items
}
);
if (res && res.action === 'accept') {
try {
const body = {
items: items,
};
const bodyToString = JSON.stringify(body);
const data = await parentEpml.request('apiCall', {
type: 'api',
method: 'POST',
url: `/lists/${list_name}?apiKey=${this.getApiKey()}`,
body: bodyToString,
headers: {
'Content-Type': 'application/json',
},
});
response = data
} catch (error) {
const data = {};
const errorMsg = "Error in adding to list"
data['error'] = errorMsg;
response = JSON.stringify(data);
} finally {
break;
}
} else {
const data = {};
const errorMsg = "User declined add to list"
data['error'] = errorMsg;
response = JSON.stringify(data);
break;
}
};
case actions.DELETE_LIST_ITEM: {
const requiredFields = ['list_name', 'item'];
const missingFields = [];
requiredFields.forEach((field) => {
if (!data[field]) {
missingFields.push(field);
}
});
if (missingFields.length > 0) {
const missingFieldsString = missingFields.join(', ');
const errorMsg = `Missing fields: ${missingFieldsString}`
let data = {};
data['error'] = errorMsg;
response = JSON.stringify(data);
break
}
const item = data.item
const list_name = data.list_name
const res = await showModalAndWait(
actions.DELETE_LIST_ITEM,
{
list_name: list_name,
item: item
}
);
if (res && res.action === 'accept') {
try {
const body = {
items: [item],
};
const bodyToString = JSON.stringify(body);
const data = await parentEpml.request('apiCall', {
type: 'api',
method: 'DELETE',
url: `/lists/${list_name}?apiKey=${this.getApiKey()}`,
body: bodyToString,
headers: {
'Content-Type': 'application/json',
},
});
response = data
} catch (error) {
const data = {};
const errorMsg = "Error in adding to list"
data['error'] = errorMsg;
response = JSON.stringify(data);
} finally {
break;
}
} else {
const data = {};
const errorMsg = "User declined add to list"
data['error'] = errorMsg;
response = JSON.stringify(data);
break;
}
};
case actions.LINK_TO_QDN_RESOURCE:
case actions.QDN_RESOURCE_DISPLAYED:
// Links are handled by the core, but the UI also listens for these actions in order to update the address bar.
// Note: don't update this.url here, as we don't want to force reload the iframe each time.
if (this.preview != null && this.preview.length > 0) {
this.displayUrl = translate("appspage.schange40");
return;
@ -2501,7 +2690,32 @@ async function showModalAndWait(type, data) {
<p class="modal-paragraph">${get("browserpage.bchange20")}</p>
</div>
` : ''}
${type === actions.GET_LIST_ITEMS ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange41")}</p>
<p class="modal-paragraph">${get("browserpage.bchange40")}: <span> ${data.list_name}</span></p>
<div class="checkbox-row">
<label for="listsButton" id="listsButtonLabel" style="color: var(--black);">
${get('browserpage.bchange39')}
</label>
<mwc-checkbox style="margin-right: -15px;" id="listsButton" ?checked=${window.parent.reduxStore.getState().app.qAPPAutoLists}></mwc-checkbox>
</div>
</div>
` : ''}
${type === actions.ADD_LIST_ITEMS ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange43")}</p>
<p class="modal-paragraph">${get("browserpage.bchange40")}: <span> ${data.list_name}</span></p>
<p class="modal-paragraph">${get("browserpage.bchange42")}: <span> ${data.items.join(', ')}</span></p>
</div>
` : ''}
${type === actions.DELETE_LIST_ITEM ? `
<div class="modal-subcontainer">
<p class="modal-paragraph">${get("browserpage.bchange44")}</p>
<p class="modal-paragraph">${get("browserpage.bchange40")}: <span> ${data.list_name}</span></p>
<p class="modal-paragraph">${get("browserpage.bchange42")}: <span> ${data.item}</span></p>
</div>
` : ''}
${type === actions.SEND_CHAT_MESSAGE ? `
<p class="modal-paragraph">${get("browserpage.bchange22")}</p>
` : ''}
@ -2563,6 +2777,22 @@ async function showModalAndWait(type, data) {
window.parent.reduxStore.dispatch(window.parent.reduxAction.allowQAPPAutoAuth(true))
})
}
const labelButton2 = modal.querySelector('#listsButtonLabel');
if (labelButton2) {
labelButton2.addEventListener('click', () => {
this.shadowRoot.getElementById('listsButton').click();
})
}
const checkbox2 = modal.querySelector('#listsButton');
if (checkbox2) {
checkbox2.addEventListener('click', (e) => {
if (e.target.checked) {
window.parent.reduxStore.dispatch(window.parent.reduxAction.removeQAPPAutoLists(false))
return
}
window.parent.reduxStore.dispatch(window.parent.reduxAction.allowQAPPAutoLists(true))
})
}
});
}
@ -2766,6 +2996,8 @@ const styles = `
font-weight: 300;
color: var(--black);
margin: 0;
word-wrap: break-word;
overflow-wrap: break-word;
}
.capitalize-first {

Loading…
Cancel
Save