Skip to content
Snippets Groups Projects
Commit 037848b8 authored by Torsten Oppermann's avatar Torsten Oppermann
Browse files

Merge branch 'master' of gitlab.sgalinski.de:typo3/sg_jobs

parents 946ebc25 407cd7e0
No related branches found
No related tags found
No related merge requests found
...@@ -30,13 +30,13 @@ use SGalinski\SgJobs\Domain\Model\JobApplication; ...@@ -30,13 +30,13 @@ use SGalinski\SgJobs\Domain\Model\JobApplication;
use SGalinski\SgJobs\Service\FrontendFilterService; use SGalinski\SgJobs\Service\FrontendFilterService;
use SGalinski\SgMail\Service\MailTemplateService; use SGalinski\SgMail\Service\MailTemplateService;
use TYPO3\CMS\Core\Log\LogLevel; use TYPO3\CMS\Core\Log\LogLevel;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Resource\DuplicationBehavior; use TYPO3\CMS\Core\Resource\DuplicationBehavior;
use TYPO3\CMS\Core\Resource\ResourceFactory; use TYPO3\CMS\Core\Resource\ResourceFactory;
use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility; use TYPO3\CMS\Core\Utility\File\ExtendedFileUtility;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Object\ObjectManager;
/** /**
* The joblist plugin controller * The joblist plugin controller
...@@ -103,6 +103,7 @@ class JoblistController extends ActionController { ...@@ -103,6 +103,7 @@ class JoblistController extends ActionController {
* *
* @param JobApplication $applyData * @param JobApplication $applyData
* @param string $error * @param string $error
* @throws \InvalidArgumentException
*/ */
public function applyFormAction(JobApplication $applyData = NULL, $error = NULL) { public function applyFormAction(JobApplication $applyData = NULL, $error = NULL) {
if ($this->request->getOriginalRequest()) { if ($this->request->getOriginalRequest()) {
...@@ -110,8 +111,8 @@ class JoblistController extends ActionController { ...@@ -110,8 +111,8 @@ class JoblistController extends ActionController {
$this->view->assign('uploadedFiles', $uploadedFiles); $this->view->assign('uploadedFiles', $uploadedFiles);
} }
if ($error !== NULL) { if ($error !== NULL && $error !== '') {
$logger = GeneralUtility::makeInstance('TYPO3\CMS\Core\Log\LogManager')->getLogger(__CLASS__); $logger = $this->objectManager->get(LogManager::class)->getLogger(__CLASS__);
$logger->log(LogLevel::ALERT, $error); $logger->log(LogLevel::ALERT, $error);
$this->view->assign('error', 1); $this->view->assign('error', 1);
} }
...@@ -129,6 +130,43 @@ class JoblistController extends ActionController { ...@@ -129,6 +130,43 @@ class JoblistController extends ActionController {
$this->view->assign('applyData', $applyData); $this->view->assign('applyData', $applyData);
} }
/**
* Pre-apply action setup, configures model-property mapping and handles file upload
*
* @return void
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
* @throws \InvalidArgumentException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
* @throws \Exception
*/
protected function initializeApplyAction() {
$propertyMappingConfiguration = $this->arguments->getArgument('applyData')->getPropertyMappingConfiguration();
$propertyMappingConfiguration->forProperty('coverLetter')->allowAllProperties();
$propertyMappingConfiguration->forProperty('cv')->allowAllProperties();
$propertyMappingConfiguration->forProperty('certificates')->allowAllProperties();
$propertyMappingConfiguration->allowAllProperties();
if ($this->request->hasArgument('folderName')) {
$uniqueFolderName = $this->request->getArgument('folderName');
} else {
$uniqueFolderName = uniqid('sgjobs-', TRUE);
}
try {
$this->handleFileUpload('coverLetter', $uniqueFolderName);
$this->handleFileUpload('cv', $uniqueFolderName);
$this->handleFileUpload('certificates', $uniqueFolderName);
} catch (\Exception $exception) {
$this->redirect('applyForm', NULL, NULL, ['error' => $exception->getMessage()]);
}
$uploadedFiles = $this->getExistingApplicationFiles($uniqueFolderName);
$this->request->setArgument('uploadedFiles', $uploadedFiles);
$this->request->setArgument('folderName', $uniqueFolderName);
}
/** /**
* Saves the application send by the applyFormAction * Saves the application send by the applyFormAction
* *
...@@ -139,6 +177,7 @@ class JoblistController extends ActionController { ...@@ -139,6 +177,7 @@ class JoblistController extends ActionController {
*/ */
public function applyAction(JobApplication $applyData) { public function applyAction(JobApplication $applyData) {
try { try {
$applyData->setPid($GLOBALS['TSFE']->id);
$folderName = $this->request->getArgument('folderName'); $folderName = $this->request->getArgument('folderName');
$this->submitApplicationFiles($applyData, $folderName); $this->submitApplicationFiles($applyData, $folderName);
...@@ -149,7 +188,6 @@ class JoblistController extends ActionController { ...@@ -149,7 +188,6 @@ class JoblistController extends ActionController {
); );
$mailService->setIgnoreMailQueue(TRUE); $mailService->setIgnoreMailQueue(TRUE);
$mailService->setToAddresses($this->settings['applicationEmail']); $mailService->setToAddresses($this->settings['applicationEmail']);
$mailService->sendEmail(); $mailService->sendEmail();
// redirect to the given page id from the flexform // redirect to the given page id from the flexform
...@@ -163,46 +201,11 @@ class JoblistController extends ActionController { ...@@ -163,46 +201,11 @@ class JoblistController extends ActionController {
->setTargetPageUid($redirectPageId) ->setTargetPageUid($redirectPageId)
->build(); ->build();
$this->redirectToUri($uri); $this->redirectToUri($uri);
} catch (\Exception $exception) {
// possible errors, because of wrong mails (maybe log that somewhere? Does this makes sense?)
$this->redirect('applyForm', NULL, NULL, ['error' => $exception->getMessage()]);
}
}
/**
* Pre-apply action setup, configures model-property mapping and handles file upload
*
* @return void
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\UnsupportedRequestTypeException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\StopActionException
* @throws \InvalidArgumentException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentNameException
* @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException
* @throws \Exception
*/
protected function initializeApplyAction() {
if ($this->request->hasArgument('folderName')) {
$uniqueFolderName = $this->request->getArgument('folderName');
} else {
$uniqueFolderName = uniqid('sgjobs-', TRUE);
}
try {
$this->handleFileUpload('coverLetter', $uniqueFolderName);
$this->handleFileUpload('cv', $uniqueFolderName);
$this->handleFileUpload('certificates', $uniqueFolderName);
} catch (\Exception $exception) { } catch (\Exception $exception) {
// possible errors, because of wrong mails // possible errors, because of wrong mails (maybe log that somewhere? Does this makes sense?)
$this->redirect('applyForm', NULL, NULL, ['error' => $exception->getMessage()]); $this->redirect('applyForm', NULL, NULL, ['error' => $exception->getMessage()]);
} }
$propertyMappingConfiguration = $this->arguments->getArgument('applyData')->getPropertyMappingConfiguration();
$propertyMappingConfiguration->forProperty('coverLetter')->allowAllProperties();
$propertyMappingConfiguration->forProperty('cv')->allowAllProperties();
$propertyMappingConfiguration->forProperty('certificates')->allowAllProperties();
$uploadedFiles = $this->getExistingApplicationFiles($uniqueFolderName);
$this->request->setArgument('uploadedFiles', $uploadedFiles);
$this->request->setArgument('folderName', $uniqueFolderName);
} }
/** /**
...@@ -258,8 +261,7 @@ class JoblistController extends ActionController { ...@@ -258,8 +261,7 @@ class JoblistController extends ActionController {
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
private function getExistingFiles($folder): array { private function getExistingFiles($folder): array {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class); $resourceFactory = $this->objectManager->get(ResourceFactory::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
$storage = $resourceFactory->getStorageObject(1); $storage = $resourceFactory->getStorageObject(1);
$folderObject = $storage->getFolder('/Extension/' . $folder); $folderObject = $storage->getFolder('/Extension/' . $folder);
...@@ -298,8 +300,7 @@ class JoblistController extends ActionController { ...@@ -298,8 +300,7 @@ class JoblistController extends ActionController {
* @throws \InvalidArgumentException * @throws \InvalidArgumentException
*/ */
private function submitApplicationFiles(JobApplication $applicationData, $folderName) { private function submitApplicationFiles(JobApplication $applicationData, $folderName) {
$objectManager = GeneralUtility::makeInstance(ObjectManager::class); $resourceFactory = $this->objectManager->get(ResourceFactory::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
$storage = $resourceFactory->getStorageObject(1); $storage = $resourceFactory->getStorageObject(1);
$newName = date('Ymd-His') . '_' . $applicationData->getFirstName(); $newName = date('Ymd-His') . '_' . $applicationData->getFirstName();
...@@ -426,8 +427,7 @@ class JoblistController extends ActionController { ...@@ -426,8 +427,7 @@ class JoblistController extends ActionController {
$data = []; $data = [];
$namespace = key($_FILES); $namespace = key($_FILES);
$objectManager = GeneralUtility::makeInstance(ObjectManager::class); $resourceFactory = $this->objectManager->get(ResourceFactory::class);
$resourceFactory = $objectManager->get(ResourceFactory::class);
$storage = $resourceFactory->getStorageObject(1); $storage = $resourceFactory->getStorageObject(1);
if (!$storage->hasFolder('/Extension/temp/' . $folderName . '/' . $fieldName)) { if (!$storage->hasFolder('/Extension/temp/' . $folderName . '/' . $fieldName)) {
$storage->createFolder('/Extension/temp/' . $folderName . '/' . $fieldName); $storage->createFolder('/Extension/temp/' . $folderName . '/' . $fieldName);
...@@ -438,9 +438,7 @@ class JoblistController extends ActionController { ...@@ -438,9 +438,7 @@ class JoblistController extends ActionController {
// Register every upload field from the form: // Register every upload field from the form:
$this->registerUploadField($data, $namespace, $fieldName, $targetFalDirectory); $this->registerUploadField($data, $namespace, $fieldName, $targetFalDirectory);
// Initializing: $fileProcessor = $this->objectManager->get(ExtendedFileUtility::class);
/** @var \TYPO3\CMS\Core\Utility\File\ExtendedFileUtility $fileProcessor */
$fileProcessor = GeneralUtility::makeInstance(ExtendedFileUtility::class);
$fileProcessor->setActionPermissions(['addFile' => TRUE]); $fileProcessor->setActionPermissions(['addFile' => TRUE]);
$fileProcessor->setFileExtensionPermissions($this->settings['allowedFileExtensions'], ''); $fileProcessor->setFileExtensionPermissions($this->settings['allowedFileExtensions'], '');
......
...@@ -7,192 +7,232 @@ ...@@ -7,192 +7,232 @@
<f:translate key="frontend.apply.error.general" /> <f:translate key="frontend.apply.error.general" />
</div> </div>
</f:if> </f:if>
<f:if condition="{job}"> <f:if condition="{job}">
<f:form.hidden value="{job.jobId}" property="jobId" /> <p>
<label for="apply-title"><f:translate key="frontend.apply.title" /></label> <f:form.hidden value="{job.jobId}" property="jobId" />
<span id="apply-title">{job.title}</span> <label for="apply-title"><f:translate key="frontend.apply.title" /></label>
<br /> <span id="apply-title">{job.title}</span>
</p>
</f:if> </f:if>
<label for="apply-gender"><f:translate key="frontend.apply.gender" /></label>
<f:form.select property="gender" id="apply-gender" class="" options="{Male: '{f:translate(key: \'frontend.apply.gender.male\')}', Female: '{f:translate(key: \'frontend.apply.gender.female\')}'}" /> <p>
<f:form.validationResults for="applyData.gender"> <label for="apply-gender"><f:translate key="frontend.apply.gender" /></label>
<f:for each="{validationResults.errors}" as="error"> <f:form.select property="gender" id="apply-gender" options="{Male: '{f:translate(key: \'frontend.apply.gender.male\')}', Female: '{f:translate(key: \'frontend.apply.gender.female\')}'}" />
<div class="sg-jobs-validation-error"> <f:form.validationResults for="applyData.gender">
{error.message} <f:for each="{validationResults.errors}" as="error">
</div> <div class="sg-jobs-validation-error">
</f:for> {error.message}
</f:form.validationResults> </div>
<br /> </f:for>
<label for="apply-firstName"><f:translate key="frontend.apply.first_name" /></label> </f:form.validationResults>
<f:form.textfield property="firstName" id="apply-firstName" class="" /> </p>
<f:form.validationResults for="applyData.firstName">
<f:for each="{validationResults.errors}" as="error"> <p>
<div class="sg-jobs-validation-error"> <label for="apply-firstName"><f:translate key="frontend.apply.first_name" /></label>
{error.message} <f:form.textfield property="firstName" id="apply-firstName" />
</div> <f:form.validationResults for="applyData.firstName">
</f:for> <f:for each="{validationResults.errors}" as="error">
</f:form.validationResults> <div class="sg-jobs-validation-error">
<br /> {error.message}
<label for="apply-lastName"><f:translate key="frontend.apply.last_name" /></label> </div>
<f:form.textfield property="lastName" id="apply-lastName" class="" /> </f:for>
<f:form.validationResults for="applyData.lastName"> </f:form.validationResults>
<f:for each="{validationResults.errors}" as="error"> </p>
<div class="sg-jobs-validation-error">
{error.message} <p>
</div> <label for="apply-lastName"><f:translate key="frontend.apply.last_name" /></label>
</f:for> <f:form.textfield property="lastName" id="apply-lastName" />
</f:form.validationResults> <f:form.validationResults for="applyData.lastName">
<br /> <f:for each="{validationResults.errors}" as="error">
<label for="apply-street"><f:translate key="frontend.apply.street" /></label> <div class="sg-jobs-validation-error">
<f:form.textfield property="street" id="apply-street" class="" /> {error.message}
<f:form.validationResults for="applyData.street"> </div>
<f:for each="{validationResults.errors}" as="error"> </f:for>
<div class="sg-jobs-validation-error"> </f:form.validationResults>
{error.message} </p>
</div>
</f:for> <p>
</f:form.validationResults> <label for="apply-street"><f:translate key="frontend.apply.street" /></label>
<br /> <f:form.textfield property="street" id="apply-street" />
<label for="apply-city"><f:translate key="frontend.apply.city" /></label> <f:form.validationResults for="applyData.street">
<f:form.textfield property="city" id="apply-city" class="" /> <f:for each="{validationResults.errors}" as="error">
<f:form.validationResults for="applyData.city"> <div class="sg-jobs-validation-error">
<f:for each="{validationResults.errors}" as="error"> {error.message}
<div class="sg-jobs-validation-error"> </div>
{error.message} </f:for>
</div> </f:form.validationResults>
</f:for> </p>
</f:form.validationResults>
<br /> <p>
<label for="apply-zip"><f:translate key="frontend.apply.zip" /></label> <label for="apply-city"><f:translate key="frontend.apply.city" /></label>
<f:form.textfield property="zip" id="apply-zip" class="" /> <f:form.textfield property="city" id="apply-city" />
<f:form.validationResults for="applyData.zip"> <f:form.validationResults for="applyData.city">
<f:for each="{validationResults.errors}" as="error"> <f:for each="{validationResults.errors}" as="error">
<div class="sg-jobs-validation-error"> <div class="sg-jobs-validation-error">
{error.message} {error.message}
</div> </div>
</f:for> </f:for>
</f:form.validationResults> </f:form.validationResults>
<br /> </p>
<label for="apply-country"><f:translate key="frontend.apply.country" /></label>
<f:form.textfield property="country" id="apply-country" class="" /> <p>
<f:form.validationResults for="applyData.country"> <label for="apply-zip"><f:translate key="frontend.apply.zip" /></label>
<f:for each="{validationResults.errors}" as="error"> <f:form.textfield property="zip" id="apply-zip" />
<div class="sg-jobs-validation-error"> <f:form.validationResults for="applyData.zip">
{error.message} <f:for each="{validationResults.errors}" as="error">
</div> <div class="sg-jobs-validation-error">
</f:for> {error.message}
</f:form.validationResults> </div>
<br /> </f:for>
<label for="apply-nationality"><f:translate key="frontend.apply.nationality" /></label> </f:form.validationResults>
<f:form.textfield property="nationality" id="apply-nationality" class="" /> </p>
<f:form.validationResults for="applyData.nationality">
<f:for each="{validationResults.errors}" as="error"> <p>
<div class="sg-jobs-validation-error"> <label for="apply-country"><f:translate key="frontend.apply.country" /></label>
{error.message} <f:form.textfield property="country" id="apply-country" />
</div> <f:form.validationResults for="applyData.country">
</f:for> <f:for each="{validationResults.errors}" as="error">
</f:form.validationResults> <div class="sg-jobs-validation-error">
<br /> {error.message}
<label for="apply-education"><f:translate key="frontend.apply.education" /></label> </div>
<f:form.textfield property="education" id="apply-education" class="" /> </f:for>
<f:form.validationResults for="applyData.education"> </f:form.validationResults>
<f:for each="{validationResults.errors}" as="error"> </p>
<div class="sg-jobs-validation-error">
{error.message} <p>
</div> <label for="apply-nationality"><f:translate key="frontend.apply.nationality" /></label>
</f:for> <f:form.textfield property="nationality" id="apply-nationality" />
</f:form.validationResults> <f:form.validationResults for="applyData.nationality">
<br /> <f:for each="{validationResults.errors}" as="error">
<label for="apply-birthDate"><f:translate key="frontend.apply.birthDate" /></label> <div class="sg-jobs-validation-error">
<f:form.textfield property="birthDate" id="apply-birthDate" class="" /> {error.message}
<f:form.validationResults for="applyData.birthDate"> </div>
<f:for each="{validationResults.errors}" as="error"> </f:for>
<div class="sg-jobs-validation-error"> </f:form.validationResults>
{error.message} </p>
</div>
</f:for> <p>
</f:form.validationResults> <label for="apply-education"><f:translate key="frontend.apply.education" /></label>
<br /> <f:form.textfield property="education" id="apply-education" />
<label for="apply-phone"><f:translate key="frontend.apply.phone" /></label> <f:form.validationResults for="applyData.education">
<f:form.textfield property="phone" id="apply-phone" class="" /> <f:for each="{validationResults.errors}" as="error">
<f:form.validationResults for="applyData.phone"> <div class="sg-jobs-validation-error">
<f:for each="{validationResults.errors}" as="error"> {error.message}
<div class="sg-jobs-validation-error"> </div>
{error.message} </f:for>
</div> </f:form.validationResults>
</f:for> </p>
</f:form.validationResults>
<br /> <p>
<label for="apply-mobile"><f:translate key="frontend.apply.mobile" /></label> <label for="apply-birthDate"><f:translate key="frontend.apply.birthDate" /></label>
<f:form.textfield property="mobile" id="apply-mobile" class="" /> <f:form.textfield property="birthDate" id="apply-birthDate" />
<f:form.validationResults for="applyData.mobile"> <f:form.validationResults for="applyData.birthDate">
<f:for each="{validationResults.errors}" as="error"> <f:for each="{validationResults.errors}" as="error">
<div class="sg-jobs-validation-error"> <div class="sg-jobs-validation-error">
{error.message} {error.message}
</div> </div>
</f:for> </f:for>
</f:form.validationResults> </f:form.validationResults>
<br /> </p>
<label for="apply-email"><f:translate key="frontend.apply.email" /></label>
<f:form.textfield type="email" property="email" id="apply-email" data="{}" class="" /> <p>
<f:form.validationResults for="applyData.email"> <label for="apply-phone"><f:translate key="frontend.apply.phone" /></label>
<f:for each="{validationResults.errors}" as="error"> <f:form.textfield property="phone" id="apply-phone" />
<div class="sg-jobs-validation-error"> <f:form.validationResults for="applyData.phone">
{error.message} <f:for each="{validationResults.errors}" as="error">
<div class="sg-jobs-validation-error">
{error.message}
</div>
</f:for>
</f:form.validationResults>
</p>
<p>
<label for="apply-mobile"><f:translate key="frontend.apply.mobile" /></label>
<f:form.textfield property="mobile" id="apply-mobile" />
<f:form.validationResults for="applyData.mobile">
<f:for each="{validationResults.errors}" as="error">
<div class="sg-jobs-validation-error">
{error.message}
</div>
</f:for>
</f:form.validationResults>
</p>
<p>
<label for="apply-email"><f:translate key="frontend.apply.email" /></label>
<f:form.textfield type="email" property="email" id="apply-email" data="{}" />
<f:form.validationResults for="applyData.email">
<f:for each="{validationResults.errors}" as="error">
<div class="sg-jobs-validation-error">
{error.message}
</div>
</f:for>
</f:form.validationResults>
</p>
<p>
<label for="apply-cover-letter"><f:translate key="frontend.apply.cover_letter" /></label>
<label for="apply-cover-letter">
<f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}
</label>
<f:form.upload multiple="true" property="coverLetter" id="apply-cover-letter" additionalAttributes="{accept: '{allowedMimeTypes}'}" />
<f:for each="{uploadedFiles.coverLetter}" as="file">
<div class="sg-jobs-uploaded-file">
<span class="filename">{file.name}</span>
<a href="#" filetype="coverLetter" class="remove-file">(remove)</a>
</div> </div>
</f:for> </f:for>
</f:form.validationResults> <f:form.validationResults for="applyData.coverLetter">
<br /> <f:for each="{validationResults.errors}" as="error">
<label for="apply-cover-letter"><f:translate key="frontend.apply.cover_letter" /></label> <div class="sg-jobs-validation-error">
<br/> {error.message}
<label for="apply-cover-letter"><f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}</label> </div>
<f:form.upload multiple="true" property="coverLetter" id="apply-cover-letter" additionalAttributes="{accept: '{allowedMimeTypes}'}" /> </f:for>
<f:for each="{uploadedFiles.coverLetter}" as="file"> </f:form.validationResults>
<div class="sg-jobs-uploaded-file"> </p>
<span class="filename">{file.name}</span>
<a href="#" filetype="coverLetter" class="remove-file">(remove)</a> <p>
</div> <label for="apply-cv"><f:translate key="frontend.apply.cv" /></label>
</f:for> <label for="apply-cover-letter">
<f:form.validationResults for="applyData.coverLetter"> <f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}</label>
<f:for each="{validationResults.errors}" as="error"> <f:form.upload multiple="true" property="cv" id="apply-cv" additionalAttributes="{accept: '{allowedMimeTypes}'}" />
<div class="sg-jobs-validation-error"> <f:for each="{uploadedFiles.cv}" as="file">
{error.message} <div class="sg-jobs-uploaded-file">
<span class="filename">{file.name}</span>
<a href="#" filetype="cv" class="remove-file">(remove)</a>
</div> </div>
</f:for> </f:for>
</f:form.validationResults> <f:form.validationResults for="applyData.cv">
<br /> <f:for each="{validationResults.errors}" as="error">
<label for="apply-cv"><f:translate key="frontend.apply.cv" /></label> <div class="sg-jobs-validation-error">
<br/> {error.message}
<label for="apply-cover-letter"><f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}</label> </div>
<f:form.upload multiple="true" property="cv" id="apply-cv" additionalAttributes="{accept: '{allowedMimeTypes}'}" /> </f:for>
<f:for each="{uploadedFiles.cv}" as="file"> </f:form.validationResults>
<div class="sg-jobs-uploaded-file"> </p>
<span class="filename">{file.name}</span>
<a href="#" filetype="cv" class="remove-file">(remove)</a> <p>
</div> <label for="apply-certificates"><f:translate key="frontend.apply.certificates" /></label>
</f:for> <label for="apply-cover-letter">
<f:form.validationResults for="applyData.cv"> <f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}</label>
<f:for each="{validationResults.errors}" as="error"> <f:form.upload multiple="true" property="certificates" id="apply-certificates" additionalAttributes="{accept: '{allowedMimeTypes}'}" />
<div class="sg-jobs-validation-error"> <f:for each="{uploadedFiles.certificates}" as="file">
{error.message} <div class="sg-jobs-uploaded-file">
<span class="filename">{file.name}</span>
<a href="#" filetype="certificates" class="remove-file">(remove)</a>
</div> </div>
</f:for> </f:for>
</f:form.validationResults> </p>
<br />
<label for="apply-certificates"><f:translate key="frontend.apply.certificates" /></label> <p>
<br/> <label for="apply-message"><f:translate key="frontend.apply.message" /></label>
<label for="apply-cover-letter"><f:translate key="frontend.apply.allowed_file_extensions" />{allowedFileExtensions}</label> <f:form.textarea property="message" id="apply-message" />
<f:form.upload multiple="true" property="certificates" id="apply-certificates" additionalAttributes="{accept: '{allowedMimeTypes}'}" /> </p>
<f:for each="{uploadedFiles.certificates}" as="file">
<div class="sg-jobs-uploaded-file"> <p>
<span class="filename">{file.name}</span> <f:form.submit value="{f:translate(key:'frontend.applyNow')}" />
<a href="#" filetype="certificates" class="remove-file">(remove)</a> </p>
</div>
</f:for>
<br />
<label for="apply-message"><f:translate key="frontend.apply.message" /></label>
<f:form.textarea property="message" id="apply-message" class="" />
<br />
<f:form.submit value="{f:translate(key:'frontend.applyNow')}" />
</f:form> </f:form>
</f:section> </f:section>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment