diff --git a/assets/img/icons/link2.svg b/assets/img/icons/link2.svg new file mode 100755 index 0000000..1b68037 --- /dev/null +++ b/assets/img/icons/link2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/link3.svg b/assets/img/icons/link3.svg new file mode 100755 index 0000000..b6b391f --- /dev/null +++ b/assets/img/icons/link3.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/img/icons/link4.svg b/assets/img/icons/link4.svg new file mode 100755 index 0000000..d613def --- /dev/null +++ b/assets/img/icons/link4.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/img/icons/link5.svg b/assets/img/icons/link5.svg new file mode 100755 index 0000000..1462c02 --- /dev/null +++ b/assets/img/icons/link5.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/img/icons/unlink.svg b/assets/img/icons/unlink.svg new file mode 100755 index 0000000..831a9e1 --- /dev/null +++ b/assets/img/icons/unlink.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/img/icons/unlink2.svg b/assets/img/icons/unlink2.svg new file mode 100755 index 0000000..76ab66d --- /dev/null +++ b/assets/img/icons/unlink2.svg @@ -0,0 +1,4 @@ + + + + diff --git a/assets/img/icons/unlink3.svg b/assets/img/icons/unlink3.svg new file mode 100755 index 0000000..4a69ad3 --- /dev/null +++ b/assets/img/icons/unlink3.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/img/icons/unlink4.svg b/assets/img/icons/unlink4.svg new file mode 100755 index 0000000..f622af7 --- /dev/null +++ b/assets/img/icons/unlink4.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/components/actors/tile.vue b/components/actors/tile.vue index 153f3a0..6de4452 100644 --- a/components/actors/tile.vue +++ b/components/actors/tile.vue @@ -14,8 +14,8 @@ > @@ -73,6 +73,7 @@ + + diff --git a/components/dialog/dialog.vue b/components/dialog/dialog.vue index 6341ec2..d75739b 100644 --- a/components/dialog/dialog.vue +++ b/components/dialog/dialog.vue @@ -59,6 +59,13 @@ onMounted(() => emit('open')); font-size: .9rem; line-height: 1.5; } + +.dialog-error { + padding: .5rem 1rem; + color: var(--text-light); + background: var(--error); + font-weight: bold; +} diff --git a/pages/entities/+onBeforeRender.js b/pages/entities/+onBeforeRender.js index f43a690..6bbca8a 100644 --- a/pages/entities/+onBeforeRender.js +++ b/pages/entities/+onBeforeRender.js @@ -1,7 +1,9 @@ import { fetchEntities } from '#/src/entities.js'; -export async function onBeforeRender(_pageContext) { - const networks = await fetchEntities({ type: 'primary' }); +export async function onBeforeRender(pageContext) { + const networks = await fetchEntities(pageContext.urlParsed.search.q + ? { query: pageContext.urlParsed.search.q } + : { type: 'primary' }); return { pageContext: { diff --git a/pages/users/@username/+Page.vue b/pages/users/@username/+Page.vue index aa04ba2..7b3b972 100644 --- a/pages/users/@username/+Page.vue +++ b/pages/users/@username/+Page.vue @@ -66,6 +66,56 @@ + +
+
+

Alerts

+ + +
+ + + + + + + + + + + + + + + + + + +
ActorsTagsEntitiesMatches
{{ alert.actors.map((actor) => actor.name).join(', ') }}{{ alert.tags.map((tag) => tag.name).join(alert.and.tags ? ' + ' : ' | ') }}{{ alert.entities.map((entity) => entity.name).join(', ') }}{{ alert.matches.map((match) => match.expression).join(', ') }} + +
+ + +
@@ -74,20 +124,23 @@ import { ref, inject } from 'vue'; import { formatDistanceStrict } from 'date-fns'; -import { get, post } from '#/src/api.js'; +import { get, post, del } from '#/src/api.js'; import StashTile from '#/components/stashes/tile.vue'; import Dialog from '#/components/dialog/dialog.vue'; +import AlertDialog from '#/components/alerts/create.vue'; const pageContext = inject('pageContext'); const user = pageContext.user; const profile = ref(pageContext.pageProps.profile); +const alerts = ref(pageContext.pageProps.alerts); const stashName = ref(null); const stashNameInput = ref(null); const done = ref(true); const showStashDialog = ref(false); +const showAlertDialog = ref(false); async function reloadProfile() { profile.value = await get(`/users/${profile.value.id}`); @@ -100,20 +153,55 @@ async function createStash() { done.value = false; - await post('/stashes', { - name: stashName.value, - public: false, - }, { - successFeedback: `Created stash '${stashName.value}'`, - errorFeedback: `Failed to create stash '${stashName.value}'`, - appendErrorMessage: true, - }).finally(() => { done.value = true; }); + try { + await post('/stashes', { + name: stashName.value, + public: false, + }, { + successFeedback: `Created stash '${stashName.value}'`, + errorFeedback: `Failed to create stash '${stashName.value}'`, + appendErrorMessage: true, + }); + } finally { + done.value = true; + } showStashDialog.value = false; stashName.value = null; await reloadProfile(); } + +async function reloadAlerts() { + alerts.value = await get('/alerts'); +} + +async function removeAlert(alert) { + if (done.value === false) { + 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; + } +}