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

User management #28

Merged
merged 25 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
cb657d0
feat(vue): add a generic admin top bar
Oct 18, 2024
dd61f71
Merge branch 'feature/actor-images' into feature/users-administration
Oct 18, 2024
16ffadb
feat(vue) add generic admin table
Oct 18, 2024
fc1b900
feat(vue): First draft of members admin panel
Oct 18, 2024
3f39b91
feat(vue): Add user edition in admin panel
Oct 21, 2024
b6d168e
review(vue): Review admin members page
Oct 21, 2024
5e86754
feat(vue): add user creation in admin panel
Oct 22, 2024
6a27e22
feat(vue): Review search function in admin panel
Oct 22, 2024
90faf9d
feat: initialize user account page
Oct 29, 2024
7c2a94b
Merge branch 'main' into feature/my-account
Oct 29, 2024
18c91dd
Merge branch 'main' into feature/users-administration
Oct 29, 2024
8bff7ab
feat(account): Update avatar and translations
Oct 29, 2024
edb8722
Merge branch 'feature/users-administration' into feature/my-account
Oct 29, 2024
4552b72
feat(account): Complete right part of the form
Oct 29, 2024
839e8fb
feat(account): Add edition form
Oct 31, 2024
17f39f3
feat(account): finalize account edition feature
Oct 31, 2024
adee785
fix(users): Fix issue on role management in admin panel
Oct 31, 2024
7732bdd
fix(admin): Fix types error in user creation form
Oct 31, 2024
c7e0d2e
fix(user account): Review responsivness
Oct 31, 2024
e3e0d6a
fix(admin): Use only one form for creating/editing users
Nov 4, 2024
3f6f993
Merge branch 'feature/users-administration' into feature/my-account
Nov 4, 2024
30e51e3
refactor(users): Split service between authentication and users manag…
Nov 4, 2024
7979c7d
fix(user): add correct edition roles on description field
Nov 4, 2024
aaed3f3
refactor(users): Remove coquillettes
Nov 4, 2024
8d4aa92
fix(deploy): Update sf migrations
Nov 5, 2024
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
2 changes: 1 addition & 1 deletion symfony/fixtures/users.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ App\Entity\User:
lastName: Editor Doe
email: [email protected]
plainPassword: Test1234
roles: [ 'ROLE_EDITOR_ACTORS', 'ROLE_EDITOR_PROJECTS', "ROLE_EDITOR_RESOURCES", "ROLE_EDITOR_DATA" ]
roles: [ 'ROLE_EDITOR_ACTORS', 'ROLE_EDITOR_PROJECTS', "ROLE_EDITOR_RESSOURCES", "ROLE_EDITOR_DATA" ]
isValidated: true
user_3:
firstName: Jane
Expand Down
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 Version20241023155547 extends AbstractMigration
final class Version20241105102005 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 NOT 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, 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 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 Down Expand Up @@ -70,7 +70,8 @@ public function up(Schema $schema): void
$this->addSql('CREATE INDEX IDX_E73AB79010DAF24A ON contracted_projects_actors (actor_id)');
$this->addSql('COMMENT ON COLUMN contracted_projects_actors.actor_id IS \'(DC2Type:uuid)\'');
$this->addSql('CREATE TABLE thematic (id INT NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE "user" (id INT NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) DEFAULT NULL, is_validated BOOLEAN NOT NULL, requested_roles JSON DEFAULT NULL, organisation VARCHAR(255) DEFAULT NULL, position VARCHAR(255) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL, sign_up_message TEXT DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE TABLE "user" (id INT NOT NULL, logo_id INT DEFAULT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, email VARCHAR(180) NOT NULL, roles JSON NOT NULL, password VARCHAR(255) DEFAULT NULL, is_validated BOOLEAN NOT NULL, requested_roles JSON DEFAULT NULL, organisation VARCHAR(255) DEFAULT NULL, position VARCHAR(255) DEFAULT NULL, phone VARCHAR(20) DEFAULT NULL, sign_up_message TEXT DEFAULT NULL, description TEXT DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649F98F144A ON "user" (logo_id)');
$this->addSql('ALTER TABLE actor ADD CONSTRAINT FK_447556F9F98F144A FOREIGN KEY (logo_id) REFERENCES media_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE actor ADD CONSTRAINT FK_447556F9DE12AB56 FOREIGN KEY (created_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE actor ADD CONSTRAINT FK_447556F916FE72E1 FOREIGN KEY (updated_by) REFERENCES "user" (id) ON DELETE SET NULL NOT DEFERRABLE INITIALLY IMMEDIATE');
Expand All @@ -91,6 +92,7 @@ public function up(Schema $schema): void
$this->addSql('ALTER TABLE financed_projects_actors ADD CONSTRAINT FK_50C6B8EC10DAF24A FOREIGN KEY (actor_id) REFERENCES actor (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE contracted_projects_actors ADD CONSTRAINT FK_E73AB790166D1F9C FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE contracted_projects_actors ADD CONSTRAINT FK_E73AB79010DAF24A FOREIGN KEY (actor_id) REFERENCES actor (id) ON DELETE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE');
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D649F98F144A FOREIGN KEY (logo_id) REFERENCES media_object (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
}

public function down(Schema $schema): void
Expand Down Expand Up @@ -123,6 +125,7 @@ public function down(Schema $schema): void
$this->addSql('ALTER TABLE financed_projects_actors DROP CONSTRAINT FK_50C6B8EC10DAF24A');
$this->addSql('ALTER TABLE contracted_projects_actors DROP CONSTRAINT FK_E73AB790166D1F9C');
$this->addSql('ALTER TABLE contracted_projects_actors DROP CONSTRAINT FK_E73AB79010DAF24A');
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D649F98F144A');
$this->addSql('DROP TABLE actor');
$this->addSql('DROP TABLE actor_actor_expertise');
$this->addSql('DROP TABLE actor_thematic');
Expand Down
2 changes: 1 addition & 1 deletion symfony/src/Entity/MediaObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class MediaObject
private ?int $id = null;

#[ApiProperty(types: ['https://schema.org/contentUrl'], writable: false)]
#[Groups(['media_object:read', Actor::ACTOR_READ_COLLECTION, Actor::ACTOR_READ_ITEM])]
#[Groups(['media_object:read', Actor::ACTOR_READ_COLLECTION, Actor::ACTOR_READ_ITEM, User::GROUP_GETME])]
public ?string $contentUrl = null;

#[Vich\UploadableField(mapping: 'media_object', fileNameProperty: 'filePath')]
Expand Down
34 changes: 33 additions & 1 deletion symfony/src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
private Collection $actorsCreated;

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

#[ORM\Column(nullable: true)]
Expand All @@ -131,6 +131,14 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
#[Groups([self::GROUP_READ, self::GROUP_WRITE])]
private ?string $signUpMessage = null;

#[ORM\OneToOne(cascade: ['persist', 'remove'])]
#[Groups([self::GROUP_READ, self::GROUP_GETME, self::GROUP_WRITE])]
private ?MediaObject $logo = null;

#[ORM\Column(type: Types::TEXT, nullable: true)]
#[Groups([self::GROUP_READ, self::GROUP_GETME, self::GROUP_WRITE])]
private ?string $description = null;

public function __construct()
{
$this->actorsCreated = new ArrayCollection();
Expand Down Expand Up @@ -349,4 +357,28 @@ public function setsignUpMessage(?string $signUpMessage): static

return $this;
}

public function getLogo(): ?MediaObject
{
return $this->logo;
}

public function setLogo(?MediaObject $logo): static
{
$this->logo = $logo;

return $this;
}

public function getDescription(): ?string
{
return $this->description;
}

public function setDescription(?string $description): static
{
$this->description = $description;

return $this;
}
}
Binary file added vue/src/assets/images/user/default_avatar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions vue/src/assets/styles/global/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
@import '@/assets/styles/global/utils';
@import '@/assets/styles/views/header';
@import '@/assets/styles/views/actors';
@import '@/assets/styles/views/ContentForm';

#app {
display: flex;
Expand Down
30 changes: 30 additions & 0 deletions vue/src/assets/styles/views/ContentForm.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
.ContentForm{
&__toValidate{
background-color: rgb(var(--v-theme-light-yellow));
padding: 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 40px;
}
&__ctn{
display: flex;
flex-direction: column;
max-width: 100%;
height: 100%;
}
&__rolesRequestCtn{
display: flex;
flex-direction: column;
max-width: 100%;
height: 100%;
background-color: rgb(var(--v-theme-light-yellow));
padding: 1rem;
font-weight: 400;
}
&__rolesRequestItem{
display: flex;
align-items: center;
}
}
42 changes: 0 additions & 42 deletions vue/src/assets/styles/views/actors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -41,46 +41,4 @@
display: flex;
flex-wrap: wrap;
}

&__form {
&__dialog{
display: flex;
flex-direction: column;
background-color: white;
overflow-y: auto;
}

@media (max-width: 600px) {
&__dialog{
width: 85vw;
height: 95vh;
}
}

&__title{
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid rgb(var(--v-theme-main-grey));
padding: 5px 40px;
}

&__toValidate{
background-color: rgb(var(--v-theme-light-yellow));
padding: 20px;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin: 0 40px;
}

&__container{
display: flex;
flex-direction: column;
max-width: 100%;
height: 100%;
}
}
}
3 changes: 1 addition & 2 deletions vue/src/assets/translations/fr/actors.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"actors": {
"actor": "acteur",
"actors": "acteurs",
"actor": "acteur | acteurs",
"title": "Annuaire\ndes acteurs",
"desc": "Consultez l’annuaire des acteurs du secteur de l’urbanisme au Cameroun.",
"search": "Rechercher un acteur",
Expand Down
5 changes: 4 additions & 1 deletion vue/src/assets/translations/fr/admin.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
"panelContentActors": "Acteurs",
"panelContentProjects": "Projets",
"panelContentResources": "Ressources",
"panelComments": "Gérer les commentaires"
"panelComments": "Gérer les commentaires",
"member": "Membre | Membres",
"add": "Ajouter",
"search": "Rechercher"
}
}
30 changes: 23 additions & 7 deletions vue/src/assets/translations/fr/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
"question": "Déjà membre ?",
"error": "Cet email est déjà utilisé.",
"form": {
"firstName": "Prénom",
"lastName": "Nom",
"email": "Email",
"password": "Mot de passe",
"confirmPassword": "Confirmez le mot de passe",
"firstName": "Prénom*",
"lastName": "Nom*",
"email": "Email*",
"password": "Mot de passe*",
"confirmPassword": "Confirmez le mot de passe*",
"passwordMatchError": "Les mots de passe ne correspondent pas",
"privacyPolicy": {
"label": "J’ai lu et j’accepte la {url1} et les {url2} de la plateforme urbaine du Cameroun.",
Expand All @@ -52,9 +52,10 @@
"subtitle": "Votre demande d’adhésion\na bien été prise en compte.",
"form": {
"info": "Pour faciliter le traitement de votre demande,\nveuillez préciser vos informations :",
"organization": "Organisation/Entreprise*",
"functions": "Titre/Fonction*",
"organization": "Organisation/Entreprise",
"functions": "Titre/Fonction",
"telephone": "Téléphone",
"description": "Ajouter une description",
"message": "Message",
"actionsRequest": {
"label": "Vous aimeriez être en mesure de :",
Expand All @@ -81,6 +82,21 @@
"info": "Consultez votre boite mail et cliquez sur le lien\nde réinitialisation de votre mot de passe.",
"submit": "Fermer"
}
},
"editForm": {
"newMember": "Nouvel utilisateur inscrit le",
"requestedRoles": "Accès privilégiés",
"waitingValidation": "En attente d'approbation",
"validated": "Approuvé",
"newRequest": "Nouvelle demande"
}
},
"account": {
"title": "Mon compte",
"changePassword": "Réinitialiser mon le mot de passe",
"roles": "Vos rôles privilégiés",
"deleteAccount": "Supprimer mon compte",
"save": "Enregistrer les modifications",
"contributions": "Mes contributions"
}
}
2 changes: 1 addition & 1 deletion vue/src/assets/translations/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"resources": "Ressources",
"services": "Services",
"map": "Ma carte",
"account": "Mon compte",
"myAccount": "Mon compte",
"administration": "Administration",
"members": "Membres",
"content": "Contenu",
Expand Down
64 changes: 64 additions & 0 deletions vue/src/components/admin/AdminTable.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<template>
<div class="AdminTable">
<div
class="AdminTableItem"
:class="{ 'AdminTableItem--overlay': !item.isValidated }"
v-for="item in items" :key="item.id"
:style="{ gridTemplateColumns: columnWidths.join(' ') }"
>
<div class="AdminTableItem">
{{ plainText ? item[tableKeys[0] as keyof typeof item] : reduceText(item[tableKeys[0] as keyof typeof item], 5) }}
</div>
<div class="AdminTableItem">
{{ plainText ? item[tableKeys[1] as keyof typeof item] : reduceText(item[tableKeys[1] as keyof typeof item], 25) }}
</div>
<div class="AdminTableItem">
{{ plainText ? item[tableKeys[2] as keyof typeof item] : reduceText(item[tableKeys[2] as keyof typeof item], 20) }}
</div>
<div class="AdminTableItem--last">
<slot name="editContentCell" :item="item"></slot>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import type { Actor } from '@/models/interfaces/Actor';
import { reduceText } from '@/services/utils/UtilsService';
import type { User } from '@sentry/vue';

const props = defineProps<{
items: Actor[] | User[];
tableKeys: (keyof Actor | keyof User)[];
columnWidths?: string[];
plainText?: boolean;
}>()
const defaultColumnWidths = ['15%', '40%', '25%', '20%'];
const columnWidths = props.columnWidths || defaultColumnWidths;
</script>

<style lang="scss">
.AdminTable {
display: flex;
flex-direction: column;
width: 100%;
margin-top: 30px;
}
.AdminTableItem {
display: grid;
flex-direction: row;
height: 3.5rem;
align-items: center;
padding-left: 10px;
border-bottom: 1px solid rgb(var(--v-theme-main-grey));
&--overlay {
background-color: rgb(var(--v-theme-light-yellow));
}
&--last {
display: flex;
align-items: center;
justify-content: flex-end;
padding-right: 10px;
}
}
</style>
Loading
Loading