Skip to content
Merged
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
29 changes: 28 additions & 1 deletion api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import dateutil
import fastapi
import pymongo
from bson.objectid import ObjectId
from db import (
create_mock_client,
create_mongo_client,
Expand Down Expand Up @@ -66,6 +67,13 @@ def filter_from_flush(credentials: HTTPBasicCredentials, flush: Flush) -> dict:
}


def filter_from_creds_and_id(credentials: HTTPBasicCredentials, flush_id: str) -> dict:
return {
"_id": ObjectId(flush_id),
"user_id": credentials.username,
}


def filter_from_user(credentials: HTTPBasicCredentials) -> dict:
return {
"_id": credentials.username,
Expand Down Expand Up @@ -184,6 +192,25 @@ def delete_flush(
return flush.time_start


@app.delete("/flush/{flush_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_flush_by_id(
flush_id: str, credentials: HTTPBasicCredentials = Depends(security)
):
check_creds(credentials)
flushes = client.flush.flushes
try:
result = flushes.delete_one(
filter=filter_from_creds_and_id(credentials, flush_id)
)
if result.deleted_count != 1:
raise Exception("Flush not deleted")
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail="Error deleting flush"
) from e
return Response(status_code=status.HTTP_204_NO_CONTENT)


@app.get("/flushes", status_code=status.HTTP_200_OK)
def get_flushes(
export_format: Union[str, None] = None,
Expand All @@ -200,7 +227,7 @@ def get_flushes(
)
]
for entry in entries:
del entry["_id"]
entry["_id"] = str(entry["_id"])
del entry["user_id"]
if export_format == "json":
for e in entries:
Expand Down
55 changes: 54 additions & 1 deletion api/tests/universal/test_flush_deletion.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from fastapi.testclient import TestClient
from universal.helpers import create_user

from api.main import app
from api.main import app, get_flush_count

client = TestClient(app)

Expand Down Expand Up @@ -68,3 +68,56 @@ def test_flush_delete_nonexistent_flush():
),
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_flush_delete_byid_nonexistent_flush():
create_user(client, "testflushdeletenonexistent2", "testflushdeletenonexistent2")
for i in range(1, 5):
response = client.request(
"DELETE",
f"/flush/{i}",
auth=httpx.BasicAuth(
username="testflushdeletenonexistent2",
password="testflushdeletenonexistent2",
),
)
assert response.status_code == status.HTTP_400_BAD_REQUEST


def test_flush_delete_byid():
create_user(client, "testflushdeletebyid", "testflushdeletebyid")
for i in range(2):
response = client.put(
"/flush",
json={
"time_start": datetime.now().isoformat(timespec="minutes"),
"time_end": (
datetime.now() + timedelta(minutes=15 * (i + 1))
).isoformat(timespec="minutes"),
"rating": 5,
"note": "",
"phone_used": False,
},
auth=httpx.BasicAuth(
username="testflushdeletebyid", password="testflushdeletebyid"
),
)
assert response.status_code == status.HTTP_201_CREATED
assert get_flush_count("testflushdeletebyid") == 2 # noqa: PLR2004
flushes = client.get(
"/flushes",
auth=httpx.BasicAuth(
username="testflushdeletebyid", password="testflushdeletebyid"
),
).json()
for key in flushes:
response = client.request(
"DELETE",
f"/flush/{key['_id']}",
auth=httpx.BasicAuth(
username="testflushdeletebyid",
password="testflushdeletebyid",
),
)
assert response.status_code == status.HTTP_204_NO_CONTENT
assert get_flush_count("testflushdeletebyid") == 0
7 changes: 5 additions & 2 deletions api/tests/universal/test_getting_flushes.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ def test_getting_flushes():
assert response.status_code == status.HTTP_200_OK
rev = flushes
rev.reverse()
js = response.json()
for i, f in enumerate(rev):
f["_id"] = js[i]["_id"]
print(rev)
print(response.json())
assert response.json() == rev
print(js)
assert js == rev


def test_getting_flushes_noflushes():
Expand Down
23 changes: 23 additions & 0 deletions pwa/flush/apicalls.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func GetFlushes(ctx app.Context) ([]Flush, error) {
Rating int `json:"rating"`
PhoneUsed bool `json:"phone_used"`
Note string `json:"note"`
ID string `json:"_id"`
}{}
err = json.Unmarshal(bytes, &temp)
if err != nil {
Expand All @@ -190,6 +191,7 @@ func GetFlushes(ctx app.Context) ([]Flush, error) {
flushes[i].Rating = temp[i].Rating
flushes[i].PhoneUsed = temp[i].PhoneUsed
flushes[i].Note = temp[i].Note
flushes[i].ID = temp[i].ID
}
log.Println("temporary flush struct: ", temp)
log.Println("Flushes: ", flushes)
Expand Down Expand Up @@ -242,3 +244,24 @@ func RemoveAccount(currentCreds string) error {
}
return nil
}

func RemoveFlush(ID string, currentCreds string) error {
apiUrl, err := GetApiUrl()
if err != nil {
return err
}
req, err := http.NewRequest("DELETE", apiUrl+"/flush/"+ID, nil)
if err != nil {
return err
}
req.Header.Add("Authorization", "Basic "+currentCreds)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer CloseBody(resp)
if resp.StatusCode >= 400 {
return errors.New("failed to remove flush")
}
return nil
}
47 changes: 42 additions & 5 deletions pwa/flush/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
InviCss = "fixed invisible"
RootContainerCss = "shadow-lg bg-white rounded-lg p-6 min-h-72 relative"
LoadingCss = "flex flex-row justify-center items-center"
RemoveButtonCss = "font-bold bg-red-500 p-2 rounded text-white hover:bg-red-700 m-1"
)

type ErrorContainer struct {
Expand Down Expand Up @@ -99,7 +100,7 @@ func (b *RootContainer) OnMount(ctx app.Context) {
ShowErrorDiv(ctx, err, 1)
} else {
app.Window().GetElementByID("hidden-hello").Set("innerHTML", "hello!")
b.FlushList = FLushTable(flushes)
b.FlushList = FlushTable(flushes)
}
}
}
Expand Down Expand Up @@ -156,7 +157,7 @@ func (b *buttonUpdate) onClick(ctx app.Context, e app.Event) {
ShowErrorDiv(ctx, err, 1)
} else {
app.Window().GetElementByID("hidden-hello").Set("innerHTML", "hello!")
b.RootContainer.FlushList = FLushTable(flushes)
b.RootContainer.FlushList = FlushTable(flushes)
}
}
})
Expand Down Expand Up @@ -473,7 +474,7 @@ func (a *AboutContainer) Render() app.UI {
).Class(CenteringDivCss).ID("about-container")
}

func FLushTable(flushes []Flush) app.UI {
func FlushTable(flushes []Flush) app.UI {
if len(flushes) == 0 {
return app.Div().Body(app.P().Text("No flushes yet."))
}
Expand All @@ -499,9 +500,10 @@ func FLushTable(flushes []Flush) app.UI {
app.Div().Body(
timeDiv(flush),
app.P().Text("Rating: "+strconv.Itoa(flush.Rating)),
&RemoveFlushButton{ID: flush.ID},
app.P().Text("Phone used: "+phoneUsed),
app.P().Text("Note: '"+flush.Note+"'"),
).Class("flex flex-col p-4 border-1 shadow-lg rounded-lg"),
).Class("flex flex-col p-4 border-1 shadow-lg rounded-lg").ID("div-"+flush.ID),
)
}
statsDiv := app.Div().Body(
Expand Down Expand Up @@ -538,6 +540,41 @@ func timeDiv(flush Flush) app.UI {
}
}

type RemoveFlushButton struct {
app.Compo
ID string
T string
}

func (b *RemoveFlushButton) Render() app.UI {
return app.Button().Text(b.T).Class(RemoveButtonCss + " max-w-10").ID(b.ID).OnClick(b.onClick)
}
func (b *RemoveFlushButton) OnMount(ctx app.Context) {
b.T = "🗑️"
}
func (b *RemoveFlushButton) onClick(ctx app.Context, e app.Event) {
log.Println("Flush remove button pressed...")
if b.T == "🗑️" {
app.Window().GetElementByID(b.ID).Set("className", RemoveButtonCss+" max-w-14")
b.T = "DEL?🗑️"
return
} else if b.T == "DEL?🗑️" {
log.Println("removing flush " + b.ID + "...")
ShowLoading("flushes-loading")
defer Hide("flushes-loading")
var creds Creds
ctx.GetState("creds", &creds)
err := RemoveFlush(b.ID, creds.UserColonPass)
if err != nil {
ShowErrorDiv(ctx, err, 1)
return
}
Hide("div-" + b.ID)
} else {
ShowErrorDiv(ctx, errors.New("Unknown error while flush deleting"), 1)
}
}

type LoadingWidget struct {
app.Compo
id string
Expand Down Expand Up @@ -747,7 +784,7 @@ type RemoveAccountButton struct {
func (c *RemoveAccountButton) Render() app.UI {
return app.Button().
Text("Remove account").
Class("font-bold bg-red-500 p-2 rounded text-white hover:bg-red-700 m-1").
Class(RemoveButtonCss).
OnClick(c.OnClick).ID("remove-account-button")
}
func (c *RemoveAccountButton) OnClick(ctx app.Context, e app.Event) {
Expand Down
1 change: 1 addition & 0 deletions pwa/flush/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type LastTriedCreds struct {
}

type Flush struct {
ID string `json:"_id"`
TimeStart time.Time `json:"time_start"`
TimeEnd time.Time `json:"time_end"`
Rating int `json:"rating"`
Expand Down
Loading