Skip to content

Commit

Permalink
feat: Added description display (#151)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kubaryt authored Feb 9, 2025
1 parent 57c90bf commit 4ccca3e
Show file tree
Hide file tree
Showing 13 changed files with 841 additions and 24 deletions.
2 changes: 1 addition & 1 deletion backend/TasksTemplate
30 changes: 30 additions & 0 deletions backend/src/routes/task/description.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::routes::task::TaskError;
use crate::utils::app_state::AppState;
use crate::utils::error::Error;
use actix_web::web::{Data, Path};
use actix_web::{get, HttpResponse};

#[utoipa::path(
responses(
(status = 200, description = "Correctly returned task description", body = String),
(status = 400, description = "Invalid task id."),
(status = 404, description = "Task not found."),
(status = 500, description = "Internal server error.")
),
tag = "tasks"
)]
#[get("/description/{task_id}")]
pub async fn description(
app_state: Data<AppState>,
task_id: Path<String>,
) -> Result<HttpResponse, Error> {
let manager = app_state
.task_manager
.read()
.map_err(|_| Error::PoisonedLock)?;
let content_bytes = manager.load_asset(&task_id, "description.md").await?;
let content =
String::from_utf8(content_bytes).map_err(TaskError::ErrorWhileReadingDescription)?;

Ok(HttpResponse::Ok().body(content))
}
15 changes: 12 additions & 3 deletions backend/src/routes/task/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use actix_web::http::StatusCode;
use actix_web::{error, HttpResponse};
use std::string;
use thiserror::Error;

mod background;
mod description;
mod icon;
mod list;
mod story;
Expand All @@ -12,24 +14,31 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
cfg.service(icon::icon);
cfg.service(story::story);
cfg.service(background::background);
cfg.service(description::description);
}

#[derive(Debug, Error)]
pub enum TaskError {
#[error("Task ID may only contain a-Z, A-Z, 0-9, - and _")]
InvalidTaskId,
#[error("Could not load task icon for task \"{id}\"")]
CouldNotLoadTaskIcon { id: String },
#[error("Could not load task asset for task \"{id}\"")]
CouldNotLoadTaskAsset { id: String },
#[error("Task \"{id}\" does not exists")]
MissingTask { id: String },
#[error("Could not load task description for task \"{id}\"")]
CouldNotLoadTaskDescription { id: String },
#[error("Error while reading task description: {0}")]
ErrorWhileReadingDescription(#[from] string::FromUtf8Error),
}

impl error::ResponseError for TaskError {
fn status_code(&self) -> StatusCode {
match self {
TaskError::InvalidTaskId => StatusCode::BAD_REQUEST,
TaskError::MissingTask { .. } => StatusCode::NOT_FOUND,
TaskError::CouldNotLoadTaskIcon { .. } => StatusCode::INTERNAL_SERVER_ERROR,
TaskError::CouldNotLoadTaskAsset { .. }
| TaskError::CouldNotLoadTaskDescription { .. }
| TaskError::ErrorWhileReadingDescription(_) => StatusCode::INTERNAL_SERVER_ERROR,
}
}

Expand Down
8 changes: 4 additions & 4 deletions backend/src/utils/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ impl TaskManager {
pub async fn load_asset(&self, id: &str, path: &str) -> Result<Vec<u8>, Error> {
self.get_task(id)?;

let icon_path = Config::get().tasks_base_path.join(id).join(path);
let asset_path = Config::get().tasks_base_path.join(id).join(path);

if !icon_path.exists() || !icon_path.is_file() {
return Err(TaskError::CouldNotLoadTaskIcon { id: id.to_string() }.into());
if !asset_path.exists() || !asset_path.is_file() {
return Err(TaskError::CouldNotLoadTaskAsset { id: id.to_string() }.into());
}

Ok(fs::read(icon_path).await?)
Ok(fs::read(asset_path).await?)
}
}
1 change: 1 addition & 0 deletions frontend/app/assets/css/main.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@import 'tailwindcss';
@import '@nuxt/ui';
@plugin "@tailwindcss/typography";
@tailwind utilities;

:root {
Expand Down
11 changes: 11 additions & 0 deletions frontend/app/components/MarkdownContent.server.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script setup lang="ts">
const props = defineProps<{
text: string
}>()
</script>

<template>
<div class="prose prose-invert">
<MDC :value="props.text" />
</div>
</template>
41 changes: 41 additions & 0 deletions frontend/app/components/TaskDescription.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<script setup lang="ts">
import { FetchError } from 'ofetch'
const props = defineProps<{
taskId: string | string[] | undefined
}>()
const description = ref('')
try {
const taskId = String(props.taskId)
const address = '/tasks/description/{task_id}'
const { data: response } = await useApi(address, {
path: { task_id: taskId },
key: `task-description-${taskId}`,
})
if (response.value === undefined) {
showError({
statusCode: 404,
message: 'Zadanie nie zostało znalezione',
})
console.error('Task not found')
} else {
description.value = String(response.value)
}
} catch (error) {
console.error(error)
if (!(error instanceof FetchError)) {
throw error
}
showError(error)
}
</script>

<template>
<div class="flex flex-col mx-[10vw] w-[80vw] pt-5">
<MarkdownContent :text="description" />
</div>
</template>
8 changes: 8 additions & 0 deletions frontend/app/pages/tasks/description/[id].vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script setup lang="ts">
const route = useRoute()
const taskId = route.params.id
</script>

<template>
<TaskDescription :task-id="taskId" />
</template>
File renamed without changes.
9 changes: 9 additions & 0 deletions frontend/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@ export default defineNuxtConfig({
'@nuxt/eslint',
'@nuxt/test-utils/module',
'@nuxtjs/seo',
'@nuxtjs/mdc',
'@nuxt/scripts',
'@formkit/auto-animate/nuxt',
'nuxt-open-fetch',
'@nuxt/image',
],

routeRules: {
'/tasks/description/**': { swr: true },
},

experimental: {
componentIslands: true,
},

site: {
url: baseUrl,
name: 'Hack4Krak CTF',
Expand Down
2 changes: 1 addition & 1 deletion frontend/openapi/api/openapi.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@nuxt/image": "1.9.0",
"@nuxt/scripts": "0.9.5",
"@nuxt/ui": "3.0.0-alpha.12",
"@nuxtjs/mdc": "0.13.4",
"@nuxtjs/seo": "2.1.1",
"nuxt": "^3.15.4",
"nuxt-open-fetch": "^0.9.5",
Expand All @@ -28,6 +29,7 @@
"@nuxt/devtools": "latest",
"@nuxt/eslint": "^1.0.1",
"@nuxt/test-utils": "3.15.4",
"@tailwindcss/typography": "^0.5.16",
"@vue/test-utils": "^2.4.6",
"eslint": "^9.19.0",
"eslint-plugin-format": "^1.0.1",
Expand Down
Loading

0 comments on commit 4ccca3e

Please sign in to comment.