Skip to content

Commit

Permalink
Merge pull request #1756 from Leantime/csvIntegration
Browse files Browse the repository at this point in the history
Csv Integration
  • Loading branch information
marcelfolaron committed Nov 4, 2023
2 parents 5da656b + 2afff29 commit 4eb77b7
Show file tree
Hide file tree
Showing 46 changed files with 1,928 additions and 430 deletions.
4 changes: 2 additions & 2 deletions app/Core/AppSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
*/
class AppSettings
{
public string $appVersion = "2.4.5";
public string $appVersion = "2.4.7";

public string $dbVersion = "2.4.5";
public string $dbVersion = "2.4.7";

protected Environment $config;

Expand Down
4 changes: 2 additions & 2 deletions app/Core/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,13 @@ public function get(int $id): mixed
/**
* getFieldAttribute - gets the field attribute for a given property
*
* @param string $class - the class to get the attribute from
* @param object|string $class - the class to get the attribute from
* @param string $property - the property to get the attribute from
* @param bool $includeId - whether or not to include the id attribute
* @return array|false
* @throws \ReflectionException
*/
protected function getFieldAttribute(string $class, string $property, bool $includeId = false): array|false
protected function getFieldAttribute(object|string $class, string $property, bool $includeId = false): array|false
{
//Don't create or update id attributes
if ($includeId === false && $property == "id") {
Expand Down
6 changes: 3 additions & 3 deletions app/Domain/Canvas/Repositories/Canvas.php
Original file line number Diff line number Diff line change
Expand Up @@ -966,16 +966,16 @@ public function addCanvasItem($values): false|string

$stmn = $this->db->database->prepare($query);

$stmn->bindValue(':description', $values['description'], PDO::PARAM_STR);
$stmn->bindValue(':description', $values['description'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':title', $values['title'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':assumptions', $values['assumptions'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':data', $values['data'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':conclusion', $values['conclusion'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':box', $values['box'], PDO::PARAM_STR);
$stmn->bindValue(':author', $values['author'], PDO::PARAM_INT);
$stmn->bindValue(':canvasId', $values['canvasId'], PDO::PARAM_INT);
$stmn->bindValue(':status', $values['status'], PDO::PARAM_STR);
$stmn->bindValue(':relates', $values['relates'], PDO::PARAM_STR);
$stmn->bindValue(':status', $values['status'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':relates', $values['relates'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':milestoneId', $values['milestoneId'] ?? "", PDO::PARAM_STR);
$stmn->bindValue(':kpi', $values['kpi'] ?? '', PDO::PARAM_STR);
$stmn->bindValue(':data1', $values['data1'] ?? '', PDO::PARAM_STR);
Expand Down
129 changes: 108 additions & 21 deletions app/Domain/Connector/Controllers/Integration.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
namespace Leantime\Domain\Connector\Controllers {

use Leantime\Core\Controller;
use Leantime\Core\Frontcontroller;
use Leantime\Domain\Auth\Models\Roles;
use Leantime\Domain\Canvas\Repositories\Canvas;
use Leantime\Domain\Connector\Services\Connector;
use Leantime\Domain\Connector\Services\Providers;
use Leantime\Domain\Connector\Services\Integrations as IntegrationService;
use Leantime\Domain\Connector\Models\Integration as IntegrationModel;
use Leantime\Domain\Connector\Repositories\LeantimeEntities;
use Leantime\Domain\Auth\Services\Auth;
use Leantime\Domain\Goalcanvas\Repositories\Goalcanvas;
use Leantime\Domain\Ideas\Repositories\Ideas;
use Leantime\Domain\Projects\Services\Projects;
use Leantime\Domain\Tickets\Services\Tickets;
use Leantime\Domain\Users\Services\Users;

/**
*
Expand All @@ -19,6 +27,19 @@ class Integration extends Controller
private IntegrationService $integrationService;
private LeantimeEntities $leantimeEntities;

private Users $userService;
private Tickets $ticketService;

private Projects $projectService;

private array $values = array();
private array $fields = array();
private Ideas $ideaRepository;
private Canvas $canvasRepository;
private Goalcanvas $goalRepository;

private Connector $connectorService;

/**
* constructor - initialize private variables
*
Expand All @@ -28,15 +49,30 @@ class Integration extends Controller
public function init(
Providers $providerService,
IntegrationService $integrationService,
LeantimeEntities $leantimeEntities
LeantimeEntities $leantimeEntities,
Users $userService,
Tickets $ticketService,
Projects $projectService,
Ideas $ideaRepository,
Goalcanvas $goalRepository,
Canvas $canvasRepository,
Connector $connectorService
) {
Auth::authOrRedirect([Roles::$owner, Roles::$admin, Roles::$manager, Roles::$editor]);
Auth::authOrRedirect([Roles::$owner, Roles::$admin]);

$this->providerService = $providerService;
$this->leantimeEntities = $leantimeEntities;
$this->integrationService = $integrationService;
$this->userService = $userService;
$this->ticketService = $ticketService;
$this->projectService = $projectService;
$this->ideaRepository = $ideaRepository;
$this->goalRepository = $goalRepository;
$this->canvasRepository = $canvasRepository;
$this->connectorService = $connectorService;
}


/**
* run - handle post
*
Expand All @@ -47,8 +83,13 @@ public function run()
{

$params = $_REQUEST;
if(!isset($_SESSION['currentImportEntity'])){
$_SESSION['currentImportEntity'] = '';
}

if (isset($params["provider"])) {


//New integration with provider
//Get the provider
$provider = $this->providerService->getProvider($params["provider"]);
Expand All @@ -61,61 +102,107 @@ public function run()
$this->tpl->assign("integrationId", $currentIntegration->id);
}

//Initiate connection

/* Steps + + + + + + + + + + + + + + + + + + + + + + + */

//STEP 0: No Step defined, new integration
if (!isset($params["step"])) {
$this->tpl->display('connector.newIntegration');
return;
}

//STEP 1: Initiate connection
if (isset($params["step"]) && $params["step"] == "connect") {
//This should handle connection UI
$provider->connect();
}

//Choose Entities to sync
if (isset($params["step"]) && $params["step"] == "entity") {

//STEP 2: Choose Entities to sync
if (isset($params["step"]) && $params["step"] == "entity") {
$this->tpl->assign("providerEntities", $provider->getEntities());
$this->tpl->assign("leantimeEntities", $this->leantimeEntities->availableLeantimeEntities);

//TODO UI to show entity picker/mapper
$this->tpl->display('connector.integrationEntity');
return;
}

//Choose fields to map
//Choose Entities to sync
if (isset($params["step"]) && $params["step"] == "fields") {
$entity = $_POST['leantimeEntities'];
//STEP 3: Choose Entities to sync
if (isset($params["step"]) && $params["step"] == "fields") {

if(isset($_POST['leantimeEntities'])){
$entity = $_POST['leantimeEntities'];
$_SESSION['currentImportEntity'] = $entity;
}else if(isset($_SESSION['currentImportEntity']) && $_SESSION['currentImportEntity'] != "") {
$entity = $_SESSION['currentImportEntity'];
}else{
$this->tpl->setNotification("Entity not set", "error");

Frontcontroller::redirect(BASE_URL . "/connector/integration?provider=" . $provider->id . "");
}

$currentIntegration->entity = $entity;

$flags = $this->connectorService->getEntityFlags($entity);

$this->integrationService->patch($currentIntegration->id, array("entity" => $entity));

//TODO UI to show field picker/mapper
if (isset($currentIntegration->fields) && $currentIntegration->fields != '') {
$this->tpl->assign("providerFields", explode(",", $currentIntegration->fields));
} else {
$this->tpl->assign("providerFields", $provider->getFields());
}
$this->tpl->assign("flags", $flags);
$this->tpl->assign("leantimeFields", $this->leantimeEntities->availableLeantimeEntities[$entity]['fields']);
$this->tpl->display('connector.integrationFields');

return;
}

if (isset($params["step"]) && $params["step"] == "sync") {
//STEP 4: Choose Entities to sync
if (isset($params["step"]) && $params["step"] == "sync") {
//TODO UI to show sync schedule/options

$this->tpl->display('connector.integrationSync');
return;
}

if (isset($params["step"]) && $params["step"] == "import") {
//TODO UI to show sync schedule/options
//STEP 5: import Review
if (isset($params["step"]) && $params["step"] == "parse") {

$this->tpl->display('connector.integrationSync');
$this->values = $provider->geValues();

//Fetching the field matching and putting it in an array
$this->fields = array();
$this->fields = $this->connectorService->getFieldMappings($_POST);

$flags = array();
$flags = $this->connectorService->parseValues($this->fields, $this->values, $_SESSION['currentImportEntity'] );

//show the imported data as confirmation
$this->tpl->assign("values", $this->values);
$this->tpl->assign("fields", $this->fields);
$this->tpl->assign("flags", $flags);

$this->tpl->display('connector.integrationImport');
return;
}

if (isset($params["step"]) && $params["step"] == "confirm") {
//confirm and store in DB
//STEP 6: Do the import
if (isset($params["step"]) && $params["step"] == "import") {

//Store data in DB
$values = unserialize($_SESSION['serValues']);
$fields = unserialize($_SESSION['serFields']);

$this->connectorService->importValues($fields, $values, $_SESSION['currentImportEntity']);

//display stored successfully message
$this->tpl->display('connector.integrationConfirm');
}

if (!isset($params["step"])) {
$this->tpl->display('connector.newIntegration');
}

}
}
}

}
2 changes: 1 addition & 1 deletion app/Domain/Connector/Controllers/Show.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class Show extends Controller
*/
public function init(Services\Providers $projectService)
{
Auth::authOrRedirect([Roles::$owner, Roles::$admin, Roles::$manager, Roles::$editor]);
Auth::authOrRedirect([Roles::$owner, Roles::$admin]);
$this->providerService = $projectService;
}

Expand Down
72 changes: 72 additions & 0 deletions app/Domain/Connector/Models/Provider.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,93 @@
class Provider
{
//Unique identifier of provider
/**
* @var
*/
public $id;

//Friendly name
/**
* @var string
*/
public string $name;

/**
* @var string
*/
public string $description;

//Image to show in UI
/**
* @var string
*/
public string $image;

//Entities available to sync/import as part of this provider
//This should be a list of strings with the exact entity name as they appear in the provider api
//project, issue, epic, ticket or similar
/**
* @var array
*/
public array $availableEntities = [];

/**
* @var array
*/
public array $availableMethods = []; //import and/or sync


/**
* Define the steps for provider integration. Some steps may not be needed for some providers
* (for example CSV does not need a sync)
* Only used for status indicator. Controller does not check this.
*
* @var array|string[]
*/
public array $steps = [
"connect",
"entity",
"fields",
"sync",
"parse",
"import"
];

public array $stepDetails = [
"connect" => array(
"title" => "Connect",
"position"=>1,
),
"entity" => array(
"title" => "Entity Mapping",
"position"=>2,
),
"fields" => array(
"title" => "Field Matching",
"position"=>3,
),
"sync" => array(
"title" => "Synchonize",
"position"=>4,
),
"parse" => array(
"title" => "Validate",
"position"=>5,
),
"import" => array(
"title" => "Import",
"position"=>6,
),
];

public array $button = array(
"url" => '',
"text" => '',
);

/**
*
*/
public function __construct()
{
}
Expand Down
2 changes: 1 addition & 1 deletion app/Domain/Connector/Repositories/Integrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Integrations extends Repository
{
public function __construct()
{
$this->entity = "integrations";
$this->entity = "integration";
$this->model = Integration::class;
}
}
Expand Down
Loading

0 comments on commit 4eb77b7

Please sign in to comment.