Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(data): Review validated fields for actors and projects #29

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20241105102005 extends AbstractMigration
final class Version20241113164118 extends AbstractMigration
{
public function getDescription(): string
{
Expand All @@ -26,7 +26,7 @@ public function up(Schema $schema): void
$this->addSql('CREATE SEQUENCE project_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE thematic_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE SEQUENCE "user_id_seq" INCREMENT BY 1 MINVALUE 1 START 1');
$this->addSql('CREATE TABLE actor (id UUID NOT NULL, logo_id INT DEFAULT NULL, created_by INT DEFAULT NULL, updated_by INT DEFAULT NULL, name VARCHAR(255) NOT NULL, acronym VARCHAR(255) NOT NULL, is_validated BOOLEAN NOT NULL, category VARCHAR(255) NOT NULL, description TEXT DEFAULT NULL, office_name VARCHAR(255) DEFAULT NULL, office_address VARCHAR(255) DEFAULT NULL, office_location geometry(POINT, 0) DEFAULT NULL, contact_name VARCHAR(255) DEFAULT NULL, contact_position VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, phone VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, external_images TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, slug VARCHAR(128) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE actor (id UUID NOT NULL, logo_id INT DEFAULT NULL, created_by INT DEFAULT NULL, updated_by INT DEFAULT NULL, name VARCHAR(255) NOT NULL, acronym VARCHAR(255) NOT NULL, category VARCHAR(255) NOT NULL, description TEXT DEFAULT NULL, office_name VARCHAR(255) DEFAULT NULL, office_address VARCHAR(255) DEFAULT NULL, office_location geometry(POINT, 0) DEFAULT NULL, contact_name VARCHAR(255) DEFAULT NULL, contact_position VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, phone VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, external_images TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, slug VARCHAR(128) DEFAULT NULL, is_validated BOOLEAN NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_447556F9989D9B62 ON actor (slug)');
$this->addSql('CREATE INDEX IDX_447556F9F98F144A ON actor (logo_id)');
$this->addSql('CREATE INDEX IDX_447556F9DE12AB56 ON actor (created_by)');
Expand All @@ -52,7 +52,7 @@ public function up(Schema $schema): void
$this->addSql('CREATE TABLE actor_expertise (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE administrative_scope (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE media_object (id INT NOT NULL, file_path VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE project (id INT NOT NULL, actor_id UUID NOT NULL, created_by INT DEFAULT NULL, updated_by INT DEFAULT NULL, name VARCHAR(255) NOT NULL, location VARCHAR(255) NOT NULL, coords geometry(POINT, 0) NOT NULL, status VARCHAR(255) NOT NULL, description TEXT DEFAULT NULL, images JSON DEFAULT NULL, partners JSON DEFAULT NULL, intervention_zone VARCHAR(255) NOT NULL, project_manager_name VARCHAR(255) DEFAULT NULL, project_manager_position VARCHAR(255) DEFAULT NULL, project_manager_email VARCHAR(255) DEFAULT NULL, project_manager_tel VARCHAR(255) DEFAULT NULL, project_manager_photo VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, logo VARCHAR(255) DEFAULT NULL, deliverables TEXT DEFAULT NULL, calendar TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, slug VARCHAR(128) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE project (id INT NOT NULL, actor_id UUID NOT NULL, created_by INT DEFAULT NULL, updated_by INT DEFAULT NULL, name VARCHAR(255) NOT NULL, location VARCHAR(255) NOT NULL, coords geometry(POINT, 0) NOT NULL, status VARCHAR(255) NOT NULL, description TEXT DEFAULT NULL, images JSON DEFAULT NULL, partners JSON DEFAULT NULL, intervention_zone VARCHAR(255) NOT NULL, project_manager_name VARCHAR(255) DEFAULT NULL, project_manager_position VARCHAR(255) DEFAULT NULL, project_manager_email VARCHAR(255) DEFAULT NULL, project_manager_tel VARCHAR(255) DEFAULT NULL, project_manager_photo VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, logo VARCHAR(255) DEFAULT NULL, deliverables TEXT DEFAULT NULL, calendar TEXT DEFAULT NULL, created_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, updated_at TIMESTAMP(0) WITHOUT TIME ZONE NOT NULL, slug VARCHAR(128) DEFAULT NULL, is_validated BOOLEAN NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_2FB3D0EE989D9B62 ON project (slug)');
$this->addSql('CREATE INDEX IDX_2FB3D0EE10DAF24A ON project (actor_id)');
$this->addSql('CREATE INDEX IDX_2FB3D0EEDE12AB56 ON project (created_by)');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public function preProcess(string $fixtureId, $object): void
{
// For testing purpose
static $callCount = 0;
if ($object instanceof Actor) {
if ($object instanceof Actor || $object instanceof Project) {
$callCount++;
$isValidated = $callCount % 4 !== 0;
$object->setIsValidated($isValidated);
Expand Down
26 changes: 6 additions & 20 deletions symfony/src/Entity/Actor.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,11 @@
use App\Entity\Trait\SluggableEntity;
use ApiPlatform\Metadata\GetCollection;
use App\Entity\Trait\TimestampableEntity;
use App\Entity\Trait\ToValidateEntity;
use Doctrine\Common\Collections\Collection;
use Jsor\Doctrine\PostGIS\Types\PostGISType;
use App\Services\State\Provider\ActorProvider;
use App\Services\State\Processor\ActorProcessor;
use App\Services\State\Processor\ValidateEntityProcessor;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
Expand All @@ -42,15 +43,15 @@
),
new Get(),
new Post(
processor: ActorProcessor::class,
processor: ValidateEntityProcessor::class,
security: "is_granted('".UserRoles::ROLE_EDITOR_ACTORS."')"
),
new Patch(
processor: ActorProcessor::class,
processor: ValidateEntityProcessor::class,
security: 'is_granted("'.ActorVoter::EDIT.'", object)'
),
new Put(
processor: ActorProcessor::class,
processor: ValidateEntityProcessor::class,
security: 'is_granted("'.ActorVoter::EDIT.'", object)'
),
new Delete(
Expand All @@ -69,6 +70,7 @@ class Actor
use TimestampableEntity;
use SluggableEntity;
use BlameableEntity;
use ToValidateEntity;

#[ORM\Id]
#[ORM\Column(type: 'uuid', unique: true)]
Expand All @@ -85,10 +87,6 @@ class Actor
#[Groups([self::ACTOR_READ_COLLECTION, self::ACTOR_READ_ITEM, self::ACTOR_WRITE, Project::PROJECT_READ_ALL, Project::PROJECT_READ])]
private ?string $acronym = null;

#[ORM\Column]
#[Groups([self::ACTOR_READ_ITEM, self::ACTOR_READ_COLLECTION])]
private ?bool $isValidated = false;

#[ORM\Column(enumType: ActorCategory::class)]
#[Groups([self::ACTOR_READ_COLLECTION, self::ACTOR_READ_ITEM, self::ACTOR_WRITE, Project::PROJECT_READ])]
private ?ActorCategory $category = null;
Expand Down Expand Up @@ -216,18 +214,6 @@ public function setAcronym(string $acronym): static
return $this;
}

public function getIsValidated(): ?bool
{
return $this->isValidated;
}

public function setIsValidated(bool $isValidated): static
{
$this->isValidated = $isValidated;

return $this;
}

public function getCategory(): ?ActorCategory
{
return $this->category;
Expand Down
22 changes: 13 additions & 9 deletions symfony/src/Entity/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@

namespace App\Entity;

use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\GetCollection;
use App\Enum\AdministrativeScope;
use App\Enum\Status;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use App\Enum\AdministrativeScope;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\QueryParameter;
use App\Controller\Project\SimilarProjectsAction;
use App\Repository\ProjectRepository;
use App\Entity\Trait\BlameableEntity;
use App\Entity\Trait\SluggableEntity;
use App\Repository\ProjectRepository;
use App\Entity\Trait\ToValidateEntity;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\QueryParameter;
use App\Entity\Trait\TimestampableEntity;
use App\Entity\Trait\BlameableEntity;
use Doctrine\Common\Collections\Collection;
use Jsor\Doctrine\PostGIS\Types\PostGISType;
use Doctrine\Common\Collections\ArrayCollection;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use App\Controller\Project\SimilarProjectsAction;
use Symfony\Component\Serializer\Attribute\Groups;
use ApiPlatform\Doctrine\Common\Filter\SearchFilterInterface;
use App\Services\State\Provider\ProjectProvider;

#[ORM\Entity(repositoryClass: ProjectRepository::class)]
#[ApiFilter(filterClass: SearchFilter::class, properties: ['slug' => SearchFilterInterface::STRATEGY_EXACT])]
#[ApiResource(
paginationEnabled: false,
operations: [
new GetCollection(
provider: ProjectProvider::class,
uriTemplate: '/projects/all',
normalizationContext: ['groups' => [self::PROJECT_READ_ALL]]
),
Expand All @@ -49,6 +52,7 @@ class Project
use TimestampableEntity;
use BlameableEntity;
use SluggableEntity;
use ToValidateEntity;

public const PROJECT_READ = 'project:read';
public const PROJECT_READ_ALL = 'project:read:all';
Expand Down
27 changes: 27 additions & 0 deletions symfony/src/Entity/Trait/ToValidateEntity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace App\Entity\Trait;

use App\Entity\Actor;
use App\Entity\Project;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Attribute\Groups;

trait ToValidateEntity
{
#[ORM\Column]
#[Groups([Project::PROJECT_READ_ALL, Project::PROJECT_READ, Actor::ACTOR_READ_COLLECTION, Actor::ACTOR_READ_ITEM])]
private ?bool $isValidated = false;

public function getIsValidated(): ?bool
{
return $this->isValidated;
}

public function setIsValidated(bool $isValidated): static
{
$this->isValidated = $isValidated;

return $this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpFoundation\RequestStack;

class ActorProcessor implements ProcessorInterface
class ValidateEntityProcessor implements ProcessorInterface
{


Expand Down
28 changes: 28 additions & 0 deletions symfony/src/Services/State/Provider/ProjectProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace App\Services\State\Provider;
use App\Model\Enums\UserRoles;
use ApiPlatform\Metadata\Operation;
use App\Repository\ProjectRepository;
use ApiPlatform\State\ProviderInterface;
use Symfony\Bundle\SecurityBundle\Security;

final class ProjectProvider implements ProviderInterface
{

public function __construct(
private ProjectRepository $projectRepository,
private Security $security
)
{
}

public function provide(Operation $operation, array $uriVariables = [], array $context = []): array
{
if ($this->security->isGranted(UserRoles::ROLE_ADMIN)) {
return $this->projectRepository->findAll();
}

return $this->projectRepository->findBy(['isValidated' => true]);
}
}
4 changes: 3 additions & 1 deletion vue/src/stores/actorsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ export const useActorsStore = defineStore(StoresList.ACTORS, () => {
const actorsThematics: Thematic[] = reactive([])
const actorsAdministrativesScopes: AdministrativeScope[] = reactive([])

async function getActors(): Promise<void> {
async function getActors(forceGet = false): Promise<void> {
if (actors.length === 0 || forceGet) {
actors.splice(0, actors.length)
actors.push(...await ActorsService.getActors())
dataLoaded.value = true
}
}

async function getActorsSelectListContent(): Promise<void> {
Expand Down
10 changes: 9 additions & 1 deletion vue/src/stores/applicationStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useProjectStore } from '@/stores/projectStore'
import { DialogKey } from '@/models/enums/app/DialogKey'
import type { Ref } from 'vue'
import { ContentPagesList } from '@/models/enums/app/ContentPagesList'
import { useActorsStore } from './actorsStore'

export const useApplicationStore = defineStore(StoresList.APPLICATION, () => {
const { mobile } = useDisplay()
Expand All @@ -35,5 +36,12 @@ export const useApplicationStore = defineStore(StoresList.APPLICATION, () => {
return route.name && typeof route.name === 'string' && lightUiRoutes.includes(route.name)
})

return { mobile, showSnackBar, snackBarMessage, activeTab, activeDialog, breadcrumbs, is100vh, isLightHeader, triggerZoomReset, showEditContentDialog, currentContentPage }
const refreshAppData = () => {
const actorsStore = useActorsStore()
actorsStore.getActors(true)
const projectStore = useProjectStore()
projectStore.getAll(true)
}

return { mobile, showSnackBar, snackBarMessage, activeTab, activeDialog, breadcrumbs, is100vh, isLightHeader, triggerZoomReset, showEditContentDialog, currentContentPage, refreshAppData }
})
4 changes: 2 additions & 2 deletions vue/src/stores/projectStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export const useProjectStore = defineStore(StoresList.PROJECTS, () => {
financialActors: [],
})

async function getAll(): Promise<void> {
if (projects.value.length === 0) {
async function getAll(forceGet = false): Promise<void> {
if (projects.value.length === 0 || forceGet) {
projects.value = await ProjectService.getAll()
}
}
Expand Down
5 changes: 5 additions & 0 deletions vue/src/stores/userStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { UserRoles } from '@/models/enums/auth/UserRoles'
import { ImageLoader } from '@/services/files/ImageLoader'
import type { MediaObject } from '@/models/interfaces/MediaObject'
import { UserService } from '@/services/userAndAuth/UserService'
import { useApplicationStore } from './applicationStore'


export const useUserStore = defineStore(StoresList.USER, () => {
Expand Down Expand Up @@ -44,6 +45,8 @@ export const useUserStore = defineStore(StoresList.USER, () => {

const setCurrentUser = async () => {
currentUser.value = (await AuthenticationService.getAuthenticatedUser()).data
const appStore = useApplicationStore()
appStore.refreshAppData()
}

const signUp = async (values: SignUpValues) => {
Expand All @@ -65,6 +68,8 @@ export const useUserStore = defineStore(StoresList.USER, () => {
currentUser.value = null
JwtCookie.clearCookies()
router.push({ name: 'home' })
const appStore = useApplicationStore()
appStore.refreshAppData()
}

const checkAuthenticated = async () => {
Expand Down
5 changes: 3 additions & 2 deletions vue/src/views/actors/ActorsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@

<div class="d-flex w-100 justify-space-between align-center">
<div class="d-flex ">
<span class="text-body-2"> {{ `${actorsStore.actors.length.toString()} ${actorsStore.actors.length > 1 ? $t('actors.actors') : $t('actors.actor')}` }}</span>
<span class="text-body-2"> {{ `${totalActors.length.toString()} ${$t('admin.member', totalActors.length)}`}}</span>
<span class="ml-3 cursor-pointer text-caption text-main-blue" @click="resetFilters">{{ $t('actors.resetFilters') }}</span>
<div class="Actors__filteredItemsCount ml-1">{{ filteredActors.length }}</div>
</div>
Expand Down Expand Up @@ -138,8 +138,9 @@ const selectedAdminScope: Ref<string[] | null> = ref(null);
const categoryItems = Object.values(ActorsCategories)
const selectedCategory: Ref<ActorsCategories[] | null> = ref(null);

const totalActors = computed(() => actorsStore.actors.filter(x => x.isValidated))
const filteredActors = computed(() => {
let filteredActors = [...actorsStore.actors]
let filteredActors = [...totalActors.value]

if (searchQuery.value) {
filteredActors = filteredActors.filter((actor: Actor) => {
Expand Down
Loading