2024-08-31 23:30:45 +00:00
< template >
< section class = "profile-section" >
< div class = "section-header" >
< h3 class = "heading" > Alerts < / h3 >
< button
class = "button"
@ click = "showAlertDialog = true"
>
< Icon icon = "alarm-add" / >
< span class = "button-label" > New alert < / span >
< / button >
< / div >
< ul class = "alerts nolist" >
< li
v - for = "alert in alerts"
: key = "`alert-${alert.id}`"
class = "alert"
>
< div
class = "alert-details"
: class = "{ and: alert.and.fields, or: !alert.and.fields }"
>
< span
v - if = "alert.tags.length > 0"
class = "alert-detail alert-tags"
: class = "{ and: alert.and.tags, or: !alert.and.tags }"
>
< span class = "alert-values" >
< span
v - for = "tag in alert.tags"
: key = "`tag-${alert.id}-${tag.id}`"
class = "alert-key"
>
< a
: href = "`/tag/${tag.slug}`"
class = "alert-value link"
> { { tag . name } } < / a >
< / span >
< / span >
< / span >
< span
v - if = "alert.actors.length > 0"
class = "alert-detail alert-actors"
: class = "{ and: alert.and.actors, or: !alert.and.actors }"
>
< span class = "alert-values" > with
< span
v - for = "actor in alert.actors"
: key = "`actor-${alert.id}-${actor.id}`"
class = "alert-key"
>
< a
: href = "`/actor/${actor.id}/${actor.slug}`"
class = "alert-value link"
> { { actor . name } } < / a >
< / span >
< / span >
< / span >
< span
v - if = "alert.entities.length > 0"
class = "alert-detail alert-entities or"
>
< span class = "alert-values" > for
< span
v - for = "entity in alert.entities"
: key = "`entity-${alert.id}-${entity.id}`"
class = "alert-key"
>
< a
: href = "`/${entity.type}/${entity.slug}`"
class = "alert-value link"
>
< Icon
v - if = "entity.type === 'network'"
icon = "device_hub"
/ > { { e n t i t y . n a m e } }
< / a >
< / span >
< / span >
< / span >
< span
v - if = "alert.matches.length > 0"
class = "alert-detail alert-matches"
: class = "{ and: alert.and.matches, or: !alert.and.matches }"
>
< span class = "alert-values" > matching
< span
v - for = "match in alert.matches"
: key = "`match-${alert.id}-${match.id}`"
class = "alert-key"
>
< span class = "alert-value" > { { match . property } } :
< span
class = "alert-regex"
title = "If your original expression was not a /regular expression/, it was converted, and new characters may have been added for syntactical purposes. These characters do not alter the function of the expression; they ensure it."
> { { match . expression } } < / span >
< / span >
< / span >
< / span >
< / span >
< / div >
< div class = "alert-meta" >
< div class = "alert-triggers" >
< Icon
v - tooltip = "alert.notify ? 'Notify in traxxx' : undefined"
icon = "bell2"
: class = "{ trigger: alert.notify }"
/ >
< Icon
v - if = "alert.stashes.some((stash) => !stash.isPrimary)"
v - tooltip = "`Add to ${alert.stashes.map((stash) => stash.name).join(', ')}`"
icon = "folder-heart"
class = "trigger"
/ >
< Icon
v - else
v - tooltip = "alert.stashes.length > 0 ? 'Add to Favorites' : undefined"
icon = "heart7"
: class = "{ trigger: alert.stashes.length > 0 }"
/ >
<!--
< Icon
icon = "envelop5"
title = "E-mail me"
: class = "{ trigger: alert.email }"
/ >
-- >
< / div >
< div class = "alert-actions" >
< span
2024-09-01 00:54:03 +00:00
v - tooltip = "format(alert.createdAt, 'yyyy-MM-dd hh:mm')"
2024-08-31 23:30:45 +00:00
class = "alert-id"
title = "Alert ID"
> # { { alert . id } } < / span >
< Icon
icon = "bin"
@ click = "removeAlert(alert)"
/ >
< / div >
< / div >
< / li >
< / ul >
< AlertDialog
v - if = "showAlertDialog"
@ close = "showAlertDialog = false; reloadAlerts();"
/ >
< / section >
< / template >
< script setup >
import { ref , inject } from 'vue' ;
2024-09-01 00:54:03 +00:00
import { format } from 'date-fns' ;
2024-08-31 23:30:45 +00:00
import AlertDialog from '#/components/alerts/create.vue' ;
import { get , del } from '#/src/api.js' ;
const pageContext = inject ( 'pageContext' ) ;
const alerts = ref ( pageContext . pageProps . alerts ) ;
const showAlertDialog = ref ( false ) ;
const done = ref ( true ) ;
async function reloadAlerts ( ) {
alerts . value = await get ( '/alerts' ) ;
}
async function removeAlert ( alert ) {
if ( done . value === false ) {
return ;
}
if ( ! confirm ( ` Are you sure you want to remove alert # ${ alert . id } ? ` ) ) { // eslint-disable-line no-restricted-globals, no-alert
return ;
}
done . value = false ;
const alertLabel = [
... alert . actors . map ( ( actor ) => actor . name ) ,
... alert . tags . map ( ( tag ) => tag . name ) ,
... alert . entities . map ( ( entity ) => entity . name ) ,
... alert . matches . map ( ( match ) => match . expression ) ,
] . filter ( Boolean ) . join ( ', ' ) ;
try {
await del ( ` /alerts/ ${ alert . id } ` , {
undoFeedback : ` Removed alert for ' ${ alertLabel } ' ` ,
errorFeedback : ` Failed to remove alert for ' ${ alertLabel } ' ` ,
appendErrorMessage : true ,
} ) ;
await reloadAlerts ( ) ;
} finally {
done . value = true ;
}
}
< / script >
< style scoped >
. alerts {
width : 100 % ;
margin - bottom : 1 rem ;
}
. alert {
padding : 0 0 0 .5 rem ;
display : flex ;
align - items : stretch ;
border - bottom : solid 1 px var ( -- glass - weak - 40 ) ;
& : hover {
border - color : var ( -- glass - weak - 30 ) ;
}
}
. alert - triggers {
display : flex ;
align - items : center ;
gap : .5 rem ;
margin - right : .75 rem ;
. icon {
fill : var ( -- glass - weak - 40 ) ;
}
. icon . trigger {
fill : var ( -- glass - weak - 10 ) ;
}
}
. alert - details {
padding : .25 rem 0 ;
flex - grow : 1 ;
line - height : 2.5 ;
color : var ( -- glass ) ;
& . and . alert - detail : not ( : last - child ) : after {
content : ' and ' ;
}
& . or . alert - detail : not ( : last - child ) : after {
content : ' or ' ;
}
}
. alert - value {
color : var ( -- text ) ;
. icon {
margin - right : .25 rem ;
fill : var ( -- glass ) ;
transform : translateY ( 2 px ) ;
}
}
. alert - values {
padding : .5 rem .5 rem ;
border - bottom : solid 1 px var ( -- primary - light - 20 ) ;
border - radius : .3 rem ;
}
. alert - detail {
& . and . alert - key : not ( : last - child ) : after {
content : ' and ' ;
}
& . or . alert - key : not ( : last - child ) : after {
content : ' or ' ;
}
}
. alert - regex {
& : before ,
& : after {
content : '╱ ' ;
padding : 0 .1 rem ;
color : var ( -- primary - light - 20 ) ;
}
}
. alert - meta {
display : flex ;
}
. alert - actions {
display : flex ;
align - items : center ;
font - size : .9 rem ;
color : var ( -- glass - weak - 10 ) ;
. icon {
height : 100 % ;
padding : 0 .75 rem ;
fill : var ( -- glass ) ;
& : hover {
cursor : pointer ;
fill : var ( -- primary ) ;
}
}
}
@ media ( -- compact ) {
. profile - header {
border - radius : 0 ;
}
. section - header {
padding : .5 rem 1 rem .5 rem 1 rem ;
}
. stashes {
padding : 0 1 rem 1 rem 1 rem ;
}
. alert {
padding : 0 .5 rem 0 1 rem ;
}
}
@ media ( -- small - 20 ) {
. alert {
flex - direction : column ;
}
. alert - meta {
padding : .5 rem 0 .75 rem 0 ;
justify - content : flex - end ;
}
}
< / style >