From 84b6708260c7a8cf8fb6171c9e6c5fbd621203bd Mon Sep 17 00:00:00 2001 From: James Cole Date: Sat, 16 Dec 2017 08:03:35 +0100 Subject: [PATCH] Massive rewrite for import routine, part 1. --- .../Controllers/Import/BankController.php | 76 ++------------ .../Import/ConfigurationController.php | 87 ++++++++++++++++ .../Controllers/Import/FileController.php | 5 +- .../Controllers/Import/IndexController.php | 72 +++++++++++++ .../Import/PrerequisitesController.php | 97 ++++++++++++++++++ app/Http/Controllers/ImportController.php | 72 ------------- .../ConfiguratorInterface.php | 2 +- .../FileConfigurator.php} | 35 ++++--- .../SpectreConfigurator.php | 18 ++-- .../Prerequisites/BunqPrerequisites.php | 4 +- .../Prerequisites/FilePrerequisites.php | 96 +++++++++++++++++ .../Prerequisites/PrerequisitesInterface.php | 2 +- .../Prerequisites/SpectrePrerequisites.php | 2 +- .../ImportJob/ImportJobRepository.php | 19 ++-- .../ImportJobRepositoryInterface.php | 4 +- .../Configuration/{Csv => File}/Initial.php | 2 +- .../Configuration/{Csv => File}/Map.php | 2 +- .../Configuration/{Csv => File}/Roles.php | 2 +- .../Import/Configuration/File/Upload.php | 89 ++++++++++++++++ config/firefly.php | 9 -- config/import.php | 42 ++++++++ public/images/logos/file.png | Bin 0 -> 2399 bytes public/js/ff/import/status.js | 3 + resources/lang/en_US/firefly.php | 2 +- .../views/import/{csv => file}/initial.twig | 2 +- resources/views/import/{csv => file}/map.twig | 2 +- .../views/import/{csv => file}/roles.twig | 2 +- resources/views/import/file/status.twig | 15 ++- resources/views/import/file/upload.twig | 53 ++++++++++ resources/views/import/index.twig | 53 ++++++---- .../views/import/spectre/input-fields.twig | 2 +- .../views/import/spectre/select-country.twig | 2 +- .../views/import/spectre/select-provider.twig | 4 +- routes/web.php | 38 +++---- 34 files changed, 671 insertions(+), 244 deletions(-) create mode 100644 app/Http/Controllers/Import/ConfigurationController.php create mode 100644 app/Http/Controllers/Import/IndexController.php create mode 100644 app/Http/Controllers/Import/PrerequisitesController.php delete mode 100644 app/Http/Controllers/ImportController.php rename app/Import/{Configurator => Configuration}/ConfiguratorInterface.php (97%) rename app/Import/{Configurator/CsvConfigurator.php => Configuration/FileConfigurator.php} (82%) rename app/Import/{Configurator => Configuration}/SpectreConfigurator.php (88%) rename app/{Support => }/Import/Prerequisites/BunqPrerequisites.php (99%) create mode 100644 app/Import/Prerequisites/FilePrerequisites.php rename app/{Support => }/Import/Prerequisites/PrerequisitesInterface.php (97%) rename app/{Support => }/Import/Prerequisites/SpectrePrerequisites.php (99%) rename app/Support/Import/Configuration/{Csv => File}/Initial.php (98%) rename app/Support/Import/Configuration/{Csv => File}/Map.php (99%) rename app/Support/Import/Configuration/{Csv => File}/Roles.php (99%) create mode 100644 app/Support/Import/Configuration/File/Upload.php create mode 100644 config/import.php create mode 100644 public/images/logos/file.png rename resources/views/import/{csv => file}/initial.twig (97%) rename resources/views/import/{csv => file}/map.twig (96%) rename resources/views/import/{csv => file}/roles.twig (97%) create mode 100644 resources/views/import/file/upload.twig diff --git a/app/Http/Controllers/Import/BankController.php b/app/Http/Controllers/Import/BankController.php index 125f8968d3..1b9358eed9 100644 --- a/app/Http/Controllers/Import/BankController.php +++ b/app/Http/Controllers/Import/BankController.php @@ -50,80 +50,16 @@ class BankController extends Controller if (!class_exists($class)) { throw new FireflyException(sprintf('Cannot find class %s', $class)); } - $importJob = $repository->create($bank); + $importJob = $repository->create($bank); + $config = $importJob->configuration; + $config['has-config-file'] = false; + $config['auto-start'] = true; + $importJob->configuration = $config; + $importJob->save(); return redirect(route('import.file.configure', [$importJob->key])); } - /** - * This method processes the prerequisites the user has entered in the previous step. - * - * Whatever storePrerequisites does, it should make sure that the system is ready to continue immediately. So - * no extra calls or stuff, except maybe to open a session - * - * @see PrerequisitesInterface::storePrerequisites - * - * @param Request $request - * @param string $bank - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * @throws FireflyException - */ - public function postPrerequisites(Request $request, string $bank) - { - Log::debug(sprintf('Now in postPrerequisites for %s', $bank)); - $class = config(sprintf('firefly.import_pre.%s', $bank)); - if (!class_exists($class)) { - throw new FireflyException(sprintf('Cannot find class %s', $class)); - } - /** @var PrerequisitesInterface $object */ - $object = app($class); - $object->setUser(auth()->user()); - if (!$object->hasPrerequisites()) { - Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank)); - return redirect(route('import.bank.create-job', [$bank])); - } - Log::debug('Going to store entered preprerequisites.'); - // store post data - $result = $object->storePrerequisites($request); - if ($result->count() > 0) { - Session::flash('error', $result->first()); - - return redirect(route('import.bank.prerequisites', [$bank])); - } - - return redirect(route('import.bank.create-job', [$bank])); - } - - /** - * This method shows you, if necessary, a form that allows you to enter any required values, such as API keys, - * login passwords or other values. - * - * @param string $bank - * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View - * @throws FireflyException - */ - public function prerequisites(string $bank) - { - $class = config(sprintf('firefly.import_pre.%s', $bank)); - if (!class_exists($class)) { - throw new FireflyException(sprintf('Cannot find class %s', $class)); - } - /** @var PrerequisitesInterface $object */ - $object = app($class); - $object->setUser(auth()->user()); - - if ($object->hasPrerequisites()) { - $view = $object->getView(); - $parameters = ['title' => strval(trans('firefly.import_index_title')), 'mainTitleIcon' => 'fa-archive']; - $parameters = $object->getViewParameters() + $parameters; - - return view($view, $parameters); - } - - return redirect(route('import.bank.create-job', [$bank])); - } } diff --git a/app/Http/Controllers/Import/ConfigurationController.php b/app/Http/Controllers/Import/ConfigurationController.php new file mode 100644 index 0000000000..79ea3ae368 --- /dev/null +++ b/app/Http/Controllers/Import/ConfigurationController.php @@ -0,0 +1,87 @@ +middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-archive'); + app('view')->share('title', trans('firefly.import_index_title')); + $this->repository = app(ImportJobRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** + * Configure the job. This method is returned to until job is deemed "configured". + * + * @param ImportJob $job + * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View + * @throws FireflyException + */ + public function index(ImportJob $job) + { + // create configuration class: + $configurator = $this->makeConfigurator($job); + + // is the job already configured? + if ($configurator->isJobConfigured()) { + $this->repository->updateStatus($job, 'configured'); + + return redirect(route('import.file.status', [$job->key])); + } + $view = $configurator->getNextView(); + $data = $configurator->getNextData(); + $subTitle = trans('firefly.import_config_bread_crumb'); + $subTitleIcon = 'fa-wrench'; + + return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon')); + } + + /** + * @param ImportJob $job + * + * @return ConfiguratorInterface + * + * @throws FireflyException + */ + private function makeConfigurator(ImportJob $job): ConfiguratorInterface + { + $type = $job->file_type; + $key = sprintf('import.configuration.%s', $type); + $className = config($key); + if (null === $className || !class_exists($className)) { + throw new FireflyException(sprintf('Cannot find configurator class for job of type "%s".',$type)); // @codeCoverageIgnore + } + /** @var ConfiguratorInterface $configurator */ + $configurator = app($className); + $configurator->setJob($job); + + return $configurator; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Import/FileController.php b/app/Http/Controllers/Import/FileController.php index ff6c86b48c..575c47ae1f 100644 --- a/app/Http/Controllers/Import/FileController.php +++ b/app/Http/Controllers/Import/FileController.php @@ -54,8 +54,8 @@ class FileController extends Controller $this->middleware( function ($request, $next) { - View::share('mainTitleIcon', 'fa-archive'); - View::share('title', trans('firefly.import_index_title')); + app('view')->share('mainTitleIcon', 'fa-archive'); + app('view')->share('title', trans('firefly.import_index_title')); $this->repository = app(ImportJobRepositoryInterface::class); return $next($request); @@ -107,6 +107,7 @@ class FileController extends Controller $config['column-roles-complete'] = false; $config['column-mapping-complete'] = false; $config['initial-config-complete'] = false; + $config['has-file-upload'] = false; $config['delimiter'] = "\t" === $config['delimiter'] ? 'tab' : $config['delimiter']; $result = json_encode($config, JSON_PRETTY_PRINT); diff --git a/app/Http/Controllers/Import/IndexController.php b/app/Http/Controllers/Import/IndexController.php new file mode 100644 index 0000000000..efaf516f35 --- /dev/null +++ b/app/Http/Controllers/Import/IndexController.php @@ -0,0 +1,72 @@ +middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-archive'); + app('view')->share('title', trans('firefly.import_index_title')); + $this->repository = app(ImportJobRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** + * Creates a new import job for $bank with the default (global) job configuration. + * + * @param string $bank + * + * @throws FireflyException + */ + public function create(string $bank) + { + if (!(config(sprintf('import.enabled.%s', $bank))) === true) { + throw new FireflyException(sprintf('Cannot import from "%s" at this time.', $bank)); + } + + $importJob = $this->repository->create($bank); + + // from here, always go to configure step. + return redirect(route('import.configure', [$importJob->key])); + + } + + /** + * General import index. + * + * @return View + */ + public function index() + { + $subTitle = trans('firefly.import_index_sub_title'); + $subTitleIcon = 'fa-home'; + $routines = config('import.enabled'); + + return view('import.index', compact('subTitle', 'subTitleIcon', 'routines')); + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Import/PrerequisitesController.php b/app/Http/Controllers/Import/PrerequisitesController.php new file mode 100644 index 0000000000..3f475d4d8e --- /dev/null +++ b/app/Http/Controllers/Import/PrerequisitesController.php @@ -0,0 +1,97 @@ +setUser(auth()->user()); + + if ($object->hasPrerequisites()) { + $view = $object->getView(); + $parameters = ['title' => strval(trans('firefly.import_index_title')), 'mainTitleIcon' => 'fa-archive']; + $parameters = $object->getViewParameters() + $parameters; + + return view($view, $parameters); + } + + // if no (more) prerequisites, return to create a job: + return redirect(route('import.create-job', [$bank])); + } + + /** + * This method processes the prerequisites the user has entered in the previous step. + * + * Whatever storePrerequisites does, it should make sure that the system is ready to continue immediately. So + * no extra calls or stuff, except maybe to open a session + * + * @see PrerequisitesInterface::storePrerequisites + * + * @param Request $request + * @param string $bank + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws FireflyException + */ + public function postPrerequisites(Request $request, string $bank) + { + Log::debug(sprintf('Now in postPrerequisites for %s', $bank)); + $class = config(sprintf('firefly.import_pre.%s', $bank)); + if (!class_exists($class)) { + throw new FireflyException(sprintf('Cannot find class %s', $class)); + } + /** @var PrerequisitesInterface $object */ + $object = app($class); + $object->setUser(auth()->user()); + if (!$object->hasPrerequisites()) { + Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank)); + + return redirect(route('import.create-job', [$bank])); + } + Log::debug('Going to store entered prerequisites.'); + // store post data + $result = $object->storePrerequisites($request); + + if ($result->count() > 0) { + $request->session()->flash('error', $result->first()); + + return redirect(route('import.prerequisites', [$bank])); + } + + return redirect(route('import.create-job', [$bank])); + } + + +} \ No newline at end of file diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php deleted file mode 100644 index 8d513b1e91..0000000000 --- a/app/Http/Controllers/ImportController.php +++ /dev/null @@ -1,72 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Http\Controllers; - -use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; -use View; - -/** - * Class ImportController. - */ -class ImportController extends Controller -{ - /** @var ImportJobRepositoryInterface */ - public $repository; - - /** - * - */ - public function __construct() - { - parent::__construct(); - - $this->middleware( - function ($request, $next) { - View::share('mainTitleIcon', 'fa-archive'); - View::share('title', trans('firefly.import_index_title')); - $this->repository = app(ImportJobRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * General import index. - * - * @return View - */ - public function index() - { - $subTitle = trans('firefly.import_index_sub_title'); - $subTitleIcon = 'fa-home'; - $importFileTypes = []; - $defaultImportType = config('firefly.default_import_format'); - - foreach (array_keys(config('firefly.import_formats')) as $type) { - $importFileTypes[$type] = trans('firefly.import_file_type_' . $type); - } - - return view('import.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType')); - } -} diff --git a/app/Import/Configurator/ConfiguratorInterface.php b/app/Import/Configuration/ConfiguratorInterface.php similarity index 97% rename from app/Import/Configurator/ConfiguratorInterface.php rename to app/Import/Configuration/ConfiguratorInterface.php index a6781310c7..3e5ad71f30 100644 --- a/app/Import/Configurator/ConfiguratorInterface.php +++ b/app/Import/Configuration/ConfiguratorInterface.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Import\Configurator; +namespace FireflyIII\Import\Configuration; use FireflyIII\Models\ImportJob; diff --git a/app/Import/Configurator/CsvConfigurator.php b/app/Import/Configuration/FileConfigurator.php similarity index 82% rename from app/Import/Configurator/CsvConfigurator.php rename to app/Import/Configuration/FileConfigurator.php index 79593ca556..1638f017c8 100644 --- a/app/Import/Configurator/CsvConfigurator.php +++ b/app/Import/Configuration/FileConfigurator.php @@ -1,6 +1,6 @@ job->configuration['has-file-upload']) { + return 'import.file.upload'; + } if (!$this->job->configuration['initial-config-complete']) { - return 'import.csv.initial'; + return 'import.file.initial'; } if (!$this->job->configuration['column-roles-complete']) { - return 'import.csv.roles'; + return 'import.file.roles'; } if (!$this->job->configuration['column-mapping-complete']) { - return 'import.csv.map'; + return 'import.file.map'; } throw new FireflyException('No view for state'); @@ -124,15 +128,17 @@ class CsvConfigurator implements ConfiguratorInterface public function isJobConfigured(): bool { $config = $this->job->configuration; + $config['has-file-upload'] = $config['has-file-upload'] ?? false; $config['initial-config-complete'] = $config['initial-config-complete'] ?? false; $config['column-roles-complete'] = $config['column-roles-complete'] ?? false; $config['column-mapping-complete'] = $config['column-mapping-complete'] ?? false; $this->job->configuration = $config; $this->job->save(); - if ($this->job->configuration['initial-config-complete'] - && $this->job->configuration['column-roles-complete'] - && $this->job->configuration['column-mapping-complete'] + if ($config['initial-config-complete'] + && $config['column-roles-complete'] + && $config['column-mapping-complete'] + && $config['has-file-upload'] ) { return true; } @@ -162,6 +168,9 @@ class CsvConfigurator implements ConfiguratorInterface { $class = false; switch (true) { + case !$this->job->configuration['has-file-upload']: + $class = Upload::class; + break; case !$this->job->configuration['initial-config-complete']: $class = Initial::class; break; diff --git a/app/Import/Configurator/SpectreConfigurator.php b/app/Import/Configuration/SpectreConfigurator.php similarity index 88% rename from app/Import/Configurator/SpectreConfigurator.php rename to app/Import/Configuration/SpectreConfigurator.php index da118f8363..d2cb4a6a33 100644 --- a/app/Import/Configurator/SpectreConfigurator.php +++ b/app/Import/Configuration/SpectreConfigurator.php @@ -20,14 +20,14 @@ */ declare(strict_types=1); -namespace FireflyIII\Import\Configurator; +namespace FireflyIII\Import\Configuration; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ImportJob; use FireflyIII\Support\Import\Configuration\ConfigurationInterface; -use FireflyIII\Support\Import\Configuration\Spectre\SelectProvider; use FireflyIII\Support\Import\Configuration\Spectre\InputMandatory; use FireflyIII\Support\Import\Configuration\Spectre\SelectCountry; +use FireflyIII\Support\Import\Configuration\Spectre\SelectProvider; use Log; /** @@ -123,14 +123,16 @@ class SpectreConfigurator implements ConfiguratorInterface */ public function isJobConfigured(): bool { - $config = $this->job->configuration; - $config['selected-country'] = $config['selected-country'] ?? false; - $config['selected-provider'] = $config['selected-provider'] ?? false; - $config['has-input-mandatory'] = $config['has-input-mandatory'] ?? false; - $this->job->configuration = $config; + $config = $this->job->configuration; + $config['selected-country'] = $config['selected-country'] ?? false; + $config['selected-provider'] = $config['selected-provider'] ?? false; + $config['has-input-mandatory'] = $config['has-input-mandatory'] ?? false; + $config['has-input-interactive'] = $config['has-input-interactive'] ?? true; // defaults to true. + $this->job->configuration = $config; $this->job->save(); - if ($config['selected-country'] && $config['selected-provider'] && $config['has-input-mandatory'] && false) { + if ($config['selected-country'] && $config['selected-provider'] && $config['has-input-mandatory'] && $config['has-input-interactive']) { + // give job another status return true; } diff --git a/app/Support/Import/Prerequisites/BunqPrerequisites.php b/app/Import/Prerequisites/BunqPrerequisites.php similarity index 99% rename from app/Support/Import/Prerequisites/BunqPrerequisites.php rename to app/Import/Prerequisites/BunqPrerequisites.php index 75614b3762..b2ec238eb4 100644 --- a/app/Support/Import/Prerequisites/BunqPrerequisites.php +++ b/app/Import/Prerequisites/BunqPrerequisites.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Prerequisites; +namespace FireflyIII\Import\Prerequisites; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Services\Bunq\Id\DeviceServerId; @@ -332,4 +332,4 @@ class BunqPrerequisites implements PrerequisitesInterface return $deviceServerId; } -} +} \ No newline at end of file diff --git a/app/Import/Prerequisites/FilePrerequisites.php b/app/Import/Prerequisites/FilePrerequisites.php new file mode 100644 index 0000000000..8456cbc457 --- /dev/null +++ b/app/Import/Prerequisites/FilePrerequisites.php @@ -0,0 +1,96 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Import\Prerequisites; + +use FireflyIII\User; +use Illuminate\Http\Request; +use Illuminate\Support\MessageBag; + +/** + * This class contains all the routines necessary to import from a file. Hint: there are none. + */ +class FilePrerequisites implements PrerequisitesInterface +{ + /** @var User */ + private $user; + + /** + * Returns view name that allows user to fill in prerequisites. Currently asks for the API key. + * + * @return string + */ + public function getView(): string + { + return ''; + } + + /** + * Returns any values required for the prerequisites-view. + * + * @return array + */ + public function getViewParameters(): array + { + return []; + } + + /** + * Returns if this import method has any special prerequisites such as config + * variables or other things. The only thing we verify is the presence of the API key. Everything else + * tumbles into place: no installation token? Will be requested. No device server? Will be created. Etc. + * + * True if prerequisites. False if not. + * + * @return bool + */ + public function hasPrerequisites(): bool + { + return false; + } + + /** + * Set the user for this Prerequisites-routine. Class is expected to implement and save this. + * + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + + return; + } + + /** + * This method responds to the user's submission of an API key. It tries to register this instance as a new Firefly III device. + * If this fails, the error is returned in a message bag and the user is notified (this is fairly friendly). + * + * @param Request $request + * + * @return MessageBag + */ + public function storePrerequisites(Request $request): MessageBag + { + return new MessageBag; + } + +} diff --git a/app/Support/Import/Prerequisites/PrerequisitesInterface.php b/app/Import/Prerequisites/PrerequisitesInterface.php similarity index 97% rename from app/Support/Import/Prerequisites/PrerequisitesInterface.php rename to app/Import/Prerequisites/PrerequisitesInterface.php index e52fad7d61..0423f696e0 100644 --- a/app/Support/Import/Prerequisites/PrerequisitesInterface.php +++ b/app/Import/Prerequisites/PrerequisitesInterface.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Prerequisites; +namespace FireflyIII\Import\Prerequisites; use FireflyIII\User; use Illuminate\Http\Request; diff --git a/app/Support/Import/Prerequisites/SpectrePrerequisites.php b/app/Import/Prerequisites/SpectrePrerequisites.php similarity index 99% rename from app/Support/Import/Prerequisites/SpectrePrerequisites.php rename to app/Import/Prerequisites/SpectrePrerequisites.php index d67960b139..3e6fae0b0a 100644 --- a/app/Support/Import/Prerequisites/SpectrePrerequisites.php +++ b/app/Import/Prerequisites/SpectrePrerequisites.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Prerequisites; +namespace FireflyIII\Import\Prerequisites; use FireflyIII\Jobs\GetSpectreProviders; use FireflyIII\Models\Preference; diff --git a/app/Repositories/ImportJob/ImportJobRepository.php b/app/Repositories/ImportJob/ImportJobRepository.php index c3bef54aee..c2e3bd81d6 100644 --- a/app/Repositories/ImportJob/ImportJobRepository.php +++ b/app/Repositories/ImportJob/ImportJobRepository.php @@ -42,20 +42,16 @@ class ImportJobRepository implements ImportJobRepositoryInterface private $user; /** - * @param string $fileType + * @param string $type * * @return ImportJob * * @throws FireflyException */ - public function create(string $fileType): ImportJob + public function create(string $type): ImportJob { - $count = 0; - $fileType = strtolower($fileType); - $keys = array_keys(config('firefly.import_formats')); - if (!in_array($fileType, $keys)) { - throw new FireflyException(sprintf('Cannot use type "%s" for import job.', $fileType)); - } + $count = 0; + $type = strtolower($type); while ($count < 30) { $key = Str::random(12); @@ -63,10 +59,10 @@ class ImportJobRepository implements ImportJobRepositoryInterface if (null === $existing->id) { $importJob = new ImportJob; $importJob->user()->associate($this->user); - $importJob->file_type = $fileType; + $importJob->file_type = $type; $importJob->key = Str::random(12); $importJob->status = 'new'; - $importJob->configuration = []; + $importJob->configuration = config(sprintf('import.default_config.%s', $type)) ?? []; $importJob->extended_status = [ 'steps' => 0, 'done' => 0, @@ -80,8 +76,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface } ++$count; } - - return new ImportJob; + throw new FireflyException('Could not create an import job with a unique key after 30 tries.'); } /** diff --git a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php index ad74c4e021..a2a9869eaf 100644 --- a/app/Repositories/ImportJob/ImportJobRepositoryInterface.php +++ b/app/Repositories/ImportJob/ImportJobRepositoryInterface.php @@ -32,11 +32,11 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; interface ImportJobRepositoryInterface { /** - * @param string $fileType + * @param string $type * * @return ImportJob */ - public function create(string $fileType): ImportJob; + public function create(string $type): ImportJob; /** * @param string $key diff --git a/app/Support/Import/Configuration/Csv/Initial.php b/app/Support/Import/Configuration/File/Initial.php similarity index 98% rename from app/Support/Import/Configuration/Csv/Initial.php rename to app/Support/Import/Configuration/File/Initial.php index 88a3ca00e2..0e5e903ec8 100644 --- a/app/Support/Import/Configuration/Csv/Initial.php +++ b/app/Support/Import/Configuration/File/Initial.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Configuration\Csv; +namespace FireflyIII\Support\Import\Configuration\File; use ExpandedForm; use FireflyIII\Models\AccountType; diff --git a/app/Support/Import/Configuration/Csv/Map.php b/app/Support/Import/Configuration/File/Map.php similarity index 99% rename from app/Support/Import/Configuration/Csv/Map.php rename to app/Support/Import/Configuration/File/Map.php index 449124bbb8..fa7b7428e2 100644 --- a/app/Support/Import/Configuration/Csv/Map.php +++ b/app/Support/Import/Configuration/File/Map.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Configuration\Csv; +namespace FireflyIII\Support\Import\Configuration\File; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Import\Mapper\MapperInterface; diff --git a/app/Support/Import/Configuration/Csv/Roles.php b/app/Support/Import/Configuration/File/Roles.php similarity index 99% rename from app/Support/Import/Configuration/Csv/Roles.php rename to app/Support/Import/Configuration/File/Roles.php index f0d1f206c5..f39f698d2b 100644 --- a/app/Support/Import/Configuration/Csv/Roles.php +++ b/app/Support/Import/Configuration/File/Roles.php @@ -20,7 +20,7 @@ */ declare(strict_types=1); -namespace FireflyIII\Support\Import\Configuration\Csv; +namespace FireflyIII\Support\Import\Configuration\File; use FireflyIII\Import\Specifics\SpecificInterface; use FireflyIII\Models\ImportJob; diff --git a/app/Support/Import/Configuration/File/Upload.php b/app/Support/Import/Configuration/File/Upload.php new file mode 100644 index 0000000000..b31e2915b9 --- /dev/null +++ b/app/Support/Import/Configuration/File/Upload.php @@ -0,0 +1,89 @@ +. + */ +declare(strict_types=1); + +namespace FireflyIII\Support\Import\Configuration\File; + +use FireflyIII\Import\Specifics\SpecificInterface; +use FireflyIII\Models\ImportJob; +use FireflyIII\Support\Import\Configuration\ConfigurationInterface; +use League\Csv\Reader; +use League\Csv\Statement; +use Log; + +/** + * Class Upload. + */ +class Upload implements ConfigurationInterface +{ + /** @var ImportJob */ + private $job; + + /** @var string */ + private $warning = ''; + + /** + * Get the data necessary to show the configuration screen. + * + * @return array + */ + public function getData(): array + { + return []; + } + + /** + * Return possible warning to user. + * + * @return string + */ + public function getWarningMessage(): string + { + return $this->warning; + } + + /** + * @param ImportJob $job + * + * @return ConfigurationInterface + */ + public function setJob(ImportJob $job): ConfigurationInterface + { + $this->job = $job; + + return $this; + } + + /** + * Store the result. + * + * @param array $data + * + * @return bool + */ + public function storeConfiguration(array $data): bool + { + echo 'do something with data.'; + exit; + return true; + } + +} diff --git a/config/firefly.php b/config/firefly.php index 3552a917ee..e389c8bc5d 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -44,18 +44,9 @@ return [ 'csv' => 'FireflyIII\Import\Configurator\CsvConfigurator', 'spectre' => '', ], - 'import_configurators' => [ - 'csv' => 'FireflyIII\Import\Configurator\CsvConfigurator', - 'spectre' => 'FireflyIII\Import\Configurator\SpectreConfigurator', - ], 'import_processors' => [ 'csv' => 'FireflyIII\Import\FileProcessor\CsvProcessor', ], - 'import_pre' => [ - 'bunq' => 'FireflyIII\Support\Import\Prerequisites\BunqPrerequisites', - 'spectre' => 'FireflyIII\Support\Import\Prerequisites\SpectrePrerequisites', - 'plaid' => 'FireflyIII\Support\Import\Prerequisites\PlaidPrerequisites', - ], 'import_info' => [ 'bunq' => 'FireflyIII\Support\Import\Information\BunqInformation', 'spectre' => 'FireflyIII\Support\Import\Information\SpectreInformation', diff --git a/config/import.php b/config/import.php new file mode 100644 index 0000000000..ad8a9d1ff3 --- /dev/null +++ b/config/import.php @@ -0,0 +1,42 @@ + [ + 'file' => true, + 'bunq' => true, + 'spectre' => true, + 'plaid' => true, + ], + 'prerequisites' => [ + 'file' => 'FireflyIII\Import\Prerequisites\FilePrerequisites', + 'bunq' => 'FireflyIII\Import\Prerequisites\BunqPrerequisites', + 'spectre' => 'FireflyIII\Import\Prerequisites\SpectrePrerequisites', + 'plaid' => 'FireflyIII\Import\Prerequisites\PlaidPrerequisites', + + ], + 'configuration' => [ + 'file' => 'FireflyIII\Import\Configuration\FileConfigurator', + 'bunq' => 'FireflyIII\Import\Configuration\BunqConfigurator', + 'spectre' => 'FireflyIII\Import\Configuration\SpectreConfigurator', + 'plaid' => 'FireflyIII\Import\Configuration\PlaidConfigurator', + ], + 'default_config' => [ + 'file' => [ + 'has-config-file' => true, + 'auto-start' => false, + ], + 'bunq' => [ + 'has-config-file' => false, + 'auto-start' => true, + ], + 'spectre' => [ + 'has-config-file' => false, + 'auto-start' => true, + ], + 'plaid' => [ + 'has-config-file' => false, + 'auto-start' => true, + ], + ], +]; \ No newline at end of file diff --git a/public/images/logos/file.png b/public/images/logos/file.png new file mode 100644 index 0000000000000000000000000000000000000000..0024f8af419524303cfc8ff70c14412df89883a1 GIT binary patch literal 2399 zcmZ`*3se)=77c%d2vuHHguZ4WAo?_u1PmdB2m}QbkU$Cv_$mPg2@n#K0b&)9pyolX zA3lowl~2?@F{lNBWk67mU$_wXQBsUhthHzqB>sf8u->55B4Jy__8pB~Oh<;K>@U3xkh9#HGkD6{C}4 zIs&0?%A(OBy1N@Oh{HxRgE@g9TEOPQY`kft`thL4?P07%)L8 zC{Vba3EkZjMd9#3)Go9Y8e>A%L7`A2UT_G}%W3bj9G=;kghCLP2mmoLG3XdeG>3N> zz}nc@02myA!|j9_JNZW=A*NtwB!A1&B7d#p1oDG;EH1?2M55&DG6OkLke!K%JkiJB zQk@VhAwI0b zu9^<+?MLC?iWD%pOUV>XT=GVeS5EW-`J9L-c?-UYWI<#cNnvOu{HY^LDhh|q<$-)Y zEFE7^)PjL)S}3MdJKgNXd7z%VcfQra(g z*A!2`H+Te4f=R%tY!dt|5ZyV!tdOHlOb8_7Fj#9M7DvS5Q5eO*8s6#^9Hk265eg4v zLL45A!-*g(T(IR+lqK4FNvRxPmXZMZIZ`@TONUm0!l#z311tY}1CVt*q5(hnebMIX zGk>VfTQsv?s zZ{w<}x(_wpo(ILP15;8p-)UpqE|z_5E)3yKyPsT)W{-<2N()44A{Ei|uSPn_Q~nI>9ZBVE z5cA+rsfxM1@FHWHZL?UO4MW-^Jn{7Hv0I)Z89WA*XZ4?O^f-axUb9a z+uX0rT1(X@9Kvfh9jpFva}3`4Qi#y8VMFIBpH8iij>>UTAy-xLS@Gq&X$EAh&MMA!AslV}&Ue z)XV{=qE;<)ndE@ydb8PnFk|k9M*O34b*lO=gOV<3rs^LZ0`xm-5uWlk#=HVzrP;T> z+0bfr?`?8LP5b>iFJBJjyziz0!t|jJkCIO!Q}>e=4hDz|FJy=ZYwxbZ%rx;W{+XKU zj0yBFtf9?5cv9UD*bk|97@i@m4`|p{Y*9n|a%Y}?WTv^aQFbDwF(K{oOV|3T4^uR; zjvIB{UQ@UD7SZ?ToVrNhsfx{o2Sw86`&@&N?g=2R9IKu)Uj3tsx#F+a+?cESU%AL-!B1vx+!3BDZTM;Xu-~1HE(gLf4i*6o z>N#$s>2-0}8P5ne>gwj=g*KAR+!!_mJ?KSQG@*DX1b()tx7ASZBIK-keAM*mc?7vjMJHohGou%ae|^}LFL3KNFvKGXw(D-y z8V=1iY1I4IzkOfbQhPaGSn$~Q_sfS 'Import data into Firefly III', 'import_index_sub_title' => 'Index', 'import_general_index_intro' => 'Welcome to Firefly\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', - 'import_general_index_csv_file' => 'Import a (CSV) file', + 'import_general_index_file' => 'Import a file', 'import_index_intro' => 'This routine will help you import files from your bank into Firefly III. Please check out the help pages in the top right corner.', 'import_index_file' => 'Select your file', 'import_index_config' => '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 configuration file.', diff --git a/resources/views/import/csv/initial.twig b/resources/views/import/file/initial.twig similarity index 97% rename from resources/views/import/csv/initial.twig rename to resources/views/import/file/initial.twig index dce077adea..fbefb1b37c 100644 --- a/resources/views/import/csv/initial.twig +++ b/resources/views/import/file/initial.twig @@ -22,7 +22,7 @@ -
+
diff --git a/resources/views/import/csv/map.twig b/resources/views/import/file/map.twig similarity index 96% rename from resources/views/import/csv/map.twig rename to resources/views/import/file/map.twig index 8f25f984f4..edc4b4b5bb 100644 --- a/resources/views/import/csv/map.twig +++ b/resources/views/import/file/map.twig @@ -22,7 +22,7 @@
- + {% for field in data %} diff --git a/resources/views/import/csv/roles.twig b/resources/views/import/file/roles.twig similarity index 97% rename from resources/views/import/csv/roles.twig rename to resources/views/import/file/roles.twig index f87ae66ec9..f35b92bfe4 100644 --- a/resources/views/import/csv/roles.twig +++ b/resources/views/import/file/roles.twig @@ -21,7 +21,7 @@ - + diff --git a/resources/views/import/file/status.twig b/resources/views/import/file/status.twig index 51858bf20c..b8b89ef64b 100644 --- a/resources/views/import/file/status.twig +++ b/resources/views/import/file/status.twig @@ -53,12 +53,17 @@

- {{ 'import_status_ready_text'|_ }} + {% if job.configuration['has-config-file'] == false %} + This should only be visible momentarily. + {% else %} + {{ 'import_status_ready_text'|_ }} + {% endif %}

php artisan firefly:start-import {{ job.key }}

+ {% if job.configuration['has-config-file'] != false %}
{{ 'import_status_ready_config'|_ }} @@ -66,13 +71,16 @@
+ {% endif %}
+ {% if job.configuration['has-config-file'] != false %}

 

{{ 'import_status_ready_share'|_ }}

+ {% endif %}
@@ -145,6 +153,11 @@ var jobImportUrl = '{{ route('import.file.json', [job.key]) }}'; var jobStartUrl = '{{ route('import.file.start', [job.key]) }}'; var token = '{{ csrf_token() }}'; + {% if job.configuration['auto-start'] == true %} + var autoStart = true; + {% else %} + var autoStart = false; + {% endif %} {% endblock %} diff --git a/resources/views/import/file/upload.twig b/resources/views/import/file/upload.twig new file mode 100644 index 0000000000..50c184e58d --- /dev/null +++ b/resources/views/import/file/upload.twig @@ -0,0 +1,53 @@ +{% extends "./layout/default" %} + +{% block breadcrumbs %} + {{ Breadcrumbs.renderIfExists }} +{% endblock %} +{% block content %} +
+
+
+
+

{{ 'import_index_title'|_ }}

+
+
+
+
+

+ {{ 'import_index_intro'|_ }} +

+
+
+ +
+ + + + +
+ + {{ ExpandedForm.file('import_file', {helpText: 'import_index_file'|_}) }} + {{ ExpandedForm.file('configuration_file', {helpText: 'import_index_config'|_|raw}) }} + {{ ExpandedForm.select('import_file_type', importFileTypes, defaultImportType, {'helpText' : 'import_index_type'|_}) }} + +
+ +
+ +
+
+
+ +
+
+
+
+
+{% endblock %} +{% block scripts %} +{% endblock %} +{% block styles %} +{% endblock %} diff --git a/resources/views/import/index.twig b/resources/views/import/index.twig index e83cef961b..73cfa3cad4 100644 --- a/resources/views/import/index.twig +++ b/resources/views/import/index.twig @@ -21,39 +21,50 @@ + {% endif %} + + {# import from Plaid #} + {% if routines.plaid == true %} + + {% endif %} + {% endblock %} {% block scripts %} {% endblock %} diff --git a/resources/views/import/spectre/input-fields.twig b/resources/views/import/spectre/input-fields.twig index de77ba5b3f..03aae3faf2 100644 --- a/resources/views/import/spectre/input-fields.twig +++ b/resources/views/import/spectre/input-fields.twig @@ -5,7 +5,7 @@ {% endblock %} {% block content %}
-
+
diff --git a/resources/views/import/spectre/select-country.twig b/resources/views/import/spectre/select-country.twig index ba4f4a0c59..6f27099bba 100644 --- a/resources/views/import/spectre/select-country.twig +++ b/resources/views/import/spectre/select-country.twig @@ -5,7 +5,7 @@ {% endblock %} {% block content %}
- +
diff --git a/resources/views/import/spectre/select-provider.twig b/resources/views/import/spectre/select-provider.twig index 5be257d082..d4c554d379 100644 --- a/resources/views/import/spectre/select-provider.twig +++ b/resources/views/import/spectre/select-provider.twig @@ -5,12 +5,12 @@ {% endblock %} {% block content %}
- +
-

{{ trans('bank.spectre_select_bank_title') }}

+

{{ trans('bank.spectre_select_provider_title') }}

diff --git a/routes/web.php b/routes/web.php index 5cb2d597d6..ee79111ec4 100755 --- a/routes/web.php +++ b/routes/web.php @@ -427,28 +427,30 @@ Route::group( Route::group( ['middleware' => 'user-full-auth', 'prefix' => 'import', 'as' => 'import.'], function () { - Route::get('', ['uses' => 'ImportController@index', 'as' => 'index']); + Route::get('', ['uses' => 'Import\IndexController@index', 'as' => 'index']); + + // import method prerequisites: + Route::get('prerequisites/{bank}', ['uses' => 'Import\PrerequisitesController@index', 'as' => 'prerequisites']); + Route::post('prerequisites/{bank}', ['uses' => 'Import\PrerequisitesController@post', 'as' => 'prerequisites.post']); + + // create the job: + Route::get('create/{bank}', ['uses' => 'Import\IndexController@create', 'as' => 'create-job']); + + // configure the job: + Route::get('configure/{importJob}', ['uses' => 'Import\ConfigurationController@index', 'as' => 'configure']); + Route::post('configure/{importJob}', ['uses' => 'Import\ConfigurationController@post', 'as' => 'configure.post']); // file import - Route::get('file', ['uses' => 'Import\FileController@index', 'as' => 'file.index']); - Route::post('file/initialize', ['uses' => 'Import\FileController@initialize', 'as' => 'file.initialize']); + // Route::get('file', ['uses' => 'Import\FileController@index', 'as' => 'file.index']); + // Route::post('file/initialize', ['uses' => 'Import\FileController@initialize', 'as' => 'file.initialize']); - Route::get('file/configure/{importJob}', ['uses' => 'Import\FileController@configure', 'as' => 'file.configure']); - Route::post('file/configure/{importJob}', ['uses' => 'Import\FileController@postConfigure', 'as' => 'file.process-configuration']); - - Route::get('file/download/{importJob}', ['uses' => 'Import\FileController@download', 'as' => 'file.download']); - Route::get('file/status/{importJob}', ['uses' => 'Import\FileController@status', 'as' => 'file.status']); - Route::get('file/json/{importJob}', ['uses' => 'Import\FileController@json', 'as' => 'file.json']); - Route::post('file/start/{importJob}', ['uses' => 'Import\FileController@start', 'as' => 'file.start']); - - // banks: - Route::get('bank/{bank}/prerequisites', ['uses' => 'Import\BankController@prerequisites', 'as' => 'bank.prerequisites']); - Route::post('bank/{bank}/prerequisites', ['uses' => 'Import\BankController@postPrerequisites', 'as' => 'bank.prerequisites.post']); - - Route::get('bank/{bank}/create', ['uses' => 'Import\BankController@createJob', 'as' => 'bank.create-job']); - Route:: get('bank/{bank}/configure/{importJob}', ['uses' => 'Import\BankController@configure', 'as' => 'bank.configure']); - Route::post('bank/{bank}/configure/{importJob}', ['uses' => 'Import\BankController@postConfigure', 'as' => 'bank.configure.post']); + // Route::get('file/download/{importJob}', ['uses' => 'Import\FileController@download', 'as' => 'file.download']); + // Route::get('file/status/{importJob}', ['uses' => 'Import\FileController@status', 'as' => 'file.status']); + // Route::get('file/json/{importJob}', ['uses' => 'Import\FileController@json', 'as' => 'file.json']); + // Route::any('file/start/{importJob}', ['uses' => 'Import\FileController@start', 'as' => 'file.start']); + // Route:: get('bank/{bank}/configure/{importJob}', ['uses' => 'Import\BankController@configure', 'as' => 'bank.configure']); + // Route::post('bank/{bank}/configure/{importJob}', ['uses' => 'Import\BankController@postConfigure', 'as' => 'bank.configure.post']); } );