Compare commits

..

2 Commits

Author SHA1 Message Date
3ceeac726b Update changelog 2022-03-04 16:29:48 +01:00
e32b8b0942 Fix phonenumber -> telephone for thirdparty 2022-03-04 16:27:53 +01:00
36 changed files with 220 additions and 543 deletions

View File

@@ -11,8 +11,6 @@ and this project adheres to
## Unreleased
<!-- write down unreleased development here -->
* [main] filter user job in undispatch acc period to assign (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/472)
* [person] Add url in accompanying period work evaluations entity and form (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/476)
* [person] Add document generation in admin and in person/{id}/document (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/464)
* [activity] do not override location if already exist (when validating new activity) (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/470)
* [parcours] Toggle emergency/intensity only by referrer (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/442)
@@ -30,9 +28,7 @@ and this project adheres to
* [confidential] Fix position of toggle button so it does not cover text nor fall outside of box (no issue)
* [parcours] Fix edit of both thirdparty and contact name (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/474)
* [template] do not list inactive templates (for doc generator)
* [parcours] location cannot be removed if linked to a user (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/478)
* [person] email added to twig personRenderbox (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/490)
* [person] Add link to current household in person banner (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/484)
* [thirdparty] Bugfix phonenumber -> telephone for thirdparty (https://gitlab.com/champs-libres/departement-de-la-vendee/chill/-/issues/487)
## Test releases

View File

@@ -12,7 +12,6 @@ declare(strict_types=1);
namespace Chill\DocStoreBundle\Workflow;
use Chill\DocStoreBundle\Entity\AccompanyingCourseDocument;
use Chill\DocStoreBundle\Security\Authorization\AccompanyingCourseDocumentVoter;
use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
@@ -37,13 +36,6 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
$this->translator = $translator;
}
public function getDeletionRoles(): array
{
return [
AccompanyingCourseDocumentVoter::DELETE,
];
}
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{
$course = $this->getRelatedEntity($entityWorkflow)
@@ -74,18 +66,6 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingCourseDocument $object
*
* @return array[]
*/
public function getRelatedObjects(object $object): array
{
return [
['entityClass' => AccompanyingCourseDocument::class, 'entityId' => $object->getId()],
];
}
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
{
return null;
@@ -104,11 +84,6 @@ class AccompanyingCourseDocumentWorkflowHandler implements EntityWorkflowHandler
];
}
public function isObjectSupported(object $object): bool
{
return $object instanceof AccompanyingCourseDocument;
}
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return $entityWorkflow->getRelatedEntityClass() === AccompanyingCourseDocument::class;

View File

@@ -20,7 +20,7 @@ class DefaultController extends AbstractController
{
public function indexAction()
{
if ($this->isGranted('ROLE_ADMIN') && !in_array('ROLE_USER',$this->getUser()->getRoles())) {
if ($this->isGranted('ROLE_ADMIN')) {
return $this->redirectToRoute('chill_main_admin_central', [], 302);
}

View File

@@ -256,13 +256,6 @@ class ChillMainExtension extends Extension implements
'channels' => ['chill'],
]);
$container->prependExtensionConfig('security', [
'access_decision_manager' => [
'strategy' => 'unanimous',
'allow_if_all_abstain' => false,
],
]);
//add crud api
$this->prependCruds($container);
}

View File

@@ -112,11 +112,6 @@ class User implements AdvancedUserInterface
*/
private string $password = '';
/**
* @ORM\Column(type="json")
*/
private array $roles = ['ROLE_USER'];
/**
* @internal must be set to null if we use bcrypt
*
@@ -151,24 +146,36 @@ class User implements AdvancedUserInterface
$this->groupCenters = new ArrayCollection();
}
public function __toString(): string
/**
* @return string
*/
public function __toString()
{
return $this->getLabel();
}
public function addGroupCenter(GroupCenter $groupCenter): self
/**
* @param \Chill\MainBundle\Entity\GroupCenter $groupCenter
*
* @return \Chill\MainBundle\Entity\User
*/
public function addGroupCenter(GroupCenter $groupCenter)
{
$this->groupCenters->add($groupCenter);
return $this;
}
// empty function... remove?
public function eraseCredentials()
{
}
public function getAttributes(): ?array
/**
* Get attributes.
*
* @return array
*/
public function getAttributes()
{
if (null === $this->attributes) {
$this->attributes = [];
@@ -182,12 +189,18 @@ class User implements AdvancedUserInterface
return $this->currentLocation;
}
/**
* @return string
*/
public function getEmail(): ?string
{
return $this->email;
}
public function getEmailCanonical(): ?string
/**
* @return string
*/
public function getEmailCanonical()
{
return $this->emailCanonical;
}
@@ -200,7 +213,12 @@ class User implements AdvancedUserInterface
return $this->groupCenters;
}
public function getId(): ?int
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
@@ -225,17 +243,23 @@ class User implements AdvancedUserInterface
return $this->mainScope;
}
public function getPassword(): string
/**
* @return string
*/
public function getPassword()
{
return $this->password;
}
public function getRoles(): array
{
return array_unique($this->roles);
return ['ROLE_USER'];
}
public function getSalt(): ?string
/**
* @return string|null
*/
public function getSalt()
{
return $this->salt;
}
@@ -245,32 +269,50 @@ class User implements AdvancedUserInterface
return $this->userJob;
}
public function getUsername(): string
/**
* @return string
*/
public function getUsername()
{
return $this->username;
}
public function getUsernameCanonical(): ?string
/**
* @return string
*/
public function getUsernameCanonical()
{
return $this->usernameCanonical;
}
public function isAccountNonExpired(): bool
/**
* @return bool
*/
public function isAccountNonExpired()
{
return true;
}
public function isAccountNonLocked(): bool
/**
* @return bool
*/
public function isAccountNonLocked()
{
return $this->locked;
}
public function isCredentialsNonExpired(): bool
/**
* @return bool
*/
public function isCredentialsNonExpired()
{
return true;
}
public function isEnabled(): bool
/**
* @return bool
*/
public function isEnabled()
{
return $this->enabled;
}
@@ -321,84 +363,97 @@ class User implements AdvancedUserInterface
return $this;
}
public function setCurrentLocation(?Location $currentLocation): self
public function setCurrentLocation(?Location $currentLocation): User
{
$this->currentLocation = $currentLocation;
return $this;
}
public function setEmail($email): self
/**
* @param $email
*
* @return $this
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
public function setEmailCanonical($emailCanonical): self
/**
* @param $emailCanonical
*
* @return $this
*/
public function setEmailCanonical($emailCanonical)
{
$this->emailCanonical = $emailCanonical;
return $this;
}
public function setEnabled(bool $enabled): self
public function setEnabled(bool $enabled)
{
$this->enabled = $enabled;
return $this;
}
public function setLabel(string $label): self
public function setLabel(string $label): User
{
$this->label = $label;
return $this;
}
public function setMainCenter(?Center $mainCenter): self
public function setMainCenter(?Center $mainCenter): User
{
$this->mainCenter = $mainCenter;
return $this;
}
public function setMainLocation(?Location $mainLocation): self
public function setMainLocation(?Location $mainLocation): User
{
$this->mainLocation = $mainLocation;
return $this;
}
public function setMainScope(?Scope $mainScope): self
public function setMainScope(?Scope $mainScope): User
{
$this->mainScope = $mainScope;
return $this;
}
public function setPassword($password): self
/**
* @param $password
*
* @return $this
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
public function setRoles($roles): self
{
$this->roles = $roles;
return $this;
}
public function setSalt($salt): self
/**
* @param $salt
*
* @return $this
*/
public function setSalt($salt)
{
$this->salt = $salt;
return $this;
}
public function setUserJob(?UserJob $userJob): self
public function setUserJob(?UserJob $userJob): User
{
$this->userJob = $userJob;
@@ -423,7 +478,12 @@ class User implements AdvancedUserInterface
return $this;
}
public function setUsernameCanonical($usernameCanonical): self
/**
* @param $usernameCanonical
*
* @return $this
*/
public function setUsernameCanonical($usernameCanonical)
{
$this->usernameCanonical = $usernameCanonical;

View File

@@ -19,7 +19,6 @@ use Chill\MainBundle\Templating\TranslatableStringHelper;
use Doctrine\ORM\EntityRepository;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\CallbackTransformer;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
@@ -60,16 +59,6 @@ class UserType extends AbstractType
return $qb;
},
])
->add('roles', ChoiceType::class, [
'required' => true,
'multiple' => true,
'expanded' => true,
'label' => 'Roles',
'choices' => [
'Usager' => 'ROLE_USER',
'Administrateur' => 'ROLE_ADMIN',
],
])
->add('mainScope', EntityType::class, [
'label' => 'Main scope',
'required' => false,
@@ -105,18 +94,6 @@ class UserType extends AbstractType
},
]);
// $builder->get('roles')
// ->addModelTransformer(new CallbackTransformer(
// function ($rolesArray) {
// // transform the array to a string
// return count($rolesArray)? $rolesArray[0]: null;
// },
// function ($rolesString) {
// // transform the string back to an array
// return [$rolesString];
// }
// ));
if ($options['is_creation']) {
$builder->add('plainPassword', RepeatedType::class, [
'mapped' => false,

View File

@@ -27,7 +27,7 @@ interface PhoneNumberHelperInterface
/**
* Get type (mobile, landline, ...) for phone number.
*/
public function getType(PhoneNumber $phonenumber): string;
public function getType(string $phonenumber): string;
/**
* Return true if the validation is configured and available.

View File

@@ -17,7 +17,6 @@ use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\ServerException;
use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumber;
use libphonenumber\PhoneNumberType;
use libphonenumber\PhoneNumberUtil;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Log\LoggerInterface;
@@ -87,19 +86,9 @@ final class PhonenumberHelper implements PhoneNumberHelperInterface
/**
* Get type (mobile, landline, ...) for phone number.
*/
public function getType(PhoneNumber $phonenumber): string
public function getType(string $phonenumber): string
{
switch ($this->phoneNumberUtil->getNumberType($phonenumber)) {
case PhoneNumberType::MOBILE:
return 'mobile';
case PhoneNumberType::FIXED_LINE:
case PhoneNumberType::VOIP:
return 'landline';
default:
return 'landline';
}
return $this->performTwilioLookup($phonenumber) ?? 'unknown';
}
/**

View File

@@ -55,30 +55,6 @@ class EntityWorkflowRepository implements ObjectRepository
return (int) $qb->getQuery()->getSingleScalarResult();
}
public function countRelatedWorkflows(array $relateds): int
{
$qb = $this->repository->createQueryBuilder('w');
$orX = $qb->expr()->orX();
$i = 0;
foreach ($relateds as $related) {
$orX->add(
$qb->expr()->andX(
$qb->expr()->eq('w.relatedEntityClass', ':entity_class_' . $i),
$qb->expr()->eq('w.relatedEntityId', ':entity_id_' . $i)
)
);
$qb
->setParameter('entity_class_' . $i, $related['entityClass'])
->setParameter('entity_id_' . $i, $related['entityId']);
++$i;
}
$qb->where($orX);
return $qb->select('COUNT(w)')->getQuery()->getSingleScalarResult();
}
public function find($id): ?EntityWorkflow
{
return $this->repository->find($id);

View File

@@ -93,7 +93,6 @@ import Modal from 'ChillMainAssets/vuejs/_components/Modal.vue';
import OnTheFlyCreate from './Create.vue';
import OnTheFlyPerson from 'ChillPersonAssets/vuejs/_components/OnTheFly/Person.vue';
import OnTheFlyThirdparty from 'ChillThirdPartyAssets/vuejs/_components/OnTheFly/ThirdParty.vue';
import { postThirdparty } from "ChillThirdPartyAssets/vuejs/_api/OnTheFly";
export default {
name: 'OnTheFly',
@@ -218,21 +217,24 @@ export default {
case 'thirdparty':
data = this.$refs.castThirdparty.$data.thirdparty;
/* never executed ? */
/* never executed ? Yes, when editing thirdparty... */
break;
default:
if (typeof this.type === 'undefined') { // action=create or addContact
console.log('will rewrite data');
console.log('will rewrite data');
if (this.action === 'addContact') {
type = 'thirdparty'
data = this.$refs.castThirdparty.$data.thirdparty;
console.log('data original', data);
data.parent = {type: "thirdparty", id: this.parent.id};
// data.civility = {type: 'chill_main_civility', id: civility.id };
// data.profession = {type: 'third_party_profession', id: profession.id };
} else {
console.log('im here')
type = this.$refs.castNew.radioType;
data = this.$refs.castNew.castDataByType();
console.log(data)
console.log('saveAction', data)
}
} else {
throw 'error with object type';

View File

@@ -22,10 +22,19 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*/
class SectionMenuBuilder implements LocalMenuBuilderInterface
{
protected AuthorizationCheckerInterface $authorizationChecker;
/**
* @var AuthorizationCheckerInterface
*/
protected $authorizationChecker;
protected TranslatorInterface $translator;
/**
* @var TranslatorInterface
*/
protected $translator;
/**
* SectionMenuBuilder constructor.
*/
public function __construct(AuthorizationCheckerInterface $authorizationChecker, TranslatorInterface $translator)
{
$this->authorizationChecker = $authorizationChecker;
@@ -45,16 +54,6 @@ class SectionMenuBuilder implements LocalMenuBuilderInterface
'order' => 0,
]);
if ($this->authorizationChecker->isGranted('ROLE_ADMIN')) {
$menu->addChild($this->translator->trans('Administration'), [
'route' => 'chill_main_admin_central',
])
->setExtras([
'icons' => ['home'],
'order' => 5,
]);
}
$menu->addChild($this->translator->trans('Global timeline'), [
'route' => 'chill_center_timeline',
])

View File

@@ -1,65 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\MainBundle\Security\Authorization;
use Chill\MainBundle\Repository\Workflow\EntityWorkflowRepository;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use RuntimeException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use function in_array;
use function is_object;
class WorkflowEntityDeletionVoter extends Voter
{
private EntityWorkflowRepository $entityWorkflowRepository;
/**
* @var iterable|EntityWorkflowHandlerInterface[]
*/
private iterable $handlers;
public function __construct($handlers, EntityWorkflowRepository $entityWorkflowRepository)
{
$this->handlers = $handlers;
$this->entityWorkflowRepository = $entityWorkflowRepository;
}
protected function supports($attribute, $subject)
{
if (!is_object($subject)) {
return false;
}
foreach ($this->handlers as $handler) {
if ($handler->isObjectSupported($subject)
&& in_array($attribute, $handler->getDeletionRoles($subject), true)) {
return true;
}
}
return false;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
foreach ($this->handlers as $handler) {
if ($handler->isObjectSupported($subject)) {
return 0 === $this->entityWorkflowRepository->countRelatedWorkflows(
$handler->getRelatedObjects($subject)
);
}
}
throw new RuntimeException('no handlers found');
}
}

View File

@@ -40,7 +40,7 @@ class PhonenumberNormalizer implements NormalizerInterface, DenormalizerInterfac
*/
public function denormalize($data, $type, $format = null, array $context = [])
{
if ('' === trim($data)) {
if ("" == trim($data)) {
return null;
}

View File

@@ -15,19 +15,12 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
interface EntityWorkflowHandlerInterface
{
/**
* @return array|string[]
*/
public function getDeletionRoles(): array;
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array;
public function getEntityTitle(EntityWorkflow $entityWorkflow, array $options = []): string;
public function getRelatedEntity(EntityWorkflow $entityWorkflow): ?object;
public function getRelatedObjects(object $object): array;
/**
* Return a string representing the role required for seeing the workflow.
*
@@ -40,8 +33,6 @@ interface EntityWorkflowHandlerInterface
public function getTemplateData(EntityWorkflow $entityWorkflow, array $options = []): array;
public function isObjectSupported(object $object): bool;
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool;
public function supportsFreeze(EntityWorkflow $entityWorkflow, array $options = []): bool;

View File

@@ -75,9 +75,3 @@ services:
$locker: '@Chill\MainBundle\Security\PasswordRecover\PasswordRecoverLocker'
tags:
- { name: security.voter }
Chill\MainBundle\Security\Authorization\WorkflowEntityDeletionVoter:
autoconfigure: true
autowire: true
arguments:
$handlers: !tagged_iterator chill_main.workflow_handler

View File

@@ -1,36 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Main;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20220308104030 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE users DROP roles');
}
public function getDescription(): string
{
return 'Add roles property to user';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE users ADD roles JSONB DEFAULT \'["ROLE_USER"]\' NOT NULL');
}
}

View File

@@ -98,8 +98,7 @@ class PersonPhone
public function isEmpty(): bool
{
return ('' === $this->getDescription() || null === $this->getDescription())
&& null === $this->getPhonenumber();
return empty($this->getDescription()) && empty($this->getPhonenumber());
}
public function setDate(DateTime $date): void

View File

@@ -62,12 +62,6 @@ class Evaluation
*/
private array $title = [];
/**
* @ORM\Column(type="text", nullable=true)
* @Serializer\Groups({"read", "docgen:read"})
*/
private ?string $url = null;
public function __construct()
{
$this->socialActions = new ArrayCollection();
@@ -107,11 +101,6 @@ class Evaluation
return $this->title;
}
public function getUrl(): ?string
{
return $this->url;
}
public function removeSocialAction(SocialAction $socialAction): self
{
if ($this->socialActions->contains($socialAction)) {
@@ -141,11 +130,4 @@ class Evaluation
return $this;
}
public function setUrl(?string $url): self
{
$this->url = $url;
return $this;
}
}

View File

@@ -27,7 +27,6 @@ use Chill\PersonBundle\Entity\Person;
use Chill\PersonBundle\Entity\PersonPhone;
use Chill\PersonBundle\Form\Type\GenderType;
use Chill\PersonBundle\Form\Type\PersonAltNameType;
use Chill\PersonBundle\Form\Type\PersonPhoneType;
use Chill\PersonBundle\Form\Type\Select2MaritalStatusType;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\Form\AbstractType;
@@ -159,7 +158,7 @@ class PersonType extends AbstractType
}
$builder->add('otherPhoneNumbers', ChillCollectionType::class, [
'entry_type' => PersonPhoneType::class,
'entry_type' => ChillPhoneNumberType::class,
'button_add_label' => 'Add new phone',
'button_remove_label' => 'Remove phone',
'required' => false,

View File

@@ -11,11 +11,11 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Form\Type;
use Chill\MainBundle\Form\Type\ChillPhoneNumberType;
use Chill\MainBundle\Phonenumber\PhonenumberHelper;
use Chill\PersonBundle\Entity\PersonPhone;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\TelType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\FormEvent;
@@ -36,7 +36,7 @@ class PersonPhoneType extends AbstractType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('phonenumber', ChillPhoneNumberType::class, [
$builder->add('phonenumber', TelType::class, [
'label' => 'Other phonenumber',
'required' => true,
]);

View File

@@ -37,68 +37,57 @@ div.banner {
margin-right: 1em;
}
}
.household-link {
border: 1px solid white;
padding: .05rem .3rem;
border-radius: 5px;
color: white;
cursor: pointer;
&:hover {
background-color: white;
color: $chill-person-context
}
}
}
}
div.person-view {
figure.person-details {
h2 {
font-family: 'Open Sans';
font-weight: 600;
margin-bottom: 0.3em;
font-variant: small-caps;
}
dl {
margin-top: 0.3em;
}
dt {
font-family: 'Open Sans';
font-weight: 600;
}
dd {
margin-left: 0;
}
/*
a.sc-button { background-color: $black; padding-top: 0.2em; padding-bottom: 0.2em; }
*/
}
/* custom fields on the home page */
div.custom-fields {
figure.person-details {
display: flex;
flex-flow: row wrap;
div.cf_title_box:nth-child(4n+1) h2 {
@extend .chill-red !optional;
}
div.cf_title_box:nth-child(4n+2) h2 {
@extend .chill-green !optional;
}
div.cf_title_box:nth-child(4n+3) h2 {
@extend .chill-orange !optional;
}
div.cf_title_box:nth-child(4n+4) h2 {
@extend .chill-blue !optional;
}
div.cf_title_box:nth-child(2n+1) {
width: 50%;
margin-right: 40px;
}
div.cf_title_box:nth-child(2n+2) {
width: calc(50% - 40px);
}
}
}
figure.person-details {
h2 {
font-family: 'Open Sans';
font-weight: 600;
margin-bottom: 0.3em;
font-variant: small-caps;
}
dl {
margin-top: 0.3em;
}
dt {
font-family: 'Open Sans';
font-weight: 600;
}
dd {
margin-left: 0;
}
/*
a.sc-button { background-color: $black; padding-top: 0.2em; padding-bottom: 0.2em; }
*/
}
/* custom fields on the home page */
div.custom-fields {
figure.person-details {
display: flex;
flex-flow: row wrap;
div.cf_title_box:nth-child(4n+1) h2 {
@extend .chill-red !optional;
}
div.cf_title_box:nth-child(4n+2) h2 {
@extend .chill-green !optional;
}
div.cf_title_box:nth-child(4n+3) h2 {
@extend .chill-orange !optional;
}
div.cf_title_box:nth-child(4n+4) h2 {
@extend .chill-blue !optional;
}
div.cf_title_box:nth-child(2n+1) {
width: 50%;
margin-right: 40px;
}
div.cf_title_box:nth-child(2n+2) {
width: calc(50% - 40px);
}
}
}
}
/*

View File

@@ -19,21 +19,22 @@ import {fetchResults} from 'ChillMainAssets/lib/api/apiMethods.js';
*/
document.querySelectorAll('[data-set-referrer-app]').forEach(function (el) {
const periodId = Number.parseInt(el.dataset.setReferrerAccompanyingPeriodId);
const jobId = Number.parseInt(el.dataset.setReferrerJobId);
let
periodId = Number.parseInt(el.dataset.setReferrerAccompanyingPeriodId);
const url = `/api/1.0/person/accompanying-course/${periodId}/referrers-suggested.json`;
fetchResults(url).then(suggested => {
const filteredSuggested = suggested.filter((s) => s.user_job ? s.user_job.id === jobId : false);
const app = createApp({
components: {
SetReferrer,
},
template:
'<set-referrer :suggested="filteredSuggested" :periodId="periodId" @referrerSet="onReferrerSet"></set-referrer>',
'<set-referrer :suggested="suggested" :periodId="periodId" @referrerSet="onReferrerSet"></set-referrer>',
data() {
return {
periodId, filteredSuggested, original: filteredSuggested,
periodId, suggested, original: suggested,
}
},
methods: {
@@ -55,7 +56,7 @@ document.querySelectorAll('[data-set-referrer-app]').forEach(function (el) {
label.textContent = ref.text;
label.classList.remove('chill-no-data-statement');
this.filteredSuggested = this.original.filter(user => user.id !== ref.id);
this.suggested = this.original.filter(user => user.id !== ref.id);
}
}
});

View File

@@ -59,6 +59,14 @@
ref="addAddress">
</add-address>
</li>
<li v-if="isPersonLocation">
<button
class="btn btn-remove"
@click="removeAddress"
:title="$t('courselocation.remove_button')">
{{ $t('action.remove') }}
</button>
</li>
</ul>
</div>
@@ -172,6 +180,22 @@ export default {
}
this.$store.commit('setAddressContext', context);
},
removeAddress() {
let payload = {
target: this.context.target.name,
targetId: this.context.target.id,
locationStatusTo: 'none'
};
//console.log('remove address');
this.$store.dispatch('updateLocation', payload)
.catch(({name, violations}) => {
if (name === 'ValidationException' || name === 'AccessException') {
violations.forEach((violation) => this.$toast.open({message: violation}));
} else {
this.$toast.open({message: 'An error occurred'})
}
});
},
displayErrors() {
return this.$refs.addAddress.errorMsg;
},

View File

@@ -171,8 +171,6 @@ export default {
body.name = payload.data.name;
body.email = payload.data.email;
body.telephone = payload.data.telephone;
body.civility = payload.data.civility;
body.profession = payload.data.profession;
body.address = payload.data.address ? { id: payload.data.address.address_id } : null;
makeFetch('PATCH', `/api/1.0/thirdparty/thirdparty/${payload.data.id}.json`, body)

View File

@@ -5,11 +5,6 @@
<span>{{ evaluation.evaluation.title.fr }}</span>
</div>
<div class="item-url mt-3 mb-4" v-if="evaluation.evaluation.url">
<i class="fa fa-link fa-lg"></i>
<a :href="evaluation.evaluation.url" target="_blank">{{ evaluation.evaluation.url }}</a>
</div>
<div>
<form-evaluation ref="FormEvaluation" :key="evaluation.key" :evaluation="evaluation"></form-evaluation>
@@ -26,7 +21,7 @@
></list-workflow-modal>
</li>
<li v-if="canDelete">
<li>
<a class="btn btn-delete" @click="modal.showModal = true" :title="$t('action.delete')"></a>
</li>
</ul>
@@ -98,19 +93,6 @@ export default {
pickedEvaluations() {
return this.$store.state.evaluationsPicked;
},
canDelete() {
if (this.evaluation.workflows.length > 0) {
return false;
}
for (let doc of this.evaluation.documents) {
if (doc.workflows.length > 0) {
return false;
}
}
return true;
},
},
methods: {
removeEvaluation(e) {
@@ -146,11 +128,4 @@ export default {
}
}
}
div.item-url {
i {
color: unset!important;
margin-left: 1rem;
margin-right: 0.5rem;
}
}
</style>

View File

@@ -101,7 +101,7 @@
<li>
<a :href="buildEditLink(d.storedObject)" class="btn btn-wopilink"></a>
</li>
<li v-if="d.workflows.length === 0">
<li>
<a class="btn btn-delete" @click="removeDocument(d)">
</a>
</li>

View File

@@ -1,12 +1,12 @@
<template>
<ul class="list-suggest add-items" v-if="suggested.length > 0">
<li v-for="(r, i) in suggested" @click="setReferrer(r)" :key="i"><span>{{ r.text }}</span></li>
<li v-for="r in suggested" @click="setReferrer(r)"><span>{{ r.text }}</span></li>
</ul>
</template>
<script>
import { makeFetch } from 'ChillMainAssets/lib/api/apiMethods.js';
import {makeFetch} from 'ChillMainAssets/lib/api/apiMethods.js';
export default {
name: "SetReferrer",

View File

@@ -130,13 +130,11 @@
href="{{ chill_path_add_return_path('chill_person_accompanying_period_work_edit', { 'id': w.id }) }}"
></a>
</li>
{% if is_granted('CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_DELETE', w) %}
<li>
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
></a>
</li>
{% endif %}
<li>
<a class="btn btn-delete" title="{{ 'Delete'|trans }}"
href="{{ path('chill_person_accompanying_period_work_delete', { 'id': w.id } ) }}"
></a>
</li>
</ul>
{% endif %}
</div>

View File

@@ -167,18 +167,6 @@
<span class="chill-no-data-statement">{{ 'No data given'|trans }}</span>
</li>
{% endif %}
{% if person.email is not empty %}
<li>
<i class="fa fa-li fa-envelope-o"></i><a href="{{ 'mailto:' ~ person.email }}">
{{ person.email }}
</a>
</li>
{% else %}
<li>
<i class="fa fa-li fa-envelope-o"></i>
<span class="chill-no-data-statement">{{ 'No data given'|trans }}</span>
</li>
{% endif %}
{% if options['addCenter'] and person|chill_resolve_center|length > 0 %}
<li>
<i class="fa fa-li fa-long-arrow-right"></i>

View File

@@ -58,13 +58,6 @@
}) }}
</span>
{%- endif -%}
{% if person.getCurrentHousehold is not null %}
<span>
<a class="household-link" href="{{ chill_path_add_return_path('chill_person_household_summary', { 'household_id' : person.getCurrentHousehold.id } ) }}">
<i class="fa fa-home"></i>
</a>
</span>
{% endif %}
</div>
</div>

View File

@@ -24,8 +24,6 @@ class AccompanyingPeriodWorkVoter extends Voter
{
public const CREATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_CREATE';
public const DELETE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_DELETE';
public const SEE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_SEE';
public const UPDATE = 'CHILL_MAIN_ACCOMPANYING_PERIOD_WORK_UPDATE';
@@ -62,7 +60,6 @@ class AccompanyingPeriodWorkVoter extends Voter
case self::CREATE:
case self::UPDATE:
case self::DELETE:
return $this->security->isGranted(AccompanyingPeriodVoter::EDIT, $subject->getAccompanyingPeriod());
default:
@@ -89,6 +86,6 @@ class AccompanyingPeriodWorkVoter extends Voter
private function getRoles(): array
{
return [self::SEE, self::CREATE, self::UPDATE, self::DELETE];
return [self::SEE, self::CREATE, self::UPDATE];
}
}

View File

@@ -37,13 +37,6 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
$this->translator = $translator;
}
public function getDeletionRoles(): array
{
return [
'_',
];
}
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{
$doc = $this->getRelatedEntity($entityWorkflow);
@@ -70,18 +63,6 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingPeriodWorkEvaluationDocument $object
*
* @return array[]
*/
public function getRelatedObjects(object $object): array
{
return [
['entityClass' => AccompanyingPeriodWorkEvaluationDocument::class, $object->getId()],
];
}
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
{
return AccompanyingPeriodWorkEvaluationDocumentVoter::SEE;
@@ -103,11 +84,6 @@ class AccompanyingPeriodWorkEvaluationDocumentWorkflowHandler implements EntityW
];
}
public function isObjectSupported(object $object): bool
{
return $object instanceof AccompanyingPeriodWorkEvaluationDocument;
}
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return $entityWorkflow->getRelatedEntityClass() === AccompanyingPeriodWorkEvaluationDocument::class;

View File

@@ -15,7 +15,6 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkEvaluationVoter;
use Symfony\Contracts\Translation\TranslatorInterface;
@@ -38,11 +37,6 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
$this->translator = $translator;
}
public function getDeletionRoles(): array
{
return ['_'];
}
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{
$evaluation = $this->getRelatedEntity($entityWorkflow);
@@ -67,20 +61,6 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingPeriodWorkEvaluation $object
*/
public function getRelatedObjects(object $object): array
{
$relateds[] = ['entityClass' => AccompanyingPeriodWorkEvaluation::class, 'entityId' => $object->getId()];
foreach ($object->getDocuments() as $doc) {
$relateds[] = ['entityClass' => AccompanyingPeriodWorkEvaluationDocument::class, 'entityId' => $doc->getId()];
}
return $relateds;
}
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
{
return AccompanyingPeriodWorkEvaluationVoter::SEE;
@@ -99,11 +79,6 @@ class AccompanyingPeriodWorkEvaluationWorkflowHandler implements EntityWorkflowH
];
}
public function isObjectSupported(object $object): bool
{
return $object instanceof AccompanyingPeriodWorkEvaluation;
}
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return $entityWorkflow->getRelatedEntityClass() === AccompanyingPeriodWorkEvaluation::class;

View File

@@ -15,10 +15,7 @@ use Chill\MainBundle\Entity\Workflow\EntityWorkflow;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\MainBundle\Workflow\EntityWorkflowHandlerInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWork;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluation;
use Chill\PersonBundle\Entity\AccompanyingPeriod\AccompanyingPeriodWorkEvaluationDocument;
use Chill\PersonBundle\Repository\AccompanyingPeriod\AccompanyingPeriodWorkRepository;
use Chill\PersonBundle\Security\Authorization\AccompanyingPeriodWorkVoter;
use Symfony\Contracts\Translation\TranslatorInterface;
class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInterface
@@ -39,11 +36,6 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
$this->translator = $translator;
}
public function getDeletionRoles(): array
{
return [AccompanyingPeriodWorkVoter::DELETE];
}
public function getEntityData(EntityWorkflow $entityWorkflow, array $options = []): array
{
return [
@@ -66,24 +58,6 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
return $this->repository->find($entityWorkflow->getRelatedEntityId());
}
/**
* @param AccompanyingPeriodWork $object
*/
public function getRelatedObjects(object $object): array
{
$relateds[] = ['entityClass' => AccompanyingPeriodWork::class, 'entityId' => $object->getId()];
foreach ($object->getAccompanyingPeriodWorkEvaluations() as $evaluation) {
$relateds[] = ['entityClass' => AccompanyingPeriodWorkEvaluation::class, 'entityId' => $evaluation->getId()];
foreach ($evaluation->getDocuments() as $doc) {
$relateds[] = ['entityClass' => AccompanyingPeriodWorkEvaluationDocument::class, 'entityId' => $doc->getId()];
}
}
return $relateds;
}
public function getRoleShow(EntityWorkflow $entityWorkflow): ?string
{
return null;
@@ -102,11 +76,6 @@ class AccompanyingPeriodWorkWorkflowHandler implements EntityWorkflowHandlerInte
];
}
public function isObjectSupported(object $object): bool
{
return $object instanceof AccompanyingPeriodWork;
}
public function supports(EntityWorkflow $entityWorkflow, array $options = []): bool
{
return $entityWorkflow->getRelatedEntityClass() === AccompanyingPeriodWork::class;

View File

@@ -1,37 +0,0 @@
<?php
/**
* Chill is a software for social workers
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
declare(strict_types=1);
namespace Chill\Migrations\Person;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Add url to SocialWork Evaluation.
*/
final class Version20220303113855 extends AbstractMigration
{
public function down(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_social_work_evaluation DROP url');
}
public function getDescription(): string
{
return 'Add url to SocialWork Evaluation';
}
public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE chill_person_social_work_evaluation ADD url TEXT DEFAULT NULL');
$this->addSql("UPDATE chill_person_social_work_evaluation SET url = CASE WHEN title->>'fr' LIKE 'http%' THEN title->>'fr' ELSE null END;");
}
}

View File

@@ -116,12 +116,12 @@
</div>
<div class="input-group mb-3">
<span class="input-group-text" id="phonenumber"><i class="fa fa-fw fa-phone"></i></span>
<span class="input-group-text" id="telephone"><i class="fa fa-fw fa-phone"></i></span>
<input class="form-control form-control-lg"
v-model="thirdparty.telephone"
v-bind:placeholder="$t('thirdparty.phonenumber')"
v-bind:aria-label="$t('thirdparty.phonenumber')"
aria-describedby="phonenumber" />
aria-describedby="telephone" />
</div>
<div v-if="parent">
@@ -266,10 +266,10 @@ export default {
this.thirdparty.name = query;
},
},
mounted() {
let dependencies = [];
dependencies.push(this.loadProfessions());
dependencies.push(this.loadCivilities());
mounted() {
let dependencies = [];
dependencies.push(this.loadProfessions());
dependencies.push(this.loadCivilities());
if (this.action !== 'create') {
if (this.id) {
dependencies.push(this.loadData());