Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
135
noc
Commits
20d3797c
Commit
20d3797c
authored
Aug 22, 2020
by
uncol
Committed by
Andrey Vertiprahov
Aug 22, 2020
Browse files
tag tree widget
parent
56ca1a06
Changes
15
Hide whitespace changes
Inline
Side-by-side
lib/app/extmodelapplication.py
View file @
20d3797c
...
...
@@ -9,6 +9,7 @@
import
datetime
from
collections
import
defaultdict
from
functools
import
reduce
import
re
# Third-party modules
from
django.http
import
HttpResponse
...
...
@@ -72,6 +73,8 @@ class ExtModelApplication(ExtApplication):
SECRET_MASK
=
"********"
file_fields_mask
=
None
rx_oper_splitter
=
re
.
compile
(
r
"^(?P<field>\S+)(?P<f_num>\d+)__in"
)
def
__init__
(
self
,
*
args
,
**
kwargs
):
super
().
__init__
(
*
args
,
**
kwargs
)
self
.
db_table
=
self
.
model
.
_meta
.
db_table
...
...
@@ -259,6 +262,19 @@ class ExtModelApplication(ExtApplication):
def
cleaned_query
(
self
,
q
):
nq
=
{}
q
=
q
.
copy
()
# Extract IN
# extjs not working with same parameter name in query
for
p
in
list
(
q
.
keys
()):
if
p
.
endswith
(
self
.
in_param
):
match
=
self
.
rx_oper_splitter
.
match
(
p
)
if
match
:
field
=
self
.
rx_oper_splitter
.
match
(
p
).
group
(
"field"
)
+
self
.
in_param
if
field
not
in
q
:
q
[
field
]
=
"%s"
%
(
q
[
p
])
else
:
q
[
field
]
+=
",%s"
%
(
q
[
p
])
del
q
[
p
]
for
p
in
q
:
if
p
.
endswith
(
"__exists"
):
v
=
BooleanParameter
().
clean
(
q
[
p
])
...
...
@@ -312,6 +328,8 @@ class ExtModelApplication(ExtApplication):
except
self
.
fk_fields
[
np
].
DoesNotExist
:
nq
[
np
]
=
0
# False search
continue
elif
np
in
self
.
clean_fields
and
self
.
in_param
in
p
:
v
=
ListOfParameter
(
self
.
clean_fields
[
np
]).
clean
(
v
)
elif
np
in
self
.
clean_fields
:
# @todo: Check for valid lookup types
v
=
self
.
clean_fields
[
np
].
clean
(
v
)
# Write back
...
...
services/web/apps/fm/alarm/views.py
View file @
20d3797c
...
...
@@ -174,6 +174,10 @@ class AlarmApplication(ExtApplication):
if
q
[
"administrative_domain"
]
!=
"_root_"
:
q
[
"adm_path"
]
=
int
(
q
[
"administrative_domain"
])
q
.
pop
(
"administrative_domain"
)
if
"administrative_domain__in"
in
q
:
if
"_root_"
not
in
q
[
"administrative_domain__in"
]:
q
[
"adm_path__in"
]
=
q
[
"administrative_domain__in"
]
q
.
pop
(
"administrative_domain__in"
)
if
"segment"
in
q
:
if
q
[
"segment"
]
!=
"_root_"
:
q
[
"segment_path"
]
=
bson
.
ObjectId
(
q
[
"segment"
])
...
...
ui/web/core/combotree/ComboTree.js
View file @
20d3797c
...
...
@@ -188,10 +188,6 @@ Ext.define("NOC.core.combotree.ComboTree", {
expanded
:
true
,
children
:
[]
},
// ToDo make variable for theme
bodyStyle
:
{
background
:
"
#ecf0f1
"
},
tbar
:
[
searchField
],
...
...
@@ -240,18 +236,15 @@ Ext.define("NOC.core.combotree.ComboTree", {
doFilter
:
function
()
{
var
me
=
this
,
parentNode
=
me
.
getParentNode
();
if
(
parentNode
)
{
parentNode
.
removeAll
();
if
(
me
.
searchField
.
getValue
())
{
parentNode
.
appendChild
(
me
.
cache
.
filter
(
function
(
node
)
{
return
node
.
data
[
me
.
displayField
].
toLowerCase
()
.
indexOf
(
me
.
searchField
.
getValue
().
toLowerCase
())
!==
-
1
;
}
));
}
else
{
parentNode
.
appendChild
(
me
.
cache
);
parentNode
.
expand
();
}
me
.
treePicker
.
getStore
().
filterBy
(
function
(
record
)
{
if
(
record
.
parentNode
.
id
!==
me
.
currentLeaf
)
{
return
true
;
}
if
(
!
me
.
searchField
.
getValue
())
{
return
true
;
}
return
record
.
get
(
me
.
displayField
).
toLowerCase
().
indexOf
(
me
.
searchField
.
getValue
().
toLowerCase
())
!==
-
1
;
})
}
},
// event handlers
...
...
ui/web/css/extjs.css
View file @
20d3797c
...
...
@@ -440,6 +440,7 @@ TABLE {
.x-fieldset
{
overflow
:
visible
;
background
:
unset
;
}
.fas
{
...
...
ui/web/css/ux.css
View file @
20d3797c
...
...
@@ -84,13 +84,13 @@
cursor
:
default
;
}
.x-panel-body-default
{
background-color
:
#ecf0f1
!important
;
}
/*
.x-panel-body-default {
*/
/*
background-color: #ecf0f1 !important;
*/
/*}*/
.x-grid-row
{
background-color
:
#ecf0f1
!important
;
}
/*
.x-grid-row {
*/
/*
background-color: #ecf0f1 !important;
*/
/*}*/
.x-summary
{
color
:
#7f8c8d
;
...
...
ui/web/fm/alarm/ApplicationController.js
View file @
20d3797c
...
...
@@ -237,12 +237,12 @@ Ext.define("NOC.fm.alarm.ApplicationController", {
Ext
.
each
([
"
managed_object
"
,
"
managedobjectselector
"
,
"
segment
"
,
"
administrative_domain
"
"
segment
"
],
restoreCombo
,
this
);
// restore tag fields
Ext
.
each
([
"
alarm_class
"
"
alarm_class
"
,
"
administrative_domain
"
],
restoreTagField
,
this
);
// don't change, http params is string compare with int, 0 == "0"
if
(
params
.
hasOwnProperty
(
"
cleared_after
"
)
&&
params
.
cleared_after
!=
0
)
{
...
...
@@ -303,12 +303,12 @@ Ext.define("NOC.fm.alarm.ApplicationController", {
{
key
:
"
timestamp__lte
"
},
// tree
{
key
:
"
segment
"
,
valueField
:
"
id
"
},
{
key
:
"
administrative_domain
"
,
valueField
:
"
id
"
},
// combo
{
key
:
"
managed_object
"
,
valueField
:
"
id
"
},
{
key
:
"
managedobjectselector
"
,
valueField
:
"
id
"
},
// tag field
{
key
:
"
alarm_class
"
,
valueField
:
"
id
"
}
{
key
:
"
alarm_class
"
,
valueField
:
"
id
"
},
{
key
:
"
administrative_domain
"
,
valueField
:
"
id
"
}
],
setParam
);
if
(
value
.
hasOwnProperty
(
"
profiles
"
))
{
var
i
,
len
=
value
.
profiles
.
length
;
...
...
ui/web/fm/alarm/view/grids/Lookup.js
View file @
20d3797c
...
...
@@ -74,7 +74,7 @@ Ext.define("NOC.fm.alarm.view.grids.Lookup", {
initComponent
:
function
()
{
this
.
store
.
proxy
.
url
=
this
.
url
;
// Fix combobox with remote paging
this
.
pickerId
=
me
.
getId
()
+
'
_picker
'
;
this
.
pickerId
=
this
.
getId
()
+
'
_picker
'
;
// end
this
.
callParent
();
}
...
...
ui/web/fm/alarm/view/grids/Sidebar.js
View file @
20d3797c
...
...
@@ -216,12 +216,13 @@ Ext.define("NOC.fm.alarm.view.grids.Sidebar", {
}
},
{
xtype
:
"
noc.core.combotree
"
,
restUrl
:
"
/sa/administrativedomain/
"
,
xtype
:
"
fm.alarm.tagfield
"
,
url
:
"
/sa/administrativedomain/lookup/
"
,
isTree
:
true
,
fieldLabel
:
__
(
"
Adm. Domain
"
),
name
:
"
administrative_domain
"
,
bind
:
{
select
ion
:
"
{activeFilter.administrative_domain}
"
select
ed
:
"
{activeFilter.administrative_domain}
"
}
},
{
...
...
ui/web/fm/alarm/view/grids/Tagfield.js
View file @
20d3797c
//---------------------------------------------------------------------
// fm.alarm
application
// fm.alarm
.tagfield widget
//---------------------------------------------------------------------
// Copyright (C) 2007-20
19
The NOC Project
// Copyright (C) 2007-20
20
The NOC Project
// See LICENSE for details
//---------------------------------------------------------------------
console
.
debug
(
"
Defining NOC.fm.alarm.view.grids.Tagfield
"
);
...
...
@@ -11,6 +11,7 @@ Ext.define("NOC.fm.alarm.view.grids.Tagfield", {
alias
:
"
widget.fm.alarm.tagfield
"
,
controller
:
"
fm.alarm.tagfield
"
,
requires
:
[
"
NOC.fm.alarm.view.grids.TreePicker
"
,
"
NOC.fm.alarm.view.grids.TagfieldController
"
],
displayField
:
"
label
"
,
...
...
@@ -21,6 +22,7 @@ Ext.define("NOC.fm.alarm.view.grids.Tagfield", {
queryDelay
:
200
,
minChars
:
2
,
pageSize
:
true
,
isTree
:
false
,
store
:
{
fields
:
[
"
id
"
,
"
label
"
],
pageSize
:
25
,
...
...
@@ -48,10 +50,21 @@ Ext.define("NOC.fm.alarm.view.grids.Tagfield", {
"
selected
"
],
listeners
:
{
change
:
"
onChange
"
change
:
"
onChange
TagValue
"
},
initComponent
:
function
()
{
this
.
store
.
proxy
.
url
=
this
.
url
;
if
(
this
.
isTree
)
{
// this.treePicker = this.createTreePicker();
this
.
triggers
.
picker
.
cls
=
"
theme-classic fas fa fa-folder-open-o
"
;
this
.
treePicker
=
Ext
.
create
({
xtype
:
"
fm.alarm.treepicker
"
,
displayField
:
this
.
displayField
,
scope
:
this
,
});
}
// Fix combobox when use remote paging
this
.
pickerId
=
this
.
getId
()
+
'
-picker
'
;
this
.
callParent
();
},
setSelected
:
function
(
value
,
skip
)
{
...
...
@@ -62,5 +75,25 @@ Ext.define("NOC.fm.alarm.view.grids.Tagfield", {
},
setWidgetValues
:
function
(
data
)
{
this
.
setSelection
(
data
);
}
},
onTriggerClick
:
function
(
el
)
{
if
(
!
el
)
{
return
;
}
if
(
this
.
isTree
)
{
var
position
,
heightAbove
=
this
.
getPosition
()[
1
]
-
Ext
.
getBody
().
getScroll
().
top
,
heightBelow
=
Ext
.
Element
.
getViewportHeight
()
-
heightAbove
-
this
.
getHeight
();
this
.
treePicker
.
setWidth
(
this
.
getWidth
());
this
.
treePicker
.
height
=
Math
.
max
(
heightAbove
,
heightBelow
)
-
5
;
this
.
setEditable
(
false
);
position
=
this
.
getPosition
();
if
(
heightAbove
>
heightBelow
)
{
position
[
1
]
-=
this
.
treePicker
.
height
-
this
.
getHeight
();
}
this
.
treePicker
.
showAt
(
position
);
}
else
{
Ext
.
form
.
field
.
Tag
.
prototype
.
onTriggerClick
.
apply
(
this
,
arguments
);
}
},
});
ui/web/fm/alarm/view/grids/TagfieldController.js
View file @
20d3797c
//---------------------------------------------------------------------
//
fm.alarm application
//
Tagfield controller
//---------------------------------------------------------------------
// Copyright (C) 2007-20
18
The NOC Project
// Copyright (C) 2007-20
20
The NOC Project
// See LICENSE for details
//---------------------------------------------------------------------
console
.
debug
(
"
Defining NOC.fm.alarm.view.grids.TagfieldController
"
);
...
...
@@ -9,8 +9,12 @@ Ext.define("NOC.fm.alarm.view.grids.TagfieldController", {
extend
:
"
Ext.app.ViewController
"
,
alias
:
"
controller.fm.alarm.tagfield
"
,
onChange
:
function
(
self
)
{
var
selected
=
self
.
getPicker
().
getSelectionModel
().
getSelection
();
this
.
getView
().
setSelected
(
selected
,
true
);
}
onChangeTagValue
:
function
(
self
)
{
var
view
=
this
.
getView
(),
selected
=
self
.
getPicker
().
getSelectionModel
().
getSelection
();
if
(
view
.
isTree
)
{
view
.
treePicker
.
getController
().
selectNode
(
selected
);
}
view
.
setSelected
(
selected
,
true
);
},
});
\ No newline at end of file
ui/web/fm/alarm/view/grids/TreePicker.js
0 → 100644
View file @
20d3797c
//---------------------------------------------------------------------
// fm.alarm.treepicker widget
//---------------------------------------------------------------------
// Copyright (C) 2007-2020 The NOC Project
// See LICENSE for details
//---------------------------------------------------------------------
console
.
debug
(
"
Defining NOC.fm.alarm.view.grids.TreePicker
"
);
Ext
.
define
(
"
NOC.fm.alarm.view.grids.TreePicker
"
,
{
extend
:
"
Ext.tree.Panel
"
,
alias
:
"
widget.fm.alarm.treepicker
"
,
controller
:
"
fm.alarm.treepicker
"
,
requires
:
[
"
NOC.fm.alarm.view.grids.TreePickerController
"
],
baseCls
:
Ext
.
baseCSSPrefix
+
"
boundlist
"
,
shrinkWrap
:
2
,
shrinkWrapDock
:
true
,
animCollapse
:
true
,
singleExpand
:
false
,
useArrows
:
true
,
scrollable
:
true
,
floating
:
true
,
manageHeight
:
false
,
collapseFirst
:
false
,
currentLeaf
:
false
,
rootVisible
:
false
,
root
:
{
expanded
:
true
,
children
:
[]
},
selModel
:
{
mode
:
"
SIMPLE
"
},
tbar
:
[
{
xtype
:
"
searchfield
"
,
width
:
"
90%
"
,
emptyText
:
__
(
"
pattern
"
),
enableKeyEvents
:
true
,
triggers
:
{
clear
:
{
cls
:
"
x-form-clear-trigger
"
,
hidden
:
true
,
handler
:
"
onClearSearchField
"
}
},
listeners
:
{
keyup
:
"
onChangeSearchField
"
}
},
{
glyph
:
NOC
.
glyph
.
times_circle
,
tooltip
:
__
(
"
Close
"
),
handler
:
"
onClosePanel
"
}
],
listeners
:
{
itemclick
:
"
onItemClick
"
,
itemkeydown
:
"
onPickerKeyDown
"
,
beforeitemexpand
:
"
onItemBeforeExpand
"
,
itemexpand
:
"
onItemExpand
"
,
focusleave
:
"
onLeaveFocusTreePicker
"
},
initComponent
:
function
()
{
// tree panel store
this
.
treeStore
=
Ext
.
create
(
"
Ext.data.Store
"
,
Ext
.
merge
(
Ext
.
clone
(
this
.
scope
.
getStore
()),
{
autoLoad
:
true
,
proxy
:
{
extraParams
:
{
parent
:
""
}
},
listeners
:
{
scope
:
this
.
getController
(),
load
:
this
.
getController
().
onLoadTree
}
},
true
));
this
.
callParent
();
}
});
\ No newline at end of file
ui/web/fm/alarm/view/grids/TreePickerController.js
0 → 100644
View file @
20d3797c
//---------------------------------------------------------------------
// fm.alarm.treepicker controller
//---------------------------------------------------------------------
// Copyright (C) 2007-2020 The NOC Project
// See LICENSE for details
//---------------------------------------------------------------------
console
.
debug
(
"
Defining NOC.fm.alarm.view.grids.TreePickerController
"
);
Ext
.
define
(
"
NOC.fm.alarm.view.grids.TreePickerController
"
,
{
extend
:
"
Ext.app.ViewController
"
,
alias
:
"
controller.fm.alarm.treepicker
"
,
requires
:
[],
// store events
onLoadTree
:
function
(
store
,
records
,
success
)
{
var
parentNode
=
this
.
getParentNode
(),
me
=
this
.
getView
(),
parentField
=
me
.
scope
;
if
(
!
parentNode
.
hasChildNodes
()
&&
success
)
{
parentNode
.
appendChild
(
records
.
map
(
function
(
item
)
{
return
Ext
.
merge
({
leaf
:
!
item
.
get
(
"
has_children
"
),
qtip
:
item
.
get
(
parentField
.
displayField
)
},
item
.
getData
());
}));
parentNode
.
expand
();
}
if
(
!
me
.
cache
)
{
// first run, root elements
me
.
cache
=
Ext
.
clone
(
parentNode
.
childNodes
);
}
},
// tree panel events
onClosePanel
:
function
()
{
this
.
getView
().
hide
();
},
onItemClick
:
function
(
view
,
record
)
{
this
.
selectItem
(
record
);
},
onPickerKeyDown
:
function
(
view
,
record
,
item
,
index
,
e
)
{
var
key
=
e
.
getKey
();
if
(
key
===
e
.
ENTER
)
{
this
.
selectItem
(
record
);
}
},
onItemBeforeExpand
:
function
(
self
)
{
var
me
=
this
.
getView
(),
node
;
if
(
me
.
currentLeaf
&&
(
me
.
currentLeaf
!==
self
.
getId
()))
{
node
=
me
.
getStore
().
getNodeById
(
me
.
currentLeaf
);
node
.
appendChild
(
me
.
cache
);
}
me
.
currentLeaf
=
self
.
getId
();
me
.
cache
=
Ext
.
clone
(
self
.
childNodes
);
if
(
!
self
.
hasChildNodes
())
{
this
.
loadChildren
(
me
.
currentLeaf
);
return
false
;
}
},
onItemExpand
:
function
()
{
this
.
doFilter
();
},
onLeaveFocusTreePicker
:
function
()
{
this
.
getView
().
scope
.
setEditable
(
true
);
this
.
getView
().
hide
();
},
// search field events
onClearSearchField
:
function
(
self
)
{
self
.
setValue
();
self
.
getTrigger
(
"
clear
"
).
hide
();
this
.
doFilter
();
},
onChangeSearchField
:
function
(
self
)
{
if
(
self
.
getValue
()
==
null
||
!
self
.
getValue
().
length
)
{
this
.
onClearSearchField
(
self
);
return
;
}
this
.
doFilter
();
self
.
getTrigger
(
"
clear
"
).
show
();
},
//
getParentNode
:
function
()
{
var
me
=
this
.
getView
(),
store
=
me
.
getStore
();
if
(
!
me
.
currentLeaf
)
{
return
store
.
getRootNode
();
}
else
{
return
store
.
getById
(
me
.
currentLeaf
);
}
},
loadChildren
:
function
(
id
)
{
var
me
=
this
.
getView
();
if
(
!
me
.
hidden
)
{
me
.
mask
(
__
(
"
loading ...
"
));
}
me
.
treeStore
.
load
({
params
:
{
parent
:
id
},
callback
:
function
()
{
if
(
!
me
.
hidden
)
{
me
.
unmask
();
}
}
});
},
selectItem
:
function
(
record
)
{
var
parent
=
this
.
getView
().
scope
,
value
=
{},
isExist
,
selected
=
parent
.
getSelected
();
if
(
selected
)
{
isExist
=
Ext
.
Array
.
findBy
(
selected
,
function
(
el
)
{
return
el
.
id
===
record
.
id
});
}
if
(
isExist
)
{
parent
.
removeValue
(
isExist
);
}
else
{
value
[
parent
.
valueField
]
=
record
.
id
;
value
[
parent
.
displayField
]
=
record
.
get
(
parent
.
displayField
);
parent
.
addValue
(
Ext
.
create
(
"
Ext.data.Model
"
,
value
));
}
},
selectNode
:
function
()
{
var
me
=
this
.
getView
(),
selection
=
[];
if
(
me
)
{
// maping to tree-picker store
Ext
.
Array
.
each
(
me
.
scope
.
getPicker
().
getSelectionModel
().
getSelection
(),
function
(
record
)
{
var
node
=
me
.
getStore
().
getNodeById
(
record
.
id
);
if
(
node
)
{
selection
.
push
(
node
);
}
});
if
(
selection
.
length
)
{
me
.
getSelectionModel
().
select
(
selection
);
}
if
(
selection
.
length
===
0
)
{
me
.
getSelectionModel
().
deselectAll
(
selection
);
}
}
},
doFilter
:
function
()
{
var
me
=
this
.
getView
(),
parentNode
=
this
.
getParentNode
(),
searchField
=
me
.
down
(
"
[xtype=searchfield]
"
);
if
(
parentNode
)
{
me
.
getStore
().
filterBy
(
function
(
record
)
{
if
(
record
.
parentNode
.
id
!==
me
.
currentLeaf
)
{
return
true
;
}
if
(
!
searchField
.
getValue
())
{
return
true
;
}
return
record
.
get
(
me
.
scope
.
displayField
).
toLowerCase
().
indexOf
(
searchField
.
getValue
().
toLowerCase
())
!==
-
1
;
})
this
.
selectNode
();
}
},
});
\ No newline at end of file
ui/web/inv/map/MapPanel.js
View file @
20d3797c
...
...
@@ -125,9 +125,6 @@ Ext.define("NOC.inv.map.MapPanel", {
xtype
:
"
component
"
,
autoScroll
:
true
,
layout
:
"
fit
"
,
style
:
{
background
:
"
#ecf0f1
"
}
}
]
});
...
...
ui/web/inv/map/MiniMap.js
View file @
20d3797c
...
...
@@ -30,9 +30,6 @@ Ext.define('NOC.inv.map.MiniMap', {
width
:
w
,
model
:
mapPanel
.
graph
,
gridSize
:
1
,
background
:
{
color
:
'
#ecf0f1
'
},
interactive
:
false
});
this
.
miniPaper
.
on
(
'
blank:pointerdown
'
,
function
(
evt
,
x
,
y
)
{
...
...
ui/web/inv/map/inspectors/Inspector.js
View file @
20d3797c
...
...
@@ -11,9 +11,6 @@ Ext.define('NOC.inv.map.inspectors.Inspector', {
title
:
undefined
,
scrollable
:
'
vertical
'
,
bodyStyle
:
{
background
:
'
#c0c0c0
'
},
defaults
:
{
padding
:
4
},
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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