Unverified Commit 5bc63fc3 authored by Sebastian Castro's avatar Sebastian Castro
Browse files

Improve Saas Project management

Let project say if they want to be visible on home page
Get admin emails & tags 
Sort by date or data-size on list
search by name or tag on project list
parent 7ba50be9
......@@ -37,10 +37,13 @@
max-width: 500px;
height: 250px;
}
.list {
.projects-container {
display: flex;
flex-wrap: wrap;
}
.pinned-projects {
margin-bottom: 4rem;
}
.search-container {
display: flex;
align-items: center;
......@@ -136,6 +139,9 @@
padding-left: 2px;
}
}
.published-at-int, .published-at, .tags {
display: none;
}
}
}
}
......
......@@ -73,6 +73,11 @@ services:
$instanceName: '%instance_name%'
$fromEmail: '%from_email%'
# Commands
App\Command\UpdateProjectsInfoCommand:
arguments:
$baseUrl: '%base_url%'
# Overide FOS Registration Controller
App\Controller\RegistrationController:
tags: ['controller.service_arguments']
......
......@@ -31,9 +31,15 @@ class ConfigurationAdmin extends ConfigurationAbstractAdmin
$dm = $this->getModelManager()->getDocumentManager('App\Document\Configuration');
$apiProperties = $dm->getRepository('App\Document\Element')->findAllCustomProperties();
$container = $this->getConfigurationPool()->getContainer();
$formMapper
->with('Le site', ['class' => 'col-md-6', 'description' => '<div class="iframe-container"><iframe height="110" sandbox="allow-same-origin allow-scripts" src="https://video.colibris-outilslibres.org/videos/embed/fc7d3784-7bd1-4f3a-b915-ab6daefdd52d" frameborder="0" allowfullscreen></iframe></div>'])
->with('Le site', ['class' => 'col-md-6', 'description' => '<div class="iframe-container"><iframe height="110" sandbox="allow-same-origin allow-scripts" src="https://video.colibris-outilslibres.org/videos/embed/fc7d3784-7bd1-4f3a-b915-ab6daefdd52d" frameborder="0" allowfullscreen></iframe></div>']);
if ($container->getParameter('use_as_saas')) {
$formMapper
->add('publishOnSaasPage', null, ['label' => 'Rendre ce projet visible sur ' . $container->getParameter('base_url'), 'required' => false]);
}
$formMapper
->add('appName', null, ['label' => 'Nom du site'])
->add('appNameShort', null, ['label' => 'Nom Court (utilisé par les téléphones, 12 caractères max.)', 'required' => false])
->add('appBaseline', null, ['label' => 'Description du site (baseline)', 'required' => false])
......
......@@ -6,12 +6,13 @@ use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
class ProjectAdmin extends AbstractAdmin
{
protected $datagridValues = [
'_page' => 1,
'_sort_order' => 'ASC',
'_sort_order' => 'DESC',
'_sort_by' => 'createdAt',
];
......@@ -29,9 +30,11 @@ class ProjectAdmin extends AbstractAdmin
{
$listMapper
->add('name', null, ['template' => 'admin/partials/list_project_name.html.twig'])
->add('domainName')
->add('description')
->add('dataSize')
->add('dataSize', null)
->add('adminEmails')
->add('published', null)
->add('pinned', null, ['editable' => true])
->add('createdAt')
->add('_action', 'actions', [
'actions' => [
......
......@@ -7,16 +7,20 @@ use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Routing\RouterInterface;
/*
* Update infos of each instance for the Saas Index page
*/
class UpdateProjectsInfoCommand extends Command
{
public function __construct(DocumentManager $dm, LoggerInterface $commandsLogger)
public function __construct(DocumentManager $dm, LoggerInterface $commandsLogger, RouterInterface $router,
$baseUrl)
{
$this->dm = $dm;
$this->router = $router;
$this->logger = $commandsLogger;
$this->baseUrl = $baseUrl;
parent::__construct();
}
......@@ -29,20 +33,21 @@ class UpdateProjectsInfoCommand extends Command
{
$projects = $this->dm->getRepository('App\Document\Project')->findAll();
$this->logger->info('Updating projects informations. '.count($projects).' projects to update');
$router = $this->getContainer()->get('router');
$apiUrl = $this->getContainer()->getParameter('base_url').$router->generate('gogo_api_project_info');
$this->logger->info('Updating projects informations. '. count($projects) .' projects to update');
$apiUrl = $this->baseUrl . $this->router->generate('gogo_api_project_info');
foreach ($projects as $key => $project) {
try {
$this->logger->info(' -> Update project '.$project->getName());
$url = 'http://'.$project->getDomainName().'.'.$apiUrl;
$url = 'https://'.$project->getDomainName().'.'.$apiUrl;
$json = file_get_contents($url);
$data = json_decode($json, true);
$project->setName($data['name']);
$project->setImageUrl($data['imageUrl']);
$project->setDescription($data['description']);
$project->setDataSize($data['dataSize']);
$project->setAdminEmails($data['adminEmails']);
$project->setPublished($data['publish']);
$this->dm->persist($project);
} catch (\Exception $e) {
$this->logger->error($e->getMessage());
......
......@@ -289,15 +289,15 @@ class APIController extends GoGoController
}
$shortName = $config->getAppNameShort() && strlen($config->getAppNameShort()) > 0 ? $config->getAppNameShort() : $config->getAppName();
$responseArray = [
'name' => $config->getAppName(),
'short_name' => str_split($shortName, 12)[0],
'lang' => 'fr',
'start_url' => '/annuaire#/carte/autour-de-moi',
'display' => 'standalone',
'theme_color' => $config->getPrimaryColor(),
'background_color' => $config->getBackgroundColor(),
'icons' => [$icon],
];
'name' => $config->getAppName(),
'short_name' => str_split($shortName, 12)[0],
'lang' => 'fr',
'start_url' => '/annuaire#/carte/autour-de-moi',
'display' => 'standalone',
'theme_color' => $config->getPrimaryColor(),
'background_color' => $config->getBackgroundColor(),
'icons' => [$icon],
];
$response = new Response(json_encode($responseArray));
$response->headers->set('Content-Type', 'application/json');
......@@ -311,12 +311,20 @@ class APIController extends GoGoController
$imageUrl = $img ? $img->getImageUrl() : null;
$dataSize = $dm->getRepository('App\Document\Element')->findVisibles(true);
$users = $dm->getRepository('App\Document\User')->findAll();
$adminEmails = [];
foreach ($users as $key => $user) {
if ($user->isAdmin()) $adminEmails[] = $user->getEmail();
}
$responseArray = [
'name' => $config->getAppName(),
'imageUrl' => $imageUrl,
'description' => $config->getAppBaseline(),
'dataSize' => $dataSize,
];
'name' => $config->getAppName(),
'imageUrl' => $imageUrl,
'description' => $config->getAppBaseline(),
'tags' => $config->getAppTags(),
'dataSize' => $dataSize,
'adminEmails' => implode(',', $adminEmails),
'publish' => $config->getPublishOnSaasPage()
];
$response = new Response(json_encode($responseArray));
$response->headers->set('Content-Type', 'application/json');
......
......@@ -94,13 +94,17 @@ class ProjectController extends Controller
$config = $dm->getRepository('App\Document\Configuration')->findConfiguration();
$projects = $repository->findBy([], ['dataSize' => 'DESC']);
$projects = $repository->findBy(['published' => true], ['publishedAt' => 'DESC']);
$pinnedProjects = $repository->findBy(['pinned' => true]);
foreach ($projects as $project) {
$project->setHomeUrl($this->generateUrlForProject($project));
}
return $this->render('saas/home.html.twig', ['projects' => $projects, 'config' => $config]);
return $this->render('saas/home.html.twig', [
'projects' => $projects,
'pinnedProjects' => $pinnedProjects,
'config' => $config]);
}
public function initializeAction(Request $request, DocumentManager $dm, UserManagerInterface $userManager,
......
......@@ -50,6 +50,12 @@ class Configuration implements \JsonSerializable
// For meta keywords header
protected $appTags;
/**
* Only for SAAS mode. Make this project visible on the SAAS home page (=project list)
* @MongoDB\Field(type="bool")
*/
protected $publishOnSaasPage = true;
/** @MongoDB\Field(type="string") */
protected $dataLicenseUrl = 'https://opendatacommons.org/licenses/odbl/summary/';
......@@ -3345,4 +3351,12 @@ class Configuration implements \JsonSerializable
{
return $this->appNameShort;
}
public function getPublishOnSaasPage() {
return $this->publishOnSaasPage;
}
public function setPublishOnSaasPage($bool) {
$this->publishOnSaasPage = $bool;
return $this;
}
}
......@@ -44,6 +44,18 @@ class Project
/** @MongoDB\Field(type="int") */
private $dataSize = 0;
/** @MongoDB\Field(type="string") */
private $adminEmails;
/** @MongoDB\Field(type="string") */
private $tags;
/**
* Pin some project to make them more visible on home page
* @MongoDB\Field(type="bool")
*/
private $pinned = false;
/**
* @var date
*
......@@ -52,6 +64,18 @@ class Project
*/
private $createdAt;
/**
* Each project can choose to be published or not on the home project list
*
* @MongoDB\Field(type="bool")
*/
private $published;
/**
* @MongoDB\Field(type="date")
*/
private $publishedAt;
/** @MongoDB\ReferenceMany(targetDocument="App\Document\ScheduledCommand", inversedBy="project", cascade={"all"}) */
private $commands;
......@@ -277,4 +301,42 @@ class Project
{
return $this->commands;
}
public function getAdminEmails() {
return $this->adminEmails;
}
public function setAdminEmails($emails) {
$this->adminEmails = $emails || "";
return $this;
}
public function getPublished() {
return $this->published;
}
public function setPublished($bool) {
$this->published = $bool;
if ($bool && !$this->publishedAt) {
$this->setPublishedAt(time());
}
}
public function getPublishedAt() {
return $this->publishedAt;
}
public function setPublishedAt($date) {
$this->publishedAt = $date;
return $this;
}
public function getPinned() {
return $this->pinned;
}
public function setPinned($bool) {
$this->pinned = $bool;
return $this;
}
public function getTags() {
return $this->tags;
}
public function setTags($tags) {
$this->tags = $tags;
return $this;
}
}
......@@ -37,7 +37,6 @@
<div class="box-body table-responsive no-padding table-box">
<table class="table">
<tbody>
{{ self.apiLink("Informations générale sur cette carte", url('gogo_api_project_info')) }}
{{ self.apiLink("GoGoCartoJs config", url('gogo_api_gogocartojs_configuration')) }}
{{ self.apiLink("GoGoCarto config", url('gogo_api_configuration')) }}
</tbody>
......
......@@ -14,33 +14,25 @@
</section>
<section class="projects">
<h2>Liste des projets déjà créés ({{ projects|length }})</h2>
{% if pinnedProjects|length > 0 %}
<h2>Projets mis en avant</h2>
<div class="pinned-projects projects-container">
{% for project in pinnedProjects %}
{% include 'saas/projects/project.html.twig' with {'project' : project } %}
{% endfor %}
</div>
{% endif %}
<h2>Tous les projets ({{ projects|length }})</h2>
<div class="project-list" id="project-list">
<div class="search-container">
<input class="search" placeholder="Chercher par nom" />
<button class="sort desc btn btn-sm btn-neutral" data-sort="size">Trier par nombre de points</button>
<button class="sort btn btn-sm btn-neutral" data-sort="name">Trier par nom</button>
<input class="search" placeholder="Chercher par nom, par tag" />
<button class="sort desc btn btn-sm btn-neutral" data-sort="published-at-int">Trier par date de publication</button>
<button class="sort btn btn-sm btn-neutral" data-sort="size">Trier par nombre de points</button>
</div>
<div class="list">
<div class="list projects-container">
{% for project in projects %}
<div class="project-container">
<div class="project-item waves-effect waves-block waves-light z-depth-1" onclick="window.open('{{ project.homeUrl }}', '_blank');">
{% if project.imageUrl %}
<img class="project-logo" src="{{ project.imageUrl }}">
{% else %}
<img class="project-logo default" src="{{ asset('img/default-icon.png') }}">
{% endif %}
<div class="project-content">
<div class="name">{{ project.name|capitalize }}</div>
<div class="data-size gogo-bg-primary">
<span class="size">{{ project.dataSize }}</span>
<span class="icon gogo-icon-marker-symbol"></span>
</div>
</div>
</div>
</div>
{% include 'saas/projects/project.html.twig' with {'project' : project } %}
{% endfor %}
</div>
<ul class="pagination"></ul>
......@@ -51,7 +43,7 @@
<script src="{{ asset('js/list.js?ver=' ~ version) }}"></script>
<script>
var userList = new List('project-list', {
valueNames: [ 'name', 'size' ],
valueNames: [ 'name', 'tags', 'size', 'published-at-int' ],
page: 36,
pagination: [{
paginationClass: "pagination",
......
<div class="project-container">
<div class="project-item waves-effect waves-block waves-light z-depth-1" onclick="window.open('{{ project.homeUrl }}', '_blank');">
{% if project.imageUrl %}
<img class="project-logo" src="{{ project.imageUrl }}">
{% else %}
<img class="project-logo default" src="{{ asset('img/default-icon.png') }}">
{% endif %}
<div class="project-content">
<div class="name">{{ project.name|capitalize }}</div>
<div class="published-at">{{ project.publishedAt|date("m/d/Y") }}</div>
<div class="published-at-int">{{ project.publishedAt.getTimestamp }}</div>
<div class="tags">{{ project.tags }}</div>
<div class="data-size gogo-bg-primary">
<span class="size">{{ project.dataSize }}</span>
<span class="icon gogo-icon-marker-symbol"></span>
</div>
</div>
</div>
</div>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment