Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions api/object_specifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,14 @@ class JobChange(BaseModel):

model_config = ConfigDict(extra='forbid')

### Watchlist

class WatchlistChange(BaseModel):
watchlist_id: int
action: Literal['delete']

model_config = ConfigDict(extra='forbid')

### Software Add

class Software(BaseModel):
Expand Down
30 changes: 28 additions & 2 deletions api/scenario_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
from datetime import date, datetime, timedelta
import pprint

from fastapi import APIRouter, Response, Depends
from fastapi import APIRouter, Response, Depends, HTTPException
from fastapi.responses import ORJSONResponse
from fastapi.exceptions import RequestValidationError

import anybadge

from api.object_specifications import Software, JobChange
from api.object_specifications import Software, JobChange, WatchlistChange
from api.api_helpers import (ORJSONResponseObjKeep, add_phase_stats_statistics,
determine_comparison_case,get_comparison_details,
get_phase_stats, get_phase_stats_object, check_run_failed,
Expand Down Expand Up @@ -147,6 +147,32 @@ async def update_job(
error_helpers.log_error('Job update did return unexpected result', params=params, status_message=status_message)
raise RuntimeError('Could not update job due to database error')

# A route for deleting watchlist entries
@router.put('/v1/watchlist')
async def update_watchlist(
change: WatchlistChange,
user: User = Depends(authenticate), # consistent with jobs
):
if change.action != 'delete':
raise RequestValidationError(f"Unsupported action: {change.action}")

query = """
DELETE FROM watchlist
WHERE id = %s
AND (TRUE = %s OR user_id = %s)
RETURNING id
"""
params = (change.watchlist_id, user.is_super_user(), user._id)
deleted = DB().fetch_one(query, params=params, fetch_mode="dict")

if not deleted:
raise HTTPException(
status_code=404,
detail="Watchlist entry not found or not owned by user",
)

return ORJSONResponse({'success': True, 'deleted_id': deleted['id']})

# A route to return all of the available entries in our catalog.
@router.get('/v1/notes/{run_id}')
async def get_notes(run_id, user: User = Depends(authenticate)):
Expand Down
33 changes: 31 additions & 2 deletions frontend/js/watchlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ $(document).ready(function () {
chart_node.classList.add('ui')
chart_node.classList.add("card");

//Giving each card a data-id
chart_node.setAttribute('data-id', id);


const url_link = `${replaceRepoIcon(repo_url)} ${createExternalIconLink(repo_url)}`;
let chart_node_html = `
<div class="image">
Expand Down Expand Up @@ -60,14 +64,39 @@ $(document).ready(function () {
<hr>
<a class="ui button grey" href="/runs.html?uri=${encodeURIComponent(repo_url)}&filename=${encodeURIComponent(filename)}&branch=${encodeURIComponent(branch)}&machine_id=${machine_id}" target="_blank">
Show All Measurements <i class="external alternate icon"></i>
</a>`
</a>
<hr>
<button class="ui red button delete-watchlist" data-id="${id}">
<i class="trash icon"></i> Delete
</button>`;


chart_node.innerHTML = chart_node_html;
document.querySelector('#scenario-runner-watchlist').appendChild(chart_node)
});
document.querySelectorAll(".copy-badge").forEach(el => {
el.addEventListener('click', copyToClipboard)
})
});

//Event listener for delete buttons
$(document).on("click", ".delete-watchlist", async function () {
const id = $(this).data("id");

if (!confirm("Are you sure you want to delete this watchlist entry?")) {
return;
}

try {
await makeAPICall('/v1/watchlist', 'PUT', {
action: "delete",
watchlist_id: id
});
showNotification("Watchlist entry deleted successfully!");
$(this).closest(".card").remove();
} catch (err) {
showNotification("Error deleting watchlist entry", err);
}
});
})();
});

Expand Down