Skip to content

Commit

Permalink
Remove restapi (#106)
Browse files Browse the repository at this point in the history
* Remove restapi

* Remove tzname treatment in frontend

* Fix traversal

* Fix pare redirection; Validate if date is valid

* Code review

* Add upgrade step to cook resources

* Fix tests

* Code review
  • Loading branch information
rodfersou authored and hvelarde committed Jun 18, 2018
1 parent 722dd68 commit 2ca89cd
Show file tree
Hide file tree
Showing 15 changed files with 125 additions and 115 deletions.
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Changelog
Esta versão também remove a dependência no collective.portlet.calendar.
Remova manualmente todos os portlets de calendario estendido e desinstale o pacote antes de atualizar.

- Corrige funcionamento da view padrão do tipo de conteúdo ``AgendaDiaria`` para evitar `problemas com proxies intermediárias <https://community.plone.org/t/6658>`_.
[rodfersou]

- Remove dependência no collective.portlet.calendar;
o layout do IDG 2.x não faz uso de portlets.
[hvelarde]
Expand Down
1 change: 1 addition & 0 deletions buildout.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ extends =
package-name = brasil.gov.agenda
package-extras = [test]
eggs +=
cssselect # XXX: needed by plone.protect
z3c.unconfigure

parts +=
Expand Down
1 change: 0 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
'plone.indexer',
'plone.memoize',
'plone.portlets',
'plone.restapi',
'plone.supermodel',
'plone.uuid',
'Products.ATContentTypes',
Expand Down
1 change: 1 addition & 0 deletions src/brasil/gov/agenda/browser/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from brasil.gov.agenda.browser.agenda import AgendaJSONView # noqa: F401
from brasil.gov.agenda.browser.agenda import AgendaView # noqa: F401
from brasil.gov.agenda.browser.agendadiaria import AgendaDiariaView # noqa: E501,F401
from brasil.gov.agenda.browser.compromisso import CompromissoView # noqa: E501,F401
Expand Down
84 changes: 79 additions & 5 deletions src/brasil/gov/agenda/browser/agenda.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
# -*- coding: utf-8 -*-
from six.moves import range # noqa: I001
from brasil.gov.agenda import _
from brasil.gov.agenda.config import AGENDADIARIAFMT
from brasil.gov.agenda.interfaces import ICompromisso
from brasil.gov.agenda.utils import AgendaMixin
from datetime import datetime
from datetime import timedelta
from DateTime import DateTime
from Products.CMFCore.utils import getToolByName
from dateutil.tz import tzlocal
from plone import api
from Products.Five.browser import BrowserView
from zExceptions import NotFound
from zope.component import getMultiAdapter
from zope.i18nmessageid import Message
from zope.interface import implementer
from zope.publisher.interfaces import IPublishTraverse
from zope.publisher.publish import mapply

import json


class AgendaView(BrowserView, AgendaMixin):
"""Visao padrao da agenda."""
Expand All @@ -18,7 +28,7 @@ def update(self):
name='plone_tools')
context_state = getMultiAdapter((self.context, self.request),
name=u'plone_context_state')
self._ts = getToolByName(self.context, 'translation_service')
self._ts = api.portal.get_tool('translation_service')
self.catalog = plone_tools.catalog()
self.agenda = self.context
self.workflow = plone_tools.workflow()
Expand All @@ -29,9 +39,9 @@ def __call__(self):
# return super(AgendaView, self).__call__()
agenda_recente = self.agenda_recente()
if agenda_recente and not self.editable:
return agenda_recente.restrictedTraverse('@@view')()
else:
return super(AgendaView, self).__call__()
response = self.request.response
response.redirect(agenda_recente.absolute_url())
return super(AgendaView, self).__call__()

def agenda_recente(self):
"""Deve retornar a agendadiaria para o dia atual
Expand Down Expand Up @@ -91,3 +101,67 @@ def imagem(self):
scale = view.scale(fieldname='image', scale='large')
tag = scale.tag()
return tag


@implementer(IPublishTraverse)
class AgendaJSONView(BrowserView, AgendaMixin):
"""JSON view."""

def publishTraverse(self, request, date):
"""Get the selected date."""
try:
datetime.strptime(date, AGENDADIARIAFMT)
except ValueError: # invalid date format
raise NotFound

self.date = date
return self

def weekday(self, date):
ts = api.portal.get_tool('translation_service')
return self._translate(ts.day_msgid(date.strftime('%w')))

def extract_data(self):
data = []
now = datetime.now()
tzname = datetime.now(tzlocal()).tzname()
selected = datetime.strptime(self.date, AGENDADIARIAFMT)
days = [selected + timedelta(days=i) for i in range(-3, 4)]
for date in days:
strday = date.strftime(AGENDADIARIAFMT)
day = {
'datetime': '{0}{1}:00'.format(date.isoformat(), tzname),
'day': date.day,
'weekday': self.weekday(date)[:3],
'items': [],
'hasAppointment': False,
'isSelected': False,
}
if self.date == strday:
day['isSelected'] = True
agendadiaria = self.context.get(strday, None)
if agendadiaria:
day['hasAppointment'] = True
compromissos = api.content.find(
context=agendadiaria,
object_provides=ICompromisso,
sort_on='start',
)
for brain in compromissos:
obj = brain.getObject()
day['items'].append({
'title': obj.title,
'start': obj.start_date.strftime('%Hh%M'),
'datetime': '{0}{1}:00'.format(obj.start_date.isoformat(), tzname),
'location': obj.location,
'href': obj.absolute_url(),
'vcal': '{0}/vcal_view'.format(obj.absolute_url()),
'isNow': obj.start_date <= now <= obj.end_date,
})
data.append(day)
return data

def __call__(self):
response = self.request.response
response.setHeader('content-type', 'application/json')
return response.setBody(json.dumps(self.extract_data()))
8 changes: 8 additions & 0 deletions src/brasil/gov/agenda/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@
template="templates/agendaview.pt"
/>

<browser:page
for="brasil.gov.agenda.interfaces.IAgenda"
name="json"
class="brasil.gov.agenda.browser.AgendaJSONView"
permission="zope2.View"
layer="brasil.gov.agenda.interfaces.IBrowserLayer"
/>

<browser:page
for="brasil.gov.agenda.interfaces.IAgendaDiaria"
name="view"
Expand Down
3 changes: 1 addition & 2 deletions src/brasil/gov/agenda/browser/templates/agendadiariaview.pt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
</metal:slot>
<metal:block fill-slot="content-core">
<div class="dados-agenda"
tal:attributes="data-url view/agenda/absolute_url;
data-tzname view/tzname">
tal:attributes="data-url view/agenda/absolute_url">
<div class="search-compromisso">
<form class="search-form"
tal:attributes="action string:${portal_url}/@@search">
Expand Down
1 change: 0 additions & 1 deletion src/brasil/gov/agenda/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<include package="plone.app.contenttypes" />
<include package="plone.app.versioningbehavior" />
<include package="plone.app.referenceablebehavior" />
<include package="plone.restapi" />

<!-- Adiciona permissoes -->
<include file="permissions.zcml" />
Expand Down
13 changes: 3 additions & 10 deletions src/brasil/gov/agenda/content/agendadiaria.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,9 @@ def Title(self):
fmt_date = date.strftime('%d/%m/%Y')
autoridade = self.autoridade
mapping = {'autoridade': autoridade, 'fmt_date': fmt_date}
if type(self.REQUEST) is str:
# this happens with plone.restapi, we lose reference of REQUEST object when
# it adapts to plone.app.contentlisting so there is no way to do get portal_state
# https://github.com/plone/plone.restapi/blob/master/src/plone/restapi/serializer/summary.py#L25
# https://github.com/plone/plone.app.contentlisting/blob/1.0.5/plone/app/contentlisting/realobject.py#L38
current_language = 'pt-br'
else:
portal_state = getMultiAdapter((self, self.REQUEST),
name=u'plone_portal_state')
current_language = portal_state.language()
portal_state = getMultiAdapter((self, self.REQUEST),
name=u'plone_portal_state')
current_language = portal_state.language()
tool = api.portal.get_tool('translation_service')
# FIXME: Ao trocar a língua de um portal, o título de uma agenda não
# será alterado no folder_contents. Como a recomendação atual de sites
Expand Down
1 change: 0 additions & 1 deletion src/brasil/gov/agenda/profiles/default/metadata.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
<dependency>profile-collective.cover:default</dependency>
<dependency>profile-plone.app.dexterity:default</dependency>
<dependency>profile-plone.app.versioningbehavior:default</dependency>
<dependency>profile-plone.restapi:default</dependency>
</dependencies>
</metadata>
3 changes: 1 addition & 2 deletions src/brasil/gov/agenda/tiles/agenda.pt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
<div class="agenda-tile tile-content"
tal:attributes="id string:agenda-$tile_id;
class python: 'agenda-tile tile-content' + (' has-image' if view.has_image else '');
data-url view/agenda_url;
data-tzname view/tzname">
data-url view/agenda_url">
tal:condition="not:is_empty">
<tal:image condition="view/has_image">
<img class="agenda-image"
Expand Down
5 changes: 0 additions & 5 deletions src/brasil/gov/agenda/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
from datetime import date
from datetime import datetime
from datetime import timedelta
from dateutil.tz import tzlocal
from Products.CMFCore.utils import getToolByName
from zope.component import getMultiAdapter
from zope.i18nmessageid import MessageFactory
Expand Down Expand Up @@ -103,7 +102,3 @@ def days(self):
'cssclass': ' '.join(cssclass),
})
return weekdays

@property
def tzname(self):
return datetime.now(tzlocal()).tzname()
38 changes: 8 additions & 30 deletions webpack/app/js/agenda.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export default class AgendaView {
this.container = container;
this.datepicker = new DatePicker(container, this.onDateChange.bind(this), true);
this.$appointments = this.$('.list-compromissos');
this.tzname = container.dataset.tzname;
}
$(selector) {
return $(selector, this.container.parentElement);
Expand All @@ -21,58 +20,37 @@ export default class AgendaView {
}
onDateChange(agendaDiaria) {
this.$appointments.html('');
if (typeof agendaDiaria.items === 'undefined') {
if (agendaDiaria.hasAppointments === false) {
this.$appointments.append(`
<li class="sem-compromisso item-compromisso">
<span>Atualmente não existem compromissos agendados.</span>
</li>
`);
return;
}
this.compromissos = [];
for (let item of agendaDiaria.items) {
$.ajax({
headers: {
Accept: 'application/json'
},
url: item['@id'],
global: false,
async: false,
context: this,
}).done((compromisso) => {
this.compromissos.push(compromisso);
});
}
this.compromissos.sort((a, b) => {
return new Date(a.start_date) - new Date(b.start_date);
});
for (let compromisso of this.compromissos) {
for (let compromisso of agendaDiaria.items) {
let $item = $(`
<li class="item-compromisso-wrapper">
<div class="item-compromisso">
<div class="compromisso-horarios">
<time class="horario compromisso-inicio"
datetime="${compromisso.start_date}">
${this.extractTime(compromisso.start_date)}
datetime="${compromisso.datetime}">
${compromisso.start}
</time>
</div>
<div class="compromisso-dados">
<h4 class="compromisso-titulo">${compromisso.title}</h4>` +
(compromisso.location == null? '' : `<p class="compromisso-local">${compromisso.location}</p>`) +
(compromisso.location == null? '': `<p class="compromisso-local">${compromisso.location}</p>`) +
`<span class="download-compromisso">
<a class="add-agenda vcal" href="${compromisso['@id']}/vcal_view">VCAL</a>
<a class="add-agenda vcal" href="${compromisso.vcal}">VCAL</a>
<span>Adicionar ao meu calendário</span>
</span>
</div>
</div>
</li>
`);
let now = new Date();
let start_date = new Date(`${compromisso.start_date}${this.tzname}:00`);
let end_date = new Date(`${compromisso.end_date}${this.tzname}:00`);
// Javascript getTime method return timestamp
if (now.getTime() > start_date.getTime() && now.getTime() < end_date.getTime()) {
$('.compromisso-horarios', $item).append('<div class="now">Agora</div>')
if (compromisso.isNow) {
$('.compromisso-horarios', $item).append('<div class="now">Agora</div>');
}
this.$appointments.append($item);
}
Expand Down
46 changes: 15 additions & 31 deletions webpack/app/js/datepicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ export default class DatePicker {
}
update() {
this.updateMonthPicker();
this.updateDayPicker();
let agendaDiariaURL = `${this.year}-${zfill(this.month + 1)}-${zfill(this.day)}`;
if (typeof this.callback === 'function') {
$.ajax({
headers: {
Accept: 'application/json'
},
url: `${this.agendaURL}/json/${agendaDiariaURL}`,
context: this,
global: false,
url: `${this.agendaURL}/${agendaDiariaURL}`,
}).always(this.callback);
}).always(function(data) {
this.callback(data[3]);
this.updateDayPicker(data);
});
}
if (this.updateTitle) {
let agendaDiaria = `${zfill(this.day)}/${zfill(this.month + 1)}/${this.year}`;
Expand Down Expand Up @@ -75,38 +75,22 @@ export default class DatePicker {
this.$year.html(this.year);
}
}
updateDayPicker() {
let dayNamesShort = this.$currentPicker.datepicker('option', 'dayNamesShort');
// get a list with 3 days before and 3 days after current day
let days = range(-3, 4).map(i => new Date(this.year, this.month, this.day + i))
updateDayPicker(data) {
this.$day.html('');
for (let day of days) {
for (let day of data) {
let cssclass = ['day'];
if (day.getFullYear() === this.year &&
day.getMonth() === this.month &&
day.getDate() === this.day) {
if (day.isSelected) {
cssclass.push('is-selected');
}

let $day = $(`
<li data-day="${day.toISOString()}" class="${cssclass.join(' ')}">
<div class="daypicker-day">${day.getDate()}</div>
<div class="daypicker-weekday">${dayNamesShort[day.getDay()]}</div>
<li data-day="${day.datetime}" class="${cssclass.join(' ')}">
<div class="daypicker-day">${day.day}</div>
<div class="daypicker-weekday">${day.weekday}</div>
</li>
`);

let agendaDiaria = `${day.getFullYear()}-${zfill(day.getMonth() + 1)}-${zfill(day.getDate())}`;
$.ajax({
headers: {
Accept: 'application/json'
},
url: `${this.agendaURL}/${agendaDiaria}`,
global: false,
context: $day,
}).done(function(result) {
this.addClass('has-appointment');
});

if (day.hasAppointment) {
$day.addClass('has-appointment');
}
this.$day.append($day);
}
// rfs
Expand Down
Loading

0 comments on commit 2ca89cd

Please sign in to comment.