Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
S
Stable Diffusion Webui
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
novelai-storage
Stable Diffusion Webui
Commits
4f962670
Commit
4f962670
authored
Jan 16, 2024
by
Sj-Si
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finish cleanup.
parent
1fdc18e6
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
288 additions
and
168 deletions
+288
-168
html/extra-networks-card-minimal.html
html/extra-networks-card-minimal.html
+0
-4
html/extra-networks-card.html
html/extra-networks-card.html
+5
-5
html/extra-networks-edit-item-button.html
html/extra-networks-edit-item-button.html
+1
-1
html/extra-networks-metadata-button.html
html/extra-networks-metadata-button.html
+1
-1
html/extra-networks-pane.html
html/extra-networks-pane.html
+3
-3
html/extra-networks-tree-button.html
html/extra-networks-tree-button.html
+1
-2
html/extra-networks-tree.html
html/extra-networks-tree.html
+7
-7
javascript/extraNetworks.js
javascript/extraNetworks.js
+90
-80
modules/ui_extra_networks.py
modules/ui_extra_networks.py
+123
-39
modules/ui_extra_networks_user_metadata.py
modules/ui_extra_networks_user_metadata.py
+1
-1
style.css
style.css
+56
-25
No files found.
html/extra-networks-card-minimal.html
deleted
100644 → 0
View file @
1fdc18e6
<div
class=
"card-minimal"
onclick=
{card_clicked}
data-name=
"{name}"
>
<span
class=
"name"
>
{name}
</span>
<span
class=
"button-row"
>
{copy_path_button}{metadata_button}{edit_button}
</span>
</div>
html/extra-networks-card.html
View file @
4f962670
<div
class=
"card"
style=
{style}
onclick=
"{card_clicked}"
data-name=
"{name}"
{
sort_keys
}
>
<div
class=
"card"
style=
"{style}"
onclick=
"{card_clicked}"
data-name=
"{name}"
{
sort_keys
}
>
{background_image}
<div
class=
"button-row"
>
{copy_path_button}{metadata_button}{edit_button}
</div>
<div
class=
'actions'
>
<div
class=
'additional'
>
{search_terms}
</div>
<span
class=
'name'
>
{name}
</span>
<span
class=
'description'
>
{description}
</span>
<div
class=
"actions"
>
<div
class=
"additional"
>
{search_terms}
</div>
<span
class=
"name"
>
{name}
</span>
<span
class=
"description"
>
{description}
</span>
</div>
</div>
html/extra-networks-edit-item-button.html
View file @
4f962670
<div
class=
"edit-button card-button"
title=
"Edit metadata"
onclick=
"extraNetworksEditUserMetadata(event, '{tabname}', '{
page_id
}', '{name}')"
>
onclick=
"extraNetworksEditUserMetadata(event, '{tabname}', '{
extra_networks_tabname
}', '{name}')"
>
</div>
\ No newline at end of file
html/extra-networks-metadata-button.html
View file @
4f962670
<div
class=
"metadata-button card-button"
title=
"Show internal metadata"
onclick=
"extraNetworksRequestMetadata(event, '{
page_id
}', '{name}')"
>
onclick=
"extraNetworksRequestMetadata(event, '{
extra_networks_tabname
}', '{name}')"
>
</div>
\ No newline at end of file
html/extra-networks-pane.html
View file @
4f962670
<div
id=
'{tabname}_{
network_type_id
}_pane'
class=
'extra-network-pane'
>
<div
id=
'{tabname}_{
network_type_id
}_tree'
class=
'extra-network-tree'
>
<div
id=
'{tabname}_{
extra_networks_tabname
}_pane'
class=
'extra-network-pane'
>
<div
id=
'{tabname}_{
extra_networks_tabname
}_tree'
class=
'extra-network-tree'
>
{tree_html}
</div>
<div
id=
'{tabname}_{
network_type_id
}_cards'
class=
'extra-network-cards'
>
<div
id=
'{tabname}_{
extra_networks_tabname
}_cards'
class=
'extra-network-cards'
>
{items_html}
</div>
</div>
\ No newline at end of file
html/extra-networks-tree-button.html
View file @
4f962670
<span
data-filterable-item-text
hidden
>
{search_terms}
</span>
<div
class=
"tree-list-content {subclass}"
expanded=
"false"
type=
"button"
onclick=
"extraNetworksTreeOnClick(event, '{tabname}', '{
tab_id
}');{onclick_extra}"
onclick=
"extraNetworksTreeOnClick(event, '{tabname}', '{
extra_networks_tabname
}');{onclick_extra}"
data-path=
"{data_path}"
data-hash=
"{data_hash}"
>
...
...
html/extra-networks-tree.html
View file @
4f962670
...
...
@@ -2,36 +2,36 @@
<div
class=
"tree-list-controls"
>
<div
class=
"tree-list-search"
>
<input
id=
"{tabname}_{
tab_id
}_extra_search"
id=
"{tabname}_{
extra_networks_tabname
}_extra_search"
class=
"tree-list-search-text"
type=
"search"
placeholder=
"Filter files"
>
</div>
<div
id=
"{tabname}_{
tab_id
}_extra_sort"
id=
"{tabname}_{
extra_networks_tabname
}_extra_sort"
class=
"tree-list-sort"
data-sortmode=
"path"
data-sortkey=
"sortPath-Ascending-640"
title=
"Sort by path"
onclick=
"extraNetworksTreeSortOnClick(event, '{tabname}', '{
tab_id
}');"
onclick=
"extraNetworksTreeSortOnClick(event, '{tabname}', '{
extra_networks_tabname
}');"
>
<i
class=
"tree-list-sort-icon"
></i>
</div>
<div
id=
"{tabname}_{
tab_id
}_extra_sort_dir"
id=
"{tabname}_{
extra_networks_tabname
}_extra_sort_dir"
class=
"tree-list-sort-dir"
data-sortdir=
"Ascending"
title=
"Sort ascending"
onclick=
"extraNetworksTreeSortDirOnClick(event, '{tabname}', '{
tab_id
}');"
onclick=
"extraNetworksTreeSortDirOnClick(event, '{tabname}', '{
extra_networks_tabname
}');"
>
<i
class=
"tree-list-sort-dir-icon"
></i>
</div>
<div
id=
"{tabname}_{
tab_id
}_extra_refresh"
id=
"{tabname}_{
extra_networks_tabname
}_extra_refresh"
class=
"tree-list-refresh"
title=
"Refresh page"
onclick=
"extraNetworksTreeRefreshOnClick(event, '{tabname}', '{
tab_id
}');"
onclick=
"extraNetworksTreeRefreshOnClick(event, '{tabname}', '{
extra_networks_tabname
}');"
>
<i
class=
"tree-list-refresh-icon"
></i>
</div>
...
...
javascript/extraNetworks.js
View file @
4f962670
...
...
@@ -31,25 +31,15 @@ function setupExtraNetworksForTab(tabname) {
var
this_tab
=
gradioApp
().
querySelector
(
'
#
'
+
tabname
+
'
_extra_tabs
'
);
this_tab
.
classList
.
add
(
'
extra-networks
'
);
this_tab
.
querySelectorAll
(
"
:scope > [id^='
"
+
tabname
+
"
_']
"
).
forEach
(
function
(
elem
)
{
var
tab_id
=
elem
.
getAttribute
(
"
id
"
);
var
search
=
gradioApp
().
querySelector
(
"
#
"
+
tab_id
+
"
_extra_search
"
);
if
(
!
search
)
{
return
;
// `continue` doesn't work in `forEach` loops. This is equivalent.
}
var
sort
=
gradioApp
().
querySelector
(
"
#
"
+
tab_id
+
"
_extra_sort
"
);
if
(
!
sort
)
{
return
;
// `continue` doesn't work in `forEach` loops. This is equivalent.
}
var
extra_networks_tabname
=
elem
.
id
;
var
search
=
gradioApp
().
querySelector
(
"
#
"
+
extra_networks_tabname
+
"
_extra_search
"
);
var
sort_mode
=
gradioApp
().
querySelector
(
"
#
"
+
extra_networks_tabname
+
"
_extra_sort
"
);
var
sort_dir
=
gradioApp
().
querySelector
(
"
#
"
+
extra_networks_tabname
+
"
_extra_sort_dir
"
);
var
refresh
=
gradioApp
().
querySelector
(
"
#
"
+
extra_networks_tabname
+
"
_extra_refresh
"
);
var
sort_dir
=
gradioApp
().
querySelector
(
"
#
"
+
tab_id
+
"
_extra_sort_dir
"
);
if
(
!
sort_dir
)
{
return
;
// `continue` doesn't work in `forEach` loops. This is equivalent.
}
var
refresh
=
gradioApp
().
querySelector
(
"
#
"
+
tab_id
+
"
_extra_refresh
"
);
if
(
!
refresh
)
{
return
;
// `continue` doesn't work in `forEach` loops. This is equivalent.
// If any of the buttons above don't exist, we want to skip this iteration of the loop.
if
(
!
search
||
!
sort_mode
||
!
sort_dir
||
!
refresh
)
{
return
;
// `return` is equivalent of `continue` but for forEach loops.
}
var
applyFilter
=
function
()
{
...
...
@@ -78,14 +68,14 @@ function setupExtraNetworksForTab(tabname) {
var
cards
=
gradioApp
().
querySelectorAll
(
'
#
'
+
tabname
+
'
_extra_tabs div.card
'
);
var
reverse
=
sort_dir
.
dataset
.
sortdir
==
"
Descending
"
;
var
sortKey
=
sort
.
dataset
.
sortmode
.
toLowerCase
().
replace
(
"
sort
"
,
""
).
replaceAll
(
"
"
,
"
_
"
).
replace
(
/_+$/
,
""
).
trim
()
||
"
name
"
;
var
sortKey
=
sort
_mode
.
dataset
.
sortmode
.
toLowerCase
().
replace
(
"
sort
"
,
""
).
replaceAll
(
"
"
,
"
_
"
).
replace
(
/_+$/
,
""
).
trim
()
||
"
name
"
;
sortKey
=
"
sort
"
+
sortKey
.
charAt
(
0
).
toUpperCase
()
+
sortKey
.
slice
(
1
);
var
sortKeyStore
=
sortKey
+
"
-
"
+
(
reverse
?
"
Descending
"
:
"
Ascending
"
)
+
"
-
"
+
cards
.
length
;
if
(
sortKeyStore
==
sort
.
dataset
.
sortkey
)
{
if
(
sortKeyStore
==
sort
_mode
.
dataset
.
sortkey
)
{
return
;
}
sort
.
dataset
.
sortkey
=
sortKeyStore
;
sort
_mode
.
dataset
.
sortkey
=
sortKeyStore
;
cards
.
forEach
(
function
(
card
)
{
card
.
originalParentElement
=
card
.
parentElement
;
...
...
@@ -115,8 +105,8 @@ function setupExtraNetworksForTab(tabname) {
applySort
();
applyFilter
();
extraNetworksApplySort
[
tab_id
]
=
applySort
;
extraNetworksApplyFilter
[
tab_id
]
=
applyFilter
;
extraNetworksApplySort
[
extra_networks_tabname
]
=
applySort
;
extraNetworksApplyFilter
[
extra_networks_tabname
]
=
applyFilter
;
});
registerPrompt
(
tabname
,
tabname
+
"
_prompt
"
);
...
...
@@ -148,14 +138,6 @@ function extraNetworksMovePromptToTab(tabname, id, showPrompt, showNegativePromp
}
}
function
clearSearch
(
tabname
)
{
// Clear search box.
var
tab_id
=
tabname
+
"
_extra_search
"
;
var
searchTextarea
=
gradioApp
().
querySelector
(
"
#
"
+
tab_id
+
'
> label > textarea
'
);
searchTextarea
.
value
=
""
;
updateInput
(
searchTextarea
);
}
function
extraNetworksUnrelatedTabSelected
(
tabname
)
{
// called from python when user selects an unrelated tab (generate)
extraNetworksMovePromptToTab
(
tabname
,
''
,
false
,
false
);
...
...
@@ -264,22 +246,20 @@ function saveCardPreview(event, tabname, filename) {
event
.
preventDefault
();
}
function
extraNetworksTreeProcessFileClick
(
event
,
btn
,
tabname
,
tab_id
)
{
function
extraNetworksTreeProcessFileClick
(
event
,
btn
,
tabname
,
extra_networks_tabname
)
{
/**
* Processes `onclick` events when user clicks on files in tree.
*
* @param event The generated event.
* @param btn The clicked `tree-list-item` button.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param
tab_id
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
* @param
extra_networks_tabname
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
var
par
=
btn
.
parentElement
;
var
search_id
=
tabname
+
"
_
"
+
tab_id
+
"
_extra_search
"
;
var
type
=
par
.
getAttribute
(
"
data-tree-entry-type
"
);
var
path
=
btn
.
getAttribute
(
"
data-path
"
);
// NOTE: Currently unused.
return
;
}
function
extraNetworksTreeProcessDirectoryClick
(
event
,
btn
,
tabname
,
tab_id
)
{
function
extraNetworksTreeProcessDirectoryClick
(
event
,
btn
,
tabname
,
extra_networks_tabname
)
{
/**
* Processes `onclick` events when user clicks on directories in tree.
*
...
...
@@ -292,7 +272,7 @@ function extraNetworksTreeProcessDirectoryClick(event, btn, tabname, tab_id) {
* @param event The generated event.
* @param btn The clicked `tree-list-item` button.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param
tab_id
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
* @param
extra_networks_tabname
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
var
ul
=
btn
.
nextElementSibling
;
// This is the actual target that the user clicked on within the target button.
...
...
@@ -301,12 +281,12 @@ function extraNetworksTreeProcessDirectoryClick(event, btn, tabname, tab_id) {
function
_expand_or_collapse
(
_ul
,
_btn
)
{
// Expands <ul> if it is collapsed, collapses otherwise. Updates button attributes.
if
(
_ul
.
hasAttribute
(
"
data-
hidden
"
))
{
_ul
.
removeAttribute
(
"
data-
hidden
"
);
_btn
.
setAttribute
(
"
expanded
"
,
"
true
"
)
;
if
(
_ul
.
hasAttribute
(
"
hidden
"
))
{
_ul
.
removeAttribute
(
"
hidden
"
);
_btn
.
dataset
.
expanded
=
""
;
}
else
{
_ul
.
setAttribute
(
"
data-
hidden
"
,
""
);
_btn
.
setAttribute
(
"
expanded
"
,
"
false
"
)
;
_ul
.
setAttribute
(
"
hidden
"
,
""
);
delete
_btn
.
dataset
.
expanded
;
}
}
...
...
@@ -314,19 +294,19 @@ function extraNetworksTreeProcessDirectoryClick(event, btn, tabname, tab_id) {
// Removes the `selected` attribute from all buttons.
var
sels
=
document
.
querySelectorAll
(
"
div.tree-list-content
"
);
[...
sels
].
forEach
(
el
=>
{
el
.
removeAttribute
(
"
selected
"
)
;
delete
el
.
dataset
.
selected
;
});
}
function
_select_button
(
_btn
)
{
// Removes `selected` attribute from all buttons then adds to passed button.
// Removes `
data-
selected` attribute from all buttons then adds to passed button.
_remove_selected_from_all
();
_btn
.
setAttribute
(
"
selected
"
,
""
)
;
_btn
.
dataset
.
selected
=
""
;
}
function
_update_search
(
_tabname
,
_
tab_id
,
_search_text
)
{
function
_update_search
(
_tabname
,
_
extra_networks_tabname
,
_search_text
)
{
// Update search input with select button's path.
var
search_input_elem
=
gradioApp
().
querySelector
(
"
#
"
+
tabname
+
"
_
"
+
tab_id
+
"
_extra_search
"
);
var
search_input_elem
=
gradioApp
().
querySelector
(
"
#
"
+
tabname
+
"
_
"
+
extra_networks_tabname
+
"
_extra_search
"
);
search_input_elem
.
value
=
_search_text
;
updateInput
(
search_input_elem
);
}
...
...
@@ -337,26 +317,26 @@ function extraNetworksTreeProcessDirectoryClick(event, btn, tabname, tab_id) {
_expand_or_collapse
(
ul
,
btn
);
}
else
{
// User clicked anywhere else on the button.
if
(
btn
.
hasAttribute
(
"
selected
"
)
&&
!
ul
.
hasAttribute
(
"
data-hidden
"
))
{
if
(
"
selected
"
in
btn
.
dataset
&&
!
(
ul
.
hasAttribute
(
"
hidden
"
)
))
{
// If folder is select and open, collapse and deselect button.
_expand_or_collapse
(
ul
,
btn
);
btn
.
removeAttribute
(
"
selected
"
)
;
_update_search
(
tabname
,
tab_id
,
""
);
}
else
if
(
!
(
!
btn
.
hasAttribute
(
"
selected
"
)
&&
!
ul
.
hasAttribute
(
"
data-hidden
"
)))
{
delete
btn
.
dataset
.
selected
;
_update_search
(
tabname
,
extra_networks_tabname
,
""
);
}
else
if
(
!
(
!
(
"
selected
"
in
btn
.
dataset
)
&&
!
(
ul
.
hasAttribute
(
"
hidden
"
)
)))
{
// If folder is open and not selected, then we don't collapse; just select.
// NOTE: Double inversion sucks but it is the clearest way to show the branching here.
_expand_or_collapse
(
ul
,
btn
);
_select_button
(
btn
,
tabname
,
tab_id
);
_update_search
(
tabname
,
tab_id
,
btn
.
getAttribute
(
"
data-path
"
)
);
_select_button
(
btn
,
tabname
,
extra_networks_tabname
);
_update_search
(
tabname
,
extra_networks_tabname
,
btn
.
dataset
.
path
);
}
else
{
// All other cases, just select the button.
_select_button
(
btn
,
tabname
,
tab_id
);
_update_search
(
tabname
,
tab_id
,
btn
.
getAttribute
(
"
data-path
"
)
);
_select_button
(
btn
,
tabname
,
extra_networks_tabname
);
_update_search
(
tabname
,
extra_networks_tabname
,
btn
.
dataset
.
path
);
}
}
}
function
extraNetworksTreeOnClick
(
event
,
tabname
,
tab_id
)
{
function
extraNetworksTreeOnClick
(
event
,
tabname
,
extra_networks_tabname
)
{
/**
* Handles `onclick` events for buttons within an `extra-network-tree .tree-list--tree`.
*
...
...
@@ -365,20 +345,30 @@ function extraNetworksTreeOnClick(event, tabname, tab_id) {
*
* @param event The generated event.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param
tab_id
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
* @param
extra_networks_tabname
The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
var
btn
=
event
.
currentTarget
;
var
par
=
btn
.
parentElement
;
if
(
par
.
getAttribute
(
"
data-tree-entry-type
"
)
===
"
file
"
)
{
extraNetworksTreeProcessFileClick
(
event
,
btn
,
tabname
,
tab_id
);
if
(
par
.
dataset
.
treeEntryType
===
"
file
"
)
{
extraNetworksTreeProcessFileClick
(
event
,
btn
,
tabname
,
extra_networks_tabname
);
}
else
{
extraNetworksTreeProcessDirectoryClick
(
event
,
btn
,
tabname
,
tab_id
);
extraNetworksTreeProcessDirectoryClick
(
event
,
btn
,
tabname
,
extra_networks_tabname
);
}
}
function
extraNetworksTreeSortOnClick
(
event
,
tabname
,
tab_id
)
{
function
extraNetworksTreeSortOnClick
(
event
,
tabname
,
extra_networks_tabname
)
{
/**
* Handles `onclick` events for the Sort Mode button.
*
* Modifies the data attributes of the Sort Mode button to cycle between
* various sorting modes.
*
* @param event The generated event.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param extra_networks_tabname The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
var
curr_mode
=
event
.
currentTarget
.
dataset
.
sortmode
;
var
el_sort_dir
=
gradioApp
().
querySelector
(
"
#
"
+
tabname
+
"
_
"
+
tab_id
+
"
_extra_sort_dir
"
);
var
el_sort_dir
=
gradioApp
().
querySelector
(
"
#
"
+
tabname
+
"
_
"
+
extra_networks_tabname
+
"
_extra_sort_dir
"
);
var
sort_dir
=
el_sort_dir
.
dataset
.
sortdir
;
if
(
curr_mode
==
"
path
"
)
{
event
.
currentTarget
.
dataset
.
sortmode
=
"
name
"
;
...
...
@@ -397,23 +387,43 @@ function extraNetworksTreeSortOnClick(event, tabname, tab_id) {
event
.
currentTarget
.
dataset
.
sortkey
=
"
sortPath-
"
+
sort_dir
+
"
-640
"
;
event
.
currentTarget
.
setAttribute
(
"
title
"
,
"
Sort by path
"
);
}
applyExtraNetworkSort
(
tabname
+
"
_
"
+
tab_id
);
applyExtraNetworkSort
(
tabname
+
"
_
"
+
extra_networks_tabname
);
}
function
extraNetworksTreeSortDirOnClick
(
event
,
tabname
,
tab_id
)
{
var
curr_dir
=
event
.
currentTarget
.
getAttribute
(
"
data-sortdir
"
);
if
(
curr_dir
==
"
Ascending
"
)
{
function
extraNetworksTreeSortDirOnClick
(
event
,
tabname
,
extra_networks_tabname
)
{
/**
* Handles `onclick` events for the Sort Direction button.
*
* Modifies the data attributes of the Sort Direction button to cycle between
* ascending and descending sort directions.
*
* @param event The generated event.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param extra_networks_tabname The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
if
(
event
.
currentTarget
.
dataset
.
sortdir
==
"
Ascending
"
)
{
event
.
currentTarget
.
dataset
.
sortdir
=
"
Descending
"
;
event
.
currentTarget
.
setAttribute
(
"
title
"
,
"
Sort descending
"
);
}
else
{
event
.
currentTarget
.
dataset
.
sortdir
=
"
Ascending
"
;
event
.
currentTarget
.
setAttribute
(
"
title
"
,
"
Sort ascending
"
);
}
applyExtraNetworkSort
(
tabname
+
"
_
"
+
tab_id
);
applyExtraNetworkSort
(
tabname
+
"
_
"
+
extra_networks_tabname
);
}
function
extraNetworksTreeRefreshOnClick
(
event
,
tabname
,
tab_id
)
{
console
.
log
(
"
refresh clicked
"
);
function
extraNetworksTreeRefreshOnClick
(
event
,
tabname
,
extra_networks_tabname
)
{
/**
* Handles `onclick` events for the Refresh Page button.
*
* In order to actually call the python functions in `ui_extra_networks.py`
* to refresh the page, we created an empty gradio button in that file with an
* event handler that refreshes the page. So what this function here does
* is it manually raises a `click` event on that button.
*
* @param event The generated event.
* @param tabname The name of the active tab in the sd webui. Ex: txt2img, img2img, etc.
* @param extra_networks_tabname The id of the active extraNetworks tab. Ex: lora, checkpoints, etc.
*/
var
btn_refresh_internal
=
gradioApp
().
getElementById
(
tabname
+
"
_extra_refresh_internal
"
);
btn_refresh_internal
.
dispatchEvent
(
new
Event
(
"
click
"
));
}
...
...
modules/ui_extra_networks.py
View file @
4f962670
...
...
@@ -155,7 +155,14 @@ class ExtraNetworksPage:
def
__init__
(
self
,
title
):
self
.
title
=
title
self
.
name
=
title
.
lower
()
self
.
id_page
=
self
.
name
.
replace
(
" "
,
"_"
)
# This is the actual name of the extra networks tab (not txt2img/img2img).
self
.
extra_networks_tabname
=
self
.
name
.
replace
(
" "
,
"_"
)
self
.
allow_prompt
=
True
self
.
allow_negative_prompt
=
False
self
.
metadata
=
{}
self
.
items
=
{}
self
.
lister
=
util
.
MassFileLister
()
# HTML Templates
self
.
pane_tpl
=
shared
.
html
(
"extra-networks-pane.html"
)
self
.
tree_tpl
=
shared
.
html
(
"extra-networks-tree.html"
)
self
.
card_tpl
=
shared
.
html
(
"extra-networks-card.html"
)
...
...
@@ -163,11 +170,6 @@ class ExtraNetworksPage:
self
.
btn_copy_path_tpl
=
shared
.
html
(
"extra-networks-copy-path-button.html"
)
self
.
btn_metadata_tpl
=
shared
.
html
(
"extra-networks-metadata-button.html"
)
self
.
btn_edit_item_tpl
=
shared
.
html
(
"extra-networks-edit-item-button.html"
)
self
.
allow_prompt
=
True
self
.
allow_negative_prompt
=
False
self
.
metadata
=
{}
self
.
items
=
{}
self
.
lister
=
util
.
MassFileLister
()
def
refresh
(
self
):
pass
...
...
@@ -202,15 +204,17 @@ class ExtraNetworksPage:
item
:
dict
,
template
:
Optional
[
str
]
=
None
,
)
->
Union
[
str
,
dict
]:
"""Generates HTML for a single ExtraNetworks Item
"""Generates HTML for a single ExtraNetworks Item
.
Args:
tabname: The name of the active tab.
item: Dictionary containing item information.
template: Optional template string to use.
Returns:
HTML string generated for this item.
If a template is passed:
HTML string generated for this item.
Can be empty if the item is not meant to be shown.
If no template is passed: A dictionary containing the generated item's attributes.
"""
metadata
=
item
.
get
(
"metadata"
)
if
metadata
:
...
...
@@ -244,14 +248,14 @@ class ExtraNetworksPage:
if
metadata
:
btn_metadata
=
self
.
btn_metadata_tpl
.
format
(
**
{
"
page_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
"name"
:
html
.
escape
(
item
[
"name"
]),
}
)
btn_edit_item
=
self
.
btn_edit_item_tpl
.
format
(
**
{
"tabname"
:
tabname
,
"
page_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
"name"
:
html
.
escape
(
item
[
"name"
]),
}
)
...
...
@@ -307,9 +311,9 @@ class ExtraNetworksPage:
"search_only"
:
" search_only"
if
search_only
else
""
,
"search_terms"
:
search_terms_html
,
"sort_keys"
:
sort_keys
,
"style"
:
f
"
'display: none; {height}{width}; font-size: {shared.opts.extra_networks_card_text_scale*100}
%
'
"
,
"style"
:
f
"
display: none; {height}{width}; font-size: {shared.opts.extra_networks_card_text_scale*100}
%
"
,
"tabname"
:
tabname
,
"
tab_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
}
if
template
:
...
...
@@ -317,7 +321,32 @@ class ExtraNetworksPage:
else
:
return
args
def
create_tree_dir_item_html
(
self
,
tabname
:
str
,
dir_path
:
str
,
content
:
Optional
[
str
]
=
None
)
->
Optional
[
str
]:
def
create_tree_dir_item_html
(
self
,
tabname
:
str
,
dir_path
:
str
,
content
:
Optional
[
str
]
=
None
,
)
->
Optional
[
str
]:
"""Generates HTML for a directory item in the tree.
The generated HTML is of the format:
```html
<li class="tree-list-item tree-list-item--has-subitem">
<div class="tree-list-content tree-list-content-dir"></div>
<ul class="tree-list tree-list--subgroup">
{content}
</ul>
</li>
```
Args:
tabname: The name of the active tab.
dir_path: Path to the directory for this item.
content: Optional HTML string that will be wrapped by this <ul>.
Returns:
HTML formatted string.
"""
if
not
content
:
return
None
...
...
@@ -326,7 +355,7 @@ class ExtraNetworksPage:
"search_terms"
:
""
,
"subclass"
:
"tree-list-content-dir"
,
"tabname"
:
tabname
,
"
tab_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
"onclick_extra"
:
""
,
"data_path"
:
dir_path
,
"data_hash"
:
""
,
...
...
@@ -337,10 +366,32 @@ class ExtraNetworksPage:
"action_list_item_action_trailing"
:
""
,
}
)
ul
=
f
"<ul class='tree-list tree-list--subgroup' data-hidden>{content}</ul>"
return
f
"<li class='tree-list-item tree-list-item--has-subitem' data-tree-entry-type='dir'>{btn + ul}</li>"
ul
=
f
"<ul class='tree-list tree-list--subgroup' hidden>{content}</ul>"
return
(
"<li class='tree-list-item tree-list-item--has-subitem' data-tree-entry-type='dir'>"
f
"{btn + ul}"
"</li>"
)
def
create_tree_file_item_html
(
self
,
tabname
:
str
,
file_path
:
str
,
item
:
dict
)
->
str
:
"""Generates HTML for a file item in the tree.
The generated HTML is of the format:
```html
<li class="tree-list-item tree-list-item--subitem">
<span data-filterable-item-text hidden></span>
<div class="tree-list-content tree-list-content-file"></div>
</li>
```
Args:
tabname: The name of the active tab.
file_path: The path to the file for this item.
item: Dictionary containing the item information.
def
create_tree_file_item_html
(
self
,
tabname
:
str
,
item_name
:
str
,
item
:
dict
)
->
str
:
Returns:
HTML formatted string.
"""
item_html_args
=
self
.
create_item_html
(
tabname
,
item
)
action_buttons
=
""
.
join
(
[
...
...
@@ -355,9 +406,9 @@ class ExtraNetworksPage:
"search_terms"
:
""
,
"subclass"
:
"tree-list-content-file"
,
"tabname"
:
tabname
,
"
tab_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
"onclick_extra"
:
item_html_args
[
"card_clicked"
],
"data_path"
:
item_name
,
"data_path"
:
file_path
,
"data_hash"
:
item
[
"shorthash"
],
"action_list_item_action_leading"
:
"<i class='tree-list-item-action-chevron'></i>"
,
"action_list_item_visual_leading"
:
"🗎"
,
...
...
@@ -366,11 +417,17 @@ class ExtraNetworksPage:
"action_list_item_action_trailing"
:
action_buttons
,
}
)
return
f
"<li class='tree-list-item tree-list-item--subitem' data-tree-entry-type='file'>{btn}</li>"
return
(
"<li class='tree-list-item tree-list-item--subitem' data-tree-entry-type='file'>"
f
"{btn}"
"</li>"
)
def
create_tree_view_html
(
self
,
tabname
:
str
)
->
str
:
"""Generates HTML for displaying folders in a tree view.
The generated HTML uses `extra-networks-tree.html` as a template.
Args:
tabname: The name of the active tab.
...
...
@@ -379,7 +436,7 @@ class ExtraNetworksPage:
"""
res
=
""
#
Generate HTML for the tree
.
#
Setup the tree dictionary
.
roots
=
self
.
allowed_directories_for_previews
()
tree_items
=
{
v
[
"filename"
]:
ExtraNetworksItem
(
v
)
for
v
in
self
.
items
.
values
()}
tree
=
get_tree
([
os
.
path
.
abspath
(
x
)
for
x
in
roots
],
items
=
tree_items
)
...
...
@@ -388,7 +445,17 @@ class ExtraNetworksPage:
return
res
def
_build_tree
(
data
:
Optional
[
dict
[
str
,
ExtraNetworksItem
]]
=
None
)
->
Optional
[
str
]:
"""Recursively builds HTML for a tree."""
"""Recursively builds HTML for a tree.
Args:
data: Dictionary representing a directory tree. Can be NoneType.
Data keys should be absolute paths from the root and values
should be subdirectory trees or an ExtraNetworksItem.
Returns:
If data is not None: HTML string
Else: None
"""
if
not
data
:
return
None
...
...
@@ -402,25 +469,36 @@ class ExtraNetworksPage:
else
:
_dir_li
.
append
(
self
.
create_tree_dir_item_html
(
tabname
,
k
,
_build_tree
(
v
)))
# Directories should always be displayed before files.
# Directories should always be displayed before files
so we order them here
.
return
""
.
join
(
_dir_li
)
+
""
.
join
(
_file_li
)
# Add each root directory to the tree.
for
k
,
v
in
sorted
(
tree
.
items
(),
key
=
lambda
x
:
shared
.
natural_sort_key
(
x
[
0
])):
# If root is empty, append the "disabled" attribute to the template details tag.
item_html
=
self
.
create_tree_dir_item_html
(
tabname
,
k
,
_build_tree
(
v
))
if
item_html
:
# Only add non-empty entries to the tree.
if
item_html
is
not
None
:
res
+=
item_html
return
self
.
tree_tpl
.
format
(
**
{
"tabname"
:
tabname
,
"
tab_id"
:
self
.
id_pag
e
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabnam
e
,
"tree"
:
f
"<ul class='tree-list tree-list--tree'>{res}</ul>"
}
)
def
create_card_view_html
(
self
,
tabname
):
def
create_card_view_html
(
self
,
tabname
:
str
)
->
str
:
"""Generates HTML for the network Card View section for a tab.
This HTML goes into the `extra-networks-pane.html` <div> with
`id='{tabname}_{extra_networks_tabname}_cards`.
Args:
tabname: The name of the active tab.
Returns:
HTML formatted string.
"""
res
=
""
self
.
items
=
{
x
[
"name"
]:
x
for
x
in
self
.
list_items
()}
for
item
in
self
.
items
.
values
():
...
...
@@ -433,20 +511,26 @@ class ExtraNetworksPage:
return
res
def
create_html
(
self
,
tabname
):
"""Generates an HTML string for the current pane.
The generated HTML uses `extra-networks-pane.html` as a template.
Args:
tabname: The name of the active tab.
Returns:
HTML formatted string.
"""
self
.
lister
.
reset
()
self
.
metadata
=
{}
self
.
items
=
{
x
[
"name"
]:
x
for
x
in
self
.
list_items
()}
tree_view_html
=
self
.
create_tree_view_html
(
tabname
)
card_view_html
=
self
.
create_card_view_html
(
tabname
)
network_type_id
=
self
.
id_page
return
self
.
pane_tpl
.
format
(
**
{
"tabname"
:
tabname
,
"
network_type_id"
:
network_type_id
,
"tree_html"
:
tree_view_html
,
"items_html"
:
card_view_html
,
"
extra_networks_tabname"
:
self
.
extra_networks_tabname
,
"tree_html"
:
self
.
create_tree_view_html
(
tabname
)
,
"items_html"
:
self
.
create_card_view_html
(
tabname
)
,
}
)
...
...
@@ -561,16 +645,16 @@ def create_ui(interface: gr.Blocks, unrelated_tabs, tabname):
button_refresh
=
gr
.
Button
(
"Refresh"
,
elem_id
=
tabname
+
"_extra_refresh_internal"
,
visible
=
False
)
for
page
in
ui
.
stored_extra_pages
:
with
gr
.
Tab
(
page
.
title
,
elem_id
=
f
"{tabname}_{page.
id_pag
e}"
,
elem_classes
=
[
"extra-page"
])
as
tab
:
with
gr
.
Column
(
elem_id
=
f
"{tabname}_{page.
id_pag
e}_prompts"
,
elem_classes
=
[
"extra-page-prompts"
]):
with
gr
.
Tab
(
page
.
title
,
elem_id
=
f
"{tabname}_{page.
extra_networks_tabnam
e}"
,
elem_classes
=
[
"extra-page"
])
as
tab
:
with
gr
.
Column
(
elem_id
=
f
"{tabname}_{page.
extra_networks_tabnam
e}_prompts"
,
elem_classes
=
[
"extra-page-prompts"
]):
pass
elem_id
=
f
"{tabname}_{page.
id_pag
e}_cards_html"
elem_id
=
f
"{tabname}_{page.
extra_networks_tabnam
e}_cards_html"
page_elem
=
gr
.
HTML
(
'Loading...'
,
elem_id
=
elem_id
)
ui
.
pages
.
append
(
page_elem
)
page_elem
.
change
(
fn
=
lambda
:
None
,
_js
=
f
"function(){{applyExtraNetworkFilter({tabname}_{page.
id_pag
e}_extra_search); return []}}"
,
_js
=
f
"function(){{applyExtraNetworkFilter({tabname}_{page.
extra_networks_tabnam
e}_extra_search); return []}}"
,
inputs
=
[],
outputs
=
[],
)
...
...
modules/ui_extra_networks_user_metadata.py
View file @
4f962670
...
...
@@ -14,7 +14,7 @@ class UserMetadataEditor:
self
.
ui
=
ui
self
.
tabname
=
tabname
self
.
page
=
page
self
.
id_part
=
f
"{self.tabname}_{self.page.
id_pag
e}_edit_user_metadata"
self
.
id_part
=
f
"{self.tabname}_{self.page.
extra_networks_tabnam
e}_edit_user_metadata"
self
.
box
=
None
...
...
style.css
View file @
4f962670
...
...
@@ -879,13 +879,6 @@ footer {
margin-bottom
:
1em
;
}
.extra-network-pane
{
height
:
calc
(
100vh
-
24rem
);
overflow
:
clip
scroll
;
resize
:
vertical
;
min-height
:
52rem
;
}
.extra-networks
>
div
.tab-nav
{
min-height
:
3.4rem
;
}
...
...
@@ -1182,23 +1175,63 @@ body.resizing .resize-handle {
/* ========================= */
.extra-network-pane
{
display
:
flex
;
}
.extra-network-pane
.extra-network-cards
{
display
:
block
;
height
:
calc
(
100vh
-
24rem
);
resize
:
vertical
;
min-height
:
52rem
;
}
.extra-network-pane
.extra-network-tree
{
display
:
block
;
flex
:
1
;
flex-direction
:
column
;
display
:
flex
;
font-size
:
1rem
;
min-width
:
25%
;
border
:
1px
solid
var
(
--block-border-color
);
overflow
:
hidden
;
}
.extra-network-tree
.tree-list
{
margin
:
0
0.25rem
;
.extra-network-pane
.extra-network-cards
{
flex
:
3
;
overflow
:
clip
auto
!important
;
border
:
1px
solid
var
(
--block-border-color
);
}
.extra-network-pane
.extra-network-tree
.tree-list
{
flex
:
1
;
display
:
flex
;
flex-direction
:
column
;
padding
:
0
;
width
:
100%
;
overflow
:
hidden
;
}
.extra-network-pane
.extra-network-tree
.tree-list
.tree-list-container
{
flex
:
1
;
overflow
:
clip
auto
!important
;
width
:
100%
;
}
.extra-network-pane
.extra-network-cards
::-webkit-scrollbar
,
.extra-network-pane
.tree-list-container
::-webkit-scrollbar
{
background-color
:
transparent
;
width
:
16px
;
}
.extra-network-pane
.extra-network-cards
::-webkit-scrollbar-track
,
.extra-network-pane
.tree-list-container
::-webkit-scrollbar-track
{
background-color
:
transparent
;
background-clip
:
content-box
;
}
.extra-network-pane
.extra-network-cards
::-webkit-scrollbar-thumb
,
.extra-network-pane
.tree-list-container
::-webkit-scrollbar-thumb
{
background-color
:
var
(
--border-color-primary
);
border-radius
:
16px
;
border
:
4px
solid
var
(
--background-fill-primary
);
}
.extra-network-pane
.extra-network-cards
::-webkit-scrollbar-button
,
.extra-network-pane
.tree-list-container
::-webkit-scrollbar-button
{
display
:
none
;
}
.extra-network-tree
.tree-list
.tree-list-controls
{
...
...
@@ -1244,17 +1277,15 @@ body.resizing .resize-handle {
background-color
:
transparent
;
}
/* Directory <ul> visibility based on expanded attribute. */
.extra-network-tree
.tree-list-content
[
expanded
=
false
]
+
.tree-list--subgroup
{
/* Directory <ul> visibility based on
data-
expanded attribute. */
.extra-network-tree
.tree-list-content
+
.tree-list--subgroup
{
height
:
0
;
overflow
:
hidden
;
visibility
:
hidden
;
opacity
:
0
;
}
.extra-network-tree
.tree-list-content
[
expanded
=
true
]+
.tree-list--subgroup
{
.extra-network-tree
.tree-list-content
[
data-expanded
]+
.tree-list--subgroup
{
height
:
auto
;
overflow
:
visible
;
visibility
:
visible
;
opacity
:
1
;
}
...
...
@@ -1307,7 +1338,7 @@ body.resizing .resize-handle {
background-color
:
var
(
--neutral-800
);
}
.dark
.extra-network-tree
div
.tree-list-content
[
selected
]
{
.dark
.extra-network-tree
div
.tree-list-content
[
data-
selected
]
{
background-color
:
var
(
--neutral-700
);
}
...
...
@@ -1317,20 +1348,20 @@ body.resizing .resize-handle {
background-color
:
var
(
--neutral-200
);
}
.extra-network-tree
div
.tree-list-content
[
selected
]
{
.extra-network-tree
div
.tree-list-content
[
data-
selected
]
{
background-color
:
var
(
--neutral-300
);
}
/* ==== CHEVRON ICON ACTIONS ==== */
/* Define the animation for the arrow when it is clicked. */
.extra-network-tree
.tree-list-content-dir
[
expanded
=
false
]
.tree-list-item-action-chevron
{
.extra-network-tree
.tree-list-content-dir
.tree-list-item-action-chevron
{
-ms-transform
:
rotate
(
135deg
);
-webkit-transform
:
rotate
(
135deg
);
transform
:
rotate
(
135deg
);
transition
:
transform
0.2s
;
}
.extra-network-tree
.tree-list-content-dir
[
expanded
=
true
]
.tree-list-item-action-chevron
{
.extra-network-tree
.tree-list-content-dir
[
data-expanded
]
.tree-list-item-action-chevron
{
-ms-transform
:
rotate
(
225deg
);
-webkit-transform
:
rotate
(
225deg
);
transform
:
rotate
(
225deg
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment