Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
scc-net
netvs
netvs-core
Commits
1544861b
Commit
1544861b
authored
Aug 19, 2020
by
gj4210
👽
Browse files
ADD: Global Search
warning: broken mess atm + also changed ''API-Tokens" to "Accounts & Tokens"
parent
36a7a677
Pipeline
#105455
passed with stages
in 7 minutes and 32 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
frontend/src/components/GlobalSearch.vue
0 → 100644
View file @
1544861b
<
template
>
<b-form
inline
@
submit=
"searchAction"
class=
"mr-2"
>
<transition
name=
"slide"
>
<b-form-group
v-if=
"show_search || ($refs.navdropdown && $refs.navdropdown.show)"
>
<b-form-input
size=
"sm"
placeholder=
"Suche"
id=
"search"
ref=
"search"
v-model=
"search_input"
class=
"mr-2 search"
@
focus=
"search_has_focus = true"
@
blur=
"search_has_focus = false"
/>
<b-button
class=
"search-clear bg-transparent"
size=
"sm"
v-if=
"search_input !== ''"
@
click=
"search_input = ''"
>
<font-awesome-icon
:icon=
"['fas','times']"
class=
"text-secondary"
/>
</b-button>
</b-form-group>
</transition>
<b-popover
custom-class=
"popover-wide suggestions-popover shadow"
:show=
"search_input !== '' && search_has_focus"
target=
"search"
placement=
"bottom"
>
<div
class=
"suggestions-wrapper"
>
<div
v-for=
"(suggestion, index) in suggestions"
:key=
"'search-suggestion-' + index"
class=
"suggestion p-3"
@
click=
"suggestionClicked(suggestion)"
>
<font-awesome-icon
class=
"text-secondary mr-2 suggestion-icon"
:icon=
"suggestion.type === 'page' ? 'link': 'question'"
/>
<font-awesome-icon
class=
"text-primary mr-2 suggestion-arrow"
:icon=
"['fas', 'arrow-right']"
/>
<b>
{{
suggestion
.
name
[
0
]
}}
</b>
{{
suggestion
.
name
[
1
]
}}
<b>
{{
suggestion
.
name
[
2
]
}}
</b>
</div>
<div
v-if=
"suggestions && suggestions.length === 0"
class=
"font-italic text-center p-3"
>
Keine Ergebnisse
</div>
</div>
</b-popover>
<b-button
class=
"search-button"
size=
"sm"
@
click=
"searchAction"
:variant=
"search_input === '' ? 'secondary' : 'success'"
>
<font-awesome-icon
:icon=
"['fas','search']"
/>
</b-button>
<div
class=
"search-cover-wrapper"
>
<div
class=
"search-cover"
/>
</div>
</b-form>
</
template
>
<
script
>
export
default
{
name
:
"
GlobalSearch
"
,
data
()
{
return
{
show_search
:
false
,
search_input
:
''
,
search_has_focus
:
false
,
pages
:
[
{
'
name
'
:
'
DNSVS
'
,
'
url
'
:
'
/dnsvs
'
},
{
'
name
'
:
'
BCDs
'
,
'
url
'
:
'
/dnsvs/bcds
'
},
{
'
name
'
:
'
Accounts & Tokens
'
,
'
url
'
:
'
/user/tokens
'
},
{
'
name
'
:
'
API (Swagger)
'
,
'
url
'
:
'
/swagger
'
},
{
'
name
'
:
'
MACAuth
'
,
'
url
'
:
'
/macauth
'
},
],
test_search_terms
:
[
'
Easter Egg
'
,
'
00:DE:AD:BE:EF:00
'
,
'
127.0.0.1
'
,
'
100.124.99.212:25565
'
,
'
Internet ist kaputt :(
'
,
'
Wörter ausdenken ist mein Job.
'
,
'
Sinn des Lebens
'
,
'
Funktioniert die Suche überhaupt?
'
,
'
Irgendwann wird Alles hier ersetzt.
'
,
'
Lorem Ipsum
'
,
'
What is love?
'
,
'
Minecraft XOR Gate Redstone Tutorial
'
,
'
Fortnite Epic Gamer Moments
'
,
'
Where can I buy Gamer Girl Bathwater?
'
,
'
How to fix ID-10-T error?
'
,
'
12345678?
'
,
'
Is password a good password?
'
,
'
Why my pc hacked?
'
,
'
VIRUS HELP
'
,
'
Why does my Windows support guy sound like his name is not George Smith?
'
,
'
scc.fail
'
,
'
Why internet not work?
'
,
'
Help
'
,
'
hellooooo?
'
],
suggestion_hover
:
[]
}
},
computed
:
{
suggestions
()
{
let
suggestions
=
[]
this
.
pages
.
forEach
(
page
=>
{
let
index
=
page
.
name
.
toLowerCase
().
indexOf
(
this
.
search_input
.
toLowerCase
())
if
(
index
!==
-
1
)
{
suggestions
.
push
({
'
name
'
:
[
page
.
name
.
substring
(
0
,
index
),
page
.
name
.
substring
(
index
,
index
+
this
.
search_input
.
length
),
page
.
name
.
substring
(
index
+
this
.
search_input
.
length
)
],
'
type
'
:
'
page
'
,
'
url
'
:
page
.
url
})
}
}
)
this
.
test_search_terms
.
forEach
(
term
=>
{
let
index
=
term
.
toLowerCase
().
indexOf
(
this
.
search_input
.
toLowerCase
())
if
(
index
!==
-
1
)
{
suggestions
.
push
({
'
name
'
:
[
term
.
substring
(
0
,
index
),
term
.
substring
(
index
,
index
+
this
.
search_input
.
length
),
term
.
substring
(
index
+
this
.
search_input
.
length
)
],
'
type
'
:
'
test
'
})
}
})
return
suggestions
}
},
methods
:
{
searchAction
(
e
)
{
e
.
preventDefault
()
if
(
this
.
search_input
===
''
)
{
this
.
show_search
=
!
this
.
show_search
if
(
this
.
show_search
)
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
search
.
focus
()
})
}
}
else
{
// TODO: actually search stuff
window
.
console
.
log
(
'
Search:
'
+
this
.
search_input
)
this
.
search_input
=
''
}
},
suggestionClicked
(
suggestion
)
{
if
(
suggestion
.
type
===
'
page
'
&&
this
.
$router
.
currentRoute
!==
suggestion
.
url
)
{
this
.
$router
.
push
(
suggestion
.
url
)
}
if
(
suggestion
.
type
===
'
test
'
)
{
window
.
console
.
log
(
'
Clicked test suggestion:
'
+
suggestion
.
name
[
0
]
+
suggestion
.
name
[
1
]
+
suggestion
.
name
[
2
])
}
}
}
}
</
script
>
<
style
scoped
>
.slide-enter-active
,
.slide-leave-active
{
transition
:
transform
250ms
;
z-index
:
-10
;
}
.slide-enter
,
.slide-leave-to
{
transform
:
translateX
(
120%
);
}
.search-cover-wrapper
{
position
:
relative
;
width
:
0
;
height
:
0
;
}
.search-cover
{
z-index
:
-1
;
position
:
absolute
;
left
:
-30px
;
top
:
-25px
;
width
:
300px
;
height
:
50px
;
background
:
#343A40
;
}
.search
{
max-width
:
250px
;
}
.search-button
{
z-index
:
1
;
}
.suggestions-popover
{
width
:
300px
;
max-height
:
75vh
;
overflow-y
:
scroll
;
}
.suggestions-popover
::-webkit-scrollbar
{
display
:
none
;
}
.suggestions-wrapper
{
margin
:
-0.5rem
-0.75rem
;
}
.suggestion
{
cursor
:
pointer
;
}
.suggestion
:nth-child
(
even
)
{
background
:
#f1f1f1
;
}
.suggestion-arrow
{
display
:
none
;
width
:
16px
;
}
.suggestion-icon
{
width
:
16px
;
}
.suggestion
:hover
{
background
:
#d7d7d7
;
}
.suggestion
:hover
>
.suggestion-arrow
{
display
:
initial
;
}
.suggestion
:hover
>
.suggestion-icon
{
display
:
none
;
}
.search-clear
,
.search-clear
:focus
,
.search-clear
:hover
,
.search-clear
:active
{
position
:
relative
;
left
:
-35px
;
margin-right
:
-35px
;
border
:
none
;
}
</
style
>
frontend/src/components/Navbar.vue
View file @
1544861b
<
template
>
<b-navbar
toggleable=
"lg"
fixed=
"top"
:type=
"$sysinfo.host_oper_mode.is_prod?'light':'dark'"
:variant=
"$sysinfo.host_oper_mode.is_prod?'light':'dark'"
:class=
"`bg-$
{$sysinfo.host_oper_mode.mode}` + ' shadow'">
<!-- Brand and toggle get grouped for better mobile display -->
<b-navbar-brand
to=
"/"
>
<img
class=
"d-inline-block align-top scc-img"
alt=
"SCC"
src=
"@/assets/img/scc_logo_small.png"
/>
<span
v-if=
"!$sysinfo.host_oper_mode.is_prod"
>
Instanz:
{{
$sysinfo
.
host_oper_mode
.
mode
}}
</span>
</b-navbar-brand>
<b-navbar-toggle
target=
"navbarNavDropdown"
>
<font-awesome-icon
icon=
"bars"
/>
</b-navbar-toggle>
<!-- Collect the nav links, forms, and other content for toggling -->
<b-collapse
is-nav
id=
"navbarNavDropdown"
ref=
"navdropdown"
>
<b-navbar-nav>
<b-nav-item
v-if=
"$sysinfo_mods_by_name['dnsvs']"
to=
"/dnsvs/"
:active=
"$route.path.startsWith('/dnsvs/')"
>
DNSVS
</b-nav-item>
<b-nav-item
v-if=
"$sysinfo_mods_by_name['dhcp_leases']"
to=
"/dhcp-leases/"
:active=
"$route.path.startsWith('/dhcp-leases/')"
>
DHCP-Leases
</b-nav-item>
<b-nav-item
href=
"https://www-net.scc.kit.edu/~netadmin/natvs/user/wrapper.cgi/"
target=
"_blank"
>
NATVS+
</b-nav-item>
<b-nav-item
href=
"https://www-net.scc.kit.edu/~netadmin/netdoc/user/wrapper.cgi/"
target=
"_blank"
>
NETDOC
</b-nav-item>
</b-navbar-nav>
<b-navbar-nav
class=
"ml-auto"
>
<b-form
inline
@
submit=
"searchAction"
class=
"mr-2"
>
<transition
name=
"slide"
>
<b-form-input
v-if=
"show_search || ($refs.navdropdown && $refs.navdropdown.show)"
ref=
"search"
size=
"sm"
placeholder=
"Suche"
v-model=
"search_input"
class=
"mr-2 search"
/>
</transition>
<b-button
class=
"search-button"
size=
"sm"
@
click=
"searchAction"
:variant=
"search_input === '' ? 'secondary' : 'success'"
>
<font-awesome-icon
:icon=
"['fas','search']"
/>
</b-button>
<div
class=
"search-cover-wrapper"
>
<div
class=
"search-cover"
/>
</div>
</b-form>
<b-nav-item
:active=
"$store.state.show_sidebar"
@
click.stop=
"$store.commit('showSidebar', !$store.state.show_sidebar)"
>
<font-awesome-icon
:icon=
"['fas', 'tasks']"
/>
Geplante Aktionen
<b-badge
variant=
"primary"
>
{{
$store
.
state
.
ta_list
?
$store
.
state
.
ta_list
.
length
:
0
}}
</b-badge>
</b-nav-item>
<b-nav-item-dropdown
v-if=
"$store.state.user"
right
:toggle-class=
"$route.path.startsWith('/user/')?'active':''"
>
<template
slot=
"button-content"
>
<font-awesome-icon
:icon=
"['fas', 'user']"
/>
<span
v-if=
"$store.state.user"
>
{{
$store
.
state
.
user
.
login_name
}}
</span>
</
template
>
<
template
v-if=
"$store.state.user"
>
<b-dropdown-item
to=
"/user/tokens"
:active=
"$route.path === '/user/tokens'"
>
<font-awesome-icon
:icon=
"['fas', 'code']"
/>
API-Tokens
</b-dropdown-item>
<b-dropdown-divider/>
<b-dropdown-item
@
click=
"logout"
>
<font-awesome-icon
:icon=
"['fas', 'sign-out-alt']"
/>
Abmelden
</b-dropdown-item>
</
template
>
</b-nav-item-dropdown>
<b-nav-item
v-else
to=
"/login"
>
<font-awesome-icon
:icon=
"['fas', 'sign-in-alt']"
/>
<span>
Anmelden
</span>
</b-nav-item>
</b-navbar-nav>
</b-collapse>
<!-- /.navbar-collapse -->
</b-navbar>
<b-navbar
toggleable=
"lg"
fixed=
"top"
:type=
"$sysinfo.host_oper_mode.is_prod?'light':'dark'"
:variant=
"$sysinfo.host_oper_mode.is_prod?'light':'dark'"
:class=
"`bg-$
{$sysinfo.host_oper_mode.mode}` + ' shadow'">
<!-- Brand and toggle get grouped for better mobile display -->
<b-navbar-brand
to=
"/"
>
<img
class=
"d-inline-block align-top scc-img"
alt=
"SCC"
src=
"@/assets/img/scc_logo_small.png"
/>
<span
v-if=
"!$sysinfo.host_oper_mode.is_prod"
>
Instanz:
{{
$sysinfo
.
host_oper_mode
.
mode
}}
</span>
</b-navbar-brand>
<b-navbar-toggle
target=
"navbarNavDropdown"
>
<font-awesome-icon
icon=
"bars"
/>
</b-navbar-toggle>
<!-- Collect the nav links, forms, and other content for toggling -->
<b-collapse
is-nav
id=
"navbarNavDropdown"
ref=
"navdropdown"
>
<b-navbar-nav>
<b-nav-item
v-if=
"$sysinfo_mods_by_name['dnsvs']"
to=
"/dnsvs/"
:active=
"$route.path.startsWith('/dnsvs/')"
>
DNSVS
</b-nav-item>
<b-nav-item
v-if=
"$sysinfo_mods_by_name['dhcp_leases']"
to=
"/dhcp-leases/"
:active=
"$route.path.startsWith('/dhcp-leases/')"
>
DHCP-Leases
</b-nav-item>
<b-nav-item
href=
"https://www-net.scc.kit.edu/~netadmin/natvs/user/wrapper.cgi/"
target=
"_blank"
>
NATVS+
</b-nav-item>
<b-nav-item
href=
"https://www-net.scc.kit.edu/~netadmin/netdoc/user/wrapper.cgi/"
target=
"_blank"
>
NETDOC
</b-nav-item>
</b-navbar-nav>
<b-navbar-nav
class=
"ml-auto"
>
<GlobalSearch/>
<b-nav-item
:active=
"$store.state.show_sidebar"
@
click.stop=
"$store.commit('showSidebar', !$store.state.show_sidebar)"
>
<font-awesome-icon
:icon=
"['fas', 'tasks']"
/>
Geplante Aktionen
<b-badge
variant=
"primary"
>
{{
$store
.
state
.
ta_list
?
$store
.
state
.
ta_list
.
length
:
0
}}
</b-badge>
</b-nav-item>
<b-nav-item-dropdown
v-if=
"$store.state.user"
right
:toggle-class=
"$route.path.startsWith('/user/')?'active':''"
>
<template
slot=
"button-content"
>
<font-awesome-icon
:icon=
"['fas', 'user']"
/>
<span
v-if=
"$store.state.user"
>
{{
$store
.
state
.
user
.
login_name
}}
</span>
</
template
>
<
template
v-if=
"$store.state.user"
>
<b-dropdown-item
to=
"/user/tokens"
:active=
"$route.path === '/user/tokens'"
>
<font-awesome-icon
:icon=
"['fas', 'code']"
/>
Accounts
&
Tokens
</b-dropdown-item>
<b-dropdown-divider/>
<b-dropdown-item
@
click=
"logout"
>
<font-awesome-icon
:icon=
"['fas', 'sign-out-alt']"
/>
Abmelden
</b-dropdown-item>
</
template
>
</b-nav-item-dropdown>
<b-nav-item
v-else
to=
"/login"
>
<font-awesome-icon
:icon=
"['fas', 'sign-in-alt']"
/>
<span>
Anmelden
</span>
</b-nav-item>
</b-navbar-nav>
</b-collapse>
<!-- /.navbar-collapse -->
</b-navbar>
</template>
<
script
>
import
LoginService
from
'
@/api-services/login.service
'
import
LoginService
from
'
@/api-services/login.service
'
import
GlobalSearch
from
"
@/components/GlobalSearch
"
;
export
default
{
name
:
"
Navbar
"
,
data
()
{
return
{
show_search
:
false
,
search_input
:
''
}
},
methods
:
{
async
logout
()
{
if
(
this
.
$store
.
token
==
null
)
{
await
LoginService
.
logout
(
null
)
}
else
{
await
LoginService
.
logout
(
this
.
$store
.
state
.
token
.
pk
||
null
)
}
this
.
$store
.
commit
(
'
logout
'
)
await
this
.
$router
.
push
(
'
/login
'
)
},
searchAction
(
e
)
{
e
.
preventDefault
()
if
(
this
.
search_input
===
''
)
{
this
.
show_search
=
!
this
.
show_search
if
(
this
.
show_search
)
{
this
.
$nextTick
(()
=>
{
this
.
$refs
.
search
.
focus
()
})
}
}
else
{
// TODO: actually search stuff
window
.
console
.
log
(
'
Search:
'
+
this
.
search_input
)
this
.
search_input
=
''
}
}
}
export
default
{
name
:
"
Navbar
"
,
components
:
{
GlobalSearch
},
data
()
{
return
{}
},
methods
:
{
async
logout
()
{
if
(
this
.
$store
.
token
==
null
)
{
await
LoginService
.
logout
(
null
)
}
else
{
await
LoginService
.
logout
(
this
.
$store
.
state
.
token
.
pk
||
null
)
}
this
.
$store
.
commit
(
'
logout
'
)
await
this
.
$router
.
push
(
'
/login
'
)
}
</
script
>
<
style
scoped
>
.slide-enter-active
,
.slide-leave-active
{
transition
:
transform
250ms
;
z-index
:
-10
;
}
.slide-enter
,
.slide-leave-to
{
transform
:
translateX
(
120%
);
}
.search-cover-wrapper
{
position
:
relative
;
width
:
0
;
height
:
0
;
}
.search-cover
{
z-index
:
-1
;
position
:
absolute
;
left
:
-30px
;
top
:
-25px
;
width
:
300px
;
height
:
50px
;
background
:
#343A40
;
}
.search
{
max-width
:
250px
;
}
.search-button
{
z-index
:
1
;
}
</
style
>
}
}
</
script
>
\ No newline at end of file
frontend/src/icons.js
View file @
1544861b
...
...
@@ -33,6 +33,9 @@ import {
faSignOutAlt
,
faUser
,
faEye
,
faLink
,
faQuestion
,
faTimes
}
from
'
@fortawesome/free-solid-svg-icons
'
import
{
...
...
@@ -81,4 +84,7 @@ library.add(
faPaperPlane
,
faOpenid
,
faEye
,
faLink
,
faQuestion
,
faTimes
)
frontend/src/router.js
View file @
1544861b
...
...
@@ -46,7 +46,7 @@ export default new Router({
component
:
()
=>
import
(
'
./views/netdb/Tokens.vue
'
),
meta
:
{
resolveName
:
function
()
{
return
"
A
PI-
Tokens
"
return
"
A
ccounts &
Tokens
"
}
}
},
...
...
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