CLN On-chain page settings

CLN On-chain page settings
This commit is contained in:
ShahanaFarooqui 2022-10-17 16:58:21 -07:00
parent 149561dedb
commit e7b03f4b2f
38 changed files with 223 additions and 181 deletions

View File

@ -44,9 +44,6 @@ export const getUTXOs = (req, res, next) => {
}
options.url = req.session.selectedNode.ln_server_url + '/v1/listFunds';
request(options).then((body) => {
if (body.outputs) {
body.outputs = common.sortDescByStrKey(body.outputs, 'status');
}
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
res.status(200).json(body);
}).catch((errRes) => {

View File

@ -57,16 +57,16 @@ export var TableSettingsFieldsEnum;
TableSettingsFieldsEnum["RECORDS_PER_PAGE"] = "recordsPerPage";
TableSettingsFieldsEnum["SORT_BY"] = "sortBy";
TableSettingsFieldsEnum["SORT_ORDER"] = "sortOrder";
TableSettingsFieldsEnum["SHOW_COLUMNS"] = "showColumns";
TableSettingsFieldsEnum["SHOW_COLUMNS_SM"] = "showColumnsSM";
TableSettingsFieldsEnum["COLUMN_SELECTION"] = "columnSelection";
TableSettingsFieldsEnum["COLUMN_SELECTION_SM"] = "columnSelectionSM";
})(TableSettingsFieldsEnum || (TableSettingsFieldsEnum = {}));
export class TableSetting {
constructor(tableId, recordsPerPage, sortBy, sortOrder, showColumns) {
constructor(tableId, recordsPerPage, sortBy, sortOrder, columnSelection) {
this.tableId = tableId;
this.recordsPerPage = recordsPerPage;
this.sortBy = sortBy;
this.sortOrder = sortOrder;
this.showColumns = showColumns;
this.columnSelection = columnSelection;
}
}
export class PageSettings {
@ -97,20 +97,20 @@ export const validatePageSettings = (documentToValidate) => {
if (!table.hasOwnProperty(CollectionFieldsEnum.RECORDS_PER_PAGE)) {
errMsg = errMsg + 'Records/Page is mandatory.';
}
if (!table.hasOwnProperty(CollectionFieldsEnum.SHOW_COLUMNS_SM)) {
errMsg = errMsg + 'Show Columns Small Screen is mandatory.';
if (!table.hasOwnProperty(CollectionFieldsEnum.COLUMN_SELECTION_SM)) {
errMsg = errMsg + 'Column Selection (Mobile) is mandatory.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS_SM].length < 1) {
errMsg = errMsg + 'Show Columns Small Screen should have at least 1 field.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION_SM].length < 1) {
errMsg = errMsg + 'Column Selection (Mobile) should have at least 1 field.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS_SM].length > 2) {
errMsg = errMsg + 'Show Columns Small Screen should have maximum 2 fields.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION_SM].length > 2) {
errMsg = errMsg + 'Column Selection (Mobile) should have maximum 2 fields.';
}
if (!table.hasOwnProperty(CollectionFieldsEnum.SHOW_COLUMNS)) {
errMsg = errMsg + 'Show Columns is mandatory.';
if (!table.hasOwnProperty(CollectionFieldsEnum.COLUMN_SELECTION)) {
errMsg = errMsg + 'Column Selection (Desktop) is mandatory.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS].length < 2) {
errMsg = errMsg + 'Show Columns should have at least 2 fields.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION].length < 2) {
errMsg = errMsg + 'Column Selection (Desktop) should have at least 2 fields.';
}
if (errMsg.trim() !== '') {
tableAcc.push({ table: (table.hasOwnProperty(CollectionFieldsEnum.TABLE_ID) ? table[CollectionFieldsEnum.TABLE_ID] : (tableIdx + 1)), message: errMsg });

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -10,9 +10,9 @@
<link i18n-rel="" rel="mask-icon" href="assets/images/favicon-light/safari-pinned-tab.svg" color="#5bbad5">
<meta i18n-content="" name="msapplication-TileColor" content="#da532c">
<meta i18n-content="" name="theme-color" content="#ffffff">
<style>@font-face{font-family:Roboto;src:url(Roboto-Thin.f7a95c9c5999532c.woff2) format("woff2"),url(Roboto-Thin.c13c157cb81e8ebb.woff) format("woff");font-weight:100;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.b0e084abf689f393.woff2) format("woff2"),url(Roboto-ThinItalic.1111028df6cea564.woff) format("woff");font-weight:100;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Light.0e01b6cd13b3857f.woff2) format("woff2"),url(Roboto-Light.603ca9a537b88428.woff) format("woff");font-weight:300;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.232ef4b20215f720.woff2) format("woff2"),url(Roboto-LightItalic.1b5e142f787151c8.woff) format("woff");font-weight:300;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Regular.475ba9e4e2d63456.woff2) format("woff2"),url(Roboto-Regular.bcefbfee882bc1cb.woff) format("woff");font-weight:400;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.e3a9ebdaac06bbc4.woff2) format("woff2"),url(Roboto-RegularItalic.0668fae6af0cf8c2.woff) format("woff");font-weight:400;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Medium.457532032ceb0168.woff2) format("woff2"),url(Roboto-Medium.6e1ae5f0b324a0aa.woff) format("woff");font-weight:500;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.872f7060602d55d2.woff2) format("woff2"),url(Roboto-MediumItalic.e06fb533801cbb08.woff) format("woff");font-weight:500;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Bold.447291a88c067396.woff2) format("woff2"),url(Roboto-Bold.fc482e6133cf5e26.woff) format("woff");font-weight:700;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.1b15168ef6fa4e16.woff2) format("woff2"),url(Roboto-BoldItalic.e26ba339b06f09f7.woff) format("woff");font-weight:700;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Black.2eaa390d458c877d.woff2) format("woff2"),url(Roboto-Black.b25f67ad8583da68.woff) format("woff");font-weight:900;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.7dc03ee444552bc5.woff2) format("woff2"),url(Roboto-BlackItalic.c8dc642467cb3099.woff) format("woff");font-weight:900;font-style:italic}html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:62.5%}body{box-sizing:border-box;height:100%;margin:0;overflow:hidden}*{margin:0;padding:0}</style><link rel="stylesheet" href="styles.43515fc39338348b.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.43515fc39338348b.css"></noscript></head>
<style>@font-face{font-family:Roboto;src:url(Roboto-Thin.f7a95c9c5999532c.woff2) format("woff2"),url(Roboto-Thin.c13c157cb81e8ebb.woff) format("woff");font-weight:100;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-ThinItalic.b0e084abf689f393.woff2) format("woff2"),url(Roboto-ThinItalic.1111028df6cea564.woff) format("woff");font-weight:100;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Light.0e01b6cd13b3857f.woff2) format("woff2"),url(Roboto-Light.603ca9a537b88428.woff) format("woff");font-weight:300;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-LightItalic.232ef4b20215f720.woff2) format("woff2"),url(Roboto-LightItalic.1b5e142f787151c8.woff) format("woff");font-weight:300;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Regular.475ba9e4e2d63456.woff2) format("woff2"),url(Roboto-Regular.bcefbfee882bc1cb.woff) format("woff");font-weight:400;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-RegularItalic.e3a9ebdaac06bbc4.woff2) format("woff2"),url(Roboto-RegularItalic.0668fae6af0cf8c2.woff) format("woff");font-weight:400;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Medium.457532032ceb0168.woff2) format("woff2"),url(Roboto-Medium.6e1ae5f0b324a0aa.woff) format("woff");font-weight:500;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-MediumItalic.872f7060602d55d2.woff2) format("woff2"),url(Roboto-MediumItalic.e06fb533801cbb08.woff) format("woff");font-weight:500;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Bold.447291a88c067396.woff2) format("woff2"),url(Roboto-Bold.fc482e6133cf5e26.woff) format("woff");font-weight:700;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BoldItalic.1b15168ef6fa4e16.woff2) format("woff2"),url(Roboto-BoldItalic.e26ba339b06f09f7.woff) format("woff");font-weight:700;font-style:italic}@font-face{font-family:Roboto;src:url(Roboto-Black.2eaa390d458c877d.woff2) format("woff2"),url(Roboto-Black.b25f67ad8583da68.woff) format("woff");font-weight:900;font-style:normal}@font-face{font-family:Roboto;src:url(Roboto-BlackItalic.7dc03ee444552bc5.woff2) format("woff2"),url(Roboto-BlackItalic.c8dc642467cb3099.woff) format("woff");font-weight:900;font-style:italic}html{width:100%;height:99%;line-height:1.5;overflow-x:hidden;font-family:Roboto,sans-serif!important;font-size:62.5%}body{box-sizing:border-box;height:100%;margin:0;overflow:hidden}*{margin:0;padding:0}</style><link rel="stylesheet" href="styles.f23210babf4d5c40.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles.f23210babf4d5c40.css"></noscript></head>
<body>
<rtl-app></rtl-app>
<script src="runtime.3a8ac8969006b863.js" type="module"></script><script src="polyfills.eddc63f1737a019a.js" type="module"></script><script src="main.0a28b146399d54a7.js" type="module"></script>
<script src="runtime.503f37ba549530ee.js" type="module"></script><script src="polyfills.eddc63f1737a019a.js" type="module"></script><script src="main.3d7b99d9830668b7.js" type="module"></script>
</body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,d)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,d]=e[i],s=!0,o=0;o<t.length;o++)(!1&d||a>=d)&&Object.keys(r.O).every(b=>r.O[b](t[o]))?t.splice(o--,1):(s=!1,d<a&&(a=d));if(s){e.splice(i--,1);var l=f();void 0!==l&&(n=l)}}return n}d=d||0;for(var i=e.length;i>0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[t,f,d]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{564:"f639cfe4254bb226",636:"167692d028bb7a59",893:"9a615c46b89a5a79",924:"244f3c9394b6cf6d"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,d,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==d)for(var o=document.getElementsByTagName("script"),l=0;l<o.length;l++){var u=o[l];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+d){a=u;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+d),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,d)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)d.push(i[2]);else if(666!=f){var a=new Promise((u,c)=>i=e[f]=[u,c]);d.push(i[2]=a);var s=r.p+r.u(f),o=new Error;r.l(s,u=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;o.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",o.name="ChunkLoadError",o.type=c,o.request=p,i[1](o)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,d)=>{var o,l,[i,a,s]=d,u=0;if(i.some(p=>0!==e[p])){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)var c=s(r)}for(f&&f(d);u<i.length;u++)r.o(e,l=i[u])&&e[l]&&e[l][0](),e[l]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,v={},g={};function r(e){var n=g[e];if(void 0!==n)return n.exports;var t=g[e]={id:e,loaded:!1,exports:{}};return v[e].call(t.exports,t,t.exports,r),t.loaded=!0,t.exports}r.m=v,e=[],r.O=(n,t,f,d)=>{if(!t){var a=1/0;for(i=0;i<e.length;i++){for(var[t,f,d]=e[i],s=!0,o=0;o<t.length;o++)(!1&d||a>=d)&&Object.keys(r.O).every(b=>r.O[b](t[o]))?t.splice(o--,1):(s=!1,d<a&&(a=d));if(s){e.splice(i--,1);var l=f();void 0!==l&&(n=l)}}return n}d=d||0;for(var i=e.length;i>0&&e[i-1][2]>d;i--)e[i]=e[i-1];e[i]=[t,f,d]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>e+"."+{258:"ef54ce47dace49e4",267:"6fb96d7d2bc58b98",564:"ff48c37cffd166ba",636:"c0cbf4123331dffc"}[e]+".js",r.miniCssF=e=>{},r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="RTLApp:";r.l=(t,f,d,i)=>{if(e[t])e[t].push(f);else{var a,s;if(void 0!==d)for(var o=document.getElementsByTagName("script"),l=0;l<o.length;l++){var u=o[l];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+d){a=u;break}}a||(s=!0,(a=document.createElement("script")).type="module",a.charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+d),a.src=r.tu(t)),e[t]=[f];var c=(m,b)=>{a.onerror=a.onload=null,clearTimeout(p);var h=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),h&&h.forEach(_=>_(b)),m)return m(b)},p=setTimeout(c.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=c.bind(null,a.onerror),a.onload=c.bind(null,a.onload),s&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:n=>n},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="",(()=>{var e={666:0};r.f.j=(f,d)=>{var i=r.o(e,f)?e[f]:void 0;if(0!==i)if(i)d.push(i[2]);else if(666!=f){var a=new Promise((u,c)=>i=e[f]=[u,c]);d.push(i[2]=a);var s=r.p+r.u(f),o=new Error;r.l(s,u=>{if(r.o(e,f)&&(0!==(i=e[f])&&(e[f]=void 0),i)){var c=u&&("load"===u.type?"missing":u.type),p=u&&u.target&&u.target.src;o.message="Loading chunk "+f+" failed.\n("+c+": "+p+")",o.name="ChunkLoadError",o.type=c,o.request=p,i[1](o)}},"chunk-"+f,f)}else e[f]=0},r.O.j=f=>0===e[f];var n=(f,d)=>{var o,l,[i,a,s]=d,u=0;if(i.some(p=>0!==e[p])){for(o in a)r.o(a,o)&&(r.m[o]=a[o]);if(s)var c=s(r)}for(f&&f(d);u<i.length;u++)r.o(e,l=i[u])&&e[l]&&e[l][0](),e[l]=0;return r.O(c)},t=self.webpackChunkRTLApp=self.webpackChunkRTLApp||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -41,7 +41,6 @@ export const getUTXOs = (req, res, next) => {
if (options.error) { return res.status(options.statusCode).json({ message: options.message, error: options.error }); }
options.url = req.session.selectedNode.ln_server_url + '/v1/listFunds';
request(options).then((body) => {
if (body.outputs) { body.outputs = common.sortDescByStrKey(body.outputs, 'status'); }
logger.log({ selectedNode: req.session.selectedNode, level: 'INFO', fileName: 'OnChain', msg: 'Funds List Received', data: body });
res.status(200).json(body);
}).catch((errRes) => {

View File

@ -61,8 +61,8 @@ export enum TableSettingsFieldsEnum {
RECORDS_PER_PAGE = 'recordsPerPage',
SORT_BY = 'sortBy',
SORT_ORDER = 'sortOrder',
SHOW_COLUMNS = 'showColumns',
SHOW_COLUMNS_SM = 'showColumnsSM'
COLUMN_SELECTION = 'columnSelection',
COLUMN_SELECTION_SM = 'columnSelectionSM'
}
export class TableSetting {
@ -72,7 +72,7 @@ export class TableSetting {
public recordsPerPage?: number,
public sortBy?: string,
public sortOrder?: SortOrderEnum,
public showColumns?: any[]
public columnSelection?: any[]
) { }
}
@ -108,20 +108,20 @@ export const validatePageSettings = (documentToValidate): any => {
if (!table.hasOwnProperty(CollectionFieldsEnum.RECORDS_PER_PAGE)) {
errMsg = errMsg + 'Records/Page is mandatory.';
}
if (!table.hasOwnProperty(CollectionFieldsEnum.SHOW_COLUMNS_SM)) {
errMsg = errMsg + 'Show Columns Small Screen is mandatory.';
if (!table.hasOwnProperty(CollectionFieldsEnum.COLUMN_SELECTION_SM)) {
errMsg = errMsg + 'Column Selection (Mobile) is mandatory.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS_SM].length < 1) {
errMsg = errMsg + 'Show Columns Small Screen should have at least 1 field.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION_SM].length < 1) {
errMsg = errMsg + 'Column Selection (Mobile) should have at least 1 field.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS_SM].length > 2) {
errMsg = errMsg + 'Show Columns Small Screen should have maximum 2 fields.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION_SM].length > 2) {
errMsg = errMsg + 'Column Selection (Mobile) should have maximum 2 fields.';
}
if (!table.hasOwnProperty(CollectionFieldsEnum.SHOW_COLUMNS)) {
errMsg = errMsg + 'Show Columns is mandatory.';
if (!table.hasOwnProperty(CollectionFieldsEnum.COLUMN_SELECTION)) {
errMsg = errMsg + 'Column Selection (Desktop) is mandatory.';
}
if (table[CollectionFieldsEnum.SHOW_COLUMNS].length < 2) {
errMsg = errMsg + 'Show Columns should have at least 2 fields.';
if (table[CollectionFieldsEnum.COLUMN_SELECTION].length < 2) {
errMsg = errMsg + 'Column Selection (Desktop) should have at least 2 fields.';
}
if (errMsg.trim() !== '') {
tableAcc.push({ table: (table.hasOwnProperty(CollectionFieldsEnum.TABLE_ID) ? table[CollectionFieldsEnum.TABLE_ID] : (tableIdx + 1)), message: errMsg });

View File

@ -4,13 +4,13 @@
<ng-template mat-tab-label>
<span matBadge="{{numUtxos}}" matBadgeOverlap="false" class="tab-badge">UTXOs</span>
</ng-template>
<rtl-cln-on-chain-utxos [utxos]="utxos" [numDustUTXOs]="numDustUtxos" [isDustUTXO]="false" xLayout="row" fxFlex="100"></rtl-cln-on-chain-utxos>
<rtl-cln-on-chain-utxos [numDustUTXOs]="numDustUtxos" [isDustUTXO]="false" xLayout="row" fxFlex="100"></rtl-cln-on-chain-utxos>
</mat-tab>
<mat-tab>
<ng-template mat-tab-label>
<span matBadge="{{numDustUtxos}}" matBadgeOverlap="false" class="tab-badge">Dust UTXOs</span>
</ng-template>
<rtl-cln-on-chain-utxos [utxos]="dustUtxos" [numDustUTXOs]="numDustUtxos" [isDustUTXO]="true" fxLayout="row" fxFlex="100"></rtl-cln-on-chain-utxos>
<rtl-cln-on-chain-utxos [numDustUTXOs]="numDustUtxos" [isDustUTXO]="true" fxLayout="row" fxFlex="100"></rtl-cln-on-chain-utxos>
</mat-tab>
</mat-tab-group>
</div>

View File

@ -1,5 +1,6 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule } from '@ngrx/store';
import { CommonService } from '../../../shared/services/common.service';
import { DataService } from '../../../shared/services/data.service';
@ -24,6 +25,7 @@ describe('CLNUTXOTablesComponent', () => {
imports: [
BrowserAnimationsModule,
SharedModule,
RouterTestingModule,
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer })
],
providers: [

View File

@ -19,9 +19,7 @@ export class CLNUTXOTablesComponent implements OnInit, OnDestroy {
@Input() selectedTableIndex = 0;
@Output() readonly selectedTableIndexChange = new EventEmitter<number>();
public utxos: UTXO[] = [];
public numUtxos = 0;
public dustUtxos: UTXO[] = [];
public numDustUtxos = 0;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
@ -31,14 +29,8 @@ export class CLNUTXOTablesComponent implements OnInit, OnDestroy {
this.store.select(utxos).pipe(takeUntil(this.unSubs[0])).
subscribe((utxosSeletor: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {
if (utxosSeletor.utxos && utxosSeletor.utxos.length > 0) {
this.utxos = utxosSeletor.utxos;
this.numUtxos = this.utxos.length;
this.dustUtxos = utxosSeletor.utxos?.filter((utxo) => +(utxo.value || 0) < 1000);
this.numDustUtxos = this.dustUtxos.length;
}
if (utxosSeletor.utxos && utxosSeletor.utxos.length > 0) {
this.utxos = utxosSeletor.utxos;
this.numUtxos = this.utxos.length;
this.numUtxos = utxosSeletor.utxos.length || 0;
this.numDustUtxos = utxosSeletor.utxos?.filter((utxo) => +(utxo.value || 0) < 1000).length || 0;
}
this.logger.info(utxosSeletor);
});

View File

@ -1,7 +1,7 @@
<div fxLayout="row wrap" fxLayoutAlign="start start" fxLayout.gt-sm="column" fxFlex="100" fxLayoutAlign.gt-sm="start stretch" class="padding-gap-x-large">
<div fxLayout="column" fxLayout.gt-xs="row wrap" fxLayoutAlign.gt-xs="start center" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70"></div>
<mat-form-field fxFlex="30">
<div fxLayout="column" fxLayoutAlign="start stretch" fxFlex="100" class="padding-gap-x-large">
<div fxLayout="column" fxLayout.gt-sm="row wrap" fxLayoutAlign="start stretch" class="page-sub-title-container">
<div fxFlex="70" fxLayoutAlign="start start" fxLayoutAlign.gt-sm="start center"></div>
<mat-form-field fxFlex="30" fxLayoutAlign="start end">
<input matInput (keyup)="applyFilter()" [(ngModel)]="selFilter" placeholder="Filter">
</mat-form-field>
</div>
@ -9,21 +9,44 @@
<div [perfectScrollbar] class="table-container" fxFlex="100">
<mat-progress-bar *ngIf="apiCallStatus?.status === apiCallStatusEnum.INITIATED" mode="indeterminate"></mat-progress-bar>
<table mat-table #table [dataSource]="listUTXOs" matSort [ngClass]="{'overflow-auto error-border': errorMessage !== '','overflow-auto': true}">
<ng-container matColumnDef="txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transaction ID </th>
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef mat-sort-header>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</th>
<td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '50rem'}">
<span fxLayout="row" fxLayoutAlign="end center" >
<span *ngIf="numDustUTXOs > 0 && !isDustUTXO">
<span *ngIf="utxo.value < 1000; else emptySpace" matTooltip="Risk of dust attack" matTooltipPosition="right">
<mat-icon fxLayoutAlign="start center" color="warn" class="mr-1">warning</mat-icon>
<mat-icon fxLayoutAlign="start start" color="warn" class="mr-1">warning</mat-icon>
</span>
</span>
<span *ngIf="utxo.status === 'confirmed'" class="dot green" matTooltip="Confirmed" matTooltipPosition="right"></span>
<span *ngIf="utxo.status !== 'confirmed'" class="dot yellow" matTooltip="{{utxo.status | titlecase}}" matTooltipPosition="right"></span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="txid">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Transaction ID </th>
<td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{utxo.txid}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="address">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Address </th>
<td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{utxo.address}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="scriptpubkey">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Script Pubkey </th>
<td mat-cell *matCellDef="let utxo">
<span fxLayout="row" class="ellipsis-parent" [ngStyle]="{'max-width': (screenSize === screenSizeEnum.XS) ? '10rem' : '30rem'}">
<span class="ellipsis-child">{{utxo.scriptpubkey}}</span>
</span>
</td>
</ng-container>
<ng-container matColumnDef="output">
<th mat-header-cell *matHeaderCellDef mat-sort-header arrowPosition="before"> Output </th>
<td mat-cell *matCellDef="let utxo"><span fxLayoutAlign="end center">
@ -41,8 +64,14 @@
<td mat-cell *matCellDef="let utxo"><span fxLayoutAlign="end center">
{{utxo?.blockheight | number}} </span></td>
</ng-container>
<ng-container matColumnDef="reserved">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="pl-3"> Reserved </th>
<td mat-cell *matCellDef="let utxo" class="pl-3">
<span>{{utxo.reserved ? 'Yes' : 'No'}}</span>
</td>
</ng-container>
<ng-container matColumnDef="actions">
<th mat-header-cell *matHeaderCellDef class="px-3">
<th mat-header-cell *matHeaderCellDef class="pr-3">
<div class="bordered-box table-actions-select">
<mat-select placeholder="Actions" tabindex="1" class="mr-0">
<mat-select-trigger></mat-select-trigger>
@ -50,7 +79,7 @@
</mat-select>
</div>
</th>
<td mat-cell *matCellDef="let utxo" class="pl-3" fxLayoutAlign="end center">
<td mat-cell *matCellDef="let utxo" fxLayoutAlign="end center">
<button mat-stroked-button color="primary" type="button" tabindex="4" (click)="onUTXOClick(utxo, $event)">View Info</button>
</td>
</ng-container>

View File

@ -1,4 +1,10 @@
.mat-column-txid {
@import '../../../../shared/theme/styles/mixins.scss';
.mat-column-status {
width: 6rem;
}
.mat-column-txid, .mat-column-address, .mat-column-scriptpubkey {
flex: 0 0 15%;
width: 15%;
& .ellipsis-parent {

View File

@ -1,5 +1,6 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouterTestingModule } from '@angular/router/testing';
import { StoreModule } from '@ngrx/store';
import { CommonService } from '../../../../shared/services/common.service';
import { DataService } from '../../../../shared/services/data.service';
@ -23,6 +24,7 @@ describe('CLNOnChainUtxosComponent', () => {
imports: [
BrowserAnimationsModule,
SharedModule,
RouterTestingModule,
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer })
],
providers: [

View File

@ -1,4 +1,5 @@
import { Component, ViewChild, Input, OnChanges, AfterViewInit, OnDestroy, OnInit } from '@angular/core';
import { Component, ViewChild, Input, AfterViewInit, OnDestroy, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { Store } from '@ngrx/store';
@ -7,14 +8,15 @@ import { MatPaginator, MatPaginatorIntl } from '@angular/material/paginator';
import { MatSort } from '@angular/material/sort';
import { MatTableDataSource } from '@angular/material/table';
import { UTXO } from '../../../../shared/models/clnModels';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum } from '../../../../shared/services/consts-enums-functions';
import { PAGE_SIZE, PAGE_SIZE_OPTIONS, getPaginatorLabel, AlertTypeEnum, DataTypeEnum, ScreenSizeEnum, APICallStatusEnum, SortOrderEnum, CLN_DEFAULT_PAGE_SETTINGS } from '../../../../shared/services/consts-enums-functions';
import { ApiCallStatusPayload } from '../../../../shared/models/apiCallsPayload';
import { LoggerService } from '../../../../shared/services/logger.service';
import { CommonService } from '../../../../shared/services/common.service';
import { RTLState } from '../../../../store/rtl.state';
import { openAlert } from '../../../../store/rtl.actions';
import { utxos } from '../../../store/cln.selector';
import { clnPageSettings, utxos } from '../../../store/cln.selector';
import { PageSettingsCLN, TableSetting } from '../../../../shared/models/pageSettings';
@Component({
selector: 'rtl-cln-on-chain-utxos',
@ -24,14 +26,16 @@ import { utxos } from '../../../store/cln.selector';
{ provide: MatPaginatorIntl, useValue: getPaginatorLabel('UTXOs') }
]
})
export class CLNOnChainUtxosComponent implements OnInit, OnChanges, AfterViewInit, OnDestroy {
export class CLNOnChainUtxosComponent implements OnInit, AfterViewInit, OnDestroy {
@ViewChild(MatSort, { static: false }) sort: MatSort | undefined;
@ViewChild(MatPaginator, { static: false }) paginator: MatPaginator | undefined;
@Input() numDustUTXOs = 0;
@Input() isDustUTXO = false;
@Input() utxos: UTXO[];
public PAGE_ID = 'on-chain';
public tableSetting: TableSetting = { tableId: 'utxos', recordsPerPage: 10, sortBy: 'status', sortOrder: SortOrderEnum.DESCENDING };
public displayedColumns: any[] = [];
public utxos: UTXO[];
public listUTXOs: any;
public pageSize = PAGE_SIZE;
public pageSizeOptions = PAGE_SIZE_OPTIONS;
@ -41,29 +45,45 @@ export class CLNOnChainUtxosComponent implements OnInit, OnChanges, AfterViewIni
public selFilter = '';
public apiCallStatus: ApiCallStatusPayload | null = null;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject()];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>) {
constructor(private logger: LoggerService, private commonService: CommonService, private store: Store<RTLState>, private router: Router) {
this.screenSize = this.commonService.getScreenSize();
if (this.screenSize === ScreenSizeEnum.XS) {
this.displayedColumns = ['txid', 'value', 'actions'];
} else if (this.screenSize === ScreenSizeEnum.SM) {
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
} else if (this.screenSize === ScreenSizeEnum.MD) {
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
} else {
this.displayedColumns = ['txid', 'output', 'value', 'blockheight', 'actions'];
}
}
ngOnInit() {
this.store.select(utxos).pipe(takeUntil(this.unSubs[0])).
this.router.routeReuseStrategy.shouldReuseRoute = () => false;
this.router.onSameUrlNavigation = 'reload';
this.tableSetting.tableId = this.isDustUTXO ? 'dust_utxos' : 'utxos';
this.store.select(clnPageSettings).pipe(takeUntil(this.unSubs[0])).
subscribe((settings: { pageSettings: PageSettingsCLN[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = settings.apiCallStatus;
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessage = this.apiCallStatus.message || '';
}
this.tableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId) || CLN_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelectionSM));
} else {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelection));
}
this.displayedColumns.unshift('status');
this.displayedColumns.push('actions');
this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE;
this.logger.info(this.displayedColumns);
});
this.store.select(utxos).pipe(takeUntil(this.unSubs[1])).
subscribe((utxosSeletor: { utxos: UTXO[], apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = utxosSeletor.apiCallStatus;
if (this.apiCallStatus.status === APICallStatusEnum.ERROR) {
this.errorMessage = !this.apiCallStatus.message ? '' : (typeof (this.apiCallStatus.message) === 'object') ? JSON.stringify(this.apiCallStatus.message) : this.apiCallStatus.message;
}
this.utxos = (this.isDustUTXO) ? utxosSeletor.utxos?.filter((utxo) => +(utxo.value || 0) < 1000) : utxosSeletor.utxos ? utxosSeletor.utxos : [];
if (this.utxos && this.utxos.length > 0 && this.sort && this.paginator) {
this.loadUTXOsTable(this.utxos);
}
this.logger.info(utxosSeletor);
});
}
@ -74,12 +94,6 @@ export class CLNOnChainUtxosComponent implements OnInit, OnChanges, AfterViewIni
}
}
ngOnChanges() {
if (this.utxos && this.utxos.length > 0) {
this.loadUTXOsTable(this.utxos);
}
}
applyFilter() {
this.listUTXOs.filter = this.selFilter.trim().toLowerCase();
}
@ -108,6 +122,7 @@ export class CLNOnChainUtxosComponent implements OnInit, OnChanges, AfterViewIni
this.listUTXOs = new MatTableDataSource<UTXO>([...utxos]);
this.listUTXOs.sortingDataAccessor = (data: any, sortHeaderId: string) => ((data[sortHeaderId] && isNaN(data[sortHeaderId])) ? data[sortHeaderId].toLocaleLowerCase() : data[sortHeaderId] ? +data[sortHeaderId] : null);
this.listUTXOs.sort = this.sort;
this.listUTXOs.sort.sort({ id: this.tableSetting.sortBy, start: this.tableSetting.sortOrder, disableClear: true });
this.listUTXOs.filterPredicate = (utxo: UTXO, fltr: string) => JSON.stringify(utxo).toLowerCase().includes(fltr);
this.listUTXOs.paginator = this.paginator;
this.applyFilter();

View File

@ -1,23 +1,7 @@
@import '../../../../shared/theme/styles/mixins.scss';
.mat-column-status {
max-width: 1rem;
& .dot {
@include for_screensize(tab-port) {
width:0.6rem;
height: 0.6rem;
left: 2.8rem;
margin-top: -0.3rem;
position: absolute;
}
@include for_screensize(phone) {
width:0.6rem;
height: 0.6rem;
left: 0.8rem;
margin-top: -0.3rem;
position: absolute;
}
}
width: 2rem;
}
.mat-column-description, .mat-column-label, .mat-column-payment_hash, .mat-column-bolt11 {

View File

@ -64,7 +64,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
public selFilter = '';
public apiCallStatus: ApiCallStatusPayload | null = null;
public apiCallStatusEnum = APICallStatusEnum;
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
private unSubs: Array<Subject<void>> = [new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject(), new Subject()];
constructor(private logger: LoggerService, private store: Store<RTLState>, private decimalPipe: DecimalPipe, private commonService: CommonService, private rtlEffects: RTLEffects, private datePipe: DatePipe, private actions: Actions) {
this.screenSize = this.commonService.getScreenSize();
@ -86,16 +86,16 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
}
this.tableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId) || CLN_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.showColumnsSM));
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelectionSM));
} else {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.showColumns));
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelection));
}
this.displayedColumns.unshift('status');
this.displayedColumns.push('actions');
this.pageSize = this.tableSetting.recordsPerPage ? +this.tableSetting.recordsPerPage : PAGE_SIZE;
this.logger.info(this.displayedColumns);
});
this.store.select(listInvoices).pipe(takeUntil(this.unSubs[2])).
this.store.select(listInvoices).pipe(takeUntil(this.unSubs[3])).
subscribe((invoicesSeletor: { listInvoices: ListInvoices, apiCallStatus: ApiCallStatusPayload }) => {
this.errorMessage = '';
this.apiCallStatus = invoicesSeletor.apiCallStatus;
@ -108,7 +108,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
}
this.logger.info(invoicesSeletor);
});
this.actions.pipe(takeUntil(this.unSubs[3]), filter((action) => (action.type === CLNActions.SET_LOOKUP_CLN || action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN))).
this.actions.pipe(takeUntil(this.unSubs[4]), filter((action) => (action.type === CLNActions.SET_LOOKUP_CLN || action.type === CLNActions.UPDATE_API_CALL_STATUS_CLN))).
subscribe((resLookup: any) => {
if (resLookup.type === CLNActions.SET_LOOKUP_CLN) {
if (this.invoiceJSONArr && this.invoiceJSONArr.length > 0 && this.sort && this.paginator && resLookup.payload) {
@ -158,7 +158,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
}
}));
this.rtlEffects.closeConfirm.
pipe(takeUntil(this.unSubs[4])).
pipe(takeUntil(this.unSubs[5])).
subscribe((confirmRes) => {
if (confirmRes) {
this.store.dispatch(deleteExpiredInvoice({ payload: null }));
@ -205,7 +205,7 @@ export class CLNLightningInvoicesTableComponent implements OnInit, AfterViewInit
if (this.selNode && this.selNode.fiatConversion && this.invoiceValue! > 99) {
this.invoiceValueHint = '';
this.commonService.convertCurrency(this.invoiceValue!, CurrencyUnitEnum.SATS, CurrencyUnitEnum.OTHER, (this.selNode?.currencyUnits && this.selNode.currencyUnits.length > 2 ? this.selNode.currencyUnits[2] : ''), this.selNode.fiatConversion).
pipe(takeUntil(this.unSubs[5])).
pipe(takeUntil(this.unSubs[6])).
subscribe({
next: (data) => {
this.invoiceValueHint = '= ' + data.symbol + this.decimalPipe.transform(data.OTHER, CURRENCY_UNIT_FORMATS.OTHER) + ' ' + data.unit;

View File

@ -1,29 +1,7 @@
@import '../../../shared/theme/styles/mixins.scss';
.mat-column-status, .mat-column-group_status {
max-width: 0.2rem;
@include for_screensize(tab-port) {
min-width: 1rem;
}
@include for_screensize(phone) {
min-width: 1rem;
}
& .dot {
@include for_screensize(tab-port) {
width:0.6rem;
height: 0.6rem;
left: 4rem;
margin-top: -0.4rem;
position: absolute;
}
@include for_screensize(phone) {
width:0.6rem;
height: 0.6rem;
left: 0;
margin-top: -0.2rem;
position: absolute;
}
}
width: 2rem;
}
.mat-column-payment_hash, .mat-column-bolt11, .mat-column-destination, .mat-column-label, .mat-column-memo {

View File

@ -83,9 +83,9 @@ export class CLNLightningPaymentsComponent implements OnInit, AfterViewInit, OnD
}
this.tableSetting = settings.pageSettings.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId) || CLN_DEFAULT_PAGE_SETTINGS.find((page) => page.pageId === this.PAGE_ID)?.tables.find((table) => table.tableId === this.tableSetting.tableId)!;
if (this.screenSize === ScreenSizeEnum.XS || this.screenSize === ScreenSizeEnum.SM) {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.showColumnsSM));
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelectionSM));
} else {
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.showColumns));
this.displayedColumns = JSON.parse(JSON.stringify(this.tableSetting.columnSelection));
}
this.displayedColumns.unshift('status');
this.displayedColumns.push('actions');

View File

@ -2,15 +2,16 @@
<form fxLayout="column" fxLayoutAlign="start stretch" class="settings-container page-sub-title-container mt-1" #form="ngForm">
<div fxLayout="row">
<fa-icon [icon]="faPenRuler" class="page-title-img mr-1"></fa-icon>
<span class="page-title">Page Settings</span>
<span class="page-title">Grid Settings</span>
</div>
<ng-container *ngIf="errorMessage && errorMessage.page === 'unknown'" [ngTemplateOutlet]="errorObjectBlock" [ngTemplateOutletContext]="{error: errorMessage}"></ng-container>
<mat-expansion-panel fxLayout="column" class="flat-expansion-panel mt-1" [ngClass]="{'error-border': errorMessage?.page === page.pageId}" expanded="true" *ngFor="let page of pageSettings">
<mat-expansion-panel-header>
<mat-panel-title>{{page.pageId | titlecase}}</mat-panel-title>
</mat-expansion-panel-header>
<div fxLayout="column" fxLayoutAlign="start stretch" *ngFor="let table of page.tables" class="padding-gap-x-large">
<div fxLayout="row" fxLayoutAlign="space-between center" class="mt-1">
<div fxLayout="column" fxLayoutAlign="start stretch" *ngFor="let table of page.tables" class="padding-gap-x-large table-setting-row">
<div fxLayout="row" fxLayoutAlign="space-between center">
<span fxFlex="10">Table {{table.tableId | camelcaseWithReplace:'_'}}: </span>
<mat-form-field fxFlex="10">
<mat-select [(ngModel)]="table.recordsPerPage" placeholder="Records/Page" name="{{table.tableId}}-page-size-options" tabindex="1" required>
<mat-option *ngFor="let pageSizeOption of pageSizeOptions" [value]="pageSizeOption">
@ -20,7 +21,7 @@
</mat-form-field>
<mat-form-field fxFlex="10">
<mat-select [(ngModel)]="table.sortBy" placeholder="Sort By" name="{{table.tableId}}-sort-by" tabindex="2" required>
<mat-option *ngFor="let field of table.showColumns" [value]="field">
<mat-option *ngFor="let field of table.columnSelection" [value]="field">
{{field | camelcaseWithReplace:'_'}}
</mat-option>
</mat-select>
@ -32,21 +33,21 @@
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field fxFlex="13">
<mat-select [(ngModel)]="table.showColumnsSM" placeholder="Small Screen Columns" name="{{table.tableId}}-show-columns-sm" tabindex="4" multiple required>
<mat-option *ngFor="let field of table.showColumns" [value]="field" [disabled]="(table.showColumns.length <= 1 && table.showColumns.includes(field)) || (table.showColumns.length >= 2 && !table.showColumns.includes(field))">
<mat-form-field fxFlex="18">
<mat-select [(ngModel)]="table.columnSelectionSM" placeholder="Column selection (Mobile)" name="{{table.tableId}}-columns-selection-sm" tabindex="4" multiple required>
<mat-option *ngFor="let field of tableFieldsDef[table.tableId].allowedColumns" [value]="field" [disabled]="(table.columnSelectionSM.length <= 1 && table.columnSelectionSM.includes(field)) || (table.columnSelectionSM.length >= 2 && !table.columnSelectionSM.includes(field))">
{{field | camelcaseWithReplace:'_'}}
</mat-option>
</mat-select>
<mat-hint>Small screen selected columns should be between 1 and 2</mat-hint>
<mat-hint>Columns (mobile) should be between 1 and 2</mat-hint>
</mat-form-field>
<mat-form-field fxFlex="55">
<mat-select [(ngModel)]="table.showColumns" (selectionChange)="onShowColumnsChange(table)" placeholder="Show Columns" name="{{table.tableId}}-show-columns" tabindex="5" multiple required>
<mat-option *ngFor="let field of tableFieldsDef[table.tableId].allowedColumns" [value]="field" [disabled]="(table.showColumns.length <= 2 && table.showColumns.includes(field)) || (table.showColumns.length >= tableFieldsDef[table.tableId].maxColumns && !table.showColumns.includes(field))">
{{field | camelcaseWithReplace:'_'}}
<mat-form-field fxFlex="40">
<mat-select [(ngModel)]="table.columnSelection" (selectionChange)="oncolumnSelectionChange(table)" placeholder="Column selection (Desktop)" name="{{table.tableId}}-columns-selection" tabindex="5" multiple required>
<mat-option *ngFor="let field of tableFieldsDef[table.tableId].allowedColumns" [value]="field" [disabled]="(table.columnSelection.length <= 2 && table.columnSelection.includes(field)) || (table.columnSelection.length >= tableFieldsDef[table.tableId].maxColumns && !table.columnSelection.includes(field))">
{{field | camelcaseWithReplace:'_'}}
</mat-option>
</mat-select>
<mat-hint>Total selected columns should be between 2 and {{tableFieldsDef[table.tableId].maxColumns}}</mat-hint>
<mat-hint>Column selection should be between 2 and {{tableFieldsDef[table.tableId].maxColumns}}</mat-hint>
</mat-form-field>
</div>
</div>
@ -54,8 +55,9 @@
</mat-expansion-panel>
</form>
<div fxLayout="row" class="mt-1">
<button class="mr-1" mat-stroked-button color="primary" (click)="onResetPageSettings()" tabindex="6">Reset</button>
<button mat-flat-button color="primary" (click)="onUpdatePageSettings()" tabindex="7">Save</button>
<button class="mr-1" mat-stroked-button color="primary" (click)="onResetPageSettings('current')" tabindex="6">Reset</button>
<button class="mr-1" mat-stroked-button color="primary" (click)="onResetPageSettings('default')" tabindex="7">Default Settings</button>
<button mat-flat-button color="primary" (click)="onUpdatePageSettings()" tabindex="8">Save</button>
</div>
</div>
<ng-template #errorObjectBlock let-error="error">

View File

@ -0,0 +1,8 @@
.table-setting-row {
&:last-child {
margin-bottom: 3rem;
}
&:not(:first-child) {
margin: 3rem 0;
}
}

View File

@ -1,4 +1,5 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { EffectsModule } from '@ngrx/effects';
import { StoreModule } from '@ngrx/store';
import { RootReducer } from '../../../../store/rtl.reducers';
@ -7,9 +8,9 @@ import { CLNReducer } from '../../../../cln/store/cln.reducers';
import { ECLReducer } from '../../../../eclair/store/ecl.reducers';
import { CommonService } from '../../../services/common.service';
import { LoggerService } from '../../../services/logger.service';
import { mockCLEffects, mockDataService, mockECLEffects, mockLNDEffects, mockLoggerService, mockRTLEffects } from '../../../../shared/test-helpers/mock-services';
import { PageSettingsComponent } from './page-settings.component';
import { mockDataService, mockLoggerService } from '../../../test-helpers/mock-services';
import { SharedModule } from '../../../shared.module';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { DataService } from '../../../services/data.service';
@ -24,7 +25,8 @@ describe('PageSettingsComponent', () => {
imports: [
BrowserAnimationsModule,
SharedModule,
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer })
StoreModule.forRoot({ root: RootReducer, lnd: LNDReducer, cln: CLNReducer, ecl: ECLReducer }),
EffectsModule.forRoot([mockRTLEffects, mockLNDEffects, mockCLEffects, mockECLEffects])
],
providers: [
CommonService,

View File

@ -59,23 +59,29 @@ export class PageSettingsComponent implements OnInit, OnDestroy {
});
}
onShowColumnsChange(table: TableSetting) {
if (table.showColumns && !table.showColumns.includes(table.sortBy)) {
table.sortBy = table.showColumns[0];
oncolumnSelectionChange(table: TableSetting) {
if (table.columnSelection && !table.columnSelection.includes(table.sortBy)) {
table.sortBy = table.columnSelection[0];
}
}
onUpdatePageSettings(): boolean | void {
if (this.pageSettings.reduce((pacc, page) => pacc || (page.tables.reduce((acc, table) => !(table.recordsPerPage && table.sortBy && table.sortOrder && table.showColumns && table.showColumns.length >= 2), false)), false)) {
if (this.pageSettings.reduce((pacc, page) => pacc || (page.tables.reduce((acc, table) => !(table.recordsPerPage && table.sortBy && table.sortOrder && table.columnSelection && table.columnSelection.length >= 2), false)), false)) {
return true;
}
this.errorMessage = '';
this.store.dispatch(savePageSettings({ payload: this.pageSettings }));
}
onResetPageSettings() {
this.errorMessage = null;
this.pageSettings = this.initialPageSettings;
onResetPageSettings(prev: string) {
if (prev === 'current') {
this.errorMessage = null;
this.pageSettings = this.initialPageSettings;
} else {
this.errorMessage = null;
this.pageSettings = CLN_DEFAULT_PAGE_SETTINGS;
this.onUpdatePageSettings();
}
}
ngOnDestroy() {

View File

@ -6,8 +6,8 @@ export class TableSetting {
recordsPerPage?: number;
sortBy?: string;
sortOrder?: SortOrderEnum;
showColumnsSM?: any[];
showColumns?: any[];
columnSelectionSM?: any[];
columnSelection?: any[];
}

View File

@ -675,12 +675,24 @@ export enum SortOrderEnum {
export const SORT_ORDERS = ['asc', 'desc'];
export const CLN_DEFAULT_PAGE_SETTINGS: PageSettingsCLN[] = [
{ pageId: 'payments', tables: [{ tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING,
showColumnsSM: ['created_at', 'msatoshi'],
showColumns: ['created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi'] }] },
{ pageId: 'invoices', tables: [{ tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expires_at', sortOrder: SortOrderEnum.DESCENDING,
showColumnsSM: ['expires_at', 'msatoshi'],
showColumns: ['expires_at', 'paid_at', 'type', 'description', 'msatoshi', 'msatoshi_received'] }] }
{ pageId: 'payments', tables: [
{ tableId: 'payments', recordsPerPage: PAGE_SIZE, sortBy: 'created_at', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['created_at', 'msatoshi'],
columnSelection: ['created_at', 'type', 'payment_hash', 'msatoshi_sent', 'msatoshi'] }
] },
{ pageId: 'invoices', tables: [
{ tableId: 'invoices', recordsPerPage: PAGE_SIZE, sortBy: 'expires_at', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['expires_at', 'msatoshi'],
columnSelection: ['expires_at', 'paid_at', 'type', 'description', 'msatoshi', 'msatoshi_received'] }
] },
{ pageId: 'on-chain', tables: [
{ tableId: 'utxos', recordsPerPage: PAGE_SIZE, sortBy: 'blockheight', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['txid', 'value'],
columnSelection: ['txid', 'output', 'value', 'blockheight'] },
{ tableId: 'dust_utxos', recordsPerPage: PAGE_SIZE, sortBy: 'blockheight', sortOrder: SortOrderEnum.DESCENDING,
columnSelectionSM: ['txid', 'value'],
columnSelection: ['txid', 'output', 'value', 'blockheight'] }
] }
];
export const CLN_TABLES_DEF = {
@ -691,5 +703,13 @@ export const CLN_TABLES_DEF = {
invoices: {
maxColumns: 6,
allowedColumns: ['expires_at', 'paid_at', 'type', 'description', 'label', 'payment_hash', 'bolt11', 'msatoshi', 'msatoshi_received']
},
utxos: {
maxColumns: 7,
allowedColumns: ['txid', 'address', 'scriptpubkey', 'output', 'value', 'blockheight', 'reserved']
},
dust_utxos: {
maxColumns: 7,
allowedColumns: ['txid', 'address', 'scriptpubkey', 'output', 'value', 'blockheight', 'reserved']
}
};

View File

@ -29,7 +29,7 @@ $red-color: #c62828;
$red-background-color: #f8d7da;
$blue-color: #004085;
$blue-background-color: #cce5ff;
$grey-color: #AAAAAA;
$grey-color: #CCCCCC;
$tiny-dot-size: 0.8rem;
$dot-size: 1.2rem;
$badge-size: 0.8rem;

View File

@ -19,16 +19,16 @@ ORDER: Base + typography > general layout + grid > page layout > components
@mixin for_screensize($breakpoint) {
@if $breakpoint == phone {
@media only screen and (max-width: 37.5em) { @content }; //600px
@media only screen and (max-width: 60rem) { @content }; //600px
}
@if $breakpoint == tab-port {
@media only screen and (max-width: 56.25em) { @content }; //900px
@media only screen and (max-width: 90rem) { @content }; //900px
}
@if $breakpoint == tab-land {
@media only screen and (max-width: 75em) { @content }; //1200px
@media only screen and (max-width: 120rem) { @content }; //1200px
}
@if $breakpoint == big-desktop {
@media only screen and (min-width: 112.5em) { @content }; //1800
@media only screen and (min-width: 180rem) { @content }; //1800px
}
}

View File

@ -258,19 +258,19 @@ mat-cell:last-of-type, mat-header-cell:last-of-type, mat-footer-cell:last-of-typ
}
.green {
color: #388e3c !important;
color: $green-color !important;
}
.yellow {
color: #ffd740 !important;
color: $yellow-color !important;
}
.red {
color: #c62828 !important;
color: $red-color !important;
}
.grey {
color: #CCCCCC !important;
color: $grey-color !important;
}
.mt-1px {
@ -1538,11 +1538,11 @@ th.mat-header-cell:last-of-type, td.mat-cell:last-of-type, td.mat-footer-cell:la
text-align: left;
}
.table-container {
// height: 400rem;
// overflow-y: auto;
// overflow-x: hidden;
}
// .table-container {
// height: 25rem;
// overflow: auto;
// overflow-x: hidden;
// }
.mat-expansion-panel.flat-expansion-panel {
box-shadow: none;