mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
Can configure file upload in file imports.
This commit is contained in:
parent
f74b9ba7ab
commit
7d80ac37a6
@ -29,6 +29,8 @@ use FireflyIII\Import\JobConfiguration\JobConfigurationInterface;
|
|||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
use Log;
|
use Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,8 +141,17 @@ class JobConfigurationController extends Controller
|
|||||||
return redirect(route('import.job.status.index', [$importJob->key]));
|
return redirect(route('import.job.status.index', [$importJob->key]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// uploaded files are attached to the job.
|
||||||
|
// the configurator can then handle them.
|
||||||
|
$result = new MessageBag;
|
||||||
|
|
||||||
|
/** @var UploadedFile $upload */
|
||||||
|
foreach ($request->allFiles() as $name => $upload) {
|
||||||
|
$result = $this->repository->storeFileUpload($importJob, $name, $upload);
|
||||||
|
}
|
||||||
$data = $request->all();
|
$data = $request->all();
|
||||||
$messages = $configurator->configureJob($data);
|
$messages = $configurator->configureJob($data);
|
||||||
|
$result->merge($messages);
|
||||||
|
|
||||||
if ($messages->count() > 0) {
|
if ($messages->count() > 0) {
|
||||||
$request->session()->flash('warning', $messages->first());
|
$request->session()->flash('warning', $messages->first());
|
||||||
|
@ -23,11 +23,20 @@ declare(strict_types=1);
|
|||||||
namespace FireflyIII\Import\JobConfiguration;
|
namespace FireflyIII\Import\JobConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
|
use FireflyIII\Support\Import\Configuration\File\ConfigurationInterface;
|
||||||
|
use FireflyIII\Support\Import\Configuration\File\ConfigureUploadHandler;
|
||||||
|
use FireflyIII\Support\Import\Configuration\File\NewFileJobHandler;
|
||||||
use Illuminate\Support\MessageBag;
|
use Illuminate\Support\MessageBag;
|
||||||
|
|
||||||
class FileJobConfiguration implements JobConfigurationInterface
|
class FileJobConfiguration implements JobConfigurationInterface
|
||||||
{
|
{
|
||||||
|
/** @var ImportJob */
|
||||||
|
private $importJob;
|
||||||
|
/** @var ImportJobRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ConfiguratorInterface constructor.
|
* ConfiguratorInterface constructor.
|
||||||
@ -43,30 +52,86 @@ class FileJobConfiguration implements JobConfigurationInterface
|
|||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
* @return MessageBag
|
* @return MessageBag
|
||||||
|
* @throws FireflyException
|
||||||
*/
|
*/
|
||||||
public function configureJob(array $data): MessageBag
|
public function configureJob(array $data): MessageBag
|
||||||
{
|
{
|
||||||
// TODO: Implement configureJob() method.
|
$configurator = $this->getConfigurationObject();
|
||||||
|
$configurator->setJob($this->importJob);
|
||||||
|
|
||||||
|
return $configurator->configureJob($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the data required for the next step in the job configuration.
|
* Return the data required for the next step in the job configuration.
|
||||||
*
|
*
|
||||||
|
* @throws FireflyException
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getNextData(): array
|
public function getNextData(): array
|
||||||
{
|
{
|
||||||
// TODO: Implement getNextData() method.
|
$configurator = $this->getConfigurationObject();
|
||||||
|
$configurator->setJob($this->importJob);
|
||||||
|
|
||||||
|
return $configurator->getNextData();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the configuration handler for this specific stage.
|
||||||
|
*
|
||||||
|
* @return ConfigurationInterface
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function getConfigurationObject(): ConfigurationInterface
|
||||||
|
{
|
||||||
|
$class = 'DoNotExist';
|
||||||
|
switch ($this->importJob->stage) {
|
||||||
|
case 'new': // has nothing, no file upload or anything.
|
||||||
|
$class = NewFileJobHandler::class;
|
||||||
|
break;
|
||||||
|
case 'configure-upload':
|
||||||
|
$class = ConfigureUploadHandler::class;
|
||||||
|
break;
|
||||||
|
// case 'upload-config': // has file, needs file config.
|
||||||
|
// $class = UploadConfig::class;
|
||||||
|
// break;
|
||||||
|
// case 'roles': // has configured file, needs roles.
|
||||||
|
// $class = Roles::class;
|
||||||
|
// break;
|
||||||
|
// case 'map': // has roles, needs mapping.
|
||||||
|
// $class = Map::class;
|
||||||
|
// break;
|
||||||
|
// default:
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
if (!class_exists($class)) {
|
||||||
|
throw new FireflyException(sprintf('Class %s does not exist in getConfigurationClass().', $class)); // @codeCoverageIgnore
|
||||||
|
}
|
||||||
|
|
||||||
|
return app($class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the view of the next step in the job configuration.
|
* Returns the view of the next step in the job configuration.
|
||||||
*
|
*
|
||||||
|
* @throws FireflyException
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getNextView(): string
|
public function getNextView(): string
|
||||||
{
|
{
|
||||||
// TODO: Implement getNextView() method.
|
switch ($this->importJob->stage) {
|
||||||
|
case 'new':
|
||||||
|
return 'import.file.new';
|
||||||
|
case 'configure-upload':
|
||||||
|
return 'import.file.configure-upload';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// @codeCoverageIgnoreStart
|
||||||
|
throw new FireflyException(
|
||||||
|
sprintf('FileJobConfiguration::getNextView() cannot handle stage "%s"', $this->importJob->stage)
|
||||||
|
);
|
||||||
|
// @codeCoverageIgnoreEnd
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -76,7 +141,11 @@ class FileJobConfiguration implements JobConfigurationInterface
|
|||||||
*/
|
*/
|
||||||
public function configurationComplete(): bool
|
public function configurationComplete(): bool
|
||||||
{
|
{
|
||||||
// TODO: Implement configurationComplete() method.
|
if ($this->importJob->stage === 'ready_to run') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +153,8 @@ class FileJobConfiguration implements JobConfigurationInterface
|
|||||||
*/
|
*/
|
||||||
public function setJob(ImportJob $job): void
|
public function setJob(ImportJob $job): void
|
||||||
{
|
{
|
||||||
// TODO: Implement setJob() method.
|
$this->importJob = $job;
|
||||||
|
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($job->user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ class AbnAmroDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getDescription(): string
|
public static function getDescription(): string
|
||||||
{
|
{
|
||||||
return 'Fixes possible problems with ABN Amro descriptions.';
|
return 'import.specific_abn_descr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,7 +50,7 @@ class AbnAmroDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
{
|
{
|
||||||
return 'ABN Amro description';
|
return 'import.specific_abn_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -43,7 +43,7 @@ class IngDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getDescription(): string
|
public static function getDescription(): string
|
||||||
{
|
{
|
||||||
return 'Create better descriptions in ING import files.';
|
return 'import.specific_ing_descr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,7 +52,7 @@ class IngDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
{
|
{
|
||||||
return 'ING description';
|
return 'import.specific_ing_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@ class PresidentsChoice implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getDescription(): string
|
public static function getDescription(): string
|
||||||
{
|
{
|
||||||
return 'Fixes problems with files from Presidents Choice Financial.';
|
return 'import.specific_pres_descr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +42,7 @@ class PresidentsChoice implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
{
|
{
|
||||||
return 'Presidents "Choice"';
|
return 'import.specific_pres_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -35,7 +35,7 @@ class RabobankDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getDescription(): string
|
public static function getDescription(): string
|
||||||
{
|
{
|
||||||
return 'Fixes possible problems with Rabobank descriptions.';
|
return 'import.specific_pres_descr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,7 +44,7 @@ class RabobankDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
{
|
{
|
||||||
return 'Rabobank description';
|
return 'import.specific_rabo_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,7 +33,7 @@ class SnsDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getDescription(): string
|
public static function getDescription(): string
|
||||||
{
|
{
|
||||||
return 'Trim quotes from SNS descriptions.';
|
return 'import.specific_sns_descr';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +42,7 @@ class SnsDescription implements SpecificInterface
|
|||||||
*/
|
*/
|
||||||
public static function getName(): string
|
public static function getName(): string
|
||||||
{
|
{
|
||||||
return 'SNS description';
|
return 'import.specific_sns_name';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +52,15 @@ class ImportJob extends Model
|
|||||||
/** @var array */
|
/** @var array */
|
||||||
protected $fillable = ['key', 'user_id', 'file_type', 'provider', 'status', 'stage', 'configuration', 'extended_status', 'transactions', 'errors'];
|
protected $fillable = ['key', 'user_id', 'file_type', 'provider', 'status', 'stage', 'configuration', 'extended_status', 'transactions', 'errors'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
|
||||||
|
*/
|
||||||
|
public function attachments()
|
||||||
|
{
|
||||||
|
return $this->morphMany(Attachment::class, 'attachable');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $value
|
* @param $value
|
||||||
*
|
*
|
||||||
|
@ -24,11 +24,13 @@ namespace FireflyIII\Repositories\ImportJob;
|
|||||||
|
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use FireflyIII\Exceptions\FireflyException;
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\Attachment;
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\Models\TransactionJournalMeta;
|
use FireflyIII\Models\TransactionJournalMeta;
|
||||||
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
use FireflyIII\Repositories\User\UserRepositoryInterface;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
use Log;
|
use Log;
|
||||||
use SplFileObject;
|
use SplFileObject;
|
||||||
@ -42,6 +44,16 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
|||||||
{
|
{
|
||||||
/** @var User */
|
/** @var User */
|
||||||
private $user;
|
private $user;
|
||||||
|
/** @var int */
|
||||||
|
private $maxUploadSize;
|
||||||
|
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
|
||||||
|
protected $uploadDisk;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->maxUploadSize = (int)config('firefly.maxUploadSize');
|
||||||
|
$this->uploadDisk = Storage::disk('upload');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ImportJob $job
|
* @param ImportJob $job
|
||||||
@ -421,6 +433,8 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
|||||||
/**
|
/**
|
||||||
* Return import file content.
|
* Return import file content.
|
||||||
*
|
*
|
||||||
|
* @deprecated
|
||||||
|
*
|
||||||
* @param ImportJob $job
|
* @param ImportJob $job
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
@ -476,4 +490,74 @@ class ImportJobRepository implements ImportJobRepositoryInterface
|
|||||||
|
|
||||||
return $job;
|
return $job;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*
|
||||||
|
* @param UploadedFile $file
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function validSize(UploadedFile $file): bool
|
||||||
|
{
|
||||||
|
$size = $file->getSize();
|
||||||
|
|
||||||
|
return $size > $this->maxUploadSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle upload for job.
|
||||||
|
*
|
||||||
|
* @param ImportJob $job
|
||||||
|
* @param string $name
|
||||||
|
* @param UploadedFile $file
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function storeFileUpload(ImportJob $job, string $name, UploadedFile $file): MessageBag
|
||||||
|
{
|
||||||
|
$messages = new MessageBag;
|
||||||
|
if ($this->validSize($file)) {
|
||||||
|
$name = e($file->getClientOriginalName());
|
||||||
|
$messages->add('size', (string)trans('validation.file_too_large', ['name' => $name]));
|
||||||
|
|
||||||
|
return $messages;
|
||||||
|
}
|
||||||
|
$count = $job->attachments()->get()->filter(
|
||||||
|
function (Attachment $att) use($name) {
|
||||||
|
return $att->filename === $name;
|
||||||
|
}
|
||||||
|
)->count();
|
||||||
|
|
||||||
|
if ($count > 0) {
|
||||||
|
// don't upload, but also don't complain about it.
|
||||||
|
Log::error(sprintf('Detected duplicate upload. Will ignore second "%s" file.', $name));
|
||||||
|
|
||||||
|
return new MessageBag;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attachment = new Attachment; // create Attachment object.
|
||||||
|
$attachment->user()->associate($job->user);
|
||||||
|
$attachment->attachable()->associate($job);
|
||||||
|
$attachment->md5 = md5_file($file->getRealPath());
|
||||||
|
$attachment->filename = $name;
|
||||||
|
$attachment->mime = $file->getMimeType();
|
||||||
|
$attachment->size = $file->getSize();
|
||||||
|
$attachment->uploaded = 0;
|
||||||
|
$attachment->save();
|
||||||
|
$fileObject = $file->openFile('r');
|
||||||
|
$fileObject->rewind();
|
||||||
|
$content = $fileObject->fread($file->getSize());
|
||||||
|
$encrypted = Crypt::encrypt($content);
|
||||||
|
|
||||||
|
// store it:
|
||||||
|
$this->uploadDisk->put($attachment->fileName(), $encrypted);
|
||||||
|
$attachment->uploaded = 1; // update attachment
|
||||||
|
$attachment->save();
|
||||||
|
|
||||||
|
// return it.
|
||||||
|
return new MessageBag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,11 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace FireflyIII\Repositories\ImportJob;
|
namespace FireflyIII\Repositories\ImportJob;
|
||||||
|
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
use FireflyIII\Models\Tag;
|
use FireflyIII\Models\Tag;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -33,6 +35,18 @@ use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|||||||
interface ImportJobRepositoryInterface
|
interface ImportJobRepositoryInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle upload for job.
|
||||||
|
*
|
||||||
|
* @param ImportJob $job
|
||||||
|
* @param string $name
|
||||||
|
* @param UploadedFile $file
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
public function storeFileUpload(ImportJob $job, string $name, UploadedFile $file): MessageBag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ImportJob $job
|
* @param ImportJob $job
|
||||||
* @param array $transactions
|
* @param array $transactions
|
||||||
|
@ -145,16 +145,6 @@ class ExpandedForm
|
|||||||
*/
|
*/
|
||||||
public function assetAccountList(string $name, $value = null, array $options = []): string
|
public function assetAccountList(string $name, $value = null, array $options = []): string
|
||||||
{
|
{
|
||||||
// properties for cache
|
|
||||||
$cache = new CacheProperties;
|
|
||||||
$cache->addProperty('exp-form-asset-list');
|
|
||||||
$cache->addProperty($name);
|
|
||||||
$cache->addProperty($value);
|
|
||||||
$cache->addProperty($options);
|
|
||||||
|
|
||||||
if ($cache->has()) {
|
|
||||||
return $cache->get();
|
|
||||||
}
|
|
||||||
// make repositories
|
// make repositories
|
||||||
/** @var AccountRepositoryInterface $repository */
|
/** @var AccountRepositoryInterface $repository */
|
||||||
$repository = app(AccountRepositoryInterface::class);
|
$repository = app(AccountRepositoryInterface::class);
|
||||||
@ -182,7 +172,6 @@ class ExpandedForm
|
|||||||
$grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')';
|
$grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')';
|
||||||
}
|
}
|
||||||
$res = $this->select($name, $grouped, $value, $options);
|
$res = $this->select($name, $grouped, $value, $options);
|
||||||
$cache->store($res);
|
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
namespace FireflyIII\Support\Import\Configuration;
|
namespace FireflyIII\Support\Import\Configuration\File;
|
||||||
|
|
||||||
use FireflyIII\Models\ImportJob;
|
use FireflyIII\Models\ImportJob;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated
|
|
||||||
* Class ConfigurationInterface.
|
* Class ConfigurationInterface.
|
||||||
*/
|
*/
|
||||||
interface ConfigurationInterface
|
interface ConfigurationInterface
|
||||||
@ -35,14 +35,7 @@ interface ConfigurationInterface
|
|||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getData(): array;
|
public function getNextData(): array;
|
||||||
|
|
||||||
/**
|
|
||||||
* Return possible warning to user.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getWarningMessage(): string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ImportJob $job
|
* @param ImportJob $job
|
||||||
@ -52,11 +45,11 @@ interface ConfigurationInterface
|
|||||||
public function setJob(ImportJob $job);
|
public function setJob(ImportJob $job);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store the result.
|
* Store data associated with current stage.
|
||||||
*
|
*
|
||||||
* @param array $data
|
* @param array $data
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return MessageBag
|
||||||
*/
|
*/
|
||||||
public function storeConfiguration(array $data): bool;
|
public function configureJob(array $data): MessageBag;
|
||||||
}
|
}
|
167
app/Support/Import/Configuration/File/ConfigureUploadHandler.php
Normal file
167
app/Support/Import/Configuration/File/ConfigureUploadHandler.php
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ConfigureUploadHandlerphp
|
||||||
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Import\Configuration\File;
|
||||||
|
|
||||||
|
use FireflyIII\Models\ImportJob;
|
||||||
|
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
|
||||||
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
use Log;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ConfigureUploadHandler
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Support\Import\Configuration\File
|
||||||
|
*/
|
||||||
|
class ConfigureUploadHandler implements ConfigurationInterface
|
||||||
|
{
|
||||||
|
/** @var ImportJob */
|
||||||
|
private $importJob;
|
||||||
|
|
||||||
|
/** @var ImportJobRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/** @var AccountRepositoryInterface */
|
||||||
|
private $accountRepos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data necessary to show the configuration screen.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getNextData(): array
|
||||||
|
{
|
||||||
|
$delimiters = [
|
||||||
|
',' => trans('form.csv_comma'),
|
||||||
|
';' => trans('form.csv_semicolon'),
|
||||||
|
'tab' => trans('form.csv_tab'),
|
||||||
|
];
|
||||||
|
$config = $this->importJob->configuration;
|
||||||
|
$config['date-format'] = $config['date-format'] ?? 'Ymd';
|
||||||
|
$specifics = [];
|
||||||
|
$this->repository->setConfiguration($this->importJob, $config);
|
||||||
|
|
||||||
|
// collect specifics.
|
||||||
|
foreach (config('csv.import_specifics') as $name => $className) {
|
||||||
|
$specifics[$name] = [
|
||||||
|
'name' => $className::getName(),
|
||||||
|
'description' => $className::getDescription(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = [
|
||||||
|
'accounts' => [],
|
||||||
|
'specifix' => [],
|
||||||
|
'delimiters' => $delimiters,
|
||||||
|
'specifics' => $specifics,
|
||||||
|
];
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ImportJob $job
|
||||||
|
*
|
||||||
|
* @return ConfigurationInterface
|
||||||
|
*/
|
||||||
|
public function setJob(ImportJob $job)
|
||||||
|
{
|
||||||
|
$this->importJob = $job;
|
||||||
|
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($job->user);
|
||||||
|
$this->accountRepos = app(AccountRepositoryInterface::class);
|
||||||
|
$this->accountRepos->setUser($job->user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store data associated with current stage.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return MessageBag
|
||||||
|
*/
|
||||||
|
public function configureJob(array $data): MessageBag
|
||||||
|
{
|
||||||
|
$config = $this->importJob->configuration;
|
||||||
|
$complete = true;
|
||||||
|
|
||||||
|
// collect values:
|
||||||
|
$importId = isset($data['csv_import_account']) ? (int)$data['csv_import_account'] : 0;
|
||||||
|
$delimiter = (string)$data['csv_delimiter'];
|
||||||
|
$config['has-headers'] = (int)($data['has_headers'] ?? 0.0) === 1;
|
||||||
|
$config['date-format'] = (string)$data['date_format'];
|
||||||
|
$config['delimiter'] = 'tab' === $delimiter ? "\t" : $delimiter;
|
||||||
|
$config['apply-rules'] = (int)($data['apply_rules'] ?? 0.0) === 1;
|
||||||
|
$config['specifics'] = $this->getSpecifics($data);
|
||||||
|
// validate values:
|
||||||
|
$account = $this->accountRepos->findNull($importId);
|
||||||
|
|
||||||
|
// respond to invalid account:
|
||||||
|
if (null === $account) {
|
||||||
|
Log::error('Could not find anything for csv_import_account.', ['id' => $importId]);
|
||||||
|
$complete = false;
|
||||||
|
}
|
||||||
|
if (null !== $account) {
|
||||||
|
$config['import-account'] = $account->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->repository->setConfiguration($this->importJob, $config);
|
||||||
|
if ($complete) {
|
||||||
|
$this->repository->setStage($this->importJob, 'roles');
|
||||||
|
}
|
||||||
|
if (!$complete) {
|
||||||
|
$messages = new MessageBag;
|
||||||
|
$messages->add('account', trans('import.invalid_import_account'));
|
||||||
|
|
||||||
|
return $messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MessageBag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
private function getSpecifics(array $data): array
|
||||||
|
{
|
||||||
|
$return = [];
|
||||||
|
// check if specifics given are correct:
|
||||||
|
if (isset($data['specifics']) && \is_array($data['specifics'])) {
|
||||||
|
|
||||||
|
foreach ($data['specifics'] as $name) {
|
||||||
|
// verify their content.
|
||||||
|
$className = sprintf('FireflyIII\Import\Specifics\%s', $name);
|
||||||
|
if (class_exists($className)) {
|
||||||
|
$return[$name] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $return;
|
||||||
|
}
|
||||||
|
}
|
176
app/Support/Import/Configuration/File/NewFileJobHandler.php
Normal file
176
app/Support/Import/Configuration/File/NewFileJobHandler.php
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* NewFileJobHandler.php
|
||||||
|
* Copyright (c) 2018 thegrumpydictator@gmail.com
|
||||||
|
*
|
||||||
|
* This file is part of Firefly III.
|
||||||
|
*
|
||||||
|
* Firefly III is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Firefly III is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Import\Configuration\File;
|
||||||
|
|
||||||
|
use Crypt;
|
||||||
|
use FireflyIII\Console\Commands\Import;
|
||||||
|
use FireflyIII\Exceptions\FireflyException;
|
||||||
|
use FireflyIII\Models\Attachment;
|
||||||
|
use FireflyIII\Models\ImportJob;
|
||||||
|
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
|
||||||
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
|
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||||
|
use Illuminate\Support\MessageBag;
|
||||||
|
use Log;
|
||||||
|
use Storage;
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class NewFileJobHandler
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Support\Import\Configuration\File
|
||||||
|
*/
|
||||||
|
class NewFileJobHandler implements ConfigurationInterface
|
||||||
|
{
|
||||||
|
/** @var ImportJob */
|
||||||
|
private $importJob;
|
||||||
|
|
||||||
|
/** @var ImportJobRepositoryInterface */
|
||||||
|
private $repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the data necessary to show the configuration screen.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getNextData(): array
|
||||||
|
{
|
||||||
|
$importFileTypes = [];
|
||||||
|
$defaultImportType = config('import.options.file.default_import_format');
|
||||||
|
|
||||||
|
foreach (config('import.options.file.import_formats') as $type) {
|
||||||
|
$importFileTypes[$type] = trans('import.import_file_type_' . $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'default_type' => $defaultImportType,
|
||||||
|
'file_types' => $importFileTypes,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ImportJob $job
|
||||||
|
*/
|
||||||
|
public function setJob(ImportJob $job): void
|
||||||
|
{
|
||||||
|
$this->importJob = $job;
|
||||||
|
$this->repository = app(ImportJobRepositoryInterface::class);
|
||||||
|
$this->repository->setUser($job->user);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store data associated with current stage.
|
||||||
|
*
|
||||||
|
* @param array $data
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
* @return MessageBag
|
||||||
|
*/
|
||||||
|
public function configureJob(array $data): MessageBag
|
||||||
|
{
|
||||||
|
// nothing to store, validate upload
|
||||||
|
// and push to next stage.
|
||||||
|
$messages = new MessageBag;
|
||||||
|
$attachments = $this->importJob->attachments;
|
||||||
|
/** @var Attachment $attachment */
|
||||||
|
foreach ($attachments as $attachment) {
|
||||||
|
|
||||||
|
// check if content is UTF8:
|
||||||
|
if (!$this->isUTF8($attachment)) {
|
||||||
|
$message = trans('import.file_not_utf8');
|
||||||
|
Log::error($message);
|
||||||
|
$messages->add('import_file', $message);
|
||||||
|
// delete attachment:
|
||||||
|
try {
|
||||||
|
$attachment->delete();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new FireflyException(sprintf('Could not delete attachment: %s', $e->getMessage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if file is configuration file, store it into the job.
|
||||||
|
if ($attachment->filename === 'configuration_file') {
|
||||||
|
$this->storeConfig($attachment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->repository->setStage($this->importJob, 'configure-upload');
|
||||||
|
|
||||||
|
return new MessageBag();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Attachment $attachment
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function isUTF8(Attachment $attachment): bool
|
||||||
|
{
|
||||||
|
$disk = Storage::disk('upload');
|
||||||
|
try {
|
||||||
|
$content = $disk->get(sprintf('at-%d.data', $attachment->id));
|
||||||
|
$content = Crypt::decrypt($content);
|
||||||
|
} catch (FileNotFoundException|DecryptException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
throw new FireflyException($e->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = mb_detect_encoding($content, 'UTF-8', true);
|
||||||
|
if ($result === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($result !== 'ASCII' && $result !== 'UTF-8') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Attachment $attachment
|
||||||
|
*
|
||||||
|
* @throws FireflyException
|
||||||
|
*/
|
||||||
|
private function storeConfig(Attachment $attachment): void
|
||||||
|
{
|
||||||
|
$disk = Storage::disk('upload');
|
||||||
|
try {
|
||||||
|
$content = $disk->get(sprintf('at-%d.data', $attachment->id));
|
||||||
|
$content = Crypt::decrypt($content);
|
||||||
|
} catch (FileNotFoundException $e) {
|
||||||
|
Log::error($e->getMessage());
|
||||||
|
throw new FireflyException($e->getMessage());
|
||||||
|
}
|
||||||
|
$json = json_decode($content, true);
|
||||||
|
if (null !== $json) {
|
||||||
|
$this->repository->setConfiguration($this->importJob, $json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
public/js/ff/import/file/configure-upload.js
vendored
Normal file
20
public/js/ff/import/file/configure-upload.js
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
$(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var importMultiSelect = {
|
||||||
|
disableIfEmpty: true,
|
||||||
|
selectAllText: selectAllText,
|
||||||
|
nonSelectedText: nonSelectedText,
|
||||||
|
nSelectedText: nSelectedText,
|
||||||
|
allSelectedText: allSelectedText,
|
||||||
|
includeSelectAllOption: true,
|
||||||
|
enableFiltering: true,
|
||||||
|
enableCaseInsensitiveFiltering: true,
|
||||||
|
filterPlaceholder: filterPlaceholder,
|
||||||
|
enableHTML: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
// make account select a hip new bootstrap multi-select thing.
|
||||||
|
$('#inputSpecifics').multiselect(importMultiSelect);
|
||||||
|
|
||||||
|
});
|
@ -80,6 +80,39 @@ return [
|
|||||||
'job_config_fake_song_text' => 'Mention the song "Golden years" to continue with the fake import.',
|
'job_config_fake_song_text' => 'Mention the song "Golden years" to continue with the fake import.',
|
||||||
'job_config_fake_album_title' => 'Enter album name',
|
'job_config_fake_album_title' => 'Enter album name',
|
||||||
'job_config_fake_album_text' => 'Some import routines require extra data halfway through the import. In the case of the fake import provider, you must answer some weird questions. Enter "Station to station" to continue.',
|
'job_config_fake_album_text' => 'Some import routines require extra data halfway through the import. In the case of the fake import provider, you must answer some weird questions. Enter "Station to station" to continue.',
|
||||||
|
// job configuration form the file provider
|
||||||
|
'job_config_file_upload_title' => 'Import setup (1/4) - Upload your file',
|
||||||
|
'job_config_file_upload_text' => 'This routine will help you import files from your bank into Firefly III. ',
|
||||||
|
'job_config_file_upload_help' => 'Select your file. Please make sure the file is UTF-8 encoded.',
|
||||||
|
'job_config_file_upload_config_help' => 'If you have previously imported data into Firefly III, you may have a configuration file, which will pre-set configuration values for you. For some banks, other users have kindly provided their <a href="https://github.com/firefly-iii/import-configurations/wiki">configuration file</a>',
|
||||||
|
'job_config_file_upload_type_help' => 'Select the type of file you will upload',
|
||||||
|
'job_config_file_upload_submit' => 'Upload files',
|
||||||
|
'import_file_type_csv' => 'CSV (comma separated values)',
|
||||||
|
'file_not_utf8' => 'The file you have uploaded is not encoded as UTF-8 or ASCII. Firefly III cannot handle such files. Please use Notepad++ or Sublime to convert your file to UTF-8.',
|
||||||
|
'job_config_uc_title' => 'Import setup (2/4) - Basic file setup',
|
||||||
|
'job_config_uc_text' => 'To be able to import your file correctly, please validate the options below.',
|
||||||
|
'job_config_uc_header_help' => 'Check this box if the first row of your CSV file are the column titles.',
|
||||||
|
'job_config_uc_date_help' => 'Date time format in your file. Follow the format as <a href="https://secure.php.net/manual/en/datetime.createfromformat.php#refsect1-datetime.createfromformat-parameters">this page</a> indicates. The default value will parse dates that look like this: :dateExample.',
|
||||||
|
'job_config_uc_delimiter_help' => 'Choose the field delimiter that is used in your input file. If not sure, comma is the safest option.',
|
||||||
|
'job_config_uc_account_help' => 'If your file does NOT contain information about your asset account(s), use this dropdown to select to which account the transactions in the file belong to.',
|
||||||
|
'job_config_uc_apply_rules_title' => 'Apply rules',
|
||||||
|
'job_config_uc_apply_rules_text' => 'Applies your rules to every imported transaction. Note that this slows the import significantly.',
|
||||||
|
'job_config_uc_specifics_title' => 'Bank-specific options',
|
||||||
|
'job_config_uc_specifics_txt' => 'Some banks deliver badly formatted files. Firefly III can fix those automatically. If your bank delivers such files, open an issue on GitHub.',
|
||||||
|
'job_config_uc_submit' => 'Continue',
|
||||||
|
'invalid_import_account' => 'You have selected an invalid account to import into.',
|
||||||
|
// specifics:
|
||||||
|
'specific_ing_name' => 'ING NL',
|
||||||
|
'specific_ing_descr' => 'Create better descriptions in ING exports',
|
||||||
|
'specific_sns_name' => 'SNS / Volksbank NL',
|
||||||
|
'specific_sns_descr' => 'Trim quotes from SNS / Volksbank export files',
|
||||||
|
'specific_abn_name' => 'ABN AMRO NL',
|
||||||
|
'specific_abn_descr' => 'Fixes potential problems with ABN AMRO files',
|
||||||
|
'specific_rabo_name' => 'Rabobank NL',
|
||||||
|
'specific_rabo_descr' => 'Fixes potential problems with Rabobank files',
|
||||||
|
'specific_pres_name' => 'President\'s Choice Financial CA',
|
||||||
|
'specific_pres_descr' => 'Fixes potential problems with PC files',
|
||||||
|
|
||||||
|
|
||||||
// import status page:
|
// import status page:
|
||||||
'import_with_key' => 'Import with key \':key\'',
|
'import_with_key' => 'Import with key \':key\'',
|
||||||
|
115
resources/views/import/file/configure-upload.twig
Normal file
115
resources/views/import/file/configure-upload.twig
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
{% extends "./layout/default" %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, importJob) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('import.job_config_uc_title') }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<p>
|
||||||
|
{{ trans('import.job_config_uc_text') }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form class="form-horizontal" action="{{ route('import.job.configuration.post', importJob.key) }}" method="post" enctype="multipart/form-data">
|
||||||
|
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-header with-border">
|
||||||
|
<h3 class="box-title">{{ trans('import.job_config_input') }}</h3>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<h4>{{ 'mandatoryFields'|_ }}</h4>
|
||||||
|
{{ ExpandedForm.checkbox('has_headers',1,importJob.configuration['has-headers'],{helpText: trans('import.job_config_uc_header_help')}) }}
|
||||||
|
{{ ExpandedForm.text('date_format',importJob.configuration['date-format'],{helpText: trans('import.job_config_uc_date_help', {dateExample: phpdate('Ymd')}) }) }}
|
||||||
|
{{ ExpandedForm.select('csv_delimiter', data.delimiters, importJob.configuration['delimiter'], {helpText: trans('import.job_config_uc_delimiter_help') } ) }}
|
||||||
|
{{ ExpandedForm.assetAccountList('csv_import_account', importJob.configuration['import-account'], {helpText: trans('import.job_config_uc_account_help')}) }}
|
||||||
|
|
||||||
|
<h4>{{ 'optionalFields'|_ }}</h4>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="apply_rules_label" class="col-sm-4 control-label">
|
||||||
|
{{ trans('import.job_config_uc_apply_rules_title') }}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<div class="checkbox"><label>
|
||||||
|
{{ Form.checkbox('apply_rules', '1',
|
||||||
|
importJob.configuration['apply-rules'] == true, {'id': 'apply_rules_label'}) }}
|
||||||
|
{{ trans('import.job_config_uc_apply_rules_text') }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="inputSpecifics" class="col-sm-4 control-label">{{ trans('import.job_config_uc_specifics_title') }}</label>
|
||||||
|
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<p>
|
||||||
|
{{ trans('import.job_config_uc_specifics_txt') }}
|
||||||
|
</p>
|
||||||
|
<select id="inputSpecifics" name="specifics[]" multiple class="form-control">
|
||||||
|
{% for type, specific in data.specifics %}
|
||||||
|
<option value="{{ type }}" {% if importJob.configuration.specifics[type] == 1 %}selected{% endif %}>
|
||||||
|
{{ trans(specific.name) }}
|
||||||
|
<small><br>{{ trans(specific.description) }}</small>
|
||||||
|
</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-body">
|
||||||
|
<button type="submit" class="pull-right btn btn-success">
|
||||||
|
{{ trans('import.job_config_uc_submit') }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<br/> <br/> <br/> <br/> <br/> <br/> <br/>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
|
{% block styles %}
|
||||||
|
<link href="css/bootstrap-multiselect.css?v={{ FF_VERSION }}" rel="stylesheet" type="text/css"/>
|
||||||
|
{% endblock %}
|
||||||
|
{% block scripts %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
var selectAllText = "{{ trans('firefly.multi_select_select_all')|escape('js') }}";
|
||||||
|
var nonSelectedText = "{{ trans('firefly.multi_select_no_selection')|escape('js') }}";
|
||||||
|
var nSelectedText = "{{ trans('firefly.multi_select_n_selected')|escape('js') }}";
|
||||||
|
var allSelectedText = "{{ trans('firefly.multi_select_all_selected')|escape('js') }}";
|
||||||
|
var filterPlaceholder = "{{ trans('firefly.multi_select_filter_placeholder')|escape('js') }}";
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="js/lib/bootstrap-multiselect.js?v={{ FF_VERSION }}"></script>
|
||||||
|
<script type="text/javascript" src="js/ff/import/file/configure-upload.js?v={{ FF_VERSION }}"></script>
|
||||||
|
{% endblock %}
|
@ -8,11 +8,11 @@
|
|||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ trans('import.file_upload_title') }}</h3>
|
<h3 class="box-title">{{ trans('import.job_config_file_upload_title') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<p>
|
<p>
|
||||||
{{ trans('import.file_upload_text') }}
|
{{ trans('import.job_config_file_upload_text') }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -28,12 +28,12 @@
|
|||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-header with-border">
|
<div class="box-header with-border">
|
||||||
<h3 class="box-title">{{ trans('import.file_upload_fields') }}</h3>
|
<h3 class="box-title">{{ trans('import.job_config_input') }}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
{{ ExpandedForm.file('import_file', {helpText: trans('import.file_upload_help')}) }}
|
{{ ExpandedForm.file('import_file', {helpText: trans('import.job_config_file_upload_help')}) }}
|
||||||
{{ ExpandedForm.file('configuration_file', {helpText: trans('import.file_upload_config_help')|raw}) }}
|
{{ ExpandedForm.file('configuration_file', {helpText: trans('import.job_config_file_upload_config_help')|raw}) }}
|
||||||
{{ ExpandedForm.select('import_file_type', data.file_types, data.default_type, {'helpText' : trans('import.file_upload_type_help')}) }}
|
{{ ExpandedForm.select('import_file_type', data.file_types, data.default_type, {'helpText' : trans('import.job_config_file_upload_type_help')}) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<div class="box">
|
<div class="box">
|
||||||
<div class="box-body">
|
<div class="box-body">
|
||||||
<button type="submit" class="btn btn-success pull-right">
|
<button type="submit" class="btn btn-success pull-right">
|
||||||
{{ trans('import.file_upload_submit') }} <i class="fa fa-arrow-right"></i>
|
{{ trans('import.job_config_file_upload_submit') }} <i class="fa fa-arrow-right"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
{% extends "./layout/default" %}
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
{{ Breadcrumbs.render(Route.getCurrentRoute.getName, job) }}
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ trans('import.csv_initial_title') }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p>
|
|
||||||
{{ trans('import.csv_initial_text') }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form class="form-horizontal" action="{{ route('import.configure.post', job.key) }}" method="post" enctype="multipart/form-data">
|
|
||||||
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ trans('import.csv_initial_box_title') }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-6">
|
|
||||||
<h4>{{ 'mandatoryFields'|_ }}</h4>
|
|
||||||
{{ ExpandedForm.checkbox('has_headers',1,job.configuration['has-headers'],{helpText: trans('import.csv_initial_header_help')}) }}
|
|
||||||
{{ ExpandedForm.text('date_format',job.configuration['date-format'],{helpText: trans('import.csv_initial_date_help', {dateExample: phpdate('Ymd')}) }) }}
|
|
||||||
{{ ExpandedForm.select('csv_delimiter', data.delimiters, job.configuration['delimiter'], {helpText: trans('import.csv_initial_delimiter_help') } ) }}
|
|
||||||
{{ ExpandedForm.select('csv_import_account', data.accounts, job.configuration['import-account'], {helpText: trans('import.csv_initial_import_account_help')} ) }}
|
|
||||||
|
|
||||||
<h4>{{ 'optionalFields'|_ }}</h4>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="apply_rules_label" class="col-sm-4 control-label">
|
|
||||||
{{ trans('import.file_apply_rules_title') }}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<div class="checkbox"><label>
|
|
||||||
{{ Form.checkbox('apply_rules', '1',
|
|
||||||
job.configuration['apply-rules'] == true, {'id': 'apply_rules_label'}) }}
|
|
||||||
{{ trans('import.file_apply_rules_description') }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% for type, specific in data.specifics %}
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="{{ type }}_label" class="col-sm-4 control-label">
|
|
||||||
{{ specific.name }}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-8">
|
|
||||||
<div class="checkbox"><label>
|
|
||||||
{{ Form.checkbox('specifics['~type~']', '1',
|
|
||||||
job.configuration.specifics[type] == '1', {'id': type ~ '_label'}) }}
|
|
||||||
{{ specific.description }}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endfor %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12">
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-body">
|
|
||||||
<button type="submit" class="pull-right btn btn-success">
|
|
||||||
{{ trans('import.csv_initial_submit') }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{% endblock %}
|
|
Loading…
Reference in New Issue
Block a user