mirror of
https://github.com/danbulant/Portfolio
synced 2026-06-18 14:01:04 +00:00
Merge remote-tracking branch 'origin' into admin_create_more_data
This commit is contained in:
commit
c5ac32d1fd
15 changed files with 353 additions and 61 deletions
|
|
@ -200,6 +200,19 @@ pub fn create_identity() -> (String, String) {
|
|||
)
|
||||
}
|
||||
|
||||
pub async fn encrypt_buffer_with_recipients(
|
||||
input_buffer: &[u8],
|
||||
recipients: &Vec<String>,
|
||||
) -> Result<Vec<u8>, ServiceError> {
|
||||
let mut output_buffer = vec![];
|
||||
age_encrypt_with_recipients(input_buffer,
|
||||
&mut output_buffer,
|
||||
&recipients.iter().map(|s| s.as_str()).collect()
|
||||
).await?;
|
||||
|
||||
Ok(output_buffer)
|
||||
}
|
||||
|
||||
async fn age_encrypt_with_recipients<W: tokio::io::AsyncWrite + Unpin>(
|
||||
input_buffer: &[u8],
|
||||
output_buffer: &mut W,
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ mod tests {
|
|||
|
||||
let encrypted_details: EncryptedApplicationDetails = EncryptedApplicationDetails::new(
|
||||
&APPLICATION_DETAILS.lock().unwrap().clone(),
|
||||
vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||
&vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||
).await.unwrap();
|
||||
|
||||
let candidate = Mutation::update_candidate_opt_details(&db, candidate, encrypted_details.candidate, 1).await.unwrap();
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ mod tests {
|
|||
|
||||
let encrypted_details: EncryptedApplicationDetails = EncryptedApplicationDetails::new(
|
||||
&APPLICATION_DETAILS.lock().unwrap().clone(),
|
||||
vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||
&vec!["age1u889gp407hsz309wn09kxx9anl6uns30m27lfwnctfyq9tq4qpus8tzmq5".to_string()],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ impl From<&parent::Model> for EncryptedParentDetails {
|
|||
impl EncryptedApplicationDetails {
|
||||
pub async fn new(
|
||||
form: &ApplicationDetails,
|
||||
recipients: Vec<String>,
|
||||
recipients: &Vec<String>,
|
||||
) -> Result<EncryptedApplicationDetails, ServiceError> {
|
||||
let candidate = EncryptedCandidateDetails::new(&form.candidate, &recipients).await?;
|
||||
let enc_parents = future::try_join_all(
|
||||
|
|
@ -459,7 +459,7 @@ pub mod tests {
|
|||
async fn test_encrypted_application_details_new() {
|
||||
let encrypted_details = EncryptedApplicationDetails::new(
|
||||
&APPLICATION_DETAILS.lock().unwrap().clone(),
|
||||
vec![PUBLIC_KEY.to_string()],
|
||||
&vec![PUBLIC_KEY.to_string()],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
@ -488,7 +488,7 @@ pub mod tests {
|
|||
async fn test_encrypted_application_details_decrypt() {
|
||||
let encrypted_details = EncryptedApplicationDetails::new(
|
||||
&APPLICATION_DETAILS.lock().unwrap().clone(),
|
||||
vec![PUBLIC_KEY.to_string()],
|
||||
&vec![PUBLIC_KEY.to_string()],
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use sea_orm::{DbConn, prelude::Uuid, IntoActiveModel};
|
|||
|
||||
use crate::{error::ServiceError, Query, utils::db::get_recipients, models::candidate_details::EncryptedApplicationDetails, models::{candidate::{ApplicationDetails, CreateCandidateResponse}, candidate_details::{EncryptedString, EncryptedCandidateDetails}, auth::AuthenticableTrait, application::ApplicationResponse}, Mutation, crypto::{hash_password, self}};
|
||||
|
||||
use super::{parent_service::ParentService, candidate_service::CandidateService, session_service::SessionService, portfolio_service::PortfolioService};
|
||||
use super::{parent_service::ParentService, candidate_service::CandidateService, session_service::SessionService, portfolio_service::{PortfolioService, SubmissionProgress}};
|
||||
|
||||
const FIELD_OF_STUDY_PREFIXES: [&str; 3] = ["101", "102", "103"];
|
||||
|
||||
|
|
@ -281,8 +281,6 @@ impl ApplicationService {
|
|||
).await
|
||||
})
|
||||
).await
|
||||
|
||||
|
||||
}
|
||||
|
||||
async fn decrypt_private_key(
|
||||
|
|
@ -307,7 +305,6 @@ impl ApplicationService {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO
|
||||
pub async fn reset_password(
|
||||
admin_private_key: String,
|
||||
db: &DbConn,
|
||||
|
|
@ -316,7 +313,6 @@ impl ApplicationService {
|
|||
let application = Query::find_application_by_id(db, id).await?
|
||||
.ok_or(ServiceError::CandidateNotFound)?;
|
||||
let candidate = ApplicationService::find_related_candidate(db, &application).await?;
|
||||
let parents = Query::find_candidate_parents(db, &candidate).await?;
|
||||
|
||||
let new_password_plain = crypto::random_12_char_string();
|
||||
let new_password_hash = crypto::hash_password(new_password_plain.clone()).await?;
|
||||
|
|
@ -335,6 +331,7 @@ impl ApplicationService {
|
|||
encrypted_priv_key
|
||||
).await?;
|
||||
|
||||
|
||||
// user might no have filled his details yet, but personal id number is filled from beginning
|
||||
let personal_id_number = EncryptedString::from(application.personal_id_number.clone())
|
||||
.decrypt(&admin_private_key)
|
||||
|
|
@ -346,25 +343,19 @@ impl ApplicationService {
|
|||
recipients.append(&mut admin_public_keys);
|
||||
recipients.append(&mut applications.iter().map(|a| a.public_key.to_owned()).collect());
|
||||
|
||||
let dec_details = EncryptedApplicationDetails::from((&candidate, &parents))
|
||||
.decrypt(admin_private_key).await?;
|
||||
|
||||
let enc_details = EncryptedApplicationDetails::new(&dec_details, recipients).await?;
|
||||
|
||||
let candidate = Mutation::update_personal_id(db,
|
||||
candidate,
|
||||
&enc_details.candidate.personal_id_number.to_owned()
|
||||
.ok_or(ServiceError::CandidateDetailsNotSet)?.to_string()
|
||||
let candidate = Self::update_all_application_details(db,
|
||||
application.id,
|
||||
candidate,
|
||||
&recipients,
|
||||
&admin_private_key
|
||||
).await?;
|
||||
|
||||
Mutation::update_candidate_opt_details(db,
|
||||
candidate,
|
||||
enc_details.candidate,
|
||||
application.id
|
||||
).await?;
|
||||
|
||||
for i in 0..enc_details.parents.len() {
|
||||
Mutation::add_parent_details(db, parents[i].clone(), enc_details.parents[i].clone()).await?;
|
||||
if PortfolioService::get_submission_progress(candidate.id).await? == SubmissionProgress::Submitted {
|
||||
PortfolioService::reencrypt_portfolio(
|
||||
candidate.id,
|
||||
admin_private_key,
|
||||
&recipients
|
||||
).await?;
|
||||
}
|
||||
|
||||
Ok(
|
||||
|
|
@ -379,6 +370,37 @@ impl ApplicationService {
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
async fn update_all_application_details(db: &DbConn,
|
||||
application_id: i32,
|
||||
candidate: candidate::Model,
|
||||
recipients: &Vec<String>,
|
||||
admin_private_key: &String
|
||||
) -> Result<candidate::Model, ServiceError> {
|
||||
let parents = Query::find_candidate_parents(db, &candidate).await?;
|
||||
let dec_details = EncryptedApplicationDetails::from((&candidate, &parents))
|
||||
.decrypt(admin_private_key.to_owned()).await?;
|
||||
|
||||
let enc_details = EncryptedApplicationDetails::new(&dec_details, recipients).await?;
|
||||
|
||||
let candidate = Mutation::update_personal_id(db,
|
||||
candidate,
|
||||
&enc_details.candidate.personal_id_number.to_owned()
|
||||
.ok_or(ServiceError::CandidateDetailsNotSet)?.to_string()
|
||||
).await?;
|
||||
|
||||
let candidate = Mutation::update_candidate_opt_details(db,
|
||||
candidate,
|
||||
enc_details.candidate,
|
||||
application_id
|
||||
).await?;
|
||||
|
||||
for i in 0..enc_details.parents.len() {
|
||||
Mutation::add_parent_details(db, parents[i].clone(), enc_details.parents[i].clone()).await?;
|
||||
}
|
||||
|
||||
Ok(candidate)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
|
|
@ -477,7 +499,6 @@ mod application_tests {
|
|||
assert!(!ApplicationService::is_application_id_valid(101));
|
||||
}
|
||||
|
||||
// TODO
|
||||
#[tokio::test]
|
||||
async fn test_password_reset() {
|
||||
let db = get_memory_sqlite_connection().await;
|
||||
|
|
|
|||
|
|
@ -368,15 +368,46 @@ impl PortfolioService {
|
|||
/// Returns decrypted portfolio zip as Vec of bytes
|
||||
pub async fn get_portfolio(candidate_id: i32, private_key: String) -> Result<Vec<u8>, ServiceError> {
|
||||
info!("PORTFOLIO {} DECRYPT STARTED", candidate_id);
|
||||
let path = Self::get_file_store_path().join(&candidate_id.to_string()).to_path_buf();
|
||||
|
||||
let path = path.join(FileType::Age.as_str());
|
||||
let path = Self::get_file_store_path()
|
||||
.join(&candidate_id.to_string())
|
||||
.join(FileType::Age.as_str())
|
||||
.to_path_buf();
|
||||
|
||||
let buffer = crypto::decrypt_file_with_private_key_as_buffer(path, &private_key).await?;
|
||||
|
||||
info!("PORTFOLIO {} DECRYPT FINISHED", candidate_id);
|
||||
Ok(buffer)
|
||||
}
|
||||
|
||||
pub async fn reencrypt_portfolio(candidate_id: i32,
|
||||
private_key: String,
|
||||
recipients: &Vec<String>
|
||||
) -> Result<(), ServiceError> {
|
||||
info!("PORTFOLIO {} REENCRYPT STARTED", candidate_id);
|
||||
let path = Self::get_file_store_path()
|
||||
.join(&candidate_id.to_string())
|
||||
.join(FileType::Age.as_str())
|
||||
.to_path_buf();
|
||||
|
||||
let plain_portfolio = crypto::decrypt_file_with_private_key_as_buffer(
|
||||
path.to_owned(),
|
||||
&private_key
|
||||
).await?;
|
||||
|
||||
|
||||
let enc_portfolio= crypto::encrypt_buffer_with_recipients(
|
||||
&plain_portfolio,
|
||||
recipients
|
||||
).await?;
|
||||
|
||||
tokio::fs::remove_file(path.to_owned()).await?;
|
||||
|
||||
tokio::fs::write(path, enc_portfolio).await?;
|
||||
|
||||
info!("PORTFOLIO {} REENCRYPT FINISHED", candidate_id);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import { fetchSubmProgress } from '$lib/stores/portfolio';
|
||||
import { apiDeleteCoverLetter, apiUploadCoverLetter } from '$lib/@api/candidate';
|
||||
import DashboardUploadCard from './DashboardUploadCard.svelte';
|
||||
|
|
@ -28,9 +30,9 @@
|
|||
{error}
|
||||
on:filedrop={(e) => onFileDrop(e.detail)}
|
||||
on:delete={onDelete}
|
||||
title="Motivační dopis"
|
||||
title={$LL.components.dashboard.coverLetterUploadCard.title()}
|
||||
filetype="PDF"
|
||||
filesize={10}
|
||||
fileType={1}
|
||||
placeholder="svůj motivanční dopis"
|
||||
placeholder={$LL.components.dashboard.coverLetterUploadCard.placeholder()}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import debounce from 'just-debounce-it';
|
||||
|
||||
import {
|
||||
|
|
@ -7,7 +9,6 @@
|
|||
apiLogout,
|
||||
apiSubmitPortfolio
|
||||
} from '$lib/@api/candidate';
|
||||
import Circles from '$lib/components/icons/Circles.svelte';
|
||||
import { fetchSubmProgress, type Status } from '$lib/stores/portfolio';
|
||||
import StatusNotificationBig from './StatusNotificationBig.svelte';
|
||||
import InfoButton from './InfoButton.svelte';
|
||||
|
|
@ -150,39 +151,39 @@
|
|||
class="mt-4 flex flex-col justify-between leading-10"
|
||||
>
|
||||
<span
|
||||
>Ev. č. přihlášky ({getField($baseCandidateData.applications[0])}):
|
||||
>{$LL.input.evidenceNumber()} ({getField($baseCandidateData.applications[0])}):
|
||||
<span class="font-bold">{$baseCandidateData.applications[0]}</span></span
|
||||
>
|
||||
{#if $baseCandidateData.applications.length > 1}
|
||||
<span
|
||||
>Ev. č. přihlášky ({getField($baseCandidateData.applications[1])}):
|
||||
>{$LL.input.evidenceNumber()} ({getField($baseCandidateData.applications[1])}):
|
||||
<span class="font-bold">{$baseCandidateData.applications[1]}</span></span
|
||||
>
|
||||
{/if}
|
||||
<span>Adresa: <span class="font-bold">{$candidateData.candidate.address}</span></span>
|
||||
<span>{$LL.input.address()}: <span class="font-bold">{$candidateData.candidate.address}</span></span>
|
||||
<span
|
||||
>Datum narození: <span class="font-bold">{$candidateData.candidate.birthdate}</span
|
||||
>{$LL.input.birthDate()}: <span class="font-bold">{$candidateData.candidate.birthdate}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Místo narození: <span class="font-bold">{$candidateData.candidate.birthplace}</span
|
||||
>{$LL.input.birthPlace()}: <span class="font-bold">{$candidateData.candidate.birthplace}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Rodné číslo: <span class="font-bold"
|
||||
>{$LL.input.personalIdentificationNumber()}: <span class="font-bold"
|
||||
>{$candidateData.candidate.personalIdNumber}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>IČO/Název školy: <span class="font-bold">{$candidateData.candidate.schoolName}</span
|
||||
>{$LL.input.schoolIzo()}: <span class="font-bold">{$candidateData.candidate.schoolName}</span
|
||||
></span
|
||||
>
|
||||
<span
|
||||
>Číslo zdravotní pojišťovny: <span class="font-bold"
|
||||
>{$LL.input.insuranceNumber()}: <span class="font-bold"
|
||||
>{$candidateData.candidate.healthInsurance}</span
|
||||
></span
|
||||
>
|
||||
<span>Telefon: <span class="font-bold">{$candidateData.candidate.telephone}</span></span
|
||||
<span>{$LL.input.telephone()}: <span class="font-bold">{$candidateData.candidate.telephone}</span></span
|
||||
>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -200,8 +201,8 @@
|
|||
<span class="text-sspsBlue text-xl font-bold"
|
||||
>{parent.name + ' ' + parent.surname}</span
|
||||
>
|
||||
<span>Email: <span class="font-bold">{parent.email}</span></span>
|
||||
<span>Telefon: <span class="font-bold">{parent.telephone}</span></span>
|
||||
<span>{$LL.input.email()}: <span class="font-bold">{parent.email}</span></span>
|
||||
<span>{$LL.input.telephone()}: <span class="font-bold">{parent.telephone}</span></span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import FileType from './FileType.svelte';
|
||||
import debounce from 'just-debounce-it';
|
||||
import { filedrop, type FileDropOptions, type Files } from 'filedrop-svelte';
|
||||
|
|
@ -103,7 +105,7 @@
|
|||
{#if status === 'uploaded'}
|
||||
<button
|
||||
class="mr-3 rounded-xl bg-[#ef8b46] py-0.5 px-2 text-white shadow-md transition-all duration-300 hover:bg-orange-400"
|
||||
on:click={debounce(() => dispatch('delete'), 150)}>Smazat</button
|
||||
on:click={debounce(() => dispatch('delete'), 150)}>{$LL.components.dashboard.dashboardUploadCard.delete()}</button
|
||||
>
|
||||
{/if}
|
||||
<StatusNotificationDot {status} />
|
||||
|
|
@ -131,9 +133,9 @@
|
|||
>
|
||||
<div class="hidden items-center xl:block">
|
||||
{#if bytesTotal === 0 || Math.round(progress * 100) === 100}
|
||||
<h2 class="text-xl font-bold">{status === 'submitted' ? 'Odesláno' : 'Nahráno'}</h2>
|
||||
<h2 class="text-xl font-bold">{status === 'submitted' ? $LL.components.dashboard.dashboardUploadCard.sent() : $LL.components.dashboard.dashboardUploadCard.uploaded()}</h2>
|
||||
{:else}
|
||||
<h2 class="text-xl">Nahráno {((bytesTotal / 1_000_000) * progress).toFixed(1)} MB</h2>
|
||||
<h2 class="text-xl">{$LL.components.dashboard.dashboardUploadCard.uploaded()} {((bytesTotal / 1_000_000) * progress).toFixed(1)} MB</h2>
|
||||
<h2 class="self-center text-xl">z {(bytesTotal / 1_000_000).toFixed(1)} MB</h2>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
@ -168,8 +170,14 @@
|
|||
{#if error}
|
||||
<span class="font-semibold text-red-600">{error}</span>
|
||||
{:else}
|
||||
<span class="text-[#406280]">Sem přetáhněte,</span>
|
||||
<span class="text-sspsGray">nebo nahrajte {placeholder}</span>
|
||||
<span class="text-[#406280]"
|
||||
>{$LL.components.dashboard.dashboardUploadCard.dropHere()}</span
|
||||
>
|
||||
<span class="text-sspsGray"
|
||||
>{$LL.components.dashboard.dashboardUploadCard.orUpload({
|
||||
placeholder
|
||||
})}</span
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import type { ApiError } from '$lib/@api';
|
||||
import { fetchSubmProgress } from '$lib/stores/portfolio';
|
||||
import { apiDeletePortfolioLetter, apiUploadPortfolioLetter } from '../../@api/candidate';
|
||||
|
|
@ -28,9 +30,9 @@
|
|||
{error}
|
||||
on:filedrop={(e) => onFileDrop(e.detail)}
|
||||
on:delete={onDelete}
|
||||
title="Portfolio"
|
||||
title={$LL.components.dashboard.portfolioLetterUploadCard.title()}
|
||||
filetype="PDF"
|
||||
filesize={10}
|
||||
fileType={2}
|
||||
placeholder="svoje portfolio"
|
||||
placeholder={$LL.components.dashboard.portfolioLetterUploadCard.placeholder()}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import { fetchSubmProgress } from '$lib/stores/portfolio';
|
||||
import { apiDeletePortfolioZip, apiUploadPortfolioZip } from '$lib/@api/candidate';
|
||||
import DashboardUploadCard from './DashboardUploadCard.svelte';
|
||||
|
|
@ -28,9 +30,9 @@
|
|||
{error}
|
||||
on:filedrop={(e) => onFileDrop(e.detail)}
|
||||
on:delete={onDelete}
|
||||
title="Další data"
|
||||
title={$LL.components.dashboard.portfolioZipUploadCard.title()}
|
||||
filetype="ZIP"
|
||||
filesize={100}
|
||||
fileType={3}
|
||||
placeholder="vaše další soubory ve formátu ZIP"
|
||||
placeholder={$LL.components.dashboard.portfolioZipUploadCard.placeholder()}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import LL from '$i18n/i18n-svelte';
|
||||
|
||||
import type { Status } from '$lib/stores/portfolio';
|
||||
|
||||
export let loading: boolean = false;
|
||||
|
|
@ -8,16 +10,16 @@
|
|||
let description: string;
|
||||
$: switch (status) {
|
||||
case 'submitted':
|
||||
title = 'Soubory odevzdány!';
|
||||
description = 'Vaše soubory smažete kliknutím zde';
|
||||
title = $LL.components.dashboard.statusNotificationBig.submitted.title();
|
||||
description = $LL.components.dashboard.statusNotificationBig.submitted.description();
|
||||
break;
|
||||
case 'uploaded':
|
||||
title = 'Soubory nebyly odevzdány!';
|
||||
description = 'Odevzdejte soubory kliknutím zde';
|
||||
title = $LL.components.dashboard.statusNotificationBig.uploaded.title();
|
||||
description = $LL.components.dashboard.statusNotificationBig.uploaded.description();
|
||||
break;
|
||||
case 'missing':
|
||||
title = 'Soubory nebyly nahrány!';
|
||||
description = 'Nahrajte včechny soubory prosím';
|
||||
title = $LL.components.dashboard.statusNotificationBig.missing.title();
|
||||
description = $LL.components.dashboard.statusNotificationBig.missing.description();
|
||||
break;
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -423,6 +423,7 @@
|
|||
<form on:submit={handleSubmit} id="triggerForm" class="invisible hidden" />
|
||||
{#if pageIndex === 0}
|
||||
<form on:submit={handleSubmit}>
|
||||
<h1 class="title mt-8">{$LL.candidate.register.first.title()}</h1>
|
||||
<h1 class="title mt-8">{$LL.candidate.register.first.title()}</h1>
|
||||
<p class="description mt-8 block text-center">
|
||||
{$LL.candidate.register.first.description()}
|
||||
|
|
@ -467,6 +468,7 @@
|
|||
<h1 class="title mt-8">{pageTexts[1]}</h1>
|
||||
<p class="description mt-8 block text-center">
|
||||
{$LL.candidate.register.third.description()}
|
||||
{$LL.candidate.register.third.description()}
|
||||
</p>
|
||||
<div class="w-full">
|
||||
<div class="flex flex-col">
|
||||
|
|
|
|||
|
|
@ -69,6 +69,41 @@ const cs: BaseTranslation = {
|
|||
}
|
||||
},
|
||||
components: {
|
||||
dashboard: {
|
||||
coverLetterUploadCard: {
|
||||
title: 'Motivační dopis',
|
||||
placeholder: 'svůj motivanční dopis'
|
||||
},
|
||||
portfolioLetterUploadCard: {
|
||||
title: 'Portfolio',
|
||||
placeholder: 'své portfolio'
|
||||
},
|
||||
portfolioZipUploadCard: {
|
||||
title: 'Další data',
|
||||
placeholder: 'vaše další soubory ve formátu ZIP'
|
||||
},
|
||||
dashboardUploadCard: {
|
||||
dropHere: 'Sem přetáhněte,',
|
||||
orUpload: 'Nebo nahrajte {placeholder:string}',
|
||||
uploaded: 'Nahráno',
|
||||
sent: 'Odesláno',
|
||||
delete: 'Smazat'
|
||||
},
|
||||
statusNotificationBig: {
|
||||
submitted: {
|
||||
title: 'Soubory odevzdány!',
|
||||
description: 'Vaše soubory smažete kliknutím zde'
|
||||
},
|
||||
uploaded: {
|
||||
title: 'Soubory nebyly odevzdány!',
|
||||
description: 'Odevzdejte soubory kliknutím zde'
|
||||
},
|
||||
missing: {
|
||||
title: 'Soubory nebyly nahrány!',
|
||||
description: 'Nahrajte včechny soubory prosím',
|
||||
}
|
||||
}
|
||||
},
|
||||
checkbox: {
|
||||
accountLinkCheckBox: {
|
||||
ok: 'Vše je v pořádku',
|
||||
|
|
@ -117,7 +152,7 @@ const cs: BaseTranslation = {
|
|||
adminId: 'Admin Id',
|
||||
password: 'Heslo',
|
||||
submit: 'Odeslat',
|
||||
continue: "Pokračovat",
|
||||
continue: 'Pokračovat',
|
||||
parent: {
|
||||
nameSurname: 'Jméno a příjmení zákonného zástupce',
|
||||
email: 'E-mail zákonného zástupce',
|
||||
|
|
|
|||
|
|
@ -150,6 +150,93 @@ type RootTranslation = {
|
|||
}
|
||||
}
|
||||
components: {
|
||||
dashboard: {
|
||||
coverLetterUploadCard: {
|
||||
/**
|
||||
* Motivační dopis
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* svůj motivanční dopis
|
||||
*/
|
||||
placeholder: string
|
||||
}
|
||||
portfolioLetterUploadCard: {
|
||||
/**
|
||||
* Portfolio
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* své portfolio
|
||||
*/
|
||||
placeholder: string
|
||||
}
|
||||
portfolioZipUploadCard: {
|
||||
/**
|
||||
* Další data
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* vaše další soubory ve formátu ZIP
|
||||
*/
|
||||
placeholder: string
|
||||
}
|
||||
dashboardUploadCard: {
|
||||
/**
|
||||
* Sem přetáhněte,
|
||||
*/
|
||||
dropHere: string
|
||||
/**
|
||||
* Nebo nahrajte {placeholder}
|
||||
* @param {string} placeholder
|
||||
*/
|
||||
orUpload: RequiredParams<'placeholder'>
|
||||
/**
|
||||
* Nahráno
|
||||
*/
|
||||
uploaded: string
|
||||
/**
|
||||
* Odesláno
|
||||
*/
|
||||
sent: string
|
||||
/**
|
||||
* Smazat
|
||||
*/
|
||||
'delete': string
|
||||
}
|
||||
statusNotificationBig: {
|
||||
submitted: {
|
||||
/**
|
||||
* Soubory odevzdány!
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* Vaše soubory smažete kliknutím zde
|
||||
*/
|
||||
description: string
|
||||
}
|
||||
uploaded: {
|
||||
/**
|
||||
* Soubory nebyly odevzdány!
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* Odevzdejte soubory kliknutím zde
|
||||
*/
|
||||
description: string
|
||||
}
|
||||
missing: {
|
||||
/**
|
||||
* Soubory nebyly nahrány!
|
||||
*/
|
||||
title: string
|
||||
/**
|
||||
* Nahrajte včechny soubory prosím
|
||||
*/
|
||||
description: string
|
||||
}
|
||||
}
|
||||
}
|
||||
checkbox: {
|
||||
accountLinkCheckBox: {
|
||||
/**
|
||||
|
|
@ -461,6 +548,92 @@ export type TranslationFunctions = {
|
|||
}
|
||||
}
|
||||
components: {
|
||||
dashboard: {
|
||||
coverLetterUploadCard: {
|
||||
/**
|
||||
* Motivační dopis
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* svůj motivanční dopis
|
||||
*/
|
||||
placeholder: () => LocalizedString
|
||||
}
|
||||
portfolioLetterUploadCard: {
|
||||
/**
|
||||
* Portfolio
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* své portfolio
|
||||
*/
|
||||
placeholder: () => LocalizedString
|
||||
}
|
||||
portfolioZipUploadCard: {
|
||||
/**
|
||||
* Další data
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* vaše další soubory ve formátu ZIP
|
||||
*/
|
||||
placeholder: () => LocalizedString
|
||||
}
|
||||
dashboardUploadCard: {
|
||||
/**
|
||||
* Sem přetáhněte,
|
||||
*/
|
||||
dropHere: () => LocalizedString
|
||||
/**
|
||||
* Nebo nahrajte {placeholder}
|
||||
*/
|
||||
orUpload: (arg: { placeholder: string }) => LocalizedString
|
||||
/**
|
||||
* Nahráno
|
||||
*/
|
||||
uploaded: () => LocalizedString
|
||||
/**
|
||||
* Odesláno
|
||||
*/
|
||||
sent: () => LocalizedString
|
||||
/**
|
||||
* Smazat
|
||||
*/
|
||||
'delete': () => LocalizedString
|
||||
}
|
||||
statusNotificationBig: {
|
||||
submitted: {
|
||||
/**
|
||||
* Soubory odevzdány!
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* Vaše soubory smažete kliknutím zde
|
||||
*/
|
||||
description: () => LocalizedString
|
||||
}
|
||||
uploaded: {
|
||||
/**
|
||||
* Soubory nebyly odevzdány!
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* Odevzdejte soubory kliknutím zde
|
||||
*/
|
||||
description: () => LocalizedString
|
||||
}
|
||||
missing: {
|
||||
/**
|
||||
* Soubory nebyly nahrány!
|
||||
*/
|
||||
title: () => LocalizedString
|
||||
/**
|
||||
* Nahrajte včechny soubory prosím
|
||||
*/
|
||||
description: () => LocalizedString
|
||||
}
|
||||
}
|
||||
}
|
||||
checkbox: {
|
||||
accountLinkCheckBox: {
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue