WIP treeview: add requests and folders, fold/unfold, switch to selected tab, renaming items changes; WIP inputbox
This commit is contained in:
parent
7d3044b07e
commit
bf13d54b71
3 changed files with 586 additions and 23 deletions
|
|
@ -100,8 +100,7 @@
|
|||
</div>
|
||||
|
||||
<div id="main_area">
|
||||
|
||||
<div id="treeview1">
|
||||
<div>
|
||||
<div id="collection_toolbar" class="navbar">
|
||||
<div class="dropdown" id="collection_add_menu">
|
||||
<button class="dropbtn">📁</button>
|
||||
|
|
@ -110,11 +109,12 @@
|
|||
<div class="dropdown-item" id="import_collection" value="import_collection">Import collection</div>
|
||||
</div>
|
||||
</div>
|
||||
<input id="collection-search" type="text" value="asd"></input>
|
||||
<input id="collection-search" type="text" value="" placeholder="search request">
|
||||
</div>
|
||||
tree
|
||||
</div>
|
||||
|
||||
<div id="treeview1">
|
||||
</div>
|
||||
</div>
|
||||
<div id="request_area">
|
||||
<div id="top_row_of_the_window">
|
||||
<div class="tabbar" id="requests_tabbar">
|
||||
|
|
@ -498,6 +498,40 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- treeview context menu -->
|
||||
|
||||
<div class="dropdown" id="treeitem_context">
|
||||
<div class="dropdown-content">
|
||||
<div id="context_add_request" class="dropdown-item" value="add_request">Add request</div>
|
||||
<div id="context_add_folder" class="dropdown-item" value="add_folder">Add folder</div>
|
||||
<div id="context_clone" class="dropdown-item" value="clone">Clone</div>
|
||||
<div id="context_export" class="dropdown-item" value="export">Export</div>
|
||||
<div id="context_delete" class="dropdown-item red" value="delete">Delete</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- treeview context menu -->
|
||||
|
||||
<!-- input box -->
|
||||
<div class="popup_wrapper" id="app_input_box">
|
||||
<div id="input_box" class="popup">
|
||||
<div id="input_box_title">
|
||||
sample title
|
||||
</div>
|
||||
<div id="input_box_message">
|
||||
this is a sample message
|
||||
</div>
|
||||
<div>
|
||||
<input id="input_box_input" type="text">
|
||||
</div>
|
||||
<div>
|
||||
<input type="button" id="yes">
|
||||
<input type="button" id="no">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- input box -->
|
||||
|
||||
|
||||
<div class="popup_wrapper" id="app_about">
|
||||
<div class="popup">
|
||||
|
|
|
|||
321
src/main.js
321
src/main.js
|
|
@ -1352,8 +1352,10 @@ function init_menus() {
|
|||
}
|
||||
|
||||
|
||||
function hide_element() {
|
||||
this.style.display = 'none'
|
||||
function hide_element(event) {
|
||||
if (event.target == this) {
|
||||
this.style.display = 'none'
|
||||
}
|
||||
}
|
||||
|
||||
function init_popups() {
|
||||
|
|
@ -1363,18 +1365,99 @@ function init_popups() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function input_box(options) {
|
||||
let output
|
||||
let box = document.getElementById('app_input_box')
|
||||
let yes = document.getElementById('yes')
|
||||
let no = document.getElementById('no')
|
||||
let title = document.getElementById('input_box_title')
|
||||
let message = document.getElementById('input_box_message')
|
||||
let input = document.getElementById('input_box_input')
|
||||
|
||||
if (options.buttons.includes('yes')) {
|
||||
yes.style.display = 'inline-block'
|
||||
yes.value = 'yes'
|
||||
} else {
|
||||
yes.style.display = 'none'
|
||||
}
|
||||
|
||||
if (options.buttons.includes('yes')) {
|
||||
no.style.display = 'inline-block'
|
||||
no.value = 'yes'
|
||||
} else {
|
||||
no.style.display = 'none'
|
||||
}
|
||||
|
||||
|
||||
if (options.buttons.includes('confirm')) {
|
||||
yes.style.display = 'inline-block'
|
||||
yes.value = 'confirm'
|
||||
} else {
|
||||
yes.style.display = 'none'
|
||||
}
|
||||
|
||||
if (options.buttons.includes('cancel')) {
|
||||
no.style.display = 'inline-block'
|
||||
no.value = 'cancel'
|
||||
} else {
|
||||
no.style.display = 'none'
|
||||
}
|
||||
|
||||
|
||||
if (options.type == 'input') {
|
||||
no.style.display = 'inline-block'
|
||||
} else {
|
||||
no.style.display = 'none'
|
||||
}
|
||||
|
||||
if (options.title) {
|
||||
title.display = 'block'
|
||||
title.textContent = options.title
|
||||
} else {
|
||||
title.display = 'none'
|
||||
}
|
||||
|
||||
if (options.title) {
|
||||
message.display = 'block'
|
||||
message.textContent = options.message
|
||||
} else {
|
||||
message.display = 'none'
|
||||
}
|
||||
|
||||
|
||||
box.style.display = 'flex'
|
||||
return output
|
||||
}
|
||||
|
||||
async function keyboard_shortcuts_handler(event) {
|
||||
//console.log(event)
|
||||
if (event.ctrlKey && event.code === 'KeyS') {
|
||||
if (event.ctrlKey) {
|
||||
//save
|
||||
if (event.code === 'KeyS') {
|
||||
// save current request
|
||||
let request = await build_request()
|
||||
app.current_request = JSON.parse(JSON.stringify(request))
|
||||
await write_request_file(app.current_tab)
|
||||
|
||||
} else if (event.ctrlKey && event.code === "Enter") {
|
||||
return
|
||||
}
|
||||
|
||||
// send
|
||||
if (event.code === "Enter") {
|
||||
// run qurent request
|
||||
await send_request()
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// renaming
|
||||
if (event.code === "F2") {
|
||||
// run qurent request
|
||||
let new_name = await input_box({type:'input', buttons: ['confirm', 'cancel'], title: 'Type a new name for selected item'})
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1759,6 +1842,7 @@ function fill_in_forms() {
|
|||
}
|
||||
|
||||
///===============================================================================
|
||||
// process response
|
||||
|
||||
|
||||
} else {
|
||||
|
|
@ -1837,7 +1921,7 @@ function window_resize_trigger() {
|
|||
let u
|
||||
|
||||
|
||||
async function add_request() {
|
||||
async function add_request(event, data) { // pass data.id to generate request data with a specific id
|
||||
if (app.current_tab) {
|
||||
let request = await build_request()
|
||||
app.current_request = JSON.parse(JSON.stringify(request))
|
||||
|
|
@ -1858,7 +1942,7 @@ async function add_request() {
|
|||
}
|
||||
}
|
||||
|
||||
let request_id = crypto.randomUUID()
|
||||
let request_id = data?.id || crypto.randomUUID()
|
||||
let request_name = "New Request" //+ " " + app.opened_tabs.length
|
||||
|
||||
let container = document.getElementById("request_body_wrapper")
|
||||
|
|
@ -1978,7 +2062,217 @@ async function load_previoursly_opened_tabs() {
|
|||
// }
|
||||
}
|
||||
|
||||
// treeview ===============================
|
||||
let ppp
|
||||
|
||||
function checkOverflow() {
|
||||
if (this.scrollWidth > this.clientWidth) {
|
||||
this.style.overflowX = 'auto'
|
||||
} else {
|
||||
this.style.overflowX = 'hidden'
|
||||
}
|
||||
}
|
||||
|
||||
function get_random_request_type() {
|
||||
let types = ["GET", "POST", "PUT", "UPDATE", "REPORT", "HEAD", "OPTIONS"]
|
||||
return types[Math.floor(Math.random()*types.length)]
|
||||
}
|
||||
|
||||
function toggle_children_display(target) {
|
||||
|
||||
target.setAttribute("opened", !JSON.parse(target.getAttribute("opened")) || "false")
|
||||
// let divs = this.getElementsByTagName("div")
|
||||
// for (let d of divs) {
|
||||
// if (d == this) {continue}
|
||||
// if (d.style.display == 'none') {
|
||||
// d.style.display = 'block'
|
||||
// } else {
|
||||
// d.style.display = 'none'
|
||||
// }
|
||||
// }
|
||||
event?.stopPropagation();
|
||||
}
|
||||
|
||||
let currently_selected_tree_node
|
||||
|
||||
function tree_item_click(event) {
|
||||
console.log(event)
|
||||
let target = event.target
|
||||
while (!target.classList.contains('treeitem')) {
|
||||
target = target.parentElement
|
||||
}
|
||||
|
||||
|
||||
if (target.classList.contains("folder")) {
|
||||
toggle_children_display(target)
|
||||
}
|
||||
event.stopPropagation()
|
||||
}
|
||||
|
||||
function select_tree_item(event, element) {
|
||||
let treeview1 = document.getElementById("treeview1")
|
||||
let items = treeview1.getElementsByClassName("treeitem")
|
||||
let target = element || this
|
||||
while (!target.classList.contains('treeitem')) {
|
||||
target = target.parentElement
|
||||
}
|
||||
|
||||
currently_selected_tree_node = target || this
|
||||
for (let item of items) {
|
||||
if (item == currently_selected_tree_node) {
|
||||
item.setAttribute("selected", true)
|
||||
} else {
|
||||
item.setAttribute("selected", false)
|
||||
}
|
||||
}
|
||||
|
||||
if (currently_selected_tree_node.classList.contains('request')) {
|
||||
let navbar = document.getElementById("requests_tabbar")
|
||||
let buttons = navbar.getElementsByClassName('request_tabbutton')
|
||||
let found_opened_tab
|
||||
for (let button of buttons) {
|
||||
if (button.id == currently_selected_tree_node.id) {
|
||||
button.click()
|
||||
found_opened_tab = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_opened_tab) {
|
||||
//
|
||||
add_request(event, {id : currently_selected_tree_node.id})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let treeview_item_menu_callee
|
||||
|
||||
function context_menu(event) {
|
||||
let target = event.target
|
||||
let treeitem_context = document.getElementById("treeitem_context")
|
||||
treeitem_context.style.display = 'none'
|
||||
let treeview1 = document.getElementById("treeview1")
|
||||
let items = treeitem_context.getElementsByClassName("dropdown-item")
|
||||
console.log(target.classList)
|
||||
for (let item of items) {
|
||||
let value = item.getAttribute('value')
|
||||
if (target.classList.contains("request") || target.parentElement.classList.contains("request")) {
|
||||
if (value == "add_request" || value == "add_folder") {
|
||||
item.style.display = 'none'
|
||||
}
|
||||
} else {
|
||||
if (value == "add_request" || value == "add_folder") {
|
||||
item.style.display = 'flex'
|
||||
}
|
||||
}
|
||||
}
|
||||
//console.log(event)
|
||||
//console.log(event.clientY, treeview1.clientHeight, treeitem_context.children[0].clientHeight)
|
||||
treeitem_context.style.top = Math.min(event.clientY - 24, treeview1.clientHeight - treeitem_context.children[0].clientHeight - 24) + 'px'
|
||||
treeitem_context.style.left = Math.min(event.clientX - 5, treeview1.clientWidth - treeitem_context.children[0].clientWidth - 5) + 'px'
|
||||
treeitem_context.style.display = 'inline-block'
|
||||
treeitem_context.children[0].style.display = 'block'
|
||||
treeview_item_menu_callee = target
|
||||
//tree_item_click(event)
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
function select_request(event) {
|
||||
console.log(this)
|
||||
select_tree_item(event, this)
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
function add_item(type, parent) {
|
||||
if (this.id == 'add_collection' || this.id == 'context_add_folder') {
|
||||
type = 'folder'
|
||||
parent = treeview_item_menu_callee
|
||||
}
|
||||
|
||||
if (this.id == 'context_add_request') {
|
||||
type = 'request'
|
||||
parent = treeview_item_menu_callee
|
||||
}
|
||||
|
||||
if (parent) {
|
||||
while (!parent.classList.contains('folder')) {
|
||||
parent = parent.parentElement
|
||||
}
|
||||
}
|
||||
|
||||
let item = document.createElement("div")
|
||||
|
||||
|
||||
if (type=="folder") {
|
||||
item.classList.add("folder")
|
||||
item.classList.add("treeitem")
|
||||
let icon = document.createElement("span")
|
||||
icon.classList.add('folder-icon')
|
||||
item.appendChild(icon)
|
||||
let text = document.createElement("span")
|
||||
text.classList.add('item-text')
|
||||
text.textContent = "New Folder"
|
||||
item.appendChild(text)
|
||||
item.setAttribute("opened", true)
|
||||
icon.addEventListener("click", tree_item_click)
|
||||
text.addEventListener("click", select_tree_item)
|
||||
item.addEventListener("contextmenu", context_menu)
|
||||
type == 'folder'
|
||||
|
||||
} else {
|
||||
item.classList.add("request")
|
||||
item.classList.add("treeitem")
|
||||
let rt = 'GET'//get_random_request_type()
|
||||
|
||||
let req_type = document.createElement("span")
|
||||
req_type.classList.add('request-type')
|
||||
req_type.classList.add(rt)
|
||||
req_type.textContent = rt
|
||||
item.appendChild(req_type)
|
||||
item.id = crypto.randomUUID()
|
||||
|
||||
let text = document.createElement("span")
|
||||
text.classList.add('item-text')
|
||||
text.textContent = "New Request"
|
||||
item.appendChild(text)
|
||||
text.addEventListener("click", select_request)
|
||||
item.addEventListener("contextmenu", context_menu)
|
||||
}
|
||||
|
||||
|
||||
|
||||
let pe = ppp || parent || document.getElementById("treeview1")
|
||||
|
||||
// if (Math.random() > 0.3 && item.classList.contains('folder')) {
|
||||
// ppp = item
|
||||
// } else {
|
||||
// ppp = document.getElementById("treeview1")
|
||||
// }
|
||||
|
||||
// if (item.classList.contains("request") && !pe.classList.contains("folder")) {
|
||||
// console.log("adding folder for a req")
|
||||
// // pe = add_item("folder", pe)
|
||||
// }
|
||||
console.log(pe, item)
|
||||
pe.appendChild(item)
|
||||
document.getElementById("treeview1").scrollBy(0, Number.MAX_SAFE_INTEGER)
|
||||
return item
|
||||
}
|
||||
|
||||
// treeview ===============================
|
||||
|
||||
|
||||
|
||||
function init() {
|
||||
// treeview plaecholder
|
||||
let treeview1 = document.getElementById("treeview1")
|
||||
treeview1.addEventListener("scroll", checkOverflow)
|
||||
for (let i=1; i<50; i++) {
|
||||
//add_item()
|
||||
}
|
||||
// --------------------
|
||||
|
||||
console.log('init')
|
||||
// enable add_row buttons (those adding rows to param tables)
|
||||
let add_row_buttons = document.getElementsByClassName('add_row_button')
|
||||
|
|
@ -2026,7 +2320,20 @@ function init() {
|
|||
button.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
// collection manipulation
|
||||
let add_collection = document.getElementById('add_collection')
|
||||
let context_add_request = document.getElementById('context_add_request')
|
||||
let context_add_folder = document.getElementById('context_add_folder')
|
||||
let context_clone = document.getElementById('context_clone')
|
||||
let context_export = document.getElementById('context_export')
|
||||
let context_delete = document.getElementById('context_delete')
|
||||
|
||||
add_collection.addEventListener("click", add_item)
|
||||
context_add_folder.addEventListener("click", add_item)
|
||||
context_add_request.addEventListener("click", add_item)
|
||||
|
||||
//---------------------------------------
|
||||
|
||||
let beautify_raw_data_body = document.getElementById('beautify_raw_data_body')
|
||||
let beautify_raw_data_response = document.getElementById('beautify_raw_data_response')
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ input:not(input[type="text"]) {
|
|||
}
|
||||
|
||||
#collection_toolbar {
|
||||
width: 100%;
|
||||
width: 200pt;
|
||||
height: 26pt;
|
||||
display: flex;
|
||||
}
|
||||
|
|
@ -392,14 +392,7 @@ input:not(input[type="text"]) {
|
|||
width:70%;
|
||||
}
|
||||
|
||||
#treeview1 {
|
||||
display: flex;
|
||||
flex-grow: initial;
|
||||
flex-direction: column;
|
||||
width: 200pt;
|
||||
height: 100%;
|
||||
/* outline: 1px solid wheat; */
|
||||
}
|
||||
|
||||
|
||||
#add_method_input {
|
||||
border: none;
|
||||
|
|
@ -796,7 +789,7 @@ footer * {
|
|||
}
|
||||
/* --------------------------- */
|
||||
|
||||
label, button, .treeview, .menuitem, .menu {
|
||||
label, button, #treeview, .menuitem, .menu {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -1035,4 +1028,233 @@ label, button, .treeview, .menuitem, .menu {
|
|||
#body_binary_file_input_label {
|
||||
display: inline-block;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* treeview */
|
||||
#treeview1 {
|
||||
display: flex;
|
||||
flex-grow: initial;
|
||||
flex-direction: column;
|
||||
width: 200pt;
|
||||
height: calc(100% - 30pt);
|
||||
/* outline: 1px solid wheat; */
|
||||
padding-left: 6pt;
|
||||
overflow: auto;
|
||||
/* overflow-x: hidden; */
|
||||
}
|
||||
|
||||
|
||||
#add {
|
||||
width: 100pt;
|
||||
height: 25pt;
|
||||
/* outline: 1px solid burlywood; */
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 5pt;
|
||||
left:220pt;
|
||||
background-color: #222;
|
||||
border-radius: 5pt;
|
||||
border-color: burlywood;
|
||||
border-style: solid;
|
||||
border-width: 1pt;
|
||||
}
|
||||
|
||||
#add:hover {
|
||||
background-color: #444;
|
||||
}
|
||||
|
||||
.folder {
|
||||
/* display: flex; */
|
||||
cursor: pointer;
|
||||
line-height: 24pt;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.folder > .request {
|
||||
margin-left:calc(16pt + 5pt);
|
||||
line-height: 24pt;
|
||||
}
|
||||
|
||||
.folder > .folder {
|
||||
margin-left: 21pt;
|
||||
}
|
||||
|
||||
|
||||
.folder:hover:not(:has(.folder:hover, .request:hover)),
|
||||
.request:hover {
|
||||
/* outline: 1px solid red; */
|
||||
/* background-color: #444; */
|
||||
/* width: 100%; */
|
||||
/* height: 24pt; */
|
||||
/* display: block; */
|
||||
/* position: absolute; */
|
||||
/* content: " " */
|
||||
color: #6bdd92;
|
||||
}
|
||||
|
||||
.folder[opened=true] > .folder,
|
||||
.folder[opened=true] > .request {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.folder[opened=false] > .folder,
|
||||
.folder[opened=false] > .request {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.folder[opened=true] > .folder-icon {
|
||||
background-image: url(folder_opened.png);
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.folder[opened=false] > .folder-icon {
|
||||
background-image: url(folder.png);
|
||||
background-size: contain;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
.folder:hover:not(:has(.folder:hover, .request:hover)) > .mdots,
|
||||
.request:hover > .mdots {
|
||||
display: none;
|
||||
/* display: flex; */
|
||||
}
|
||||
|
||||
.request > .mdots,
|
||||
.folder > .mdots {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.folder-icon {
|
||||
width: 16pt;
|
||||
height: 16pt;
|
||||
|
||||
|
||||
background-position-y: 0pt;
|
||||
position: relative;
|
||||
top: 3pt;
|
||||
margin-right: 5pt;
|
||||
}
|
||||
|
||||
.request-type {
|
||||
width: 32pt;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
top: 0pt;
|
||||
right: 0pt;
|
||||
margin-right: 5pt;
|
||||
font-size: 7pt;
|
||||
text-align: center;
|
||||
border-width: 1pt;
|
||||
border-radius: 5pt;
|
||||
border-style: solid;
|
||||
border-color: #666;
|
||||
padding-left: 3pt;
|
||||
padding-right: 3pt;
|
||||
outline: 1px solid #f5f5f545;
|
||||
outline-offset: -3pt;
|
||||
line-height: 16pt;
|
||||
}
|
||||
|
||||
.request-type[class*="GET"] {
|
||||
color: #6bdd92;
|
||||
background-color: #234730;
|
||||
}
|
||||
|
||||
.request-type[class*="POST"] {
|
||||
color: #ffe479;
|
||||
background-color: #3a341c;
|
||||
}
|
||||
|
||||
.request-type[class*="PUT"] {
|
||||
color: #74aeed;
|
||||
background-color: #203142;
|
||||
}
|
||||
|
||||
.request-type[class*="UPDATE"] {
|
||||
color: #c0a8d9;
|
||||
background-color: #3c3444;
|
||||
}
|
||||
|
||||
.request-type[class*="REPORT"] {
|
||||
color: #f15eae;
|
||||
background-color: #471b33;
|
||||
}
|
||||
|
||||
.request-type[class*="HEAD"] {
|
||||
color: #7cfad0;
|
||||
background-color: #2a4e42;
|
||||
}
|
||||
|
||||
.request-type[class*="OPTIONS"] {
|
||||
color: #f79a87;
|
||||
background-color: #684139;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.mdots {
|
||||
position: relative;
|
||||
float: right;
|
||||
margin-right: 5pt;
|
||||
padding: 0pt 5pt;
|
||||
text-align: inherit;
|
||||
display: flex;
|
||||
height: 21pt;
|
||||
outline: 1px solid lime;
|
||||
background: #222;
|
||||
border-radius: 5pt;
|
||||
}
|
||||
|
||||
.treeitem > .item-text{
|
||||
padding-right: 10pt;
|
||||
line-height: 24pt;
|
||||
}
|
||||
|
||||
#treeitem_context {
|
||||
position: absolute;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.treeitem[selected=true] > .item-text {
|
||||
text-shadow: 0 0 1pt orange;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.treeitem[selected=false] > .item-text {
|
||||
text-shadow: initial;
|
||||
text-decoration: initial;
|
||||
}
|
||||
|
||||
/* inputbox */
|
||||
|
||||
#input_box_title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 10pt;
|
||||
}
|
||||
|
||||
#input_box_input {
|
||||
width: calc(100% - 10pt);
|
||||
padding: 0pt;
|
||||
margin: 5pt 0;
|
||||
padding: 0 5pt;
|
||||
}
|
||||
|
||||
#input_box {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#input_box input {
|
||||
border-radius: 5pt;
|
||||
}
|
||||
|
||||
#yes, #no {
|
||||
min-width: 100pt;
|
||||
float: right;
|
||||
margin-right: 0;
|
||||
margin-left: 10pt;
|
||||
}
|
||||
/* inputbox */
|
||||
Loading…
Add table
Add a link
Reference in a new issue