Profile page #30
|
@ -2,8 +2,8 @@ pipeline {
|
||||||
agent any
|
agent any
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
DatabaseUrl = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh ${BRANCH_NAME} DatabaseUrl').trim()
|
DatabaseUrl = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh dev DatabaseUrl').trim()
|
||||||
ProjectPath = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh ${BRANCH_NAME} ProjectPath').trim()
|
ProjectPath = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh dev ProjectPath').trim()
|
||||||
DatabaseUrlTesting = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh master DatabaseUrl').trim()
|
DatabaseUrlTesting = sh(returnStdout: true, script: 'bash /var/lib/jenkins/variables/CureNet/var.sh master DatabaseUrl').trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,8 +74,8 @@ pipeline {
|
||||||
stage('Backend') {
|
stage('Backend') {
|
||||||
steps {
|
steps {
|
||||||
dir(path: 'src/backend') {
|
dir(path: 'src/backend') {
|
||||||
sh 'APP_SECRET=`php8.0 -r "echo md5(\\"branch=${BRANCH_NAME};\\");"` && sed -i "s/APP_SECRET=.*/APP_SECRET=${APP_SECRET}/g" .env'
|
sh "echo `php8.0 -r 'echo md5(\"branch=${BRANCH_NAME};\");'` | php8.0 ../../tools/putenv/putenv.php .env.test APP_SECRET"
|
||||||
sh '''sed -i 's/DATABASE_URL=.*/DATABASE_URL=${DatabaseUrlTesting}/g' .env.test'''
|
sh "php8.0 ../../tools/putenv/putenv.php .env.test DATABASE_URL \"${DatabaseUrlTesting}\""
|
||||||
sh 'php8.0 /usr/local/bin/composer dump-env test'
|
sh 'php8.0 /usr/local/bin/composer dump-env test'
|
||||||
sh 'php8.0 bin/console doctrine:schema:update --force';
|
sh 'php8.0 bin/console doctrine:schema:update --force';
|
||||||
}
|
}
|
||||||
|
@ -123,9 +123,9 @@ pipeline {
|
||||||
stage('Backend') {
|
stage('Backend') {
|
||||||
steps {
|
steps {
|
||||||
dir(path: 'src/backend') {
|
dir(path: 'src/backend') {
|
||||||
sh '''APP_SECRET=`php8.0 -r "echo md5(\\"branch=${BRANCH_NAME};\\");"` && sed -i 's/APP_SECRET=.*/APP_SECRET=${APP_SECRET}/g' .env'''
|
sh "echo `php8.0 -r 'echo md5(\"branch=${BRANCH_NAME};\");'` | php8.0 ../../tools/putenv/putenv.php .env APP_SECRET"
|
||||||
sh '''sed -i 's/DATABASE_URL=.*/DATABASE_URL=${DatabaseUrl}/g' .env.dev'''
|
sh "php8.0 ../../tools/putenv/putenv.php .env DATABASE_URL \"${DatabaseUrl}\""
|
||||||
sh 'php8.0 /usr/local/bin/composer dump-env dev'
|
sh 'php8.0 /usr/local/bin/composer dump-env prod'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -164,6 +164,7 @@ pipeline {
|
||||||
branch 'staging'
|
branch 'staging'
|
||||||
branch 'beta'
|
branch 'beta'
|
||||||
branch 'dev'
|
branch 'dev'
|
||||||
|
branch '29-profile-page'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -186,6 +187,10 @@ pipeline {
|
||||||
sh 'ssh web@fufle.net touch ${ProjectPath}/backend/REMOVEME'
|
sh 'ssh web@fufle.net touch ${ProjectPath}/backend/REMOVEME'
|
||||||
sh 'ssh web@fufle.net rm -rf ${ProjectPath}/backend/*'
|
sh 'ssh web@fufle.net rm -rf ${ProjectPath}/backend/*'
|
||||||
sh 'scp -r ./* web@fufle.net:${ProjectPath}/backend/'
|
sh 'scp -r ./* web@fufle.net:${ProjectPath}/backend/'
|
||||||
|
sh 'scp -r ./.env web@fufle.net:${ProjectPath}/backend/.env'
|
||||||
|
sh 'ssh web@fufle.net chmod 777 ${ProjectPath}/backend/var -R'
|
||||||
|
sh 'ssh web@fufle.net "cd ${ProjectPath}/backend; php8.0 bin/console doctrine:schema:update --force"'
|
||||||
|
sh 'ssh web@fufle.net "cd ${ProjectPath}/backend; php8.0 bin/console lexik:jwt:generate-keypair --skip-if-exists"'
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
echo "> Configure cache"
|
#echo "> Configure cache"
|
||||||
mkdir -p /tmp/app/vendor
|
# mkdir -p /tmp/app/vendor
|
||||||
ln -s /tmp/app/vendor /web/backend/vendor
|
# ln -s /tmp/app/vendor /web/backend/vendor
|
||||||
|
|
||||||
echo "> Configure user"
|
echo "> Configure user"
|
||||||
useradd developer
|
useradd developer
|
||||||
|
@ -14,10 +14,10 @@ echo "> Configure logs"
|
||||||
chown postgres:adm /var/log/postgresql -R
|
chown postgres:adm /var/log/postgresql -R
|
||||||
chown root:postgres /var/log/postgresql
|
chown root:postgres /var/log/postgresql
|
||||||
|
|
||||||
echo "> Configure volumes"
|
#echo "> Configure volumes"
|
||||||
[ -e /web/frontend/node_modules ] || ln -s /web/node /web/frontend/node_modules
|
# [ -e /web/frontend/node_modules ] || ln -s /web/node /web/frontend/node_modules
|
||||||
[ -e /web/backend/var ] || ln -s /web/var /web/backend/var
|
# [ -e /web/backend/var ] || ln -s /web/var /web/backend/var
|
||||||
[ -e /web/backend/vendor ] || ln -s /web/vendor /web/backend/vendor
|
# [ -e /web/backend/vendor ] || ln -s /web/vendor /web/backend/vendor
|
||||||
|
|
||||||
echo "> Starting php8.0-fpm server"
|
echo "> Starting php8.0-fpm server"
|
||||||
[ -e /etc/php/8.0/fpm/conf.d/20-xdebug.ini ] && rm /etc/php/8.0/fpm/conf.d/20-xdebug.ini || echo OK
|
[ -e /etc/php/8.0/fpm/conf.d/20-xdebug.ini ] && rm /etc/php/8.0/fpm/conf.d/20-xdebug.ini || echo OK
|
||||||
|
|
|
@ -2,3 +2,4 @@ lexik_jwt_authentication:
|
||||||
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
|
secret_key: '%env(resolve:JWT_SECRET_KEY)%'
|
||||||
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
|
public_key: '%env(resolve:JWT_PUBLIC_KEY)%'
|
||||||
pass_phrase: '%env(JWT_PASSPHRASE)%'
|
pass_phrase: '%env(JWT_PASSPHRASE)%'
|
||||||
|
token_ttl: 3600
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -14,7 +14,7 @@ final class Version20210723170329 extends AbstractMigration
|
||||||
{
|
{
|
||||||
public function getDescription(): string
|
public function getDescription(): string
|
||||||
{
|
{
|
||||||
return '';
|
return 'create user table';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
|
|
|
@ -14,7 +14,7 @@ final class Version20210723171757 extends AbstractMigration
|
||||||
{
|
{
|
||||||
public function getDescription(): string
|
public function getDescription(): string
|
||||||
{
|
{
|
||||||
return '';
|
return 'update user table';
|
||||||
}
|
}
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
public function up(Schema $schema): void
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20210806124058 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'create country and country_region tables';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SEQUENCE country_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||||
|
$this->addSql('CREATE SEQUENCE country_region_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||||
|
$this->addSql('CREATE TABLE country (id INT NOT NULL, code VARCHAR(4) NOT NULL, name VARCHAR(255) NOT NULL, subname VARCHAR(255) DEFAULT NULL, locale_name VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE TABLE country_region (id INT NOT NULL, country_id INT NOT NULL, code VARCHAR(4) NOT NULL, name VARCHAR(255) NOT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_4F1A1A05F92F3E70 ON country_region (country_id)');
|
||||||
|
$this->addSql('ALTER TABLE country_region ADD CONSTRAINT FK_4F1A1A05F92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD country_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD state_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP country');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP state');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D649F92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D6495D83CC1 FOREIGN KEY (state_id) REFERENCES country_region (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8D93D649F92F3E70 ON "user" (country_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_8D93D6495D83CC1 ON "user" (state_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE country_region DROP CONSTRAINT FK_4F1A1A05F92F3E70');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D649F92F3E70');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D6495D83CC1');
|
||||||
|
$this->addSql('DROP SEQUENCE country_id_seq CASCADE');
|
||||||
|
$this->addSql('DROP SEQUENCE country_region_id_seq CASCADE');
|
||||||
|
$this->addSql('DROP TABLE country');
|
||||||
|
$this->addSql('DROP TABLE country_region');
|
||||||
|
$this->addSql('DROP INDEX IDX_8D93D649F92F3E70');
|
||||||
|
$this->addSql('DROP INDEX IDX_8D93D6495D83CC1');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD country VARCHAR(3) DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD state VARCHAR(10) DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP country_id');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP state_id');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20210806124110 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return 'import countries';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
$dataDirectory = dirname(__FILE__, 2).'/data';
|
||||||
|
$countries = json_decode(file_get_contents($dataDirectory.'/countries.json'));
|
||||||
|
foreach ($countries as $country) {
|
||||||
|
$this->addSql('INSERT INTO country (id, name, locale_name, code) VALUES (:id, :name, :localeName, :code)', [
|
||||||
|
'id' => $country->id,
|
||||||
|
'name' => $country->name,
|
||||||
|
'localeName' => $country->localeName,
|
||||||
|
'code' => $country->code,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$states = json_decode(file_get_contents($dataDirectory.'/states.json'));
|
||||||
|
foreach ($states as $state) {
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country_id) VALUES (:id, :name, :code, :country)', [
|
||||||
|
'id' => $state->id,
|
||||||
|
'name' => $state->name,
|
||||||
|
'code' => $state->code,
|
||||||
|
'country' => $state->countryId,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
$this->addSql('TRUNCATE country');
|
||||||
|
$this->addSql('TRUNCATE country_region');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20210901131245 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SEQUENCE person_id_seq INCREMENT BY 1 MINVALUE 1 START 1');
|
||||||
|
$this->addSql('CREATE TABLE person (id INT NOT NULL, country_id INT DEFAULT NULL, state_id INT DEFAULT NULL, name VARCHAR(255) NOT NULL, surname VARCHAR(255) NOT NULL, city VARCHAR(255) DEFAULT NULL, zip VARCHAR(7) DEFAULT NULL, avatar VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
|
||||||
|
$this->addSql('CREATE INDEX IDX_34DCD176F92F3E70 ON person (country_id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_34DCD1765D83CC1 ON person (state_id)');
|
||||||
|
$this->addSql('ALTER TABLE person ADD CONSTRAINT FK_34DCD176F92F3E70 FOREIGN KEY (country_id) REFERENCES country (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE person ADD CONSTRAINT FK_34DCD1765D83CC1 FOREIGN KEY (state_id) REFERENCES country_region (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT fk_8d93d649f92f3e70');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT fk_8d93d6495d83cc1');
|
||||||
|
$this->addSql('DROP INDEX idx_8d93d649f92f3e70');
|
||||||
|
$this->addSql('DROP INDEX idx_8d93d6495d83cc1');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD person_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP country_id');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP state_id');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP name');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP surname');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP avatar');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT FK_8D93D649217BBB47 FOREIGN KEY (person_id) REFERENCES person (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('CREATE UNIQUE INDEX UNIQ_8D93D649217BBB47 ON "user" (person_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('CREATE SCHEMA public');
|
||||||
|
$this->addSql('ALTER TABLE "user" DROP CONSTRAINT FK_8D93D649217BBB47');
|
||||||
|
$this->addSql('DROP SEQUENCE person_id_seq CASCADE');
|
||||||
|
$this->addSql('DROP TABLE person');
|
||||||
|
$this->addSql('DROP INDEX UNIQ_8D93D649217BBB47');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD state_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD name VARCHAR(255) NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD surname VARCHAR(255) NOT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD avatar VARCHAR(255) DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE "user" RENAME COLUMN person_id TO country_id');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT fk_8d93d649f92f3e70 FOREIGN KEY (country_id) REFERENCES country (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('ALTER TABLE "user" ADD CONSTRAINT fk_8d93d6495d83cc1 FOREIGN KEY (state_id) REFERENCES country_region (id) NOT DEFERRABLE INITIALLY IMMEDIATE');
|
||||||
|
$this->addSql('CREATE INDEX idx_8d93d649f92f3e70 ON "user" (country_id)');
|
||||||
|
$this->addSql('CREATE INDEX idx_8d93d6495d83cc1 ON "user" (state_id)');
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use App\Entity\User;
|
use App\Entity\User;
|
||||||
|
use App\Entity\Person;
|
||||||
use App\Traits\JsonResponseTrait;
|
use App\Traits\JsonResponseTrait;
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -37,13 +38,20 @@ class AuthController extends AbstractController
|
||||||
return $this->notAcceptable("User email exists");
|
return $this->notAcceptable("User email exists");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$person = new Person();
|
||||||
|
$person->setName($name);
|
||||||
|
$person->setSurname($surname);
|
||||||
|
$person->generateAvatar($email);
|
||||||
|
$em->persist($person);
|
||||||
|
$em->flush();
|
||||||
|
|
||||||
$user = new User();
|
$user = new User();
|
||||||
$user->setPassword($encoder->hashPassword($user, $password));
|
$user->setPassword($encoder->hashPassword($user, $password));
|
||||||
$user->setEmail($email);
|
$user->setEmail($email);
|
||||||
$user->setName($name);
|
$user->setPerson($person);
|
||||||
$user->setSurname($surname);
|
|
||||||
$em->persist($user);
|
$em->persist($user);
|
||||||
$em->flush();
|
$em->flush();
|
||||||
|
|
||||||
return $this->created($user);
|
return $this->created($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +68,7 @@ class AuthController extends AbstractController
|
||||||
if (!$user) {
|
if (!$user) {
|
||||||
return $this->unauthorized([]);
|
return $this->unauthorized([]);
|
||||||
}
|
}
|
||||||
$user->generateAvatar();
|
$user->getPerson()->generateAvatar($user->getEmail());
|
||||||
return $this->ok($user);
|
return $this->ok($user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Traits\JsonResponseTrait;
|
||||||
|
use App\Repository\CountryRepository;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
|
||||||
|
class CountryController extends AbstractController
|
||||||
|
{
|
||||||
|
use JsonResponseTrait;
|
||||||
|
|
||||||
|
public function __construct(private CountryRepository $countryRepository) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/country', methods: ["GET"])]
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$countries = $this->countryRepository->findAllFlat();
|
||||||
|
//dd($countries);
|
||||||
|
return $this->ok($countries);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller;
|
||||||
|
|
||||||
|
use App\Traits\JsonResponseTrait;
|
||||||
|
use App\Repository\PersonRepository;
|
||||||
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
|
||||||
|
class PersonController extends AbstractController
|
||||||
|
{
|
||||||
|
use JsonResponseTrait;
|
||||||
|
|
||||||
|
public function __construct(private PersonRepository $personRepository) {
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route('/api/person/{personId}', methods: ["GET"])]
|
||||||
|
public function show(int $personId)
|
||||||
|
{
|
||||||
|
$person = $this->personRepository->get($personId);
|
||||||
|
return $this->ok($person);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
namespace App\Entity\Abstraction;
|
namespace App\Entity\Abstraction;
|
||||||
|
|
||||||
use ReflectionClass;
|
|
||||||
use Symfony\Component\Serializer\Serializer;
|
use Symfony\Component\Serializer\Serializer;
|
||||||
use Symfony\Component\Serializer\Encoder\JsonEncoder;
|
|
||||||
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
|
||||||
|
use Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer;
|
||||||
|
|
||||||
class BaseEntity {
|
class BaseEntity {
|
||||||
protected array $hidden = [];
|
protected array $hidden = [];
|
||||||
|
@ -13,9 +13,14 @@ class BaseEntity {
|
||||||
private array $systemParams = ['hidden', 'map', 'systemParams'];
|
private array $systemParams = ['hidden', 'map', 'systemParams'];
|
||||||
public function toArray() {
|
public function toArray() {
|
||||||
$output = [];
|
$output = [];
|
||||||
$normalizers = [new ObjectNormalizer()];
|
$defaultContext = [
|
||||||
|
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, $format, $context) {
|
||||||
|
return '$' . basename(str_replace('\\', '/', $object::class));
|
||||||
|
},
|
||||||
|
];
|
||||||
|
$normalizers = [new ObjectNormalizer(defaultContext: $defaultContext)];
|
||||||
$serializer = new Serializer($normalizers);
|
$serializer = new Serializer($normalizers);
|
||||||
$array = $serializer->normalize($this, null);
|
$array = $serializer->normalize($this, null, [ AbstractObjectNormalizer::ENABLE_MAX_DEPTH => true ]);
|
||||||
|
|
||||||
$hidden = array_merge($this->hidden, $this->systemParams);
|
$hidden = array_merge($this->hidden, $this->systemParams);
|
||||||
foreach ($array as $key => $value) {
|
foreach ($array as $key => $value) {
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use App\Repository\CountryRepository;
|
||||||
|
use App\Entity\Abstraction\BaseEntity;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity(repositoryClass=CountryRepository::class)
|
||||||
|
*/
|
||||||
|
class Country extends BaseEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=4)
|
||||||
|
*/
|
||||||
|
private $code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255)
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\OneToMany(targetEntity=CountryRegion::class, mappedBy="country")
|
||||||
|
*/
|
||||||
|
private $regions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255, nullable=true)
|
||||||
|
*/
|
||||||
|
private $subname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255, nullable=true)
|
||||||
|
*/
|
||||||
|
private $localeName;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->regions = new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCode(): ?string
|
||||||
|
{
|
||||||
|
return $this->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCode(string $code): self
|
||||||
|
{
|
||||||
|
$this->code = $code;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): ?string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(string $name): self
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Collection|CountryRegion[]
|
||||||
|
*/
|
||||||
|
public function getRegions(): Collection
|
||||||
|
{
|
||||||
|
return $this->regions ?? new ArrayCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addRegion(CountryRegion $region): self
|
||||||
|
{
|
||||||
|
if (!$this->regions->contains($region)) {
|
||||||
|
$this->regions[] = $region;
|
||||||
|
$region->setCountry($this);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeRegion(CountryRegion $region): self
|
||||||
|
{
|
||||||
|
if ($this->regions->removeElement($region)) {
|
||||||
|
// set the owning side to null (unless already changed)
|
||||||
|
if ($region->getCountry() === $this) {
|
||||||
|
$region->setCountry(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSubname(): ?string
|
||||||
|
{
|
||||||
|
return $this->subname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSubname(?string $subname): self
|
||||||
|
{
|
||||||
|
$this->subname = $subname;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLocaleName(): ?string
|
||||||
|
{
|
||||||
|
return $this->localeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLocaleName(?string $localeName): self
|
||||||
|
{
|
||||||
|
$this->localeName = $localeName;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use App\Entity\Abstraction\BaseEntity;
|
||||||
|
use App\Repository\CountryRegionRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity(repositoryClass=CountryRegionRepository::class)
|
||||||
|
*/
|
||||||
|
class CountryRegion extends BaseEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=4)
|
||||||
|
*/
|
||||||
|
private $code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Country::class, inversedBy="regions")
|
||||||
|
* @ORM\JoinColumn(nullable=false)
|
||||||
|
*/
|
||||||
|
private $country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255)
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCode(): ?string
|
||||||
|
{
|
||||||
|
return $this->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCode(string $code): self
|
||||||
|
{
|
||||||
|
$this->code = $code;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountry(): ?Country
|
||||||
|
{
|
||||||
|
return $this->country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCountry(?Country $country): self
|
||||||
|
{
|
||||||
|
$this->country = $country;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): ?string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(string $name): self
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,150 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
use App\Repository\PersonRepository;
|
||||||
|
use App\Entity\Abstraction\BaseEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Entity(repositoryClass=PersonRepository::class)
|
||||||
|
*/
|
||||||
|
class Person extends BaseEntity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @ORM\Id
|
||||||
|
* @ORM\GeneratedValue
|
||||||
|
* @ORM\Column(type="integer")
|
||||||
|
*/
|
||||||
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255)
|
||||||
|
*/
|
||||||
|
private $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255)
|
||||||
|
*/
|
||||||
|
private $surname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=Country::class)
|
||||||
|
*/
|
||||||
|
private $country;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\ManyToOne(targetEntity=CountryRegion::class)
|
||||||
|
*/
|
||||||
|
private $state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255, nullable=true)
|
||||||
|
*/
|
||||||
|
private $city;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=7, nullable=true)
|
||||||
|
*/
|
||||||
|
private $zip;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ORM\Column(type="string", length=255, nullable=true)
|
||||||
|
*/
|
||||||
|
private $avatar;
|
||||||
|
|
||||||
|
public function getId(): ?int
|
||||||
|
{
|
||||||
|
return $this->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName(): ?string
|
||||||
|
{
|
||||||
|
return $this->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setName(string $name): self
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSurname(): ?string
|
||||||
|
{
|
||||||
|
return $this->surname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setSurname(string $surname): self
|
||||||
|
{
|
||||||
|
$this->surname = $surname;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCountry(): ?Country
|
||||||
|
{
|
||||||
|
return $this->country;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCountry(?Country $country): self
|
||||||
|
{
|
||||||
|
$this->country = $country;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getState(): ?CountryRegion
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setState(?CountryRegion $state): self
|
||||||
|
{
|
||||||
|
$this->state = $state;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCity(): ?string
|
||||||
|
{
|
||||||
|
return $this->city;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCity(string $city): self
|
||||||
|
{
|
||||||
|
$this->city = $city;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getZip(): ?string
|
||||||
|
{
|
||||||
|
return $this->zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setZip(string $zip): self
|
||||||
|
{
|
||||||
|
$this->zip = $zip;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAvatar(): ?string
|
||||||
|
{
|
||||||
|
return $this->avatar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setAvatar(string $avatar): self
|
||||||
|
{
|
||||||
|
$this->avatar = $avatar;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateAvatar($email) {
|
||||||
|
if (!$this->avatar) {
|
||||||
|
$this->avatar = 'https://www.gravatar.com/avatar/' . md5($email) . '?s=512&d=robohash';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Entity\Person;
|
||||||
|
use App\Enums\UserRoleEnum;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use App\Repository\UserRepository;
|
use App\Repository\UserRepository;
|
||||||
use App\Entity\Abstraction\BaseEntity;
|
use App\Entity\Abstraction\BaseEntity;
|
||||||
|
@ -41,29 +43,10 @@ class User extends BaseEntity implements UserInterface, PasswordAuthenticatedUse
|
||||||
private $email;
|
private $email;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string", length=255)
|
* @ORM\OneToOne(targetEntity=Person::class, cascade={"persist", "remove"})
|
||||||
*/
|
*/
|
||||||
private $name;
|
private $person;
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Column(type="string", length=255)
|
|
||||||
*/
|
|
||||||
private $surname;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Column(type="string", length=255, nullable=true)
|
|
||||||
*/
|
|
||||||
private $avatar;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Column(type="string", length=3, nullable=true)
|
|
||||||
*/
|
|
||||||
private $country;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ORM\Column(type="string", length=10, nullable=true)
|
|
||||||
*/
|
|
||||||
private $state;
|
|
||||||
|
|
||||||
public static function createFromPayload($username, array $payload)
|
public static function createFromPayload($username, array $payload)
|
||||||
{
|
{
|
||||||
|
@ -108,7 +91,12 @@ class User extends BaseEntity implements UserInterface, PasswordAuthenticatedUse
|
||||||
{
|
{
|
||||||
$roles = $this->roles;
|
$roles = $this->roles;
|
||||||
// guarantee every user at least has ROLE_USER
|
// guarantee every user at least has ROLE_USER
|
||||||
$roles[] = 'ROLE_USER';
|
$roles[] = UserRoleEnum::User;
|
||||||
|
if ($this->id === 1) {
|
||||||
|
$roles[] = UserRoleEnum::UserVerified;
|
||||||
|
$roles[] = UserRoleEnum::Moderator;
|
||||||
|
$roles[] = UserRoleEnum::Administrator;
|
||||||
|
}
|
||||||
|
|
||||||
return array_unique($roles);
|
return array_unique($roles);
|
||||||
}
|
}
|
||||||
|
@ -167,69 +155,15 @@ class User extends BaseEntity implements UserInterface, PasswordAuthenticatedUse
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName(): ?string
|
public function getPerson(): ?Person
|
||||||
{
|
{
|
||||||
return $this->name;
|
return $this->person;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName(string $name): self
|
public function setPerson(?Person $person): self
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->person = $person;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getSurname(): ?string
|
|
||||||
{
|
|
||||||
return $this->surname;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setSurname(string $surname): self
|
|
||||||
{
|
|
||||||
$this->surname = $surname;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAvatar(): ?string
|
|
||||||
{
|
|
||||||
return $this->avatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setAvatar(?string $avatar): self
|
|
||||||
{
|
|
||||||
$this->avatar = $avatar;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCountry(): ?string
|
|
||||||
{
|
|
||||||
return $this->country;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setCountry(?string $country): self
|
|
||||||
{
|
|
||||||
$this->country = $country;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getState(): ?string
|
|
||||||
{
|
|
||||||
return $this->state;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function setState(?string $state): self
|
|
||||||
{
|
|
||||||
$this->state = $state;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function generateAvatar() {
|
|
||||||
if (!$this->avatar) {
|
|
||||||
$this->avatar = 'https://www.gravatar.com/avatar/' . md5($this->email) . '?s=514&d=robohash';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Enums;
|
||||||
|
|
||||||
|
class UserRoleEnum {
|
||||||
|
const None = 'none';
|
||||||
|
const User = 'user';
|
||||||
|
const UserVerified = 'user2';
|
||||||
|
const Doctor = 'doc';
|
||||||
|
const DoctorVerified = 'doc2';
|
||||||
|
const Moderator = 'mod';
|
||||||
|
const Administrator = 'admin';
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\CountryRegion;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method CountryRegion|null find($id, $lockMode = null, $lockVersion = null)
|
||||||
|
* @method CountryRegion|null findOneBy(array $criteria, array $orderBy = null)
|
||||||
|
* @method CountryRegion[] findAll()
|
||||||
|
* @method CountryRegion[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||||
|
*/
|
||||||
|
class CountryRegionRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, CountryRegion::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return CountryRegion[] Returns an array of CountryRegion objects
|
||||||
|
// */
|
||||||
|
/*
|
||||||
|
public function findByExampleField($value)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->andWhere('c.exampleField = :val')
|
||||||
|
->setParameter('val', $value)
|
||||||
|
->orderBy('c.id', 'ASC')
|
||||||
|
->setMaxResults(10)
|
||||||
|
->getQuery()
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
public function findOneBySomeField($value): ?CountryRegion
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->andWhere('c.exampleField = :val')
|
||||||
|
->setParameter('val', $value)
|
||||||
|
->getQuery()
|
||||||
|
->getOneOrNullResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\Country;
|
||||||
|
use Doctrine\ORM\Query;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method Country|null find($id, $lockMode = null, $lockVersion = null)
|
||||||
|
* @method Country|null findOneBy(array $criteria, array $orderBy = null)
|
||||||
|
* @method Country[] findAll()
|
||||||
|
* @method Country[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||||
|
*/
|
||||||
|
class CountryRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, Country::class);
|
||||||
|
}
|
||||||
|
public function findAllFlat()
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->orderBy('c.name', 'ASC')
|
||||||
|
->getQuery()
|
||||||
|
->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return Country[] Returns an array of Country objects
|
||||||
|
// */
|
||||||
|
/*
|
||||||
|
public function findByExampleField($value)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->andWhere('c.exampleField = :val')
|
||||||
|
->setParameter('val', $value)
|
||||||
|
->orderBy('c.id', 'ASC')
|
||||||
|
->setMaxResults(10)
|
||||||
|
->getQuery()
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
public function findOneBySomeField($value): ?Country
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('c')
|
||||||
|
->andWhere('c.exampleField = :val')
|
||||||
|
->setParameter('val', $value)
|
||||||
|
->getQuery()
|
||||||
|
->getOneOrNullResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\Person;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @method Person|null find($id, $lockMode = null, $lockVersion = null)
|
||||||
|
* @method Person|null findOneBy(array $criteria, array $orderBy = null)
|
||||||
|
* @method Person[] findAll()
|
||||||
|
* @method Person[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||||
|
*/
|
||||||
|
class PersonRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, Person::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return Person[] Returns an array of Person objects
|
||||||
|
// */
|
||||||
|
/*
|
||||||
|
public function findByExampleField($value)
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('p')
|
||||||
|
->andWhere('p.exampleField = :val')
|
||||||
|
->setParameter('val', $value)
|
||||||
|
->orderBy('p.id', 'ASC')
|
||||||
|
->setMaxResults(10)
|
||||||
|
->getQuery()
|
||||||
|
->getResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function get(int $personId): ?Person
|
||||||
|
{
|
||||||
|
return $this->createQueryBuilder('p')
|
||||||
|
->andWhere('p.id = :id')
|
||||||
|
->setParameter('id', $personId)
|
||||||
|
->getQuery()
|
||||||
|
->getOneOrNullResult()
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,6 @@
|
||||||
namespace App\Traits;
|
namespace App\Traits;
|
||||||
|
|
||||||
use App\Entity\Abstraction\BaseEntity;
|
use App\Entity\Abstraction\BaseEntity;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
|
||||||
|
@ -30,6 +29,14 @@ trait JsonResponseTrait {
|
||||||
$data = $data->toArray();
|
$data = $data->toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_array($data)) {
|
||||||
|
foreach ($data as $key => $value) {
|
||||||
|
if ($value instanceof BaseEntity) {
|
||||||
|
$data[$key] = $value->toArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonResponse($data, $code, $headers);
|
return new JsonResponse($data, $code, $headers);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,17 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Route, RouterModule } from '@angular/router';
|
import { Route, RouterModule } from '@angular/router';
|
||||||
|
import { AuthTabEnum } from './modules/auth/enums/auth-tab.enum';
|
||||||
|
import { UserRoleEnum } from './modules/auth/enums/user-role.enum';
|
||||||
import { AuthGuard } from './modules/auth/services/auth/auth.guard';
|
import { AuthGuard } from './modules/auth/services/auth/auth.guard';
|
||||||
import { NotFoundComponent } from './modules/shared/components/not-found/not-found.component';
|
import { NotFoundComponent } from './modules/shared/components/not-found/not-found.component';
|
||||||
|
|
||||||
interface AppMenuEntry {
|
export interface AppMenuEntry {
|
||||||
label: string;
|
label: string;
|
||||||
icon: string;
|
icon: string;
|
||||||
path?: string;
|
path?: string;
|
||||||
matchExact?: boolean;
|
matchExact?: boolean;
|
||||||
level?: number;
|
level?: number;
|
||||||
|
roles: UserRoleEnum[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AppRoute extends Route {
|
interface AppRoute extends Route {
|
||||||
|
@ -16,10 +19,6 @@ interface AppRoute extends Route {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const appRoutes: AppRoute[] = [
|
export const appRoutes: AppRoute[] = [
|
||||||
{
|
|
||||||
path: 'auth',
|
|
||||||
loadChildren: () => import('./modules/auth/auth.module').then(m => m.AuthModule),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: NotFoundComponent,
|
component: NotFoundComponent,
|
||||||
|
@ -27,19 +26,49 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.HOME',
|
label: 'MENU.HOME',
|
||||||
icon: 'fa fa-home',
|
icon: 'fa fa-home',
|
||||||
|
roles: [],
|
||||||
matchExact: true,
|
matchExact: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
canActivateChild: [ AuthGuard, ],
|
canActivateChild: [ AuthGuard, ],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'auth',
|
||||||
|
loadChildren: () => import('./modules/auth/auth.module').then(m => m.AuthModule),
|
||||||
|
menuEntries: [
|
||||||
|
{
|
||||||
|
path: `auth/${AuthTabEnum.Login}`,
|
||||||
|
label: 'AUTH.SIGN_IN',
|
||||||
|
icon: 'fa fa-sign-in',
|
||||||
|
roles: [ UserRoleEnum.None ],
|
||||||
|
matchExact: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `auth/${AuthTabEnum.Register}`,
|
||||||
|
label: 'AUTH.SIGN_UP',
|
||||||
|
icon: 'fa fa-sign-out',
|
||||||
|
roles: [ UserRoleEnum.None ],
|
||||||
|
matchExact: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: `auth/${AuthTabEnum.RestorePassword}`,
|
||||||
|
label: 'AUTH.RESTORE_ACCOUNT',
|
||||||
|
icon: 'fa fa-undo',
|
||||||
|
roles: [ UserRoleEnum.None ],
|
||||||
|
matchExact: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'profile',
|
path: 'profile',
|
||||||
component: NotFoundComponent,
|
loadChildren: () => import('./modules/profile/profile.module').then(m => m.ProfileModule),
|
||||||
menuEntries: [
|
menuEntries: [
|
||||||
{
|
{
|
||||||
label: 'MENU.PROFILE',
|
label: 'MENU.PROFILE',
|
||||||
icon: 'fa fa-user',
|
icon: 'fa fa-user',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
|
@ -52,6 +81,7 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.COMMUNITY',
|
label: 'MENU.COMMUNITY',
|
||||||
icon: 'fa fa-users',
|
icon: 'fa fa-users',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
|
@ -64,6 +94,7 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.QUESTIONS',
|
label: 'MENU.QUESTIONS',
|
||||||
icon: 'fa fa-question',
|
icon: 'fa fa-question',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
level: 1,
|
level: 1,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -77,6 +108,7 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.MESSAGES',
|
label: 'MENU.MESSAGES',
|
||||||
icon: 'fa fa-comments',
|
icon: 'fa fa-comments',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
|
@ -89,6 +121,7 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.TESTS',
|
label: 'MENU.TESTS',
|
||||||
icon: 'fa fa-heartbeat',
|
icon: 'fa fa-heartbeat',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
|
@ -101,6 +134,7 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.RESEARCH',
|
label: 'MENU.RESEARCH',
|
||||||
icon: 'fa fa-flask',
|
icon: 'fa fa-flask',
|
||||||
|
roles: [ UserRoleEnum.User ],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
canActivate: [ AuthGuard, ],
|
canActivate: [ AuthGuard, ],
|
||||||
|
@ -113,12 +147,14 @@ export const appRoutes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
label: 'MENU.ADMIN',
|
label: 'MENU.ADMIN',
|
||||||
icon: 'fa fa-id-card',
|
icon: 'fa fa-id-card',
|
||||||
|
roles: [ UserRoleEnum.Administrator, UserRoleEnum.Moderator ],
|
||||||
matchExact: true,
|
matchExact: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'admin/users',
|
path: 'admin/users',
|
||||||
label: 'MENU.USERS',
|
label: 'MENU.USERS',
|
||||||
icon: 'fa fa-users',
|
icon: 'fa fa-users',
|
||||||
|
roles: [ UserRoleEnum.Administrator, UserRoleEnum.Moderator ],
|
||||||
level: 1,
|
level: 1,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,79 +1,77 @@
|
||||||
|
<app-loader *ngIf="!loaded"></app-loader>
|
||||||
<ng-template #toolbar>
|
<ng-container *ngIf="loaded">
|
||||||
<mat-toolbar class="toolbar-background">
|
<ng-template #toolbar>
|
||||||
<button mat-icon-button (click)="toggleSidebar()" *ngIf="!isSidebarHidden">
|
<mat-toolbar class="toolbar-background">
|
||||||
<i class="fa fa-bars"></i>
|
<button mat-icon-button (click)="toggleSidebar()">
|
||||||
</button>
|
<i class="fa fa-bars"></i>
|
||||||
<span>{{ 'APP.NAME' | translate }}</span>
|
</button>
|
||||||
<span class="flex-grow-1"></span>
|
<span>{{ 'APP.NAME' | translate }}</span>
|
||||||
<div>
|
<span class="flex-grow-1"></span>
|
||||||
<div *ngFor="let component of dynamicToolbarComponents">
|
|
||||||
<ng-container [ngComponentOutlet]="component"></ng-container>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</mat-toolbar>
|
|
||||||
</ng-template>
|
|
||||||
<ng-container *ngIf="!isMobile">
|
|
||||||
<ng-container *ngTemplateOutlet="toolbar"></ng-container>
|
|
||||||
</ng-container>
|
|
||||||
<mat-drawer-container class="flex-grow-1">
|
|
||||||
<mat-drawer [mode]="sidebarMode" [opened]="isSidebarOpen" (openedChange)="onSidebarOpenedChange($event)" *ngIf="!isSidebarHidden">
|
|
||||||
<div class="menu">
|
|
||||||
<div>
|
<div>
|
||||||
<ng-container *ngFor="let route of appRoutes">
|
<div *ngFor="let component of dynamicToolbarComponents">
|
||||||
<ng-container *ngIf="route.menuEntries">
|
<ng-container [ngComponentOutlet]="component"></ng-container>
|
||||||
<div
|
</div>
|
||||||
*ngFor="let menu of route.menuEntries"
|
</div>
|
||||||
class="menu-item"
|
</mat-toolbar>
|
||||||
[attr.style]="menu.level ? 'margin-left: '+(menu.level * 20)+'px' : ''"
|
</ng-template>
|
||||||
[routerLink]="menu.path ? menu.path : route.path"
|
<ng-container *ngIf="!isMobile">
|
||||||
routerLinkActive="active"
|
<ng-container *ngTemplateOutlet="toolbar"></ng-container>
|
||||||
[routerLinkActiveOptions]="{exact: menu.matchExact}">
|
</ng-container>
|
||||||
<i [class]="menu.icon" [title]="menu.label | translate"></i>
|
<mat-drawer-container class="flex-grow-1">
|
||||||
<span>{{ menu.label | translate }}</span>
|
<mat-drawer [mode]="sidebarMode" [opened]="isSidebarOpen" (openedChange)="onSidebarOpenedChange($event)">
|
||||||
</div>
|
<div class="menu">
|
||||||
|
<div>
|
||||||
|
<ng-container *ngFor="let route of appRoutes">
|
||||||
|
<ng-container *ngIf="route.menuEntries">
|
||||||
|
<ng-container
|
||||||
|
*ngFor="let menu of route.menuEntries">
|
||||||
|
<div
|
||||||
|
*ngIf="canShowMenuEntry(menu)"
|
||||||
|
class="menu-item"
|
||||||
|
[attr.style]="menu.level ? 'margin-left: '+(menu.level * 20)+'px' : ''"
|
||||||
|
[routerLink]="menu.path ? menu.path : route.path"
|
||||||
|
routerLinkActive="active"
|
||||||
|
[routerLinkActiveOptions]="{exact: menu.matchExact}">
|
||||||
|
<i [class]="menu.icon" [title]="menu.label | translate"></i>
|
||||||
|
<span>{{ menu.label | translate }}</span>
|
||||||
|
</div>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</div>
|
||||||
</div>
|
<div>
|
||||||
<div>
|
<div class="d-flex user-box" *ngIf="user">
|
||||||
<div class="d-flex user-box" *ngIf="user">
|
<div class="avatar" [style.background-image]="url(user.person.avatar)"></div>
|
||||||
<div class="avatar" [style.background-image]="url(user.avatar)"></div>
|
<div class="d-flex align-items-center flex-grow-1 p-2">{{ user.person.name }} {{ user.person.surname }}</div>
|
||||||
<div class="d-flex align-items-center flex-grow-1 p-2">{{ user.name }} {{ user.surname }}</div>
|
<div class="user-menu-container">
|
||||||
<div class="user-menu-container">
|
<div class="user-menu">
|
||||||
<div class="user-menu">
|
<button mat-icon-button [matMenuTriggerFor]="usermenu">
|
||||||
<button mat-icon-button [matMenuTriggerFor]="usermenu">
|
<i class="fa fa-cog"></i>
|
||||||
<i class="fa fa-cog"></i>
|
</button>
|
||||||
</button>
|
</div>
|
||||||
|
<mat-menu #usermenu="matMenu" yPosition="above" xPosition="before" class="w-220">
|
||||||
|
<button mat-menu-item routerLink="/profile">
|
||||||
|
{{ 'APP.USER_SETTINGS' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item routerLink="/profile/settings">
|
||||||
|
{{ 'APP.USER_SITE_SETTINGS' | translate }}
|
||||||
|
</button>
|
||||||
|
<button mat-menu-item (click)="logout()">
|
||||||
|
{{ 'APP.LOGOUT' | translate}}
|
||||||
|
</button>
|
||||||
|
</mat-menu>
|
||||||
</div>
|
</div>
|
||||||
<mat-menu #usermenu="matMenu" yPosition="above" xPosition="before" class="w-220">
|
|
||||||
<mat-form-field class="w-100 px-3">
|
|
||||||
<mat-label>{{ 'APP.LANGUAGE' | translate }}</mat-label>
|
|
||||||
<mat-select [formControl]="langControl">
|
|
||||||
<mat-option *ngFor="let lang of langs" [value]="lang">{{ 'LANGUAGE.'+lang.toUpperCase() | translate }}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
|
|
||||||
<mat-form-field class="w-100 px-3">
|
|
||||||
<mat-label>{{ 'APP.THEME' | translate }}</mat-label>
|
|
||||||
<mat-select [formControl]="themeControl">
|
|
||||||
<mat-option *ngFor="let theme of themes" [value]="theme">{{ 'THEME.'+theme.toUpperCase() | translate }}</mat-option>
|
|
||||||
</mat-select>
|
|
||||||
</mat-form-field>
|
|
||||||
<button mat-menu-item (click)="logout()">
|
|
||||||
Wyloguj
|
|
||||||
</button>
|
|
||||||
</mat-menu>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</mat-drawer>
|
||||||
</mat-drawer>
|
|
||||||
|
|
||||||
<ng-container *ngIf="isMobile">
|
<ng-container *ngIf="isMobile">
|
||||||
<ng-container *ngTemplateOutlet="toolbar"></ng-container>
|
<ng-container *ngTemplateOutlet="toolbar"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<div class="example-sidenav-content">
|
<div class="content">
|
||||||
<router-outlet></router-outlet>
|
<router-outlet></router-outlet>
|
||||||
</div>
|
</div>
|
||||||
</mat-drawer-container>
|
</mat-drawer-container>
|
||||||
|
</ng-container>
|
|
@ -88,4 +88,9 @@ $sidebar-width: 250px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative;
|
||||||
|
overflow: auto;
|
||||||
}
|
}
|
|
@ -1,162 +1,139 @@
|
||||||
import { Component } from '@angular/core';
|
import { AfterContentInit, Component } from '@angular/core';
|
||||||
import { FormControl } from '@angular/forms';
|
import { AppMenuEntry, appRoutes } from './app-routing.module';
|
||||||
import { appRoutes } from './app-routing.module';
|
|
||||||
import { AppService, WindowSize } from './modules/shared/services/app/app.service';
|
import { AppService, WindowSize } from './modules/shared/services/app/app.service';
|
||||||
import { BrowserStorageService } from './modules/shared/services/browser-storage/browser-storage.service';
|
import { BrowserStorageService } from './modules/shared/services/browser-storage/browser-storage.service';
|
||||||
import { ThemeService } from './modules/shared/services/theme/theme.service';
|
|
||||||
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||||
import { AuthService } from './modules/auth/services/auth/auth.service';
|
import { AuthService } from './modules/auth/services/auth/auth.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
import { UserModel } from './modules/auth/models/user.model';
|
import { UserModel } from './modules/auth/models/user.model';
|
||||||
|
import { UserRoleEnum } from './modules/auth/enums/user-role.enum';
|
||||||
|
|
||||||
enum SidebarOpenEnum {
|
enum SidebarOpenEnum {
|
||||||
Default,
|
Default,
|
||||||
Open,
|
Open,
|
||||||
Closed,
|
Closed,
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrls: ['./app.component.scss']
|
styleUrls: ['./app.component.scss']
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent implements AfterContentInit {
|
||||||
isMobile = true;
|
|
||||||
title = 'CureNet';
|
|
||||||
sidebarOpen = SidebarOpenEnum.Default;
|
|
||||||
sidebarMode = 'over';
|
|
||||||
defaultSidebarOpen = false;
|
|
||||||
lang: string;
|
|
||||||
theme: string;
|
|
||||||
langs: string[] = [];
|
|
||||||
themes: string[] = [];
|
|
||||||
themeControl = new FormControl();
|
|
||||||
langControl = new FormControl();
|
|
||||||
appRoutes = appRoutes;
|
|
||||||
user: UserModel;
|
|
||||||
isSidebarHidden = false;
|
|
||||||
dynamicToolbarComponents = [];
|
|
||||||
|
|
||||||
get isSidebarOpen(): boolean {
|
isMobile = true;
|
||||||
switch (this.sidebarOpen) {
|
title = 'CureNet';
|
||||||
case SidebarOpenEnum.Open:
|
sidebarOpen = SidebarOpenEnum.Default;
|
||||||
return true;
|
sidebarMode = 'over';
|
||||||
case SidebarOpenEnum.Closed:
|
defaultSidebarOpen = false;
|
||||||
return false;
|
appRoutes = appRoutes;
|
||||||
default:
|
user: UserModel;
|
||||||
return this.defaultSidebarOpen;
|
loaded = false;
|
||||||
|
dynamicToolbarComponents = [];
|
||||||
|
roles: UserRoleEnum[] = [ UserRoleEnum.None ];
|
||||||
|
|
||||||
|
get isSidebarOpen(): boolean {
|
||||||
|
switch (this.sidebarOpen) {
|
||||||
|
case SidebarOpenEnum.Open:
|
||||||
|
return true;
|
||||||
|
case SidebarOpenEnum.Closed:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return this.defaultSidebarOpen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private appService: AppService,
|
private appService: AppService,
|
||||||
private themeService: ThemeService,
|
private browserStorageService: BrowserStorageService,
|
||||||
private browserStorageService: BrowserStorageService,
|
private sanitizer: DomSanitizer,
|
||||||
private sanitizer: DomSanitizer,
|
private authService: AuthService,
|
||||||
private authService: AuthService,
|
private router: Router,
|
||||||
private router: Router,
|
) {
|
||||||
) {
|
}
|
||||||
this.configureSidebarEvents();
|
|
||||||
this.configureThemeEvents();
|
|
||||||
this.configureLanguageEvents();
|
|
||||||
this.configureResizeEvents();
|
|
||||||
this.configureUserEvents();
|
|
||||||
}
|
|
||||||
|
|
||||||
configureUserEvents(): void {
|
ngAfterContentInit(): void {
|
||||||
this.user = this.authService.getUser();
|
this.configureResizeEvents();
|
||||||
this.authService.userChange.subscribe(user => {
|
this.configureUserEvents();
|
||||||
|
this.configureSidebarEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
canShowMenuEntry(menu: AppMenuEntry): boolean {
|
||||||
|
return !menu.roles.some(i => !this.roles.includes(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
configureUserEvents(): void {
|
||||||
|
this.authService.checkUser().then(user => {
|
||||||
|
this.setUser(user);
|
||||||
|
this.loaded = true;
|
||||||
|
}).catch(() => {
|
||||||
|
this.setUser(null);
|
||||||
|
this.loaded = true;
|
||||||
|
});
|
||||||
|
this.setUser(this.authService.getUser());
|
||||||
|
this.authService.userChange.subscribe(user => {
|
||||||
|
this.setUser(user);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setUser(user: UserModel): void {
|
||||||
|
if (!user && !this.user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (user && this.user) {
|
||||||
|
if (user.id === this.user.id && user.roles.join(',') === this.user.roles.join(',')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
this.user = user;
|
this.user = user;
|
||||||
});
|
if (this.user) {
|
||||||
}
|
this.roles = this.user.roles;
|
||||||
|
} else {
|
||||||
configureSidebarEvents(): void {
|
this.roles = [ UserRoleEnum.None ];
|
||||||
this.isSidebarHidden = this.appService.getSidebarHidden();
|
}
|
||||||
this.appService.sidebarHiddenChange.subscribe(hidden => {
|
|
||||||
this.isSidebarHidden = hidden;
|
|
||||||
});
|
|
||||||
const sidebarUserPrefference = this.browserStorageService.getItem('sidebar.open');
|
|
||||||
if (sidebarUserPrefference !== null) {
|
|
||||||
this.sidebarOpen = sidebarUserPrefference;
|
|
||||||
}
|
|
||||||
this.appService.dynamicToolbarComponentsChange.subscribe(components => {
|
|
||||||
this.dynamicToolbarComponents = components;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
configureThemeEvents(): void {
|
|
||||||
this.themes = this.themeService.getThemes();
|
|
||||||
this.themeControl.valueChanges.subscribe(theme => {
|
|
||||||
this.themeService.setTheme(theme);
|
|
||||||
});
|
|
||||||
this.onThemeChanged(this.themeService.getTheme());
|
|
||||||
this.themeService.themeChange.subscribe(theme => {
|
|
||||||
this.onThemeChanged(theme);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
configureLanguageEvents(): void {
|
|
||||||
this.langs = this.appService.getLangs();
|
|
||||||
this.lang = this.appService.getLang();
|
|
||||||
|
|
||||||
this.appService.changeLang(this.lang);
|
|
||||||
this.langControl.valueChanges.subscribe(lang => {
|
|
||||||
this.appService.changeLang(lang);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.onLangChanged(this.appService.getLang());
|
|
||||||
this.appService.langChange.subscribe(lang => {
|
|
||||||
this.onLangChanged(lang);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
configureResizeEvents(): void {
|
|
||||||
this.onResize(this.appService.size);
|
|
||||||
this.appService.sizeChange.subscribe(size => {
|
|
||||||
this.onResize(size);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
onThemeChanged(theme: string): void {
|
|
||||||
if (theme === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this.theme = theme;
|
|
||||||
this.themeControl.setValue(theme);
|
|
||||||
}
|
|
||||||
|
|
||||||
onResize(size: WindowSize): void {
|
configureSidebarEvents(): void {
|
||||||
if (size === undefined) {
|
const sidebarUserPrefference = this.browserStorageService.getItem('sidebar.open');
|
||||||
return;
|
if (sidebarUserPrefference !== null) {
|
||||||
|
this.sidebarOpen = sidebarUserPrefference;
|
||||||
|
}
|
||||||
|
this.appService.dynamicToolbarComponentsChange.subscribe(components => {
|
||||||
|
this.dynamicToolbarComponents = components;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.isMobile = size.isMobile;
|
|
||||||
this.defaultSidebarOpen = !size.isMobile;
|
|
||||||
this.sidebarMode = this.isMobile ? 'over' : 'side';
|
|
||||||
}
|
|
||||||
|
|
||||||
onLangChanged(lang: string): void {
|
configureResizeEvents(): void {
|
||||||
if (lang === undefined) {
|
this.onResize(this.appService.size);
|
||||||
return;
|
this.appService.sizeChange.subscribe(size => {
|
||||||
|
this.onResize(size);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
this.lang = lang;
|
|
||||||
this.langControl.setValue(lang);
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSidebar(): void {
|
onResize(size: WindowSize): void {
|
||||||
this.sidebarOpen = this.isSidebarOpen ? SidebarOpenEnum.Closed : SidebarOpenEnum.Open;
|
if (size === undefined) {
|
||||||
this.browserStorageService.setItem('sidebar.open', this.sidebarOpen);
|
return;
|
||||||
}
|
}
|
||||||
|
this.isMobile = size.isMobile;
|
||||||
|
this.defaultSidebarOpen = !size.isMobile;
|
||||||
|
this.sidebarMode = this.isMobile ? 'over' : 'side';
|
||||||
|
}
|
||||||
|
|
||||||
onSidebarOpenedChange(opened: boolean): void {
|
toggleSidebar(): void {
|
||||||
this.sidebarOpen = opened ? SidebarOpenEnum.Open : SidebarOpenEnum.Closed;
|
this.sidebarOpen = this.isSidebarOpen ? SidebarOpenEnum.Closed : SidebarOpenEnum.Open;
|
||||||
}
|
this.browserStorageService.setItem('sidebar.open', this.sidebarOpen);
|
||||||
|
}
|
||||||
|
|
||||||
url(url: string): SafeStyle {
|
onSidebarOpenedChange(opened: boolean): void {
|
||||||
return this.sanitizer.bypassSecurityTrustStyle(`url('${url}')`);
|
this.sidebarOpen = opened ? SidebarOpenEnum.Open : SidebarOpenEnum.Closed;
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
url(url: string): SafeStyle {
|
||||||
this.authService.logout();
|
return this.sanitizer.bypassSecurityTrustStyle(`url('${url}')`);
|
||||||
this.router.navigateByUrl('/');
|
}
|
||||||
}
|
|
||||||
|
logout(): void {
|
||||||
|
this.authService.logout();
|
||||||
|
this.router.navigateByUrl('/');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,41 +13,52 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
||||||
import { TokenInterceptor } from './modules/shared/interceptors/token/token.interceptor';
|
import { TokenInterceptor } from './modules/shared/interceptors/token/token.interceptor';
|
||||||
import { AuthTokenService } from './modules/shared/services/auth/auth-token.service';
|
import { AuthTokenService } from './modules/shared/services/auth/auth-token.service';
|
||||||
import { AuthService } from './modules/auth/services/auth/auth.service';
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { ErrorHandlerInterceptor } from './modules/shared/interceptors/error-handler/error-handler.interceptor';
|
||||||
|
import { NotificationService } from './modules/shared/notification/notification.service';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { SharedModule } from './modules/shared/shared.module';
|
||||||
|
|
||||||
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
|
export function HttpLoaderFactory(http: HttpClient): TranslateHttpLoader {
|
||||||
return new TranslateHttpLoader(http, '/assets/lang/', '.json');
|
return new TranslateHttpLoader(http, '/assets/lang/', '.json');
|
||||||
}
|
}
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
CommonModule,
|
||||||
AppRoutingModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
AppRoutingModule,
|
||||||
MaterialModule,
|
BrowserAnimationsModule,
|
||||||
FormsModule,
|
MaterialModule,
|
||||||
ReactiveFormsModule,
|
SharedModule,
|
||||||
HttpClientModule,
|
FormsModule,
|
||||||
TranslateModule.forRoot({
|
ReactiveFormsModule,
|
||||||
defaultLanguage: 'en',
|
HttpClientModule,
|
||||||
loader: {
|
TranslateModule.forRoot({
|
||||||
provide: TranslateLoader,
|
defaultLanguage: 'en',
|
||||||
useFactory: HttpLoaderFactory,
|
loader: {
|
||||||
deps: [HttpClient]
|
provide: TranslateLoader,
|
||||||
}
|
useFactory: HttpLoaderFactory,
|
||||||
}),
|
deps: [HttpClient]
|
||||||
],
|
}
|
||||||
providers: [
|
}),
|
||||||
AppService,
|
],
|
||||||
ThemeService,
|
providers: [
|
||||||
BrowserStorageService,
|
AppService,
|
||||||
AuthTokenService,
|
ThemeService,
|
||||||
AuthService,
|
BrowserStorageService,
|
||||||
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true }
|
AuthTokenService,
|
||||||
],
|
NotificationService,
|
||||||
bootstrap: [AppComponent]
|
MatSnackBar,
|
||||||
|
{ provide: HTTP_INTERCEPTORS, useClass: TokenInterceptor, multi: true },
|
||||||
|
{ provide: HTTP_INTERCEPTORS, useClass: ErrorHandlerInterceptor, multi: true },
|
||||||
|
],
|
||||||
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
export class AppModule { }
|
export class AppModule {
|
||||||
|
constructor(public themeService: ThemeService) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,16 +8,16 @@ import { AdminUserService } from './services/admin-user/admin-user.service';
|
||||||
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
UsersComponent
|
UsersComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
AdminRoutingModule,
|
AdminRoutingModule,
|
||||||
SharedModule,
|
SharedModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
AdminUserService,
|
AdminUserService,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AdminModule { }
|
export class AdminModule { }
|
||||||
|
|
|
@ -16,7 +16,6 @@ const routes: Route[] = [
|
||||||
path: AuthTabEnum.RestorePassword,
|
path: AuthTabEnum.RestorePassword,
|
||||||
component: AuthComponent,
|
component: AuthComponent,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: 'login',
|
redirectTo: 'login',
|
||||||
|
|
|
@ -8,6 +8,9 @@ import { MaterialModule } from '../material/material.module';
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { AuthService } from './services/auth/auth.service';
|
import { AuthService } from './services/auth/auth.service';
|
||||||
import { NgStackFormsModule } from '@ng-stack/forms';
|
import { NgStackFormsModule } from '@ng-stack/forms';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { HttpLoaderFactory } from 'src/app/app.module';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -21,9 +24,14 @@ import { NgStackFormsModule } from '@ng-stack/forms';
|
||||||
FormsModule,
|
FormsModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
NgStackFormsModule,
|
NgStackFormsModule,
|
||||||
],
|
TranslateModule.forChild({
|
||||||
providers: [
|
defaultLanguage: 'en',
|
||||||
AuthService,
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useFactory: HttpLoaderFactory,
|
||||||
|
deps: [HttpClient]
|
||||||
|
}
|
||||||
|
}),
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AuthModule { }
|
export class AuthModule { }
|
||||||
|
|
|
@ -1,63 +1,63 @@
|
||||||
<div class="primary-background toolbar-background"></div>
|
<div class="primary-background toolbar-background"></div>
|
||||||
<div class="col-11 col-lg-7 col-xl-5 p-3 content">
|
<div class="col-11 col-lg-7 col-xl-5 p-3 content">
|
||||||
<mat-card class="px-0">
|
<mat-card class="px-0">
|
||||||
|
|
||||||
<mat-tab-group mat-align-tabs="center" [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)">
|
<mat-tab-group mat-align-tabs="center" [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)">
|
||||||
<mat-tab label="Logowanie">
|
<mat-tab [label]="'AUTH.SIGN_IN' | translate">
|
||||||
<div [formGroup]="loginForm" class="row align-items-center p-4 m-0">
|
<div [formGroup]="loginForm" class="row align-items-center p-4 m-0">
|
||||||
<div class="col-12 col-md-4" required>Email</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.EMAIL_SHORT' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Adres email</mat-label>
|
<mat-label>{{ 'AUTH.EMAIL' | translate }}</mat-label>
|
||||||
<input formControlName="email" matInput>
|
<input formControlName="email" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="col-12 col-md-4" required>Hasło</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.PASSWORD' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Hasło</mat-label>
|
<mat-label>{{ 'AUTH.PASSWORD' | translate }}</mat-label>
|
||||||
<input formControlName="password" type="password" matInput>
|
<input formControlName="password" type="password" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="text-end">
|
<div class="text-end">
|
||||||
<button mat-button (click)="selectedIndexChange(getSelectedIndex(AuthTabEnum.RestorePassword))">Odzyskaj hasło</button>
|
<button mat-button (click)="selectedIndexChange(getSelectedIndex(AuthTabEnum.RestorePassword))">{{ 'AUTH.RESTORE_ACCOUNT' | translate }}</button>
|
||||||
<button mat-flat-button color="primary" (click)="login()">Zaloguj</button>
|
<button mat-flat-button color="primary" (click)="login()" [attr.is-working]="isWorking || null" [disabled]="isWorking">{{ 'AUTH.SIGN_IN' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab label="Rejestracja">
|
<mat-tab [label]="'AUTH.SIGN_UP' | translate">
|
||||||
<div [formGroup]="registerForm" class="row align-items-center p-4 m-0">
|
<div [formGroup]="registerForm" class="row align-items-center p-4 m-0">
|
||||||
<div class="col-12 col-md-4" required>Imię</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.NAME' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Imię</mat-label>
|
<mat-label>{{ 'AUTH.NAME' | translate }}</mat-label>
|
||||||
<input formControlName="name" matInput>
|
<input formControlName="name" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="col-12 col-md-4">Nazwisko</div>
|
<div class="col-12 col-md-4">{{ 'AUTH.SURNAME' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Nazwisko</mat-label>
|
<mat-label>{{ 'AUTH.SURNAME' | translate }}</mat-label>
|
||||||
<input formControlName="surname" matInput>
|
<input formControlName="surname" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="col-12 col-md-4" required>Email</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.EMAIL_SHORT' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Adres email</mat-label>
|
<mat-label>{{ 'AUTH.EMAIL' | translate }}</mat-label>
|
||||||
<input formControlName="email" matInput>
|
<input formControlName="email" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="col-12 col-md-4" required>Hasło</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.PASSWORD' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Hasło</mat-label>
|
<mat-label>{{ 'AUTH.PASSWORD' | translate }}</mat-label>
|
||||||
<input formControlName="password" type="password" matInput>
|
<input formControlName="password" type="password" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="text-end">
|
<div class="text-end">
|
||||||
<button mat-flat-button color="primary" (click)="register()">Zarejestruj</button>
|
<button mat-flat-button color="primary" (click)="register()" [attr.is-working]="isWorking || null" [disabled]="isWorking">{{ 'AUTH.SIGN_UP' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
<mat-tab label="Odzyskiwanie hasła" *ngIf="selectedIndex === 2">
|
<mat-tab [label]="'AUTH.RESTORE_ACCOUNT' | translate" *ngIf="selectedIndex === 2">
|
||||||
<div [formGroup]="restoreForm" class="row align-items-center p-4 m-0">
|
<div [formGroup]="restoreForm" class="row align-items-center p-4 m-0">
|
||||||
<div class="col-12 col-md-4" required>Email</div>
|
<div class="col-12 col-md-4" required>{{ 'AUTH.EMAIL_SHORT' | translate }}</div>
|
||||||
<mat-form-field class="col-12 col-md-8">
|
<mat-form-field class="col-12 col-md-8">
|
||||||
<mat-label>Adres email</mat-label>
|
<mat-label>{{ 'AUTH.EMAIL' | translate }}</mat-label>
|
||||||
<input formControlName="email" matInput>
|
<input formControlName="email" matInput>
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
<div class="text-end">
|
<div class="text-end">
|
||||||
<button mat-button (click)="selectedIndexChange(getSelectedIndex(AuthTabEnum.Login))">Anuluj</button>
|
<button mat-button (click)="selectedIndexChange(getSelectedIndex(AuthTabEnum.Login))">{{ 'AUTH.CANCEL' | translate }}</button>
|
||||||
<button mat-flat-button color="primary">Odzyskaj hasło</button>
|
<button mat-flat-button color="primary" [attr.is-working]="isWorking || null" [disabled]="isWorking">{{ 'AUTH.SEND_NEW_PASSWORD' | translate }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</mat-tab>
|
</mat-tab>
|
||||||
|
|
|
@ -30,6 +30,7 @@ export class AuthComponent implements OnInit, OnDestroy {
|
||||||
];
|
];
|
||||||
showRestore = false;
|
showRestore = false;
|
||||||
AuthTabEnum = AuthTabEnum;
|
AuthTabEnum = AuthTabEnum;
|
||||||
|
isWorking = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private appService: AppService,
|
private appService: AppService,
|
||||||
|
@ -91,7 +92,9 @@ export class AuthComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.appService.setSidebarHidden(true);
|
this.appService.setSidebarHidden(true);
|
||||||
this.appService.addDynamicToolbarComponent(ThemeSwitcherComponent);
|
setTimeout(() => {
|
||||||
|
this.appService.addDynamicToolbarComponent(ThemeSwitcherComponent);
|
||||||
|
}, 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
|
@ -100,19 +103,25 @@ export class AuthComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
register(): void {
|
register(): void {
|
||||||
|
this.isWorking = true;
|
||||||
this.authService.createAccount(this.registerForm.getRawValue()).subscribe(data => {
|
this.authService.createAccount(this.registerForm.getRawValue()).subscribe(data => {
|
||||||
this.loginForm.patchValue({
|
this.loginForm.patchValue({
|
||||||
email: this.registerForm.controls.email.value,
|
email: this.registerForm.controls.email.value,
|
||||||
password: this.registerForm.controls.password.value,
|
password: this.registerForm.controls.password.value,
|
||||||
});
|
});
|
||||||
this.selectedIndexChange(this.getSelectedIndex(AuthTabEnum.Login));
|
this.selectedIndexChange(this.getSelectedIndex(AuthTabEnum.Login));
|
||||||
|
}).add(() => {
|
||||||
|
this.isWorking = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
login(): void {
|
login(): void {
|
||||||
this.authService.login(this.loginForm.getRawValue()).subscribe(data => {
|
this.isWorking = true;
|
||||||
|
this.authService.login(this.loginForm.getRawValue()).subscribe(() => {
|
||||||
const afterUrl = '/';
|
const afterUrl = '/';
|
||||||
this.router.navigateByUrl(afterUrl);
|
this.router.navigateByUrl(afterUrl);
|
||||||
|
}).add(() => {
|
||||||
|
this.isWorking = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
export enum UserRoleEnum {
|
||||||
|
None = 'none',
|
||||||
|
User = 'user',
|
||||||
|
UserVerified = 'user2',
|
||||||
|
Doctor = 'doc',
|
||||||
|
DoctorVerified = 'doc2',
|
||||||
|
Moderator = 'mod',
|
||||||
|
Administrator = 'admin',
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
export class PersonModel {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
surname: string;
|
||||||
|
avatar: string | null;
|
||||||
|
country: number | null;
|
||||||
|
state: string | null;
|
||||||
|
|
||||||
|
constructor(data: PersonModel) {
|
||||||
|
if (data) {
|
||||||
|
Object.assign(this, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,17 @@
|
||||||
export interface UserModel {
|
import { UserRoleEnum } from '../enums/user-role.enum';
|
||||||
|
import { PersonModel } from './person.model';
|
||||||
|
|
||||||
|
export class UserModel {
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
roles: UserRoleEnum[];
|
||||||
surname: string;
|
person: PersonModel;
|
||||||
avatar: string | null;
|
|
||||||
country: string | null;
|
constructor(data?: UserModel) {
|
||||||
state: string | null;
|
if (data) {
|
||||||
|
Object.assign(this, data);
|
||||||
|
if (data.person && typeof data.person !== 'string') {
|
||||||
|
this.person = new PersonModel(data.person);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { EventEmitter, Injectable, ModuleWithProviders } from '@angular/core';
|
||||||
import { Observable, Subject } from 'rxjs';
|
import { Observable, Subject } from 'rxjs';
|
||||||
import { LoginModel } from '../../models/login.model';
|
import { LoginModel } from '../../models/login.model';
|
||||||
import { RegisterModel } from '../../models/register.model';
|
import { RegisterModel } from '../../models/register.model';
|
||||||
|
@ -8,39 +8,46 @@ import { UserModel } from '../../models/user.model';
|
||||||
import { AuthTokenService } from '../../../shared/services/auth/auth-token.service';
|
import { AuthTokenService } from '../../../shared/services/auth/auth-token.service';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
|
|
||||||
private static updateAgent: any;
|
private static updateAgent: any;
|
||||||
private user: UserModel;
|
private user: UserModel | null = null;
|
||||||
public userChange = new Subject<UserModel>();
|
public userChange = new EventEmitter<UserModel | null>();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private http: HttpClient,
|
private http: HttpClient,
|
||||||
private authTokenService: AuthTokenService,
|
private authTokenService: AuthTokenService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
) {
|
) {
|
||||||
this.checkUser();
|
|
||||||
this.userChange.subscribe(user => {
|
this.userChange.subscribe(user => {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getUser(): UserModel {
|
getUser(): UserModel | null {
|
||||||
return this.user;
|
return this.user;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkUser(): void {
|
checkUser(): Promise<UserModel> {
|
||||||
this.http.post<UserModel>('/api/user-check', {}).subscribe(user => {
|
return new Promise<UserModel>((resolve, reject) => {
|
||||||
this.userChange.next(user);
|
this.http.post<UserModel>('/api/user-check', {}).subscribe(user => {
|
||||||
if (AuthService.updateAgent) {
|
this.userChange.emit(user);
|
||||||
clearTimeout(AuthService.updateAgent);
|
if (AuthService.updateAgent) {
|
||||||
}
|
clearTimeout(AuthService.updateAgent);
|
||||||
AuthService.updateAgent = setTimeout(() => {
|
}
|
||||||
this.checkUser();
|
AuthService.updateAgent = setTimeout(() => {
|
||||||
}, 2000) as any;
|
this.checkUser();
|
||||||
}, () => {
|
}, 2000) as any;
|
||||||
this.logout();
|
resolve(user);
|
||||||
|
}, err => {
|
||||||
|
if (err.status === 401) {
|
||||||
|
this.logout();
|
||||||
|
}
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,14 +62,23 @@ export class AuthService {
|
||||||
password: data.password,
|
password: data.password,
|
||||||
}).subscribe(response => {
|
}).subscribe(response => {
|
||||||
this.authTokenService.setToken(response.token);
|
this.authTokenService.setToken(response.token);
|
||||||
this.checkUser();
|
this.checkUser().then(() => {
|
||||||
out.next(response);
|
out.next(response);
|
||||||
|
}, () => {
|
||||||
|
out.next(null);
|
||||||
|
}).catch(() => {
|
||||||
|
out.next(null);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
logout(): void {
|
logout(): void {
|
||||||
|
if (AuthService.updateAgent) {
|
||||||
|
clearTimeout(AuthService.updateAgent);
|
||||||
|
}
|
||||||
this.authTokenService.removeToken();
|
this.authTokenService.removeToken();
|
||||||
|
this.userChange.emit(null);
|
||||||
this.router.navigate(['/auth']);
|
this.router.navigate(['/auth']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,8 @@ import {MatMenuModule} from '@angular/material/menu';
|
||||||
import {MatCardModule} from '@angular/material/card';
|
import {MatCardModule} from '@angular/material/card';
|
||||||
import {MatTabsModule} from '@angular/material/tabs';
|
import {MatTabsModule} from '@angular/material/tabs';
|
||||||
import {MatInputModule} from '@angular/material/input';
|
import {MatInputModule} from '@angular/material/input';
|
||||||
|
import {MatFormFieldModule} from '@angular/material/form-field';
|
||||||
|
import {MatAutocompleteModule} from '@angular/material/autocomplete';
|
||||||
|
|
||||||
const itemsToExport = [
|
const itemsToExport = [
|
||||||
MatToolbarModule,
|
MatToolbarModule,
|
||||||
|
@ -18,6 +20,8 @@ const itemsToExport = [
|
||||||
MatCardModule,
|
MatCardModule,
|
||||||
MatTabsModule,
|
MatTabsModule,
|
||||||
MatInputModule,
|
MatInputModule,
|
||||||
|
MatFormFieldModule,
|
||||||
|
MatAutocompleteModule,
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
<div class="full-height-form">
|
||||||
|
<div class="form-content position-relative">
|
||||||
|
<div>
|
||||||
|
<div class="container" [formGroup]="form">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<h5>{{ 'PROFILE.BASICS' | translate }}</h5>
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'AUTH.NAME' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input matInput formControlName="name">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'AUTH.SURNAME' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input matInput formControlName="surname">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5>{{ 'PROFILE.CONTACT' | translate }}</h5>
|
||||||
|
<div class="form-group">
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.COUNTRY' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input type="text"
|
||||||
|
matInput
|
||||||
|
formControlName="country"
|
||||||
|
(keyup)="countryFieldChanged($event)"
|
||||||
|
[matAutocomplete]="autocompleteCountry">
|
||||||
|
<mat-autocomplete autoActiveFirstOption #autocompleteCountry="matAutocomplete" [displayWith]="displayCountry">
|
||||||
|
<mat-option *ngFor="let country of filteredCountries | async" [value]="country.id">
|
||||||
|
{{ country.name }}
|
||||||
|
</mat-option>
|
||||||
|
</mat-autocomplete>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.STATE' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input matInput formControlName="state">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.CITY' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input matInput formControlName="city">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.ZIP' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
<mat-form-field class="w-100">
|
||||||
|
<input matInput formControlName="zip">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.PHONES' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
phones
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.CONTACTS.EMAILS' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
emails
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="pt-4">{{ 'PROFILE.AVATAR' | translate }}</h5>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label width-200">{{ 'PROFILE.AVATAR' | translate }}</div>
|
||||||
|
<div>
|
||||||
|
avatar
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-template #footer>
|
||||||
|
<div class="form-footer">
|
||||||
|
<button mat-flat-button color="primary">{{ 'PROFILE.SAVE' | translate }}</button>
|
||||||
|
</div>
|
||||||
|
</ng-template>
|
|
@ -0,0 +1,6 @@
|
||||||
|
.container{
|
||||||
|
max-width: 720px;
|
||||||
|
}
|
||||||
|
.form-footer{
|
||||||
|
width: 100%;
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||||
|
import { FormBuilder, FormGroup } from '@ng-stack/forms';
|
||||||
|
import { Observable, Subject } from 'rxjs';
|
||||||
|
import { CountryModel } from 'src/app/modules/shared/models/country.model';
|
||||||
|
import { CountryService } from 'src/app/modules/shared/services/country/country.service';
|
||||||
|
import { map, startWith } from 'rxjs/operators';
|
||||||
|
import { AuthService } from 'src/app/modules/auth/services/auth/auth.service';
|
||||||
|
import { ProfileEditComponent } from '../profile-edit/profile-edit.component';
|
||||||
|
|
||||||
|
interface PhoneEntry{
|
||||||
|
number: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
interface EmailEntry{
|
||||||
|
number: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileInformationBasicModel {
|
||||||
|
name: string;
|
||||||
|
surname: string;
|
||||||
|
|
||||||
|
country: number;
|
||||||
|
state: string;
|
||||||
|
city: string;
|
||||||
|
zip: string;
|
||||||
|
phones: PhoneEntry[];
|
||||||
|
emails: EmailEntry[];
|
||||||
|
|
||||||
|
}
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit-basics',
|
||||||
|
templateUrl: './profile-edit-basics.component.html',
|
||||||
|
styleUrls: ['./profile-edit-basics.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditBasicsComponent implements OnInit {
|
||||||
|
|
||||||
|
form: FormGroup<ProfileInformationBasicModel>;
|
||||||
|
filteredCountries: Observable<CountryModel[]>;
|
||||||
|
countryInputChnage = new Subject<string>();
|
||||||
|
countries: CountryModel[] = [];
|
||||||
|
countryInput = '';
|
||||||
|
@ViewChild('footer') footerElement: ElementRef;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private countryService: CountryService,
|
||||||
|
authService: AuthService,
|
||||||
|
formBuilder: FormBuilder,
|
||||||
|
parent: ProfileEditComponent,
|
||||||
|
) {
|
||||||
|
const phones = formBuilder.array<PhoneEntry>([]);
|
||||||
|
const emails = formBuilder.array<EmailEntry>([]);
|
||||||
|
const user = authService.getUser();
|
||||||
|
|
||||||
|
this.form = formBuilder.group<ProfileInformationBasicModel>({
|
||||||
|
name: parent.person.name,
|
||||||
|
surname: parent.person.surname,
|
||||||
|
|
||||||
|
country: parent.person.country,
|
||||||
|
state: 'state',
|
||||||
|
city: 'city',
|
||||||
|
zip: 'zip',
|
||||||
|
phones,
|
||||||
|
emails,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.countryService.getCountries().subscribe(countries => {
|
||||||
|
this.countries = countries;
|
||||||
|
this.countryInputChnage.next(this.countryInput);
|
||||||
|
this.form.patchValue({
|
||||||
|
country: this.form.value.country,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.filteredCountries = this.countryInputChnage.pipe(
|
||||||
|
startWith(''),
|
||||||
|
map(name => name ? this.filterCountries(name) : this.countries.slice())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayCountry = (countryId: number) => {
|
||||||
|
const country = this.countries.find(i => i.id === countryId);
|
||||||
|
return country ? country.name : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
filterCountries(name: string): CountryModel[] {
|
||||||
|
return this.countries.filter(i => i.name.toLowerCase().includes(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
countryFieldChanged(event): void {
|
||||||
|
this.countryInput = event.target.value.toLowerCase();
|
||||||
|
this.countryInputChnage.next(this.countryInput);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>profile-edit-credentials works!</p>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit-credentials',
|
||||||
|
templateUrl: './profile-edit-credentials.component.html',
|
||||||
|
styleUrls: ['./profile-edit-credentials.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditCredentialsComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>profile-edit-health works!</p>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit-health',
|
||||||
|
templateUrl: './profile-edit-health.component.html',
|
||||||
|
styleUrls: ['./profile-edit-health.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditHealthComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>profile-edit-roles works!</p>
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit-roles',
|
||||||
|
templateUrl: './profile-edit-roles.component.html',
|
||||||
|
styleUrls: ['./profile-edit-roles.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditRolesComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label">{{ 'APP.LANGUAGE' | translate }}</div>
|
||||||
|
<div class="width-200">
|
||||||
|
<mat-form-field class="w-100 px-3">
|
||||||
|
<mat-select [formControl]="langControl">
|
||||||
|
<mat-option *ngFor="let lang of langs" [value]="lang">{{ 'LANGUAGE.'+lang.toUpperCase() | translate }}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<div class="form-label">{{ 'APP.THEME' | translate }}</div>
|
||||||
|
<div class="width-200">
|
||||||
|
<mat-form-field class="w-100 px-3">
|
||||||
|
<mat-select [formControl]="themeControl">
|
||||||
|
<mat-option *ngFor="let theme of themes" [value]="theme.name">{{ 'THEME.'+theme.name.toUpperCase() | translate }}</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormControl } from '@angular/forms';
|
||||||
|
import { AppService } from 'src/app/modules/shared/services/app/app.service';
|
||||||
|
import { ThemeDefinition, ThemeService } from 'src/app/modules/shared/services/theme/theme.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit-settings',
|
||||||
|
templateUrl: './profile-edit-settings.component.html',
|
||||||
|
styleUrls: ['./profile-edit-settings.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditSettingsComponent implements OnInit {
|
||||||
|
themeControl = new FormControl();
|
||||||
|
langControl = new FormControl();
|
||||||
|
lang: string;
|
||||||
|
theme: string;
|
||||||
|
langs: string[] = [];
|
||||||
|
themes: ThemeDefinition[] = [];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private themeService: ThemeService,
|
||||||
|
private appService: AppService,
|
||||||
|
) {
|
||||||
|
this.configureThemeEvents();
|
||||||
|
this.configureLanguageEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
configureLanguageEvents(): void {
|
||||||
|
this.langs = this.appService.getLangs();
|
||||||
|
this.lang = this.appService.getLang();
|
||||||
|
this.appService.changeLang(this.lang);
|
||||||
|
this.langControl.valueChanges.subscribe(lang => {
|
||||||
|
this.appService.changeLang(lang);
|
||||||
|
});
|
||||||
|
this.onLangChanged(this.appService.getLang());
|
||||||
|
this.appService.langChange.subscribe(lang => {
|
||||||
|
this.onLangChanged(lang);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
configureThemeEvents(): void {
|
||||||
|
this.themes = this.themeService.getThemes();
|
||||||
|
this.themeControl.valueChanges.subscribe(theme => {
|
||||||
|
this.themeService.setTheme(theme);
|
||||||
|
});
|
||||||
|
this.onThemeChanged(this.themeService.getTheme());
|
||||||
|
this.themeService.themeChange.subscribe(theme => {
|
||||||
|
this.onThemeChanged(theme);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onThemeChanged(theme: string): void {
|
||||||
|
if (theme === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.theme = theme;
|
||||||
|
this.themeControl.setValue(theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
onLangChanged(lang: string): void {
|
||||||
|
if (lang === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.lang = lang;
|
||||||
|
this.langControl.setValue(lang);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
<div class="scroller" [style.--scrollbar-width]="scrollWidth+'px'">
|
||||||
|
<div class="user-cover">
|
||||||
|
<div class="toolbar-background"></div>
|
||||||
|
</div>
|
||||||
|
<div class="user-header-container">
|
||||||
|
<div class="header" #scrollHeader [style.margin-top.px]="-headerMove">
|
||||||
|
<div class="p-4">
|
||||||
|
<mat-card *ngIf="person === undefined" class="loading-card">
|
||||||
|
loading
|
||||||
|
</mat-card>
|
||||||
|
<mat-card *ngIf="person !== undefined">
|
||||||
|
<div class="user-header">
|
||||||
|
<div>
|
||||||
|
<div class="user-avatar" [style.background-image]="url(person.avatar)"></div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex align-items-end flex-grow-1">
|
||||||
|
<h3>{{ person.name }} {{ person.surname }}</h3>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</mat-card>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="person !== null" class="main-background">
|
||||||
|
<div class="p-3 d-block d-md-none">
|
||||||
|
<h6>{{ currentTabName | translate }}</h6>
|
||||||
|
</div>
|
||||||
|
<div class="tab-container">
|
||||||
|
<mat-tab-group [selectedIndex]="selectedIndex" (selectedIndexChange)="selectedIndexChange($event)">
|
||||||
|
<ng-container *ngFor="let tab of tabs">
|
||||||
|
<mat-tab>
|
||||||
|
<ng-template mat-tab-label>
|
||||||
|
<i *ngIf="tab.icon" class="me-0 me-md-3" [ngClass]="tab.icon"></i>
|
||||||
|
<span class="d-none d-md-inline-block">{{ tab.label | translate }}</span>
|
||||||
|
</ng-template>
|
||||||
|
</mat-tab>
|
||||||
|
</ng-container>
|
||||||
|
</mat-tab-group>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="content" #scrollContent [style.padding-top.px]="headerHeight" (scroll)="onscrol($event)">
|
||||||
|
<div class="h-100 main-background" *ngIf="person !== undefined && loaded === true">
|
||||||
|
<router-outlet (activate)="activated($event)" (deactivate)="deactivated($event)"></router-outlet>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="footer" *ngIf="footerElement !== undefined">
|
||||||
|
<ng-container *ngTemplateOutlet="footerElement"></ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,71 @@
|
||||||
|
:host{
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.user-cover{
|
||||||
|
position: relative;
|
||||||
|
z-index: -1;
|
||||||
|
height: 0px;
|
||||||
|
width: calc(100% - var(--scrollbar-width));
|
||||||
|
div{
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
height: 100px;
|
||||||
|
background-color: var(--toolbar-background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.user-header-container{
|
||||||
|
position: relative;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
.user-header{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row-reverse;
|
||||||
|
}
|
||||||
|
.user-avatar{
|
||||||
|
width: 128px;
|
||||||
|
height: 128px;
|
||||||
|
background-color: rgba(0,0,0, 0.25);
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
border-radius: 27px;
|
||||||
|
}
|
||||||
|
.tab-container{
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.loading-card{
|
||||||
|
margin-top: 50px;
|
||||||
|
}
|
||||||
|
.main-background{
|
||||||
|
background: var(--main-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.scroller{
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
--scrollbar-width: 0px;
|
||||||
|
.header{
|
||||||
|
position: relative;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: calc(100% - var(--scrollbar-width));
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
position: relative;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
import { AfterViewInit, Component, ElementRef, ViewChild } from '@angular/core';
|
||||||
|
import { DomSanitizer, SafeStyle } from '@angular/platform-browser';
|
||||||
|
import { ActivatedRoute, Data, Router, RoutesRecognized } from '@angular/router';
|
||||||
|
import { PersonModel } from 'src/app/modules/auth/models/person.model';
|
||||||
|
import { AuthService } from 'src/app/modules/auth/services/auth/auth.service';
|
||||||
|
import { ProfileTabEnum } from '../../enums/profile-tab.enum';
|
||||||
|
import { profileTabRoutes } from '../../profile-routing';
|
||||||
|
import { PersonService } from '../../service/person/person.service';
|
||||||
|
|
||||||
|
interface ProfileTab {
|
||||||
|
tab: ProfileTabEnum;
|
||||||
|
label: string;
|
||||||
|
icon?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-profile-edit',
|
||||||
|
templateUrl: './profile-edit.component.html',
|
||||||
|
styleUrls: ['./profile-edit.component.scss']
|
||||||
|
})
|
||||||
|
export class ProfileEditComponent implements AfterViewInit {
|
||||||
|
|
||||||
|
profileTabRoutes = profileTabRoutes;
|
||||||
|
currentTabName: string;
|
||||||
|
person: PersonModel | null = null;
|
||||||
|
selectedIndex = 0;
|
||||||
|
defaultProfileTab = ProfileTabEnum.Basics;
|
||||||
|
footerElement: ElementRef;
|
||||||
|
loaded = false;
|
||||||
|
@ViewChild('scrollHeader', {static: false}) scrollHeader: ElementRef;
|
||||||
|
@ViewChild('scrollContent', {static: false}) scrollContent: ElementRef;
|
||||||
|
headerHeight = 200;
|
||||||
|
headerMove = 0;
|
||||||
|
maxHeaderMove = 0;
|
||||||
|
scrollWidth = 30;
|
||||||
|
tabs: ProfileTab[] = [
|
||||||
|
{
|
||||||
|
tab: ProfileTabEnum.Basics,
|
||||||
|
label: 'PROFILE.BASICS',
|
||||||
|
icon: 'fa fa-id-badge',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: ProfileTabEnum.Health,
|
||||||
|
label: 'PROFILE.HEALTH',
|
||||||
|
icon: 'fa fa-heartbeat',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: ProfileTabEnum.Roles,
|
||||||
|
label: 'PROFILE.ROLES',
|
||||||
|
icon: 'fa fa-user',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: ProfileTabEnum.Credentials,
|
||||||
|
label: 'PROFILE.PASSWORD',
|
||||||
|
icon: 'fa fa-unlock-alt',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tab: ProfileTabEnum.Settings,
|
||||||
|
label: 'PROFILE.SITE_SETTINGS',
|
||||||
|
icon: 'fa fa-sliders',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
authService: AuthService,
|
||||||
|
private activatedRoute: ActivatedRoute,
|
||||||
|
private router: Router,
|
||||||
|
private personService: PersonService,
|
||||||
|
) {
|
||||||
|
const personId = parseInt(activatedRoute.snapshot.params.personId, 10);
|
||||||
|
if (personId) {
|
||||||
|
this.loadPerson(personId);
|
||||||
|
} else {
|
||||||
|
this.loadPerson(authService.getUser().person.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onRouteChange(activatedRoute.snapshot.firstChild?.data);
|
||||||
|
this.router.events.subscribe(event => {
|
||||||
|
if (event instanceof RoutesRecognized) {
|
||||||
|
console.log({event});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadPerson(personId: number): void {
|
||||||
|
this.person = undefined;
|
||||||
|
this.loaded = false;
|
||||||
|
this.personService.get(personId).subscribe(person => {
|
||||||
|
this.person = person;
|
||||||
|
this.loaded = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateScroller(): void {
|
||||||
|
this.scrollHeader.nativeElement.style.height = '0px';
|
||||||
|
this.headerHeight = this.scrollHeader.nativeElement.scrollHeight;
|
||||||
|
this.maxHeaderMove = this.scrollHeader.nativeElement.firstChild.scrollHeight;
|
||||||
|
this.scrollWidth = this.scrollContent.nativeElement.parentElement.scrollWidth - this.scrollContent.nativeElement.scrollWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.loaded = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updateScroller();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
activated(component): void {
|
||||||
|
if (component.footerElement) {
|
||||||
|
this.footerElement = component.footerElement;
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
if (component.footerElement) {
|
||||||
|
this.footerElement = component.footerElement;
|
||||||
|
}
|
||||||
|
this.updateScroller();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivated(component): void {
|
||||||
|
this.footerElement = undefined;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.updateScroller();
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
onscrol(e): void {
|
||||||
|
this.headerMove = Math.min(e.target.scrollTop, this.maxHeaderMove);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRouteChange(data: Data): void {
|
||||||
|
this.currentTabName = undefined;
|
||||||
|
if (data?.tab) {
|
||||||
|
const tab = data.tab as ProfileTabEnum;
|
||||||
|
const tabIndex = this.tabs.findIndex(i => i.tab === tab);
|
||||||
|
if (tabIndex !== -1) {
|
||||||
|
this.selectedIndex = tabIndex;
|
||||||
|
this.currentTabName = this.tabs[tabIndex].label;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const index = this.tabs.findIndex(i => i.tab === this.defaultProfileTab);
|
||||||
|
if (index !== -1) {
|
||||||
|
this.selectedIndexChange(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedIndexChange(index: number): void {
|
||||||
|
this.selectedIndex = index;
|
||||||
|
this.currentTabName = undefined;
|
||||||
|
const tab = this.tabs[index];
|
||||||
|
if (tab) {
|
||||||
|
const route = this.profileTabRoutes.find(i => i.data.tab === tab.tab);
|
||||||
|
this.currentTabName = tab.label;
|
||||||
|
if (route) {
|
||||||
|
this.router.navigate([route.path], {
|
||||||
|
relativeTo: this.activatedRoute,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url(url: string): SafeStyle {
|
||||||
|
return this.sanitizer.bypassSecurityTrustStyle(`url('${url}')`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
export enum ProfileTabEnum {
|
||||||
|
Health,
|
||||||
|
Roles,
|
||||||
|
Basics,
|
||||||
|
Contact,
|
||||||
|
Credentials,
|
||||||
|
Avatar,
|
||||||
|
Settings,
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { RouterModule } from '@angular/router';
|
||||||
|
import { profileRoutes } from './profile-routing';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(profileRoutes)],
|
||||||
|
exports: [RouterModule]
|
||||||
|
})
|
||||||
|
export class ProfileRoutingModule { }
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { Route } from '@angular/router';
|
||||||
|
import { ProfileEditBasicsComponent } from './components/profile-edit-basics/profile-edit-basics.component';
|
||||||
|
import { ProfileEditCredentialsComponent } from './components/profile-edit-credentials/profile-edit-credentials.component';
|
||||||
|
import { ProfileEditHealthComponent } from './components/profile-edit-health/profile-edit-health.component';
|
||||||
|
import { ProfileEditRolesComponent } from './components/profile-edit-roles/profile-edit-roles.component';
|
||||||
|
import { ProfileEditSettingsComponent } from './components/profile-edit-settings/profile-edit-settings.component';
|
||||||
|
import { ProfileEditComponent } from './components/profile-edit/profile-edit.component';
|
||||||
|
import { ProfileTabEnum } from './enums/profile-tab.enum';
|
||||||
|
|
||||||
|
export const profileTabRoutes: Route[] = [
|
||||||
|
{
|
||||||
|
path: 'health',
|
||||||
|
component: ProfileEditHealthComponent,
|
||||||
|
data: {
|
||||||
|
tab: ProfileTabEnum.Health,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'roles',
|
||||||
|
component: ProfileEditRolesComponent,
|
||||||
|
data: {
|
||||||
|
tab: ProfileTabEnum.Roles,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'basics',
|
||||||
|
component: ProfileEditBasicsComponent,
|
||||||
|
data: {
|
||||||
|
tab: ProfileTabEnum.Basics,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'credentials',
|
||||||
|
component: ProfileEditCredentialsComponent,
|
||||||
|
data: {
|
||||||
|
tab: ProfileTabEnum.Credentials,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'settings',
|
||||||
|
component: ProfileEditSettingsComponent,
|
||||||
|
data: {
|
||||||
|
tab: ProfileTabEnum.Settings,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export const profileRoutes: Route[] = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: ProfileEditComponent,
|
||||||
|
children: profileTabRoutes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: ':personId',
|
||||||
|
component: ProfileEditComponent,
|
||||||
|
children: profileTabRoutes,
|
||||||
|
},
|
||||||
|
];
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { ProfileRoutingModule } from './profile-routing.module';
|
||||||
|
import { ProfileEditComponent } from './components/profile-edit/profile-edit.component';
|
||||||
|
import { MaterialModule } from '../material/material.module';
|
||||||
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { HttpLoaderFactory } from 'src/app/app.module';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { ProfileEditBasicsComponent } from './components/profile-edit-basics/profile-edit-basics.component';
|
||||||
|
import { ProfileEditCredentialsComponent } from './components/profile-edit-credentials/profile-edit-credentials.component';
|
||||||
|
import { ProfileEditSettingsComponent } from './components/profile-edit-settings/profile-edit-settings.component';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
|
import { NgStackFormsModule } from '@ng-stack/forms';
|
||||||
|
import { ProfileEditHealthComponent } from './components/profile-edit-health/profile-edit-health.component';
|
||||||
|
import { ProfileEditRolesComponent } from './components/profile-edit-roles/profile-edit-roles.component';
|
||||||
|
import { CountryService } from '../shared/services/country/country.service';
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [
|
||||||
|
ProfileEditComponent,
|
||||||
|
ProfileEditBasicsComponent,
|
||||||
|
ProfileEditCredentialsComponent,
|
||||||
|
ProfileEditSettingsComponent,
|
||||||
|
ProfileEditHealthComponent,
|
||||||
|
ProfileEditRolesComponent,
|
||||||
|
],
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
ProfileRoutingModule,
|
||||||
|
FormsModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
NgStackFormsModule,
|
||||||
|
MaterialModule,
|
||||||
|
TranslateModule.forChild({
|
||||||
|
defaultLanguage: 'en',
|
||||||
|
loader: {
|
||||||
|
provide: TranslateLoader,
|
||||||
|
useFactory: HttpLoaderFactory,
|
||||||
|
deps: [HttpClient]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
CountryService,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class ProfileModule { }
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { PersonModel } from 'src/app/modules/auth/models/person.model';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class PersonService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
}
|
||||||
|
|
||||||
|
get(personId: number): Observable<PersonModel> {
|
||||||
|
return this.http.get<PersonModel>(`/api/person/${personId}`);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<div class="loader-container">
|
||||||
|
<div class="loader-box">
|
||||||
|
<i class="fa fa-2x fa-spin fa-spinner"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,22 @@
|
||||||
|
.loader-container{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 100;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: var(--main-background);
|
||||||
|
.loader-box{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 3px;
|
||||||
|
width: 100px;
|
||||||
|
height: 60px;
|
||||||
|
background: var(--toolbar-background);
|
||||||
|
color: var(--toolbar-color);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-loader',
|
||||||
|
templateUrl: './loader.component.html',
|
||||||
|
styleUrls: ['./loader.component.scss']
|
||||||
|
})
|
||||||
|
export class LoaderComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
||||||
|
import { Injectable, Injector } from '@angular/core';
|
||||||
|
import { Observable, throwError } from 'rxjs';
|
||||||
|
import { catchError } from 'rxjs/operators';
|
||||||
|
import { NotificationService } from '../../notification/notification.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ErrorHandlerInterceptor implements HttpInterceptor {
|
||||||
|
|
||||||
|
get notificationService(): NotificationService {
|
||||||
|
return this.injector.get(NotificationService);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private injector: Injector,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||||
|
return next.handle(httpRequest).pipe(
|
||||||
|
catchError(response => {
|
||||||
|
switch (response.status) {
|
||||||
|
case 406:
|
||||||
|
if (response.error instanceof Blob && response.error.type === 'application/json') {
|
||||||
|
const result = new Promise((resolve) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e: Event) => {
|
||||||
|
resolve(JSON.parse((e.target as any).result));
|
||||||
|
};
|
||||||
|
reader.readAsText(response.error);
|
||||||
|
});
|
||||||
|
result.then((data) => {
|
||||||
|
response.error = data;
|
||||||
|
this.displayNotificationIfValidationError(response);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
this.displayNotificationIfValidationError(response);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return throwError(response);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
displayNotificationIfValidationError(response): void {
|
||||||
|
if (response?.error?.data) {
|
||||||
|
this.notificationService.error(response.error.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
export interface CountryRegion {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
countryId: number;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
export interface CountryModel {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
code: string;
|
||||||
|
}
|
|
@ -1,9 +1,9 @@
|
||||||
export class User {
|
export class UserModel {
|
||||||
id: number;
|
id: number;
|
||||||
email: string;
|
email: string;
|
||||||
name: string;
|
name: string;
|
||||||
surname: string;
|
surname: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
country: string;
|
country: number;
|
||||||
state: string;
|
state: string;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
|
||||||
|
enum NotificationType {
|
||||||
|
Success,
|
||||||
|
Error,
|
||||||
|
Info,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class NotificationService {
|
||||||
|
|
||||||
|
constructor(private snackBar: MatSnackBar) { }
|
||||||
|
|
||||||
|
notify(type: NotificationType, title: string): void {
|
||||||
|
let action: string;
|
||||||
|
let panelClass: string;
|
||||||
|
const duration = 1500000;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case NotificationType.Success:
|
||||||
|
action = 'OK';
|
||||||
|
panelClass = 'notify-success';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NotificationType.Error:
|
||||||
|
action = 'OK';
|
||||||
|
panelClass = 'notify-error';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.snackBar.open(title, action, {
|
||||||
|
panelClass,
|
||||||
|
duration,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
success(title: string): void {
|
||||||
|
return this.notify(NotificationType.Success, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
error(title: string): void {
|
||||||
|
return this.notify(NotificationType.Error, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -8,7 +8,7 @@ export class BrowserStorageService {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.storage = localStorage;
|
this.storage = localStorage;
|
||||||
this.namespace = 'default';
|
this.namespace = 'app';
|
||||||
}
|
}
|
||||||
|
|
||||||
setNamespace(namespace: string): void {
|
setNamespace(namespace: string): void {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { CountryModel } from '../../models/country.model';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CountryService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {
|
||||||
|
}
|
||||||
|
|
||||||
|
getCountries(): Observable<CountryModel[]> {
|
||||||
|
return this.http.get<CountryModel[]>('/api/country');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,6 +2,12 @@ import { Injectable } from '@angular/core';
|
||||||
import { Subject } from 'rxjs';
|
import { Subject } from 'rxjs';
|
||||||
import { BrowserStorageService } from '../browser-storage/browser-storage.service';
|
import { BrowserStorageService } from '../browser-storage/browser-storage.service';
|
||||||
|
|
||||||
|
export class ThemeDefinition {
|
||||||
|
name: string;
|
||||||
|
isDark: boolean;
|
||||||
|
isDefault: boolean;
|
||||||
|
relatedTheme: string | undefined;
|
||||||
|
}
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ThemeService {
|
export class ThemeService {
|
||||||
private theme: string;
|
private theme: string;
|
||||||
|
@ -32,10 +38,20 @@ export class ThemeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getThemes(): string[] {
|
getThemes(): ThemeDefinition[] {
|
||||||
return [
|
return [
|
||||||
'light',
|
{
|
||||||
'dark',
|
name: 'light',
|
||||||
|
isDark: false,
|
||||||
|
isDefault: true,
|
||||||
|
relatedTheme: 'dark',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dark',
|
||||||
|
isDark: true,
|
||||||
|
isDefault: true,
|
||||||
|
relatedTheme: 'light',
|
||||||
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,23 @@
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule, Type } from '@angular/core';
|
||||||
import { CommonModule } from '@angular/common';
|
import { CommonModule } from '@angular/common';
|
||||||
import { NotFoundComponent } from './components/not-found/not-found.component';
|
import { NotFoundComponent } from './components/not-found/not-found.component';
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { HttpLoaderFactory } from 'src/app/app.module';
|
import { HttpLoaderFactory } from 'src/app/app.module';
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient } from '@angular/common/http';
|
||||||
import { MaterialModule } from '../material/material.module';
|
import { MaterialModule } from '../material/material.module';
|
||||||
|
import { LoaderComponent } from './components/loader/loader.component';
|
||||||
|
|
||||||
|
const componentList: (any[] | Type<any>)[] = [
|
||||||
|
LoaderComponent,
|
||||||
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
NotFoundComponent
|
NotFoundComponent,
|
||||||
|
...componentList,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
...componentList,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|
|
@ -5,12 +5,18 @@ $toolbar-background: map.get($theme, color, background, app-bar);
|
||||||
$toolbar-color: map.get($theme, color, primary, contrast, 500) !default;
|
$toolbar-color: map.get($theme, color, primary, contrast, 500) !default;
|
||||||
$main-background: map.get($theme, color, background, background) !default;
|
$main-background: map.get($theme, color, background, background) !default;
|
||||||
$warn-color: map.get($theme, warn, 500) !default;
|
$warn-color: map.get($theme, warn, 500) !default;
|
||||||
|
$success-color: map.get($theme, success, 500) !default;
|
||||||
|
$divider-color: map.get($theme, foreground, divider) !default;
|
||||||
|
$dialog-background: map.get($theme, background, dialog) !default;
|
||||||
body {
|
body {
|
||||||
--primary-color: #{$primary-color};
|
--primary-color: #{$primary-color};
|
||||||
--toolbar-background: #{$toolbar-background};
|
--toolbar-background: #{$toolbar-background};
|
||||||
--toolbar-color: #{$toolbar-color};
|
--toolbar-color: #{$toolbar-color};
|
||||||
--main-background: #{$main-background};
|
--main-background: #{$main-background};
|
||||||
--warn-color: #{$warn-color};
|
--warn-color: #{$warn-color};
|
||||||
|
--success-color: #{$success-color};
|
||||||
|
--divider-color: #{$divider-color};
|
||||||
|
--dialog-background: #{$dialog-background};
|
||||||
.mat-toolbar{
|
.mat-toolbar{
|
||||||
background-color: var(--toolbar-background);
|
background-color: var(--toolbar-background);
|
||||||
color: var(--toolbar-color);
|
color: var(--toolbar-color);
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
.form-group{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 1rem;
|
||||||
|
&:not(:last-child){
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
.form-row{
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
width: 100%;
|
||||||
|
border-bottom: 1px solid var(--divider-color);
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
&:last-child{
|
||||||
|
border-bottom: 0px;
|
||||||
|
}
|
||||||
|
.form-label{
|
||||||
|
padding-top: 0.75rem;
|
||||||
|
}
|
||||||
|
&.form-row-400{
|
||||||
|
max-width: 400px;
|
||||||
|
}
|
||||||
|
> *{
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
.width-200{
|
||||||
|
flex-grow: inherit;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.full-height-form{
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.form-content{
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.form-footer{
|
||||||
|
background: var(--dialog-background);
|
||||||
|
border-top: 1px solid var(--divider-color);
|
||||||
|
padding: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
> div{
|
||||||
|
display: flex;
|
||||||
|
&:first-child{
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scrollable-content{
|
||||||
|
overflow: auto;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
left: 0px;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ $theme-accent: mat.define-palette(mat.$green-palette, A200, A100, A400);
|
||||||
|
|
||||||
// The warn palette is optional (defaults to red).
|
// The warn palette is optional (defaults to red).
|
||||||
$theme-warn: mat.define-palette(mat.$red-palette);
|
$theme-warn: mat.define-palette(mat.$red-palette);
|
||||||
|
$theme-success: mat.define-palette(mat.$green-palette);
|
||||||
|
|
||||||
// Create the theme object. A theme consists of configurations for individual
|
// Create the theme object. A theme consists of configurations for individual
|
||||||
// theming systems such as "color" or "typography".
|
// theming systems such as "color" or "typography".
|
||||||
|
@ -24,6 +25,7 @@ $theme: mat.define-dark-theme((
|
||||||
primary: $theme-primary,
|
primary: $theme-primary,
|
||||||
accent: $theme-accent,
|
accent: $theme-accent,
|
||||||
warn: $theme-warn,
|
warn: $theme-warn,
|
||||||
|
success: $theme-success,
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ $theme-accent: mat.define-palette(mat.$light-blue-palette, A200, A100, A400);
|
||||||
|
|
||||||
// The warn palette is optional (defaults to red).
|
// The warn palette is optional (defaults to red).
|
||||||
$theme-warn: mat.define-palette(mat.$red-palette);
|
$theme-warn: mat.define-palette(mat.$red-palette);
|
||||||
|
$theme-success: mat.define-palette(mat.$green-palette);
|
||||||
|
|
||||||
// Create the theme object. A theme consists of configurations for individual
|
// Create the theme object. A theme consists of configurations for individual
|
||||||
// theming systems such as "color" or "typography".
|
// theming systems such as "color" or "typography".
|
||||||
|
@ -25,6 +26,7 @@ $theme: mat.define-light-theme((
|
||||||
primary: $theme-primary,
|
primary: $theme-primary,
|
||||||
accent: $theme-accent,
|
accent: $theme-accent,
|
||||||
warn: $theme-warn,
|
warn: $theme-warn,
|
||||||
|
success: $theme-success,
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
{
|
{
|
||||||
"APP": {
|
"APP": {
|
||||||
"NAME": "CureNet",
|
"NAME": "App",
|
||||||
"THEME": "Theme",
|
"THEME": "Theme",
|
||||||
"LANGUAGE": "Language"
|
"LANGUAGE": "Language",
|
||||||
|
"LOGOUT": "Logout",
|
||||||
|
"USER_SETTINGS": "User settings",
|
||||||
|
"USER_SITE_SETTINGS": "Site settings"
|
||||||
},
|
},
|
||||||
"ERROR": {
|
"ERROR": {
|
||||||
"PAGE_NOT_FOUND": "Page not found or not implemented yet!"
|
"PAGE_NOT_FOUND": "Page not found or not implemented yet!"
|
||||||
|
@ -26,5 +29,35 @@
|
||||||
"RESEARCH": "Research",
|
"RESEARCH": "Research",
|
||||||
"ADMIN": "Admin",
|
"ADMIN": "Admin",
|
||||||
"USERS": "Users"
|
"USERS": "Users"
|
||||||
|
},
|
||||||
|
"AUTH": {
|
||||||
|
"EMAIL_SHORT": "Email",
|
||||||
|
"EMAIL": "Address email",
|
||||||
|
"PASSWORD": "Password",
|
||||||
|
"SIGN_IN": "Sign in",
|
||||||
|
"NAME": "Name",
|
||||||
|
"SURNAME": "Surname",
|
||||||
|
"SIGN_UP": "Sign up",
|
||||||
|
"CANCEL": "Cancel",
|
||||||
|
"SEND_NEW_PASSWORD": "Send new password",
|
||||||
|
"RESTORE_ACCOUNT": "Restore account"
|
||||||
|
},
|
||||||
|
"PROFILE": {
|
||||||
|
"HEALTH": "Health",
|
||||||
|
"ROLES": "Roles",
|
||||||
|
"BASICS": "Basic information",
|
||||||
|
"CONTACT": "Contact information",
|
||||||
|
"AVATAR": "Avatar",
|
||||||
|
"PASSWORD": "Password",
|
||||||
|
"SITE_SETTINGS": "Site settings",
|
||||||
|
"SAVE": "Save",
|
||||||
|
"CONTACTS": {
|
||||||
|
"COUNTRY": "Country",
|
||||||
|
"STATE": "State",
|
||||||
|
"CITY": "City",
|
||||||
|
"ZIP": "Zip code",
|
||||||
|
"PHONES": "Phone numbers",
|
||||||
|
"EMAILS": "Email addresses"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,11 @@
|
||||||
{
|
{
|
||||||
"APP": {
|
"APP": {
|
||||||
"NAME": "CureNet",
|
"NAME": "App",
|
||||||
"THEME": "Motyw",
|
"THEME": "Motyw",
|
||||||
"LANGUAGE": "Język"
|
"LANGUAGE": "Język",
|
||||||
|
"LOGOUT": "Wyloguj",
|
||||||
|
"USER_SETTINGS": "Ustawienia konta",
|
||||||
|
"USER_SITE_SETTINGS": "Ustawienia strony"
|
||||||
},
|
},
|
||||||
"ERROR": {
|
"ERROR": {
|
||||||
"PAGE_NOT_FOUND": "Nie znaleziono strony lub nie została ona jeszcze zaimplementowana!"
|
"PAGE_NOT_FOUND": "Nie znaleziono strony lub nie została ona jeszcze zaimplementowana!"
|
||||||
|
@ -26,5 +29,35 @@
|
||||||
"RESEARCH": "Badania naukowe",
|
"RESEARCH": "Badania naukowe",
|
||||||
"ADMIN": "Panel administratora",
|
"ADMIN": "Panel administratora",
|
||||||
"USERS": "Użytkownicy"
|
"USERS": "Użytkownicy"
|
||||||
|
},
|
||||||
|
"AUTH": {
|
||||||
|
"EMAIL_SHORT": "Email",
|
||||||
|
"EMAIL": "Adres email",
|
||||||
|
"PASSWORD": "Hasło",
|
||||||
|
"SIGN_IN": "Zaloguj",
|
||||||
|
"NAME": "Imię",
|
||||||
|
"SURNAME": "Nazwisko",
|
||||||
|
"SIGN_UP": "Zarejestruj",
|
||||||
|
"CANCEL": "Anuluj",
|
||||||
|
"SEND_NEW_PASSWORD": "Wyślij nowe hasło",
|
||||||
|
"RESTORE_ACCOUNT": "Odzyskaj konto"
|
||||||
|
},
|
||||||
|
"PROFILE": {
|
||||||
|
"HEALTH": "Zdrowie",
|
||||||
|
"ROLES": "Role",
|
||||||
|
"BASICS": "Podstawowe informacje",
|
||||||
|
"CONTACT": "Dane kontaktowe",
|
||||||
|
"AVATAR": "Zdjęcie profilowe",
|
||||||
|
"PASSWORD": "Hasło",
|
||||||
|
"SITE_SETTINGS": "Ustawienia strony",
|
||||||
|
"SAVE": "Zapisz",
|
||||||
|
"CONTACTS": {
|
||||||
|
"COUNTRY": "Kraj",
|
||||||
|
"STATE": "Województwo",
|
||||||
|
"CITY": "Miasto",
|
||||||
|
"ZIP": "Kod pocztowy",
|
||||||
|
"PHONES": "Numery telefonów",
|
||||||
|
"EMAILS": "Adresy email"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,6 +5,7 @@ body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
|
||||||
|
|
||||||
@import "~bootstrap/dist/css/bootstrap.css";
|
@import "~bootstrap/dist/css/bootstrap.css";
|
||||||
@import "~font-awesome/css/font-awesome.css";
|
@import "~font-awesome/css/font-awesome.css";
|
||||||
|
@import "./app/styles/bundles/form.scss";
|
||||||
|
|
||||||
body .mat-drawer.mat-drawer-side {
|
body .mat-drawer.mat-drawer-side {
|
||||||
visibility: visible !important;
|
visibility: visible !important;
|
||||||
|
@ -37,14 +38,52 @@ body .mat-drawer.mat-drawer-side {
|
||||||
}
|
}
|
||||||
& ~ .mat-drawer-content {
|
& ~ .mat-drawer-content {
|
||||||
margin-left: 60px !important;
|
margin-left: 60px !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.w-220{
|
.w-220{
|
||||||
width: 220px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
[required]:after{
|
[required]:after{
|
||||||
content: "*";
|
content: " *";
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: var(--warn-color);
|
color: var(--warn-color);
|
||||||
|
}
|
||||||
|
body .mat-drawer-content{
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
.notify-error{
|
||||||
|
border-left: 5px solid var(--warn-color);
|
||||||
|
.mat-simple-snackbar-action{
|
||||||
|
color: var(--warn-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.notify-success{
|
||||||
|
border-left: 5px solid var(--success-color);
|
||||||
|
.mat-simple-snackbar-action{
|
||||||
|
color: var(--success-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button[is-working]{
|
||||||
|
position: relative;
|
||||||
|
&,
|
||||||
|
& *{
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
&:before{
|
||||||
|
font-family: "FontAwesome";
|
||||||
|
content: "\f013";
|
||||||
|
display: flex;
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
margin: -10px;
|
||||||
|
font-size: inherit;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
animation: fa-spin 2s infinite linear;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
.cache
|
|
@ -0,0 +1,93 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$countries = [];
|
||||||
|
$states = [];
|
||||||
|
$countryId = 0;
|
||||||
|
$stateId = 0;
|
||||||
|
|
||||||
|
class Country {
|
||||||
|
public int $id;
|
||||||
|
public function __construct(
|
||||||
|
public string $code,
|
||||||
|
public string $name,
|
||||||
|
public ?string $localeName,
|
||||||
|
public ?string $subname,
|
||||||
|
public bool $haveSubregions = false) {
|
||||||
|
global $countryId;
|
||||||
|
$this->id = ++$countryId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class State {
|
||||||
|
public int $id;
|
||||||
|
public function __construct(
|
||||||
|
public string $code,
|
||||||
|
public string $name,
|
||||||
|
public string $countryCode,
|
||||||
|
public int $countryId,
|
||||||
|
) {
|
||||||
|
global $stateId;
|
||||||
|
$this->id = ++$stateId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_url($url) {
|
||||||
|
$cacheFile = './.cache/'.md5($url);
|
||||||
|
if (file_exists($cacheFile)) {
|
||||||
|
return file_get_contents($cacheFile);
|
||||||
|
}
|
||||||
|
$content = file_get_contents($url);
|
||||||
|
file_put_contents($cacheFile, $content);
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
$content = get_url('https://unece.org/trade/uncefact/unlocode-country-subdivisions-iso-3166-2');
|
||||||
|
if (preg_match_all('/<td ([^>]{1,})>([a-z]{1,4})<\/td>([^<]{0,})<td ([^>]{1,})>(.*?)<\/td>/i', $content, $matches)) {
|
||||||
|
foreach ($matches[0] as $mid => $m) {
|
||||||
|
$name = strip_tags($matches[5][$mid]);
|
||||||
|
$subname = null;
|
||||||
|
$a = strpos($name, ',');
|
||||||
|
if ($a !== false) {
|
||||||
|
$subname = trim(substr($name, $a+1));
|
||||||
|
$name = mb_substr($name, 0, $a);
|
||||||
|
}
|
||||||
|
$country = new Country(
|
||||||
|
code: $matches[2][$mid],
|
||||||
|
name: html_entity_decode(trim($name)),
|
||||||
|
localeName: null,
|
||||||
|
subname: $subname,
|
||||||
|
haveSubregions: strpos($matches[5][$mid], '<a href=') !== false,
|
||||||
|
);
|
||||||
|
if ($country->code === 'PL') {
|
||||||
|
$country->localeName = 'Polska';
|
||||||
|
}
|
||||||
|
$countries[] = $country;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$i = 0;
|
||||||
|
$count = sizeof($countries);
|
||||||
|
foreach ($countries as $country) {
|
||||||
|
if ($country->haveSubregions) {
|
||||||
|
$code = strtolower($country->code);
|
||||||
|
$url = 'https://unece.org/DAM/cefact/locode/Subdivision/'. $code .'Sub.htm';
|
||||||
|
$content = str_replace(' ',' ', get_url($url));
|
||||||
|
if (preg_match_all('/<td ([^>]{1,})>([^>]{2,14})<\/td>([^<]{0,})<td ([^>]{1,})>(.*?)<\/td>([^<]{0,})<td ([^>]{1,})>(.*?)<\/td>/i', $content, $matches)) {
|
||||||
|
foreach ($matches[0] as $mid => $m) {
|
||||||
|
$states[] = new State(
|
||||||
|
code: trim($matches[5][$mid]),
|
||||||
|
name: html_entity_decode(trim($matches[8][$mid])),
|
||||||
|
countryCode: $country->code,
|
||||||
|
countryId: $country->id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$i++;
|
||||||
|
echo round(100*$i/$count, 2)."% $country->name\n";
|
||||||
|
} else {
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$dir = dirname(__FILE__, 3). '/src/backend/data';
|
||||||
|
file_put_contents($dir.'/countries.json', json_encode($countries, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||||
|
file_put_contents($dir.'/states.json', json_encode($states, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,269 @@
|
||||||
|
|
||||||
|
// coutries
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (1, "Afghanistan", NULL, "AF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (2, "Åland Islands", NULL, "AX")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (3, "Albania", NULL, "AL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (4, "Algeria", NULL, "DZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (5, "American Samoa", NULL, "AS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (6, "Andorra", NULL, "AD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (7, "Angola", NULL, "AO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (8, "Anguilla", NULL, "AI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (9, "Antarctica", NULL, "AQ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (10, "Antigua and Barbuda", NULL, "AG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (11, "Argentina", NULL, "AR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (12, "Armenia", NULL, "AM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (13, "Aruba", NULL, "AW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (14, "Australia", NULL, "AU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (15, "Austria", NULL, "AT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (16, "Azerbaijan", NULL, "AZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (17, "Bahamas", NULL, "BS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (18, "Bahrain", NULL, "BH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (19, "Bangladesh", NULL, "BD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (20, "Barbados", NULL, "BB")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (21, "Belarus", NULL, "BY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (22, "Belgium", NULL, "BE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (23, "Belize", NULL, "BZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (24, "Benin", NULL, "BJ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (25, "Bermuda", NULL, "BM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (26, "Bhutan", NULL, "BT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (27, "Bolivia", "Plurinational State of", "BO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (28, "Bonaire", "Sint Eustatius and Saba", "BQ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (29, "Bosnia and Herzegovina", NULL, "BA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (30, "Botswana", NULL, "BW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (31, "Bouvet Island", NULL, "BV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (32, "Brazil", NULL, "BR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (33, "British Indian Ocean Territory", NULL, "IO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (34, "Brunei Darussalam", NULL, "BN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (35, "Bulgaria", NULL, "BG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (36, "Burkina Faso", NULL, "BF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (37, "Burundi", NULL, "BI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (38, "Cambodia", NULL, "KH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (39, "Cameroon", NULL, "CM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (40, "Canada", NULL, "CA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (41, "Cape Verde", NULL, "CV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (42, "Cayman Islands", NULL, "KY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (43, "Central African Republic", NULL, "CF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (44, "Chad", NULL, "TD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (45, "Chile", NULL, "CL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (46, "China", NULL, "CN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (47, "Christmas Island", NULL, "CX")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (48, "Cocos (Keeling) Islands", NULL, "CC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (49, "Colombia", NULL, "CO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (50, "Comoros", NULL, "KM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (51, "Congo", NULL, "CG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (52, "Congo", "The Democratic Republic of the", "CD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (53, "Cook Islands", NULL, "CK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (54, "Costa Rica", NULL, "CR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (55, "Côte D\\\'Ivoire", NULL, "CI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (56, "Croatia", NULL, "HR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (57, "Cuba", NULL, "CU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (58, "Curaçao", NULL, "CW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (59, "Cyprus", NULL, "CY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (60, "Czech Republic", NULL, "CZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (61, "Denmark", NULL, "DK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (62, "Djibouti", NULL, "DJ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (63, "Dominica", NULL, "DM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (64, "Dominican Republic", NULL, "DO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (65, "Ecuador", NULL, "EC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (66, "Egypt", NULL, "EG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (67, "El Salvador", NULL, "SV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (68, "Equatorial Guinea", NULL, "GQ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (69, "Eritrea", NULL, "ER")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (70, "Estonia", NULL, "EE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (71, "Ethiopia", NULL, "ET")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (72, "Falkland Islands (Malvinas)", NULL, "FK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (73, "Faroe Islands", NULL, "FO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (74, "Fiji", NULL, "FJ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (75, "Finland", NULL, "FI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (76, "France", NULL, "FR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (77, "French Guiana", NULL, "GF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (78, "French Polynesia", NULL, "PF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (79, "French Southern Territories", NULL, "TF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (80, "Gabon", NULL, "GA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (81, "Gambia", NULL, "GM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (82, "Georgia", NULL, "GE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (83, "Germany", NULL, "DE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (84, "Ghana", NULL, "GH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (85, "Gibraltar", NULL, "GI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (86, "Greece", NULL, "GR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (87, "Greenland", NULL, "GL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (88, "Grenada", NULL, "GD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (89, "Guadeloupe", NULL, "GP")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (90, "Guam", NULL, "GU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (91, "Guatemala", NULL, "GT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (92, "Guernsey", NULL, "GG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (93, "Guinea", NULL, "GN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (94, "Guinea-Bissau", NULL, "GW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (95, "Guyana", NULL, "GY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (96, "Haiti", NULL, "HT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (97, "Heard Island and Mcdonald Islands", NULL, "HM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (98, "Holy See (Vatican City State)", NULL, "VA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (99, "Honduras", NULL, "HN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (100, "Hong Kong", NULL, "HK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (101, "Hungary", NULL, "HU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (102, "Iceland", NULL, "IS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (103, "India", NULL, "IN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (104, "Indonesia", NULL, "ID")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (105, "Iran", "Islamic Republic of", "IR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (106, "Iraq", NULL, "IQ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (107, "Ireland", NULL, "IE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (108, "Isle of Man", NULL, "IM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (109, "Israel", NULL, "IL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (110, "Italy", NULL, "IT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (111, "Jamaica", NULL, "JM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (112, "Japan", NULL, "JP")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (113, "Jersey", NULL, "JE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (114, "Jordan", NULL, "JO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (115, "Kazakhstan", NULL, "KZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (116, "Kenya", NULL, "KE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (117, "Kiribati", NULL, "KI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (118, "Korea", "Democratic People\\\'s Republic of", "KP")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (119, "Korea", "Republic of", "KR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (120, "Kuwait", NULL, "KW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (121, "Kyrgyzstan", NULL, "KG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (122, "Lao People\\\'s Democratic Republic", NULL, "LA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (123, "Latvia", NULL, "LV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (124, "Lebanon", NULL, "LB")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (125, "Lesotho", NULL, "LS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (126, "Liberia", NULL, "LR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (127, "Libya", NULL, "LY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (128, "Liechtenstein", NULL, "LI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (129, "Lithuania", NULL, "LT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (130, "Luxembourg", NULL, "LU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (131, "Macao", NULL, "MO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (132, "Macedonia", "The former Yugoslav Republic of", "MK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (133, "Madagascar", NULL, "MG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (134, "Malawi", NULL, "MW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (135, "Malaysia", NULL, "MY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (136, "Maldives", NULL, "MV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (137, "Mali", NULL, "ML")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (138, "Malta", NULL, "MT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (139, "Marshall Islands", NULL, "MH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (140, "Martinique", NULL, "MQ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (141, "Mauritania", NULL, "MR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (142, "Mauritius", NULL, "MU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (143, "Mayotte", NULL, "YT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (144, "Mexico", NULL, "MX")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (145, "Micronesia", "Federated States of", "FM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (146, "Moldova", "Republic of", "MD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (147, "Monaco", NULL, "MC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (148, "Mongolia", NULL, "MN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (149, "Montenegro", NULL, "ME")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (150, "Montserrat", NULL, "MS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (151, "Morocco", NULL, "MA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (152, "Mozambique", NULL, "MZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (153, "Myanmar", NULL, "MM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (154, "Namibia", NULL, "NA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (155, "Nauru", NULL, "NR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (156, "Nepal", NULL, "NP")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (157, "Netherlands", NULL, "NL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (158, "New Caledonia", NULL, "NC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (159, "New Zealand", NULL, "NZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (160, "Nicaragua", NULL, "NI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (161, "Niger", NULL, "NE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (162, "Nigeria", NULL, "NG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (163, "Niue", NULL, "NU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (164, "Norfolk Island", NULL, "NF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (165, "Northern Mariana Islands", NULL, "MP")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (166, "Norway", NULL, "NO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (167, "Oman", NULL, "OM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (168, "Pakistan", NULL, "PK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (169, "Palau", NULL, "PW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (170, "Palestine", "State of", "PS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (171, "Panama", NULL, "PA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (172, "Papua New Guinea", NULL, "PG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (173, "Paraguay", NULL, "PY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (174, "Peru", NULL, "PE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (175, "Philippines", NULL, "PH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (176, "Pitcairn", NULL, "PN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (177, "Poland", NULL, "PL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (178, "Portugal", NULL, "PT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (179, "Puerto Rico", NULL, "PR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (180, "Qatar", NULL, "QA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (181, "Réunion", NULL, "RE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (182, "Romania", NULL, "RO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (183, "Russian Federation", NULL, "RU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (184, "Rwanda", NULL, "RW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (185, "Saint Barthélemy", NULL, "BL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (186, "Saint Helena", "Ascension and Tristan da Cunha", "SH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (187, "Saint Kitts and Nevis", NULL, "KN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (188, "Saint Lucia", NULL, "LC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (189, "Saint Martin (French Part)", NULL, "MF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (190, "Saint Pierre and Miquelon", NULL, "PM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (191, "Saint Vincent and the Grenadines", NULL, "VC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (192, "Samoa", NULL, "WS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (193, "San Marino", NULL, "SM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (194, "Sao Tome and Principe", NULL, "ST")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (195, "Saudi Arabia", NULL, "SA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (196, "Senegal", NULL, "SN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (197, "Serbia", NULL, "RS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (198, "Seychelles", NULL, "SC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (199, "Sierra Leone", NULL, "SL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (200, "Singapore", NULL, "SG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (201, "Sint Maarten (Dutch Part)", NULL, "SX")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (202, "Slovakia", NULL, "SK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (203, "Slovenia", NULL, "SI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (204, "Solomon Islands", NULL, "SB")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (205, "Somalia", NULL, "SO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (206, "South Africa", NULL, "ZA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (207, "South Georgia and the South Sandwich Islands", NULL, "GS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (208, "South Sudan", NULL, "SS")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (209, "Spain", NULL, "ES")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (210, "Sri Lanka", NULL, "LK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (211, "Sudan", NULL, "SD")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (212, "Suriname", NULL, "SR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (213, "Svalbard and Jan Mayen", NULL, "SJ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (214, "Swaziland", NULL, "SZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (215, "Sweden", NULL, "SE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (216, "Switzerland", NULL, "CH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (217, "Syrian Arab Republic", NULL, "SY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (218, "Taiwan", "Province of China", "TW")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (219, "Tajikistan", NULL, "TJ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (220, "Tanzania", "United Republic of", "TZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (221, "Thailand", NULL, "TH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (222, "Timor-Leste", NULL, "TL")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (223, "Togo", NULL, "TG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (224, "Tokelau", NULL, "TK")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (225, "Tonga", NULL, "TO")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (226, "Trinidad and Tobago", NULL, "TT")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (227, "Tunisia", NULL, "TN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (228, "Turkey", NULL, "TR")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (229, "Turkmenistan", NULL, "TM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (230, "Turks and Caicos Islands", NULL, "TC")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (231, "Tuvalu", NULL, "TV")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (232, "Uganda", NULL, "UG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (233, "Ukraine", NULL, "UA")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (234, "United Arab Emirates", NULL, "AE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (235, "United Kingdom", NULL, "GB")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (236, "United States", NULL, "US")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (237, "United States Minor Outlying Islands", NULL, "UM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (238, "Uruguay", NULL, "UY")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (239, "Uzbekistan", NULL, "UZ")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (240, "Vanuatu", NULL, "VU")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (241, "Venezuela", "Bolivarian Republic of", "VE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (242, "Viet Nam", NULL, "VN")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (243, "Virgin Islands", "British", "VG")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (244, "Virgin Islands", "U.S.", "VI")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (245, "Wallis and Futuna", NULL, "WF")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (246, "Western Sahara", NULL, "EH")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (247, "Yemen", NULL, "YE")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (248, "Zambia", NULL, "ZM")');
|
||||||
|
$this->addSql('INSERT INTO country (id, name, subname, code) VALUES (249, "Zimbabwe", NULL, "ZW")');
|
||||||
|
|
||||||
|
// states
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (1, \'Dolnoslaskie\', \'DS\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (2, \'Kujawsko-pomorskie\', \'KP\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (3, \'Lubuskie\', \'LB\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (4, \'Lódzkie\', \'LD\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (5, \'Lubelskie\', \'LU\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (6, \'Malopolskie\', \'MA\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (7, \'Mazowieckie\', \'MZ\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (8, \'Opolskie\', \'OP\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (9, \'Podlaskie\', \'PD\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (10, \'Podkarpackie\', \'PK\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (11, \'Pomorskie\', \'PM\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (12, \'Swietokrzyskie\', \'SK\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (13, \'Slaskie\', \'SL\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (14, \'Warminsko-mazurskie\', \'WN\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (15, \'Wielkopolskie\', \'WP\', 177)');
|
||||||
|
$this->addSql('INSERT INTO country_region (id, name, code, country) VALUES (16, \'Zachodniopomorskie\', \'ZP\', 177)');
|
|
@ -0,0 +1,114 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"code": "DS",
|
||||||
|
"name": "Dolnoslaskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"code": "KP",
|
||||||
|
"name": "Kujawsko-pomorskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"code": "LB",
|
||||||
|
"name": "Lubuskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"code": "LD",
|
||||||
|
"name": "Lódzkie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"code": "LU",
|
||||||
|
"name": "Lubelskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"code": "MA",
|
||||||
|
"name": "Malopolskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"code": "MZ",
|
||||||
|
"name": "Mazowieckie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 8,
|
||||||
|
"code": "OP",
|
||||||
|
"name": "Opolskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 9,
|
||||||
|
"code": "PD",
|
||||||
|
"name": "Podlaskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 10,
|
||||||
|
"code": "PK",
|
||||||
|
"name": "Podkarpackie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 11,
|
||||||
|
"code": "PM",
|
||||||
|
"name": "Pomorskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 12,
|
||||||
|
"code": "SK",
|
||||||
|
"name": "Swietokrzyskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 13,
|
||||||
|
"code": "SL",
|
||||||
|
"name": "Slaskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 14,
|
||||||
|
"code": "WN",
|
||||||
|
"name": "Warminsko-mazurskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 15,
|
||||||
|
"code": "WP",
|
||||||
|
"name": "Wielkopolskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 16,
|
||||||
|
"code": "ZP",
|
||||||
|
"name": "Zachodniopomorskie",
|
||||||
|
"countryCode": "PL",
|
||||||
|
"countryId": 177
|
||||||
|
}
|
||||||
|
]
|
|
@ -2,11 +2,15 @@
|
||||||
|
|
||||||
namespace Tools;
|
namespace Tools;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
class PutEnv {
|
class PutEnv {
|
||||||
|
|
||||||
private string $file;
|
private string $file;
|
||||||
private string $key;
|
private string $key;
|
||||||
private string $value;
|
private string $value;
|
||||||
private array $content;
|
private array $content;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
$argv = $_SERVER['argv'];
|
$argv = $_SERVER['argv'];
|
||||||
$argc = sizeof($argv);
|
$argc = sizeof($argv);
|
||||||
|
@ -41,7 +45,8 @@ class PutEnv {
|
||||||
}
|
}
|
||||||
$this->content = file($this->file);
|
$this->content = file($this->file);
|
||||||
foreach ($this->content as $l => $line) {
|
foreach ($this->content as $l => $line) {
|
||||||
if (strlen(trim($line)) < 1) {
|
$this->content[$l] = $line = trim($line);
|
||||||
|
if (strlen($line) < 1) {
|
||||||
if ($lineWasEmpty) {
|
if ($lineWasEmpty) {
|
||||||
$this->content[$l] = null;
|
$this->content[$l] = null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,7 +62,7 @@ class PutEnv {
|
||||||
if (strlen($next) === 0 || $next[0] !== '=') {
|
if (strlen($next) === 0 || $next[0] !== '=') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$this->content[$l] = $key . '=' . $value;
|
$this->content[$l] = $key . '=' . $value . \PHP_EOL;
|
||||||
$changed++;
|
$changed++;
|
||||||
}
|
}
|
||||||
if ($changed === 0) {
|
if ($changed === 0) {
|
||||||
|
@ -72,7 +77,7 @@ class PutEnv {
|
||||||
$this->content[] = $line;
|
$this->content[] = $line;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$content = implode('', $this->content);
|
$content = implode(PHP_EOL, $this->content);
|
||||||
file_put_contents($this->file, $content);
|
file_put_contents($this->file, $content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue