Skip to content

Commit

Permalink
review commit msg WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
nikromen committed Jul 16, 2024
1 parent 35b685d commit 378d157
Show file tree
Hide file tree
Showing 23 changed files with 625 additions and 201 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ COMPOSE ?= $(shell command -v podman-compose 2> /dev/null || echo docker-compose
CONTAINER_ENGINE ?= $(shell command -v podman 2> /dev/null || echo docker)
TEST_IMAGE_NAME=log-detective-website_test-backend
FEEDBACK_DIR=/persistent/results
REVIEWS_DIR=/persistent/reviews
PYTHONPATH=/opt/log-detective-website/backend


Expand All @@ -28,6 +29,7 @@ test-backend-in-container:
$(CONTAINER_ENGINE) run -t -i \
-e PYTHONPATH="$(PYTHONPATH)" \
-e FEEDBACK_DIR="$(FEEDBACK_DIR)" \
-e REVIEWS_DIR="$(REVIEWS_DIR)" \
-e ENV="devel" \
-v .:/opt/log-detective-website:z \
$(TEST_IMAGE_NAME) \
Expand Down
76 changes: 62 additions & 14 deletions backend/src/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
COPR_BUILD_URL,
KOJI_BUILD_URL,
FEEDBACK_DIR,
REVIEWS_DIR,
BuildIdTitleEnum,
ProvidersEnum,
)
Expand All @@ -34,9 +35,10 @@
ContributeResponseSchema,
FeedbackInputSchema,
FeedbackSchema,
FeedbackLogSchema,
schema_inp_to_out,
)
from src.spells import make_tar, get_temporary_dir
from src.spells import make_tar, get_temporary_dir, find_file_by_name
from src.store import Storator3000

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -259,26 +261,72 @@ def contribute_review_container_logs(


@app.get("/frontend/review/random")
def frontend_review_random() -> FeedbackSchema:
if os.environ.get("ENV") == "production":
raise NotImplementedError("Reviewing is not ready yet")

def frontend_review_random():
random_feedback_file = Storator3000.get_random()
with open(random_feedback_file) as random_file:
content = json.loads(random_file.read())
return FeedbackSchema(**content)
return FeedbackSchema(**content).dict() | {"id": random_feedback_file.name.rstrip(".json")}


def _get_text_from_feedback(item: dict) -> str:
if item["vote"] != 1:
return ""

return item["text"]

@app.get("/frontend/review/latest")
def frontend_review_latest() -> FeedbackSchema:
if os.environ.get("ENV") == "production":
raise NotImplementedError("Reviewing is not ready yet")

feedback_file = Storator3000.get_latest()
def _parse_snippet(snippet: dict) -> dict:
return {
"start_index": snippet["start-index"],
"end_index": snippet["end-index"],
"user_comment": snippet["comment"],
"text": snippet["text"],
}

with open(feedback_file) as file:
content = json.loads(file.read())
return FeedbackSchema(**content)

def _parse_logs(logs_orig: dict[str, FeedbackLogSchema], review_snippets: list[dict]) -> dict:
for name, item in logs_orig.items():
item.snippets = []
for snippet in review_snippets:
if snippet["file"] == name and snippet["vote"] == 1:
item.snippets.append(_parse_snippet(snippet))


def _parse_feedback(review: dict, origin_id: int) -> FeedbackSchema:
original_file_path = find_file_by_name(f"{origin_id}.json", Path(FEEDBACK_DIR))
with open(original_file_path) as fp:
original_content = json.load(fp)
schema = FeedbackSchema(**original_content)
# no reason to store username
schema.username = None
schema.fail_reason = _get_text_from_feedback(review["fail_reason"])
schema.how_to_fix = _get_text_from_feedback(review["how_to_fix"])
_parse_logs(schema.logs, review["snippets"])
return schema.dict(exclude_unset=True)


@app.post("/frontend/review")
async def store_random_review(feedback_input: Request) -> OkResponse:
# TODO: temporary silly solution until database is created
# (missing provider but we can dig it from original feedback file)
reviews_dir = Path(REVIEWS_DIR)
parsed_reviews_dir = reviews_dir / "parsed"
parsed_reviews_dir.mkdir(parents=True, exist_ok=True)
content = await feedback_input.json()
original_file_id = content.pop("id")
# avoid duplicates - same ID can be reviewed multiple times
file_name = original_file_id + "-" + str(int(datetime.now().timestamp()))
with open(reviews_dir / f"{file_name}.json", "w") as fp:
json.dump(content | {"id": original_file_id}, fp, indent=4)

with open(parsed_reviews_dir / f"{file_name}.json", "w") as fp:
json.dump(
_parse_feedback(content, original_file_id) | {"id": original_file_id},
fp,
indent=4
)

return OkResponse()


def _make_tpm_tar_file_from_results() -> Iterator[Path]:
Expand Down
1 change: 1 addition & 0 deletions backend/src/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
COPR_BUILD_URL = "https://copr.fedorainfracloud.org/coprs/build/{0}"
KOJI_BUILD_URL = "https://koji.fedoraproject.org/koji/buildinfo?buildID={0}"
FEEDBACK_DIR = os.environ.get("FEEDBACK_DIR", "/persistent/results")
REVIEWS_DIR = os.environ.get("REVIEWS_DIR", "/persistent/reviews")

COPR_RESULT_TEMPLATE = "https://download.copr.fedorainfracloud.org" + \
"/results/{0}/{1}/srpm-builds/{2:08}"
Expand Down
2 changes: 1 addition & 1 deletion backend/src/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class SnippetSchema(BaseModel):
start_index: int
end_index: int
user_comment: str
text: str
text: Optional[str] = None

# def _splitter(self, return_lines: bool) -> tuple[int, int]:
# fst, snd = self.log_part.split("-")
Expand Down
18 changes: 17 additions & 1 deletion backend/src/spells.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tempfile
from contextlib import contextmanager
from pathlib import Path
from typing import Iterator
from typing import Iterator, Optional


@contextmanager
Expand Down Expand Up @@ -36,3 +36,19 @@ def make_tar(name: str, source: Path, destination: Path) -> Path:
tar_f.add(source, arcname=name)

return tar_path


def find_file_by_name(name: str, path: Path) -> Optional[Path]:
"""
Find file by name in the path.
Args:
name: Name of the file
path: Path where to search
"""

for file in path.rglob(name):
if file.is_file():
return file

raise None
12 changes: 0 additions & 12 deletions backend/src/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,6 @@ def get_logs(cls) -> list:
raise NoDataFound(f"Results directory {FEEDBACK_DIR} is empty")
return all_files

@classmethod
def get_latest(cls) -> Path:
"""Sort stored logs by timestamp and return the newest.
"""
files = cls.get_logs()
files = sorted(
files,
key=lambda x: x.split('/')[-1],
reverse=True)

return Path(files[0])

@classmethod
def get_random(cls) -> Path:
# TODO: instead of random, we should go from oldest to newest?
Expand Down
1 change: 1 addition & 0 deletions files/env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
STORAGE_DIR=/persistent
FEEDBACK_DIR=/persistent/results
REVIEWS_DIR=/persistent/reviews
24 changes: 20 additions & 4 deletions frontend/public/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -191,10 +191,6 @@ a:hover {
--bs-btn-active-border-color: var(--newblue);
}

.snippet {
background-color: var(--lightpurple);
}

#left-column h4 {
color: var(--darkblue);
}
Expand Down Expand Up @@ -300,3 +296,23 @@ a:hover {
right: 0;
text-align: center;
}

#right-column .review-card>.card-body {
padding: 0px;
}

#right-column .review-card>*>.card-title {
background-color: var(--gray-1);
padding-top: 10px;
padding-bottom: 10px;
padding-left: 15px;
margin-bottom: 0px;
}


button.btn-vote:hover {
/* Remove hover for vote buttons to easily distinguish clicked and */
/* unclicked buttons */
background-color: var(--bs-btn-bg) !important;
color: var(--bs-btn-color) !important;
}
5 changes: 5 additions & 0 deletions frontend/public/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mb-2 mb-lg-0 ms-auto">
<li class="nav-item">
<a class="nav-link active" href="/review/">
Review logs
</a>
</li>
<li class="nav-item">
<a class="nav-link active" href="/documentation/">
Documentation
Expand Down
5 changes: 4 additions & 1 deletion frontend/shadow-cljs.edn
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@
[clojure-interop/cljs-web-api "1.0.10"]
[lambdaisland/fetch "1.2.69"]
[clj-kondo "2022.05.31"]
[dev.weavejester/lein-cljfmt "0.12.0"]]
[dev.weavejester/lein-cljfmt "0.12.0"]
[metosin/malli "0.14.0"]
[cljs-ajax "0.8.4"]]

:dev-http {3000 "public"}
:nrepl {:port 3333}
:source-paths ["src"]}
5 changes: 3 additions & 2 deletions frontend/src/app/components/accordion.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
:data-bs-toggle "collapse"
:data-bs-target (str "#itemCollapse" i)
:aria-controls (str "itemCollapse" i)}
(str (:title item) " " (+ i 1))]]
[:<> (:title item) " " (inc i)]]]

[:div {:id (str "itemCollapse" i)
:class ["accordion-collapse collapse" (if show? "show" nil)]
Expand All @@ -21,7 +21,8 @@
(:body item)
[:div {:class "accordion-buttons"
:data-index-number i}
(into [:<>] (:buttons item))]]]])
[:div {:class "btn-group"}
(into [:<>] (:buttons item))]]]]])

(defn accordion-items [items]
(doall (for [enumerated-item (map-indexed list items)
Expand Down
Loading

0 comments on commit 378d157

Please sign in to comment.