Skip to content

Commit

Permalink
Merge pull request #17 from tchapi/feature/delegation-refactor
Browse files Browse the repository at this point in the history
[WIP] Refactor delegation
  • Loading branch information
tchapi authored Dec 18, 2020
2 parents 17bf976 + 49df373 commit 076baef
Show file tree
Hide file tree
Showing 14 changed files with 985 additions and 981 deletions.
1,353 changes: 539 additions & 814 deletions composer.lock

Large diffs are not rendered by default.

45 changes: 43 additions & 2 deletions public/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,47 @@ $(document).ready(function() {
$('a.delete-modal').click(function() {
// Grab real target url for deletion
let targetUrl = $(this).attr('data-href');
let modalFlavour = $(this).attr('data-flavour');

// Put it into the modal's OK button
$('#delete .target-url').attr('href', targetUrl);
$('#delete-' + modalFlavour + ' .target-url').attr('href', targetUrl);

// Show the modal
$('#delete').modal('show');
$('#delete-' + modalFlavour).modal('show');
})

// "Sharing settings" modals
$('a.share-modal').click(function() {
// Grab calendar shares url and add url
let shareesUrl = $(this).attr('data-sharees-href');
let targetUrl = $(this).attr('data-href');

// Put it into the modal's OK button
$('#share .add-sharee').attr('data-href', targetUrl);

// Get calendar shares
$.get(shareesUrl, function(data) {
// Catch error TODO
$('#shares').empty()
if (data.length === 0) {
$('.none').removeClass('d-none')
} else {
$('.none').addClass('d-none')
data.forEach(element => {
const newShare = $($('#template-share').html())
newShare.find('span.name').text(element.displayName)
newShare.find('span.badge').text(element.accessText)
newShare.find('a.revoke').attr('href', element.revokeUrl)
if (element.isWriteAccess) {
newShare.find('span.badge').addClass('badge-success').removeClass('badge-info')
}
newShare.appendTo($('#shares'));
});
}
})

// Show the modal
$('#share').modal('show');
})

// Color swatch : update it live (not working in IE ¯\_(ツ)_/¯ but it's just a nice to have)
Expand All @@ -22,6 +57,12 @@ $(document).ready(function() {
})
document.body.style.setProperty('--calendar-color', $('#calendar_instance_calendarColor').val());

// Modal to add a sharee on a calendar, catch the click to add the query parameter
$('a.add-sharee').click(function(e) {
e.preventDefault()
window.location = $(this).attr('data-href') + "?principalId=" + $("#member").val() + "&write=" + ($("#write").is(':checked') ? 'true' : 'false')
})

// Modal to add delegate, catch the click to add the query parameter
$('a.add-delegate').click(function(e) {
e.preventDefault()
Expand Down
344 changes: 214 additions & 130 deletions src/Controller/AdminController.php

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/Form/CalendarInstanceType.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,21 @@ public function buildForm(FormBuilderInterface $builder, array $options)
->add('events', CheckboxType::class, [
'label' => 'form.events',
'mapped' => false,
'disabled' => $options['shared'],
'help' => 'form.events.help',
'required' => false,
])
->add('todos', CheckboxType::class, [
'label' => 'form.todos',
'mapped' => false,
'disabled' => $options['shared'],
'help' => 'form.todos.help',
'required' => false,
])
->add('notes', CheckboxType::class, [
'label' => 'form.notes',
'mapped' => false,
'disabled' => $options['shared'],
'help' => 'form.notes.help',
'required' => false,
])
Expand All @@ -67,6 +70,7 @@ public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'new' => false,
'shared' => false,
'data_class' => CalendarInstance::class,
]);
}
Expand Down
42 changes: 23 additions & 19 deletions src/Repository/CalendarInstanceRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Repository;

use App\Entity\CalendarInstance;
use App\Entity\Principal;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;

Expand All @@ -19,32 +20,35 @@ public function __construct(ManagerRegistry $registry)
parent::__construct($registry, CalendarInstance::class);
}

// /**
// * @return CalendarInstance[] Returns an array of CalendarInstance objects
// */
/*
public function findByExampleField($value)
/**
* @return CalendarInstance[] Returns an array of CalendarInstance objects
*/
public function findSharedInstancesOfInstance(int $calendarId)
{
return $this->createQueryBuilder('c')
->andWhere('c.exampleField = :val')
->setParameter('val', $value)
->orderBy('c.id', 'ASC')
->setMaxResults(10)
->leftJoin(Principal::class, 'p', \Doctrine\ORM\Query\Expr\Join::WITH, 'c.principalUri = p.uri')
->addSelect('p.displayName', 'p.email')
->where('c.calendar = :id')
->setParameter('id', $calendarId)
->andWhere('c.access != :ownerAccess')
->setParameter('ownerAccess', CalendarInstance::ACCESS_OWNER)
->getQuery()
->getResult()
;
->getArrayResult();
}
*/

/*
public function findOneBySomeField($value): ?CalendarInstance
/**
* @return CalendarInstance Returns a CalendarInstance object
*/
public function findSharedInstanceOfInstanceFor(int $calendarId, string $principalUri)
{
return $this->createQueryBuilder('c')
->andWhere('c.exampleField = :val')
->setParameter('val', $value)
->where('c.calendar = :id')
->setParameter('id', $calendarId)
->andWhere('c.access != :ownerAccess')
->setParameter('ownerAccess', CalendarInstance::ACCESS_OWNER)
->andWhere('c.principalUri = :principalUri')
->setParameter('principalUri', $principalUri)
->getQuery()
->getOneOrNullResult()
;
->getOneOrNullResult();
}
*/
}
3 changes: 0 additions & 3 deletions symfony.lock
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@
"doctrine/persistence": {
"version": "2.0.0"
},
"doctrine/reflection": {
"version": "1.2.1"
},
"doctrine/sql-formatter": {
"version": "1.1.1"
},
Expand Down
3 changes: 2 additions & 1 deletion templates/_partials/add_delegate_modal.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<option value="{{ principal.id}}">{{ principal.displayName }} ({{ principal.email }})</option>
{% endfor %}
</select>
<small class="form-text text-muted">{{ "delegates.member.help"|trans }}</small>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="write">
Expand All @@ -27,7 +28,7 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ "cancel"|trans }}</button>
<a data-href="{{ path('calendar_delegate_add', {id: calendar.id}) }}" href="#" class="btn btn-primary add-delegate">{{ "add"|trans }}</a>
<a data-href="{{ path('user_delegate_add', {username: principal.username}) }}" href="#" class="btn btn-primary add-delegate">{{ "add"|trans }}</a>
</div>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions templates/_partials/delegate_row.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
{% endif %}
</h5>
<div class="mr-0 text-right d-lg-block d-none">
<a href="#" data-href="{{ path('calendar_delegate_remove',{id: calendar.id, principalProxyId: has_write ? principalProxyWrite.id : principalProxyRead.id, delegateId: delegate.id})}}" class="btn btn-sm btn-outline-danger ml-1 mb-1 delete-modal">⚠&nbsp;{{ "remove"|trans }}</a>
<a href="#" data-href="{{ path('user_delegate_remove',{username: principal.username, principalProxyId: has_write ? principalProxyWrite.id : principalProxyRead.id, delegateId: delegate.id})}}" data-flavour="delegates" class="btn btn-sm btn-outline-danger ml-1 mb-1 delete-modal">⚠&nbsp;{{ "remove"|trans }}</a>
</div>
</div>
<p class="mb-1">{{ "users.username"|trans }} : <code>{{ delegate.username }}</code></p>
<small>{{ "users.uri"|trans }} : <code>{{ delegate.uri }}</code></small>
<div class="btn-group btn-group-sm mt-3 d-flex d-lg-none" role="group">
<a href="#" data-href="{{ path('calendar_delegate_remove',{id: calendar.id, principalProxyId: has_write ? principalProxyWrite.id : principalProxyRead.id, delegateId: delegate.id})}}" class="btn btn-outline-danger flex-fill flex-shrink-1 delete-modal"><span class="d-none d-sm-inline">⚠&nbsp;</span>{{ "remove"|trans }}</a>
<a href="#" data-href="{{ path('user_delegate_remove',{username: principal.username, principalProxyId: has_write ? principalProxyWrite.id : principalProxyRead.id, delegateId: delegate.id})}}" data-flavour="delegates" class="btn btn-outline-danger flex-fill flex-shrink-1 delete-modal"><span class="d-none d-sm-inline">⚠&nbsp;</span>{{ "remove"|trans }}</a>
</div>
</div>
2 changes: 1 addition & 1 deletion templates/_partials/delete_modal.html.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div id="delete" class="modal fade" tabindex="-1" role="dialog">
<div id="delete-{{ flavour }}" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
Expand Down
48 changes: 48 additions & 0 deletions templates/_partials/share_modal.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<div class="modal fade" id="share" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{ "calendars.delegates.new"|trans }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4>{{ "calendars.delegates.existing"|trans }}</h4>
<template id="template-share">
<div class="list-group-item d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<span class="name"></span>
<span class="badge badge-info badge-pill ml-2"></span>
</div>
<a href="#" class="btn btn-sm btn-danger revoke">{{ "revoke"|trans }}</a>
</div>
</template>
<span class="d-none none"><em>{{ "calendars.delegates.none"|trans }}</em></span>
<ul class="list-group" id="shares">
</ul>
<form class="mt-2">
<div class="form-group">
<label for="member" class="col-form-label">{{ "calendars.delegates.member.add"|trans }}</label>
<select class="form-control" id="member">
{% for principal in principals %}
<option value="{{ principal.id}}">{{ principal.displayName }} ({{ principal.email }})</option>
{% endfor %}
</select>
<small class="form-text text-muted">{{ "calendars.delegates.member.help"|trans }}</small>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" value="" id="write">
<label class="form-check-label" for="write">
{{ "calendars.delegates.write.give"|trans }}
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ "cancel"|trans }}</button>
<a href="#" class="btn btn-primary add-sharee">{{ "add"|trans }}</a>
</div>
</div>
</div>
</div>
50 changes: 46 additions & 4 deletions templates/calendars/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1 mr-auto">{{ calendar.displayName }} <span class="badge badge-pill" style="background-color: {{ calendar.calendarColor }}">&nbsp;</span></h5>
<div class="mr-0 text-right d-md-block d-none">
<a href="{{ path('calendar_delegates',{id: calendar.id}) }}" class="btn btn-sm btn-outline-secondary">💁 {{ "users.delegates"|trans }}</a>
<a href="#" data-sharees-href="{{ path('calendar_shares',{username: username, calendarid: calendar.calendar.id})}}" data-href="{{ path('calendar_share_add', {username: principal.username, instanceid: calendar.id}) }}" class="btn btn-sm btn-outline-info ml-1 share-modal">🔗 {{ "sharing"|trans }}</a>
<a href="{{ path('calendar_edit',{username: username, id: calendar.id})}}" class="btn btn-sm btn-outline-primary ml-1">✎ {{ "edit"|trans }}</a>
<a href="#" data-href="{{ path('calendar_delete',{username: username, id: calendar.id})}}" class="btn btn-sm btn-outline-danger ml-1 delete-modal">⚠ {{ "delete"|trans }}</a>
<a href="#" data-href="{{ path('calendar_delete',{username: username, id: calendar.id})}}" data-flavour="calendars" class="btn btn-sm btn-outline-danger ml-1 delete-modal">⚠ {{ "delete"|trans }}</a>
</div>
</div>
<p class="mb-1">{{ calendar.description }}</p>
Expand All @@ -28,14 +28,56 @@
— {{ "calendars.entries"|trans({'%count%': calendar.calendar.objects|length}) }}
</small>
<div class="btn-group btn-group-sm mt-3 d-flex d-md-none" role="group">
<a href="{{ path('calendar_delegates',{id: calendar.id}) }}" class="btn btn-outline-secondary">💁 {{ "users.delegates"|trans }}</a>
<a href="#" data-sharees-href="{{ path('calendar_shares',{username: username, calendarid: calendar.calendar.id})}}" data-href="{{ path('calendar_share_add', {username: principal.username, instanceid: calendar.id}) }}" class="btn btn-outline-info share-modal">🔗 {{ "sharing"|trans }}</a>
<a href="{{ path('calendar_edit',{username: username, id: calendar.id})}}" class="btn btn-outline-primary">✎ {{ "edit"|trans }}</a>
<a href="#" data-href="{{ path('calendar_delete',{username: username, id: calendar.id})}}" class="btn btn-outline-danger delete-modal">⚠ {{ "delete"|trans }}</a>
<a href="#" data-href="{{ path('calendar_delete',{username: username, id: calendar.id})}}" data-flavour="calendars" class="btn btn-outline-danger delete-modal">⚠ {{ "delete"|trans }}</a>
</div>
</div>
{% endfor %}
</div>

{% if shared|length > 0 %}
<h2 class="display-5 mt-4 font-weight-lighter">{{ "calendars.shared.with"|trans({'who': principal.displayName}) }}</h2>

<div class="list-group mt-3">
{% for calendar in shared %}
<div class="list-group-item list-group-item-action p-3">
<div class="d-flex w-100 justify-content-between">
<h5 class="mb-1 mr-auto">
{{ calendar.displayName }}
{% if calendar.access == constant('\\App\\Entity\\CalendarInstance::ACCESS_READWRITE') %}
<span class="badge badge-success ml-1">{{ ('calendar.share_access.' ~ calendar.access)|trans }}</span>
{% else %}
<span class="badge badge-info ml-1">{{ ('calendar.share_access.' ~ calendar.access)|trans }}</span>
{% endif %}
<span class="badge badge-pill" style="background-color: {{ calendar.calendarColor }}">&nbsp;</span>
</h5>
<div class="mr-0 text-right d-md-block d-none">
<a href="{{ path('calendar_edit',{username: username, id: calendar.id})}}" class="btn btn-sm btn-outline-primary ml-1">✎ {{ "edit"|trans }}</a>
<a href="#" data-href="{{ path('calendar_revoke',{username: username, id: calendar.id})}}" data-flavour="revoke" class="btn btn-sm btn-outline-danger ml-1 delete-modal">🚫 {{ "revoke"|trans }}</a>
</div>
</div>
<p class="mb-1">{{ calendar.description }}</p>
<small>{{ "calendars.uri"|trans }} : <code>{{ calendar.uri }}</code>
{% if calendar.calendar.components|split(',')|length > 0 %}
{% if constant('\\App\\Entity\\Calendar::COMPONENT_EVENTS') in calendar.calendar.components %}<span class="badge badge-success">{{ "calendars.component.events"|trans }}</span>{% endif %}
{% if constant('\\App\\Entity\\Calendar::COMPONENT_NOTES') in calendar.calendar.components %}<span class="badge badge-info">{{ "calendars.component.notes"|trans }}</span>{% endif %}
{% if constant('\\App\\Entity\\Calendar::COMPONENT_TODOS') in calendar.calendar.components %}<span class="badge badge-primary">{{ "calendars.component.todos"|trans }}</span>{% endif %}
{% endif %}
— {{ "calendars.entries"|trans({'%count%': calendar.calendar.objects|length}) }}
</small>
<div class="btn-group btn-group-sm mt-3 d-flex d-md-none" role="group">
<a href="{{ path('calendar_edit',{username: username, id: calendar.id})}}" class="btn btn-outline-primary">✎ {{ "edit"|trans }}</a>
<a href="#" data-href="{{ path('calendar_revoke',{username: username, id: calendar.id})}}" data-flavour="revoke" class="btn btn-outline-danger delete-modal">🚫 {{ "revoke"|trans }}</a>
</div>
</div>
{% endfor %}
</div>

{% include '_partials/delete_modal.html.twig' with {flavour: 'revoke'} %}
{% endif %}

{% include '_partials/share_modal.html.twig' with {principals: allPrincipals} %}
{% include '_partials/delete_modal.html.twig' with {flavour: 'calendars'} %}

{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@

{% block body %}

<a href="{{ path('calendars', {username: principal.username}) }}" class="btn btn-link">« {{ "calendars.back"|trans({'user': principal.displayName}) }}</a>
<a href="{{ path('users') }}" class="btn btn-link">« {{ "users.back"|trans }}</a>

<h1 class="display-4 font-weight-lighter d-flex justify-content-between">{{ "calendars.delegates.for"|trans({'what': calendar.displayName}) }}{% if delegation %} <a href="#" data-toggle="modal" data-target="#add_delegate" class="btn btn-sm btn-success mb-auto mt-auto">+ {{ "calendars.delegates.add"|trans }}</a>{% endif %}</h1>
<h1 class="display-4 font-weight-lighter d-flex justify-content-between">{{ "calendars.delegates.for"|trans({'what': principal.displayName}) }}{% if delegation %} <a href="#" data-toggle="modal" data-target="#add_delegate" class="btn btn-sm btn-success mb-auto mt-auto">+ {{ "calendars.delegates.add"|trans }}</a>{% endif %}</h1>

<div class="list-group">

{% if delegation %}
<div class="alert alert-success d-flex justify-content-between mb-4 mt-2" role="alert">
<div>{{ "delegates.enabled.text"|trans }}<br><small>{{ "delegates.disable.warning"|trans }}</small></div>
<a href="{{ path('calendar_delegation_toggle', {id: calendar.id, toggle: 'off'})}}" class="btn btn-sm my-auto btn-outline-danger">{{ "delegates.disable"|trans }}</a>
<a href="{{ path('user_delegation_toggle', {username: principal.username, toggle: 'off'})}}" class="btn btn-sm my-auto btn-outline-danger">{{ "delegates.disable"|trans }}</a>
</div>
{% for delegate in principalProxyRead.delegees %}
{% include '_partials/delegate_row.html.twig' with {has_write: false} %}
Expand All @@ -23,7 +23,7 @@

{% else %}
<div class="alert alert-warning d-flex justify-content-between mb-4 mt-2" role="alert">
{{ "delegates.disabled.text"|trans }}<a href="{{ path('calendar_delegation_toggle', {id: calendar.id, toggle: 'on'})}}" class="btn btn-sm my-auto btn-warning">{{ "delegates.enable"|trans }}</a>
{{ "delegates.disabled.text"|trans }}<a href="{{ path('user_delegation_toggle', {username: principal.username, toggle: 'on'})}}" class="btn btn-sm my-auto btn-warning">{{ "delegates.enable"|trans }}</a>
</div>
{% endif %}

Expand Down
Loading

0 comments on commit 076baef

Please sign in to comment.