mirror of
https://github.com/yzernik/squeaknode.git
synced 2026-08-20 13:28:20 +02:00
Add clear image dialog (#811)
* Added clear profile image dialog * Reload profile without reloading page after making changes * Update static build
This commit is contained in:
parent
37609a85d4
commit
b2dd9e7ff3
21 changed files with 230 additions and 32 deletions
|
|
@ -0,0 +1,111 @@
|
|||
import React, {useState, useEffect} from 'react';
|
||||
import {
|
||||
Paper,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Typography,
|
||||
Grid,
|
||||
Box,
|
||||
Link,
|
||||
Dialog,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
TextField,
|
||||
DialogActions,
|
||||
Button,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Select,
|
||||
} from "@material-ui/core";
|
||||
import { MoreVert as MoreIcon } from "@material-ui/icons";
|
||||
import {useHistory} from "react-router-dom";
|
||||
import classnames from "classnames";
|
||||
|
||||
// styles
|
||||
import useStyles from "./styles";
|
||||
|
||||
import Widget from "../../components/Widget";
|
||||
import SqueakThreadItem from "../../components/SqueakThreadItem";
|
||||
|
||||
import {
|
||||
clearSqueakProfileImageRequest,
|
||||
} from "../../squeakclient/requests"
|
||||
import {
|
||||
reloadRoute,
|
||||
} from "../../navigation/navigation"
|
||||
|
||||
|
||||
export default function ClearProfileImageDialog({
|
||||
open,
|
||||
handleClose,
|
||||
squeakProfile,
|
||||
reloadProfile,
|
||||
...props
|
||||
}) {
|
||||
var classes = useStyles();
|
||||
const history = useHistory();
|
||||
|
||||
const handleResponse = (response) => {
|
||||
reloadProfile();
|
||||
};
|
||||
|
||||
const handleErr = (err) => {
|
||||
alert('Error clearing profile image: ' + err);
|
||||
};
|
||||
|
||||
const clearProfileImage = () => {
|
||||
clearSqueakProfileImageRequest(
|
||||
squeakProfile.getProfileId(),
|
||||
handleResponse,
|
||||
handleErr,
|
||||
);
|
||||
};
|
||||
|
||||
function handleSubmit(event) {
|
||||
event.preventDefault();
|
||||
clearProfileImage();
|
||||
handleClose();
|
||||
}
|
||||
|
||||
function CancelButton() {
|
||||
return (
|
||||
<Button
|
||||
onClick={handleClose}
|
||||
variant="contained"
|
||||
color="secondary"
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
function ClearProfileImageButton() {
|
||||
return (
|
||||
<Button
|
||||
type="submit"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.button}
|
||||
>
|
||||
Clear Profile Image
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onClose={handleClose} aria-labelledby="form-dialog-title">
|
||||
<DialogTitle id="form-dialog-title">Clear Profile Image</DialogTitle>
|
||||
<form className={classes.root} onSubmit={handleSubmit} noValidate autoComplete="off">
|
||||
<DialogContent>
|
||||
Are you sure you want to clear the image for this profile?
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
{CancelButton()}
|
||||
{ClearProfileImageButton()}
|
||||
</DialogActions>
|
||||
</form>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "ClearProfileImageDialog",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"main": "ClearProfileImageDialog.js"
|
||||
}
|
||||
43
frontend/src/components/ClearProfileImageDialog/styles.js
Normal file
43
frontend/src/components/ClearProfileImageDialog/styles.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import { makeStyles } from "@material-ui/styles";
|
||||
|
||||
export default makeStyles(theme => ({
|
||||
widgetWrapper: {
|
||||
display: "flex",
|
||||
minHeight: "100%",
|
||||
},
|
||||
widgetHeader: {
|
||||
padding: theme.spacing(3),
|
||||
paddingBottom: theme.spacing(1),
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
},
|
||||
widgetRoot: {
|
||||
boxShadow: theme.customShadows.widget,
|
||||
},
|
||||
widgetBody: {
|
||||
paddingBottom: theme.spacing(3),
|
||||
paddingRight: theme.spacing(3),
|
||||
paddingLeft: theme.spacing(3),
|
||||
},
|
||||
noPadding: {
|
||||
padding: 0,
|
||||
},
|
||||
paper: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
flexGrow: 1,
|
||||
overflow: "hidden",
|
||||
},
|
||||
moreButton: {
|
||||
margin: -theme.spacing(1),
|
||||
padding: 0,
|
||||
width: 40,
|
||||
height: 40,
|
||||
color: theme.palette.text.hint,
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.primary.main,
|
||||
color: "rgba(255, 255, 255, 0.35)",
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
|
@ -40,6 +40,7 @@ export default function DeleteProfileDialog({
|
|||
open,
|
||||
handleClose,
|
||||
profile,
|
||||
reloadProfile,
|
||||
...props
|
||||
}) {
|
||||
var classes = useStyles();
|
||||
|
|
@ -47,7 +48,7 @@ export default function DeleteProfileDialog({
|
|||
|
||||
const deleteProfile = (profileId) => {
|
||||
deleteProfileRequest(profileId, (response) => {
|
||||
reloadRoute(history);
|
||||
reloadProfile();
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ export default function RenameProfileDialog({
|
|||
open,
|
||||
handleClose,
|
||||
profile,
|
||||
reloadProfile,
|
||||
...props
|
||||
}) {
|
||||
var classes = useStyles();
|
||||
|
|
@ -57,7 +58,7 @@ export default function RenameProfileDialog({
|
|||
};
|
||||
|
||||
const handleResponse = (response) => {
|
||||
reloadRoute(history);
|
||||
reloadProfile();
|
||||
};
|
||||
|
||||
const handleErr = (err) => {
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import RenameProfileDialog from "../../components/RenameProfileDialog";
|
|||
import ExportPrivateKeyDialog from "../../components/ExportPrivateKeyDialog";
|
||||
import ConfigureProfileDialog from "../../components/ConfigureProfileDialog";
|
||||
import UpdateProfileImageDialog from "../../components/UpdateProfileImageDialog";
|
||||
import ClearProfileImageDialog from "../../components/ClearProfileImageDialog";
|
||||
|
||||
|
||||
import {
|
||||
|
|
@ -68,6 +69,7 @@ export default function SqueakProfileDetailItem({
|
|||
const [exportPrivateKeyDialogOpen, setExportPrivateKeyDialogOpen] = useState(false);
|
||||
const [configureDialogOpen, setConfigureDialogOpen] = useState(false);
|
||||
const [updateImageDialogOpen, setUpdateImageDialogOpen] = useState(false);
|
||||
const [clearImageDialogOpen, setClearImageDialogOpen] = useState(false);
|
||||
|
||||
const handleClick = (event) => {
|
||||
setAnchorEl(event.currentTarget);
|
||||
|
|
@ -115,6 +117,15 @@ export default function SqueakProfileDetailItem({
|
|||
setUpdateImageDialogOpen(true);
|
||||
}
|
||||
|
||||
const onClearImageClick = () => {
|
||||
console.log("Handling clear image click...");
|
||||
handleClose();
|
||||
if (!squeakProfile) {
|
||||
return;
|
||||
}
|
||||
setClearImageDialogOpen(true);
|
||||
}
|
||||
|
||||
const onExportClick = () => {
|
||||
console.log("Handling export click...");
|
||||
handleClose();
|
||||
|
|
@ -153,6 +164,10 @@ export default function SqueakProfileDetailItem({
|
|||
setUpdateImageDialogOpen(false);
|
||||
};
|
||||
|
||||
const handleCloseClearImageDialog = () => {
|
||||
setClearImageDialogOpen(false);
|
||||
};
|
||||
|
||||
const profileImageBase64String = squeakProfile.getProfileImage();
|
||||
|
||||
|
||||
|
|
@ -163,6 +178,7 @@ export default function SqueakProfileDetailItem({
|
|||
open={deleteDialogOpen}
|
||||
handleClose={handleCloseDeleteDialog}
|
||||
profile={squeakProfile}
|
||||
reloadProfile={handleReloadProfile}
|
||||
></DeleteProfileDialog>
|
||||
</>
|
||||
)
|
||||
|
|
@ -175,6 +191,7 @@ export default function SqueakProfileDetailItem({
|
|||
open={renameDialogOpen}
|
||||
handleClose={handleCloseRenameDialog}
|
||||
profile={squeakProfile}
|
||||
reloadProfile={handleReloadProfile}
|
||||
></RenameProfileDialog>
|
||||
</>
|
||||
)
|
||||
|
|
@ -218,6 +235,19 @@ export default function SqueakProfileDetailItem({
|
|||
)
|
||||
}
|
||||
|
||||
function ClearImageDialogContent() {
|
||||
return (
|
||||
<>
|
||||
<ClearProfileImageDialog
|
||||
open={clearImageDialogOpen}
|
||||
handleClose={handleCloseClearImageDialog}
|
||||
squeakProfile={squeakProfile}
|
||||
reloadProfile={handleReloadProfile}
|
||||
></ClearProfileImageDialog>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -239,6 +269,7 @@ export default function SqueakProfileDetailItem({
|
|||
<MenuItem onClick={onConfigureClick}>Configure</MenuItem>
|
||||
<MenuItem onClick={onRenameClick}>Rename</MenuItem>
|
||||
<MenuItem onClick={onChangeImageClick}>Change Image</MenuItem>
|
||||
<MenuItem onClick={onClearImageClick}>Clear Image</MenuItem>
|
||||
{squeakProfile.getHasPrivateKey() &&
|
||||
<MenuItem onClick={onExportClick}>Export</MenuItem>
|
||||
}
|
||||
|
|
@ -278,6 +309,7 @@ export default function SqueakProfileDetailItem({
|
|||
{ExportPrivateKeyDialogContent()}
|
||||
{ConfigureProfileDialogContent()}
|
||||
{UpdateImageDialogContent()}
|
||||
{ClearImageDialogContent()}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ export default function UpdateProfileImageDialog({
|
|||
};
|
||||
|
||||
const handleResponse = (response) => {
|
||||
// TODO: reload profile only.
|
||||
reloadRoute(history);
|
||||
reloadProfile();
|
||||
};
|
||||
|
||||
const handleErr = (err) => {
|
||||
|
|
|
|||
|
|
@ -75,8 +75,12 @@ export default function ProfilePage() {
|
|||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const handleGetSqueakProfileErr = (err) => {
|
||||
setSqueakProfile(null);
|
||||
};
|
||||
|
||||
const getSqueakProfile = (id) => {
|
||||
getSqueakProfileRequest(id, setSqueakProfile);
|
||||
getSqueakProfileRequest(id, setSqueakProfile, handleGetSqueakProfileErr);
|
||||
};
|
||||
|
||||
useEffect(()=>{
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ export function lndPendingChannelsRequest(handleResponse) {
|
|||
);
|
||||
}
|
||||
|
||||
export function getSqueakProfileRequest(id, handleResponse) {
|
||||
export function getSqueakProfileRequest(id, handleResponse, handleErr) {
|
||||
var request = new GetSqueakProfileRequest();
|
||||
request.setProfileId(id);
|
||||
makeRequest(
|
||||
|
|
@ -247,7 +247,8 @@ export function getSqueakProfileRequest(id, handleResponse) {
|
|||
GetSqueakProfileReply.deserializeBinary,
|
||||
(response) => {
|
||||
handleResponse(response.getSqueakProfile());
|
||||
}
|
||||
},
|
||||
handleErr,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,7 +247,7 @@ def create_app(handler, username, password):
|
|||
@login_required
|
||||
def clearsqueakprofileimage():
|
||||
return handle_request(
|
||||
squeak_admin_pb2.ClearSqueakProfileImage(),
|
||||
squeak_admin_pb2.ClearSqueakProfileImageRequest(),
|
||||
handler.handle_clear_squeak_profile_image,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
{
|
||||
"files": {
|
||||
"main.js": "/static/js/main.6d2e758d.chunk.js",
|
||||
"main.js.map": "/static/js/main.6d2e758d.chunk.js.map",
|
||||
"main.js": "/static/js/main.6bec17f9.chunk.js",
|
||||
"main.js.map": "/static/js/main.6bec17f9.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.9f0ba400.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.9f0ba400.js.map",
|
||||
"static/css/2.15110fae.chunk.css": "/static/css/2.15110fae.chunk.css",
|
||||
"static/js/2.c9e1641e.chunk.js": "/static/js/2.c9e1641e.chunk.js",
|
||||
"static/js/2.c9e1641e.chunk.js.map": "/static/js/2.c9e1641e.chunk.js.map",
|
||||
"static/js/2.0730cb3f.chunk.js": "/static/js/2.0730cb3f.chunk.js",
|
||||
"static/js/2.0730cb3f.chunk.js.map": "/static/js/2.0730cb3f.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"precache-manifest.8cd0391333d184d8cd73c2566f3ab102.js": "/precache-manifest.8cd0391333d184d8cd73c2566f3ab102.js",
|
||||
"precache-manifest.3ca520d21d6c54a7d5b0bb7f09da1d86.js": "/precache-manifest.3ca520d21d6c54a7d5b0bb7f09da1d86.js",
|
||||
"service-worker.js": "/service-worker.js",
|
||||
"static/css/2.15110fae.chunk.css.map": "/static/css/2.15110fae.chunk.css.map",
|
||||
"static/js/2.c9e1641e.chunk.js.LICENSE.txt": "/static/js/2.c9e1641e.chunk.js.LICENSE.txt",
|
||||
"static/js/2.0730cb3f.chunk.js.LICENSE.txt": "/static/js/2.0730cb3f.chunk.js.LICENSE.txt",
|
||||
"static/media/font-awesome.min.css": "/static/media/fontawesome-webfont.fee66e71.woff",
|
||||
"static/media/google.svg": "/static/media/google.695a3160.svg",
|
||||
"static/media/logo.svg": "/static/media/logo.a0185b04.svg"
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
"entrypoints": [
|
||||
"static/js/runtime-main.9f0ba400.js",
|
||||
"static/css/2.15110fae.chunk.css",
|
||||
"static/js/2.c9e1641e.chunk.js",
|
||||
"static/js/main.6d2e758d.chunk.js"
|
||||
"static/js/2.0730cb3f.chunk.js",
|
||||
"static/js/main.6bec17f9.chunk.js"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.15110fae.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.c9e1641e.chunk.js"></script><script src="/static/js/main.6d2e758d.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Squeak Node</title><meta name="description" content="Squeak Node is a frontend for accessing a squeak node"><meta name="keywords" content="squeak, bitcoin, lightning"><meta name="author" content="Flatlogic LLC."><link href="/static/css/2.15110fae.chunk.css" rel="stylesheet"></head><body style="font-family:Roboto,sans-serif"><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(e){function r(r){for(var n,f,l=r[0],a=r[1],i=r[2],c=0,s=[];c<l.length;c++)f=l[c],Object.prototype.hasOwnProperty.call(o,f)&&o[f]&&s.push(o[f][0]),o[f]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,i||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=f(f.s=t[0]))}return e}var n={},o={1:0},u=[];function f(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.m=e,f.c=n,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)f.d(t,n,function(r){return e[r]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var l=this["webpackJsonpsqueak-node-frontend"]=this["webpackJsonpsqueak-node-frontend"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var i=0;i<l.length;i++)r(l[i]);var p=a;t()}([])</script><script src="/static/js/2.0730cb3f.chunk.js"></script><script src="/static/js/main.6bec17f9.chunk.js"></script></body></html>
|
||||
|
|
@ -1,23 +1,23 @@
|
|||
self.__precacheManifest = (self.__precacheManifest || []).concat([
|
||||
{
|
||||
"revision": "cc531ec5cff09fde2ee277e3175665dc",
|
||||
"revision": "aa56f07a2e96bf2e6bd530574a814d8a",
|
||||
"url": "/index.html"
|
||||
},
|
||||
{
|
||||
"revision": "e2886d792fef8b9e79d8",
|
||||
"revision": "6b11e9073fc53930c2fe",
|
||||
"url": "/static/css/2.15110fae.chunk.css"
|
||||
},
|
||||
{
|
||||
"revision": "e2886d792fef8b9e79d8",
|
||||
"url": "/static/js/2.c9e1641e.chunk.js"
|
||||
"revision": "6b11e9073fc53930c2fe",
|
||||
"url": "/static/js/2.0730cb3f.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "7156b2c9571000777b9be03b3c6006ee",
|
||||
"url": "/static/js/2.c9e1641e.chunk.js.LICENSE.txt"
|
||||
"url": "/static/js/2.0730cb3f.chunk.js.LICENSE.txt"
|
||||
},
|
||||
{
|
||||
"revision": "747a77f8ec4a9d53e827",
|
||||
"url": "/static/js/main.6d2e758d.chunk.js"
|
||||
"revision": "9b3cddbef0b73ca9c223",
|
||||
"url": "/static/js/main.6bec17f9.chunk.js"
|
||||
},
|
||||
{
|
||||
"revision": "cc9816de5a8639d377ea",
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js");
|
||||
|
||||
importScripts(
|
||||
"/precache-manifest.8cd0391333d184d8cd73c2566f3ab102.js"
|
||||
"/precache-manifest.3ca520d21d6c54a7d5b0bb7f09da1d86.js"
|
||||
);
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
|
|
|
|||
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
Loading…
Add table
Add a link
Reference in a new issue