diff --git a/src/brasil/gov/agenda/browser/configure.zcml b/src/brasil/gov/agenda/browser/configure.zcml
index 8e0386b..bac0b16 100644
--- a/src/brasil/gov/agenda/browser/configure.zcml
+++ b/src/brasil/gov/agenda/browser/configure.zcml
@@ -62,6 +62,22 @@
layer="brasil.gov.agenda.interfaces.IBrowserLayer"
/>
+
+
+
+
final_date:
+ msg = _(u'Final date less than initial date')
+ raise WidgetActionExecutionError('final_date', Invalid(msg))
+ else:
+ next_year = initial_date + relativedelta(years=1)
+ if final_date > next_year:
+ msg = _(u'Final date greater than 1 year after the initial date')
+ raise WidgetActionExecutionError('final_date', Invalid(msg))
+
+ @button.buttonAndHandler(_(u'Export'), name='export')
+ def handleExport(self, action): # @UnusedVariable
+ data, errors = self.extractData()
+ initial_date = data.get('initial_date', None)
+ final_date = data.get('final_date', None)
+ self.valid_dates(initial_date, final_date)
+ if errors:
+ self.status = self.formErrorsMessage
+ return
+
+ review_state = data['review_state']
+ context_url = self.context.absolute_url()
+ state_url = ''
+ for state in review_state:
+ state_url += '&review_state={0}'.format(state.encode('utf-8'))
+ self.request.RESPONSE.redirect(
+ '{0}/export_agenda_file?initial_date={1}&final_date={2}{3}'.format(
+ context_url, initial_date, final_date, state_url),
+ )
+
+
+class ExportAgendaFormWrapper(FormWrapper):
+ """View do formulário de exportação de Agenda."""
+ form = ExportAgendaForm
+ label = _(u'Export Schedule')
diff --git a/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot b/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot
index 9eabb98..14a1d6a 100644
--- a/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot
+++ b/src/brasil/gov/agenda/locales/brasil.gov.agenda.pot
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2019-04-03 13:15+0000\n"
+"POT-Creation-Date: 2020-03-12 16:11+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -22,7 +22,7 @@ msgstr ""
msgid ".gov.br: Remoção do suporte a Agenda"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90
#: brasil/gov/agenda/browser/templates/compromissoview.pt:81
msgid "Adicionar ao meu calendario"
msgstr ""
@@ -53,14 +53,30 @@ msgstr ""
msgid "Agenda do {0}"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57
msgid "Agora"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:33
+msgid "Appointment"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:38
+msgid "Appointment Agenda"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:34
+msgid "Appointment Location"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Atualizacao"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:30
+msgid "Authority Name"
+msgstr ""
+
#: brasil/gov/agenda/behaviors/configure.zcml:15
msgid "Automatically generate short URL name for content based on a date field"
msgstr ""
@@ -87,10 +103,18 @@ msgstr ""
msgid "Compromissos do dia"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:31
+msgid "Daily Schedule Date"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Data da Agenda"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:29
+msgid "Department Name"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao."
msgstr ""
@@ -99,14 +123,43 @@ msgstr ""
msgid "Detalhe do compromisso"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96
msgid "Editar"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:36
+msgid "End Time"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:232
+msgid "Export"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:256
+#: brasil/gov/agenda/profiles/default/actions.xml
+msgid "Export Schedule"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:206
+msgid "Final Date"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:229
+msgid "Final date greater than 1 year after the initial date"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:224
+msgid "Final date less than initial date"
+msgstr ""
+
#: brasil/gov/agenda/profiles.zcml:17
msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:32
+msgid "General information"
+msgstr ""
+
#: brasil/gov/agenda/tiles/agenda.py:27
msgid "Image"
msgstr ""
@@ -123,6 +176,10 @@ msgstr ""
msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:203
+msgid "Initial Date"
+msgstr ""
+
#: brasil/gov/agenda/content/agendadiaria.py:111
msgid "Ja existe uma agenda para esta data"
msgstr ""
@@ -157,16 +214,20 @@ msgstr ""
msgid "Orgao"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:37
+msgid "Other attendees"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Outros participantes deste compromisso, um por linha."
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73
#: brasil/gov/agenda/browser/templates/compromissoview.pt:64
msgid "Participante(s)"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78
#: brasil/gov/agenda/browser/templates/compromissoview.pt:70
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Pauta"
@@ -176,7 +237,7 @@ msgstr ""
msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101
msgid "Remover"
msgstr ""
@@ -184,6 +245,14 @@ msgstr ""
msgid "Rodapé da Agenda"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:28
+msgid "Schedule Description"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:27
+msgid "Schedule Title"
+msgstr ""
+
#: brasil/gov/agenda/tiles/agenda.py:50
msgid "Seletor Dia"
msgstr ""
@@ -196,7 +265,7 @@ msgstr ""
msgid "Sem compromissos oficiais."
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68
#: brasil/gov/agenda/browser/templates/compromissoview.pt:59
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Solicitante"
@@ -206,6 +275,14 @@ msgstr ""
msgid "Solicitante da Reuniao e o Orgao ou entidade que representa."
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:35
+msgid "Start Time"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:209
+msgid "State"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/Agenda.xml
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Tags são utilizadas para organização de conteúdo"
@@ -223,7 +300,7 @@ msgstr ""
msgid "Title"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87
#: brasil/gov/agenda/browser/templates/compromissoview.pt:79
msgid "VCAL"
msgstr ""
@@ -259,7 +336,7 @@ msgid "label_event_start"
msgstr ""
#. Default: "Atualmente não existem compromissos agendados."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110
msgid "label_no_appointments"
msgstr ""
@@ -267,3 +344,11 @@ msgstr ""
#: brasil/gov/agenda/browser/compromisso.py:64
msgid "long_date_agenda"
msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:45
+msgid "private"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:49
+msgid "published"
+msgstr ""
diff --git a/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po b/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po
index 59d108b..4adb01e 100644
--- a/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po
+++ b/src/brasil/gov/agenda/locales/en/LC_MESSAGES/brasil.gov.agenda.po
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: brasil.gov.agenda\n"
-"POT-Creation-Date: 2019-04-03 13:15+0000\n"
+"POT-Creation-Date: 2020-03-12 16:11+0000\n"
"PO-Revision-Date: 2012-09-18 23:00+0000\n"
"Last-Translator: PloneGov.Br \n"
"Language-Team: PloneGov.Br \n"
@@ -22,7 +22,7 @@ msgstr ""
msgid ".gov.br: Remoção do suporte a Agenda"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90
#: brasil/gov/agenda/browser/templates/compromissoview.pt:81
msgid "Adicionar ao meu calendario"
msgstr "Add to my calendar"
@@ -53,14 +53,30 @@ msgstr "Brazilian government official's schedule"
msgid "Agenda do {0}"
msgstr "{0}'s Schedule"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57
msgid "Agora"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:33
+msgid "Appointment"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:38
+msgid "Appointment Agenda"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:34
+msgid "Appointment Location"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Atualizacao"
msgstr "Update"
+#: brasil/gov/agenda/browser/export_agenda.py:30
+msgid "Authority Name"
+msgstr ""
+
#: brasil/gov/agenda/behaviors/configure.zcml:15
msgid "Automatically generate short URL name for content based on a date field"
msgstr ""
@@ -87,10 +103,18 @@ msgstr "Appointments"
msgid "Compromissos do dia"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:31
+msgid "Daily Schedule Date"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Data da Agenda"
msgstr "Date of Schedule"
+#: brasil/gov/agenda/browser/export_agenda.py:29
+msgid "Department Name"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao."
msgstr "Describe here if this schedule has been updated. Leave this field blank if not there is no updating."
@@ -99,14 +123,43 @@ msgstr "Describe here if this schedule has been updated. Leave this field blank
msgid "Detalhe do compromisso"
msgstr "Appointment's details"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96
msgid "Editar"
msgstr "Edit"
+#: brasil/gov/agenda/browser/export_agenda.py:36
+msgid "End Time"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:232
+msgid "Export"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:256
+#: brasil/gov/agenda/profiles/default/actions.xml
+msgid "Export Schedule"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:206
+msgid "Final Date"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:229
+msgid "Final date greater than 1 year after the initial date"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:224
+msgid "Final date less than initial date"
+msgstr ""
+
#: brasil/gov/agenda/profiles.zcml:17
msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr ""
+#: brasil/gov/agenda/browser/export_agenda.py:32
+msgid "General information"
+msgstr ""
+
#: brasil/gov/agenda/tiles/agenda.py:27
msgid "Image"
msgstr ""
@@ -123,6 +176,10 @@ msgstr "Info"
msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica"
msgstr "Tell which department this schedule belongs. ex: The Presidency of The Republic"
+#: brasil/gov/agenda/browser/export_agenda.py:203
+msgid "Initial Date"
+msgstr ""
+
#: brasil/gov/agenda/content/agendadiaria.py:111
msgid "Ja existe uma agenda para esta data"
msgstr "There's already an schedule for this date."
@@ -157,16 +214,20 @@ msgstr "Authority's name"
msgid "Orgao"
msgstr "Department"
+#: brasil/gov/agenda/browser/export_agenda.py:37
+msgid "Other attendees"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Outros participantes deste compromisso, um por linha."
msgstr "Other attendees in this appointment, one per line."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73
#: brasil/gov/agenda/browser/templates/compromissoview.pt:64
msgid "Participante(s)"
msgstr "Participants"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78
#: brasil/gov/agenda/browser/templates/compromissoview.pt:70
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Pauta"
@@ -176,7 +237,7 @@ msgstr "Agenda"
msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101
msgid "Remover"
msgstr "Remove"
@@ -184,6 +245,14 @@ msgstr "Remove"
msgid "Rodapé da Agenda"
msgstr "Schedule's footer"
+#: brasil/gov/agenda/browser/export_agenda.py:28
+msgid "Schedule Description"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:27
+msgid "Schedule Title"
+msgstr ""
+
#: brasil/gov/agenda/tiles/agenda.py:50
msgid "Seletor Dia"
msgstr ""
@@ -196,7 +265,7 @@ msgstr ""
msgid "Sem compromissos oficiais."
msgstr ""
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68
#: brasil/gov/agenda/browser/templates/compromissoview.pt:59
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Solicitante"
@@ -206,6 +275,14 @@ msgstr "Requester"
msgid "Solicitante da Reuniao e o Orgao ou entidade que representa."
msgstr "Requester of the Meeting and the Organ or entity it represents."
+#: brasil/gov/agenda/browser/export_agenda.py:35
+msgid "Start Time"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:209
+msgid "State"
+msgstr ""
+
#: brasil/gov/agenda/content/schema/Agenda.xml
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Tags são utilizadas para organização de conteúdo"
@@ -223,7 +300,7 @@ msgstr ""
msgid "Title"
msgstr "Title"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87
#: brasil/gov/agenda/browser/templates/compromissoview.pt:79
msgid "VCAL"
msgstr "VCAL"
@@ -259,7 +336,7 @@ msgid "label_event_start"
msgstr "Event Starts"
#. Default: "Atualmente não existem compromissos agendados."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110
msgid "label_no_appointments"
msgstr ""
@@ -267,3 +344,11 @@ msgstr ""
#: brasil/gov/agenda/browser/compromisso.py:64
msgid "long_date_agenda"
msgstr "${day} ${month} ${year}"
+
+#: brasil/gov/agenda/browser/export_agenda.py:45
+msgid "private"
+msgstr ""
+
+#: brasil/gov/agenda/browser/export_agenda.py:49
+msgid "published"
+msgstr ""
diff --git a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po
index 1c87f53..f6dc4cb 100644
--- a/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po
+++ b/src/brasil/gov/agenda/locales/pt_BR/LC_MESSAGES/brasil.gov.agenda.po
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: brasil.gov.agenda\n"
-"POT-Creation-Date: 2019-04-03 13:15+0000\n"
+"POT-Creation-Date: 2020-03-12 16:11+0000\n"
"PO-Revision-Date: 2018-09-25 11:03-0300\n"
"Last-Translator: PloneGov.Br \n"
"Language-Team: PloneGov.Br \n"
@@ -24,7 +24,7 @@ msgstr ".gov.br: Agenda de Membros do Governo Brasileiro"
msgid ".gov.br: Remoção do suporte a Agenda"
msgstr ".gov.br: Remoção do suporte a Agenda"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:89
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:90
#: brasil/gov/agenda/browser/templates/compromissoview.pt:81
msgid "Adicionar ao meu calendario"
msgstr "Adicionar ao meu calendário"
@@ -55,14 +55,30 @@ msgstr "Agenda de um membro do Governo Brasileiro"
msgid "Agenda do {0}"
msgstr "Agenda do {0}"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:56
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:57
msgid "Agora"
msgstr "Agora"
+#: brasil/gov/agenda/browser/export_agenda.py:33
+msgid "Appointment"
+msgstr "Compromisso"
+
+#: brasil/gov/agenda/browser/export_agenda.py:38
+msgid "Appointment Agenda"
+msgstr "Pauta"
+
+#: brasil/gov/agenda/browser/export_agenda.py:34
+msgid "Appointment Location"
+msgstr "Local do Compromisso"
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Atualizacao"
msgstr "Atualização"
+#: brasil/gov/agenda/browser/export_agenda.py:30
+msgid "Authority Name"
+msgstr "Nome da Autoridade"
+
#: brasil/gov/agenda/behaviors/configure.zcml:15
msgid "Automatically generate short URL name for content based on a date field"
msgstr "Gera automaticamente um ID a partir de um campo de data."
@@ -89,10 +105,18 @@ msgstr "Compromissos"
msgid "Compromissos do dia"
msgstr "Compromissos do dia"
+#: brasil/gov/agenda/browser/export_agenda.py:31
+msgid "Daily Schedule Date"
+msgstr "Data da Agenda Diária"
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Data da Agenda"
msgstr "Data desta Agenda"
+#: brasil/gov/agenda/browser/export_agenda.py:29
+msgid "Department Name"
+msgstr "Nome do Órgão"
+
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se nao houver nenhuma atualizacao."
msgstr "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco se não houver nenhuma atualização."
@@ -101,14 +125,43 @@ msgstr "Descreva aqui se esta agenda foi atualizada. Deixe este campo em branco
msgid "Detalhe do compromisso"
msgstr "Detalhe do compromisso"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:95
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:96
msgid "Editar"
msgstr "Editar"
+#: brasil/gov/agenda/browser/export_agenda.py:36
+msgid "End Time"
+msgstr "Horário de Término"
+
+#: brasil/gov/agenda/browser/export_agenda.py:232
+msgid "Export"
+msgstr "Exportar"
+
+#: brasil/gov/agenda/browser/export_agenda.py:256
+#: brasil/gov/agenda/profiles/default/actions.xml
+msgid "Export Schedule"
+msgstr "Exportar Agenda"
+
+#: brasil/gov/agenda/browser/export_agenda.py:206
+msgid "Final Date"
+msgstr "Data Final"
+
+#: brasil/gov/agenda/browser/export_agenda.py:229
+msgid "Final date greater than 1 year after the initial date"
+msgstr "Data final maior que 1 ano após a data inicial"
+
+#: brasil/gov/agenda/browser/export_agenda.py:224
+msgid "Final date less than initial date"
+msgstr "Data final deve ser maior que a data inicial"
+
#: brasil/gov/agenda/profiles.zcml:17
msgid "Fornece suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr "Fornece suporte de agenda de compromissos dentro de um Portal Padrão"
+#: brasil/gov/agenda/browser/export_agenda.py:32
+msgid "General information"
+msgstr "Informações Gerais"
+
#: brasil/gov/agenda/tiles/agenda.py:27
msgid "Image"
msgstr "Imagem"
@@ -125,6 +178,10 @@ msgstr "Info"
msgid "Informe o orgao ao qual esta agenda pertence. ex: Presidencia da Republica"
msgstr "Informe o órgão ao qual esta agenda pertence. ex: Presidência da República"
+#: brasil/gov/agenda/browser/export_agenda.py:203
+msgid "Initial Date"
+msgstr "Data Inicial"
+
#: brasil/gov/agenda/content/agendadiaria.py:111
msgid "Ja existe uma agenda para esta data"
msgstr "Já existe uma agenda para esta data."
@@ -159,16 +216,20 @@ msgstr "Nome da autoridade"
msgid "Orgao"
msgstr "Órgão"
+#: brasil/gov/agenda/browser/export_agenda.py:37
+msgid "Other attendees"
+msgstr "Outros Participantes"
+
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Outros participantes deste compromisso, um por linha."
msgstr "Outros participantes deste compromisso, um por linha."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:72
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:73
#: brasil/gov/agenda/browser/templates/compromissoview.pt:64
msgid "Participante(s)"
msgstr "Participante(s)"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:77
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:78
#: brasil/gov/agenda/browser/templates/compromissoview.pt:70
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Pauta"
@@ -178,7 +239,7 @@ msgstr "Pauta"
msgid "Remove suporte de agenda de compromissos dentro de um Portal Padrão"
msgstr "Remove suporte de agenda de compromissos dentro de um Portal Padrão"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:100
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:101
msgid "Remover"
msgstr "Remover"
@@ -186,6 +247,14 @@ msgstr "Remover"
msgid "Rodapé da Agenda"
msgstr "Rodapé da Agenda"
+#: brasil/gov/agenda/browser/export_agenda.py:28
+msgid "Schedule Description"
+msgstr "Descrição da Agenda"
+
+#: brasil/gov/agenda/browser/export_agenda.py:27
+msgid "Schedule Title"
+msgstr "Título da Agenda"
+
#: brasil/gov/agenda/tiles/agenda.py:50
msgid "Seletor Dia"
msgstr "Seletor dia"
@@ -198,7 +267,7 @@ msgstr "Seletor mês"
msgid "Sem compromissos oficiais."
msgstr "Sem compromissos oficiais."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:67
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:68
#: brasil/gov/agenda/browser/templates/compromissoview.pt:59
#: brasil/gov/agenda/content/schema/Compromisso.xml
msgid "Solicitante"
@@ -208,6 +277,14 @@ msgstr "Solicitante"
msgid "Solicitante da Reuniao e o Orgao ou entidade que representa."
msgstr "Solicitante da Reunião e o Órgão ou entidade que representa."
+#: brasil/gov/agenda/browser/export_agenda.py:35
+msgid "Start Time"
+msgstr "Horário de Inicio"
+
+#: brasil/gov/agenda/browser/export_agenda.py:209
+msgid "State"
+msgstr "Estado"
+
#: brasil/gov/agenda/content/schema/Agenda.xml
#: brasil/gov/agenda/content/schema/AgendaDiaria.xml
msgid "Tags são utilizadas para organização de conteúdo"
@@ -225,7 +302,7 @@ msgstr "Tile que exibe uma agenda"
msgid "Title"
msgstr "Título"
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:86
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:87
#: brasil/gov/agenda/browser/templates/compromissoview.pt:79
msgid "VCAL"
msgstr "VCAL"
@@ -261,7 +338,7 @@ msgid "label_event_start"
msgstr "Data e hora de início"
#. Default: "Atualmente não existem compromissos agendados."
-#: brasil/gov/agenda/browser/templates/agenda_macros.pt:109
+#: brasil/gov/agenda/browser/templates/agenda_macros.pt:110
msgid "label_no_appointments"
msgstr "Atualmente não existem compromissos agendados."
@@ -269,3 +346,11 @@ msgstr "Atualmente não existem compromissos agendados."
#: brasil/gov/agenda/browser/compromisso.py:64
msgid "long_date_agenda"
msgstr "${day} de ${month} de ${year}"
+
+#: brasil/gov/agenda/browser/export_agenda.py:45
+msgid "private"
+msgstr "privado"
+
+#: brasil/gov/agenda/browser/export_agenda.py:49
+msgid "published"
+msgstr "publicado"
diff --git a/src/brasil/gov/agenda/permissions.zcml b/src/brasil/gov/agenda/permissions.zcml
index ff6ac58..9178235 100644
--- a/src/brasil/gov/agenda/permissions.zcml
+++ b/src/brasil/gov/agenda/permissions.zcml
@@ -17,4 +17,9 @@
title="brasil.gov.agenda: Add Compromisso"
/>
+
+
diff --git a/src/brasil/gov/agenda/profiles/default/actions.xml b/src/brasil/gov/agenda/profiles/default/actions.xml
new file mode 100644
index 0000000..b18ca70
--- /dev/null
+++ b/src/brasil/gov/agenda/profiles/default/actions.xml
@@ -0,0 +1,20 @@
+
+
\ No newline at end of file
diff --git a/src/brasil/gov/agenda/profiles/default/metadata.xml b/src/brasil/gov/agenda/profiles/default/metadata.xml
index 9e26bda..e747933 100644
--- a/src/brasil/gov/agenda/profiles/default/metadata.xml
+++ b/src/brasil/gov/agenda/profiles/default/metadata.xml
@@ -1,6 +1,6 @@
- 4104
+ 4105
profile-collective.cover:default
profile-plone.app.dexterity:default
diff --git a/src/brasil/gov/agenda/profiles/default/rolemap.xml b/src/brasil/gov/agenda/profiles/default/rolemap.xml
index 9f3e568..e183fc9 100644
--- a/src/brasil/gov/agenda/profiles/default/rolemap.xml
+++ b/src/brasil/gov/agenda/profiles/default/rolemap.xml
@@ -19,5 +19,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/brasil/gov/agenda/setuphandlers.py b/src/brasil/gov/agenda/setuphandlers.py
index da4425b..98311c7 100644
--- a/src/brasil/gov/agenda/setuphandlers.py
+++ b/src/brasil/gov/agenda/setuphandlers.py
@@ -16,6 +16,7 @@ def getNonInstallableProducts():
u'brasil.gov.agenda.upgrades.v4101',
u'brasil.gov.agenda.upgrades.v4102',
u'brasil.gov.agenda.upgrades.v4104',
+ u'brasil.gov.agenda.upgrades.v4105',
# BBB: https://github.com/plonegovbr/brasil.gov.agenda/issues/137
u'collective.portlet.calendar',
]
@@ -44,6 +45,26 @@ def list_agendadiaria_calendar(p):
calendar.calendar_types = tuple(types)
+def setup_catalog(portal):
+ """ Cria indice e metadados no catalog.
+ Foi feito aqui em vez de em profiles/default/catalog.xml para que
+ não precise reindexar esses índices após cada reinstalação.
+ https://docs.plone.org/develop/plone/searching_and_indexing/indexing.html#adding-index-using-add-on-product-installer
+ """
+ catalog = api.portal.get_tool('portal_catalog')
+
+ if 'date' not in catalog.indexes():
+ catalog.addIndex('date', 'DateIndex')
+
+ metadatas = ['date', 'autoridade', 'attendees']
+
+ idsMetadatas = catalog.schema()
+
+ for metadata in metadatas:
+ if metadata not in idsMetadatas:
+ catalog.addColumn(metadata)
+
+
def setup_site(context):
""" Ajustamos o site para receber o produto de agenda
"""
@@ -52,3 +73,4 @@ def setup_site(context):
return
site = context.getSite()
list_agendadiaria_calendar(site)
+ setup_catalog(site)
diff --git a/src/brasil/gov/agenda/tests/test_export_agendas.py b/src/brasil/gov/agenda/tests/test_export_agendas.py
new file mode 100644
index 0000000..3e0ed14
--- /dev/null
+++ b/src/brasil/gov/agenda/tests/test_export_agendas.py
@@ -0,0 +1,220 @@
+# -*- coding: utf-8 -*-
+"""Testes da exportação de Agendas."""
+
+from brasil.gov.agenda.testing import INTEGRATION_TESTING
+from plone import api
+from plone.app.testing import setRoles
+from plone.app.testing import TEST_USER_ID
+from plone.app.textfield.value import RichTextValue
+
+import datetime
+import unittest
+
+
+class TestExportAgendaFile(unittest.TestCase):
+
+ layer = INTEGRATION_TESTING
+
+ def setUp(self):
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+ setRoles(self.portal, TEST_USER_ID, ['Site Administrator'])
+ ltool = api.portal.get_tool('portal_languages')
+ ltool.setLanguageBindings()
+ self.agenda = api.content.create(
+ self.portal,
+ 'Agenda',
+ 'agenda',
+ u'Agenda de Autoridade',
+ description=u'Agenda de José',
+ orgao=u'Órgão de José',
+ autoridade=u'José',
+ location=u'Local',
+ update=RichTextValue(u'Atualização',
+ 'text/html',
+ 'text/x-html-safe',
+ encoding='utf-8'),
+ )
+ agenda_diariaPublica = api.content.create(
+ self.agenda, 'AgendaDiaria', '2019-12-01')
+ api.content.transition(obj=agenda_diariaPublica, transition='publish')
+ agenda_diariaPrivada = api.content.create(
+ self.agenda, 'AgendaDiaria', '2019-12-25')
+ api.content.create(
+ agenda_diariaPublica,
+ 'Compromisso',
+ 'compromisso01',
+ u'Compromisso 01',
+ start_date=datetime.datetime(2019, 12, 1, 12, 0),
+ end_date=datetime.datetime(2019, 12, 1, 13, 0),
+ description=u'Pauta 01',
+ attendees=u'Maria',
+ )
+ api.content.create(
+ agenda_diariaPrivada,
+ 'Compromisso',
+ 'compromisso25',
+ u'Compromisso 25',
+ start_date=datetime.datetime(2019, 12, 25, 8, 0),
+ end_date=datetime.datetime(2019, 12, 25, 9, 0),
+ description=u'Pauta 25',
+ attendees=u'Marta',
+ )
+
+ def test_file_without_date_and_state(self):
+ """Testa o arquivo quando não são passadas datas e estado."""
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ self.assertFalse(view())
+
+ def test_get_compromissos_all(self):
+ """Testa get_compromissos retornando todos os Compromissos."""
+ self.request.set('initial_date', '2019-01-01')
+ self.request.set('final_date', '2019-12-25')
+ self.request.set('review_state', ['private', 'published'])
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ compormissos = view.get_compromissos()
+ self.assertEqual(len(compormissos), 2)
+
+ def test_get_compromissos_less(self):
+ """Testa get_compromissos retornando o menor Compromisso."""
+ self.request.set('initial_date', '2019-01-01')
+ self.request.set('final_date', '2019-12-01')
+ self.request.set('review_state', ['published'])
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ compormissos = view.get_compromissos()
+ self.assertEqual(len(compormissos), 1)
+ self.assertEqual(compormissos[0]['compromisso'], 'Compromisso 01')
+
+ def test_get_compromissos_more(self):
+ """Testa get_compromissos retornando o maior Compromisso."""
+ self.request.set('initial_date', '2019-12-25')
+ self.request.set('final_date', '2019-12-25')
+ self.request.set('review_state', ['private'])
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ compormissos = view.get_compromissos()
+ self.assertEqual(len(compormissos), 1)
+ self.assertEqual(compormissos[0]['compromisso'], 'Compromisso 25')
+
+ def test_write_csv(self):
+ """Testa a geração do arquivo csv."""
+ self.request.set('initial_date', '2019-01-01')
+ self.request.set('final_date', '2019-12-25')
+ self.request.set('review_state', ['private', 'published'])
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ csv = view.write_csv()
+ linha0 = '"Título da Agenda","Descrição da Agenda","Nome do Órgão","Nome da Autoridade",'
+ '"Data da Agenda Diária","Informações Gerais","Compromisso","Local do Compromisso",'
+ '"Horário de Inicio","Horário de Término","Outros Participantes,Pauta"'
+ linha1 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"'
+ '"01/12/2019","Atualização","Compromisso 01","Local"'
+ '"12:00","13:00","Maria","Pauta 01"'
+ linha2 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"'
+ '"25/12/2019","Atualização","Compromisso 25","Local"'
+ '"08:00","09:00","Marta","Pauta 25"'
+ self.assertIn(linha0, csv)
+ self.assertIn(linha1, csv)
+ self.assertIn(linha2, csv)
+
+ def test_export_agenda_file(self):
+ """Testa a view export_agenda_file."""
+ self.request.set('initial_date', '2019-01-01')
+ self.request.set('final_date', '2019-12-25')
+ self.request.set('review_state', ['private', 'published'])
+ view = api.content.get_view(
+ 'export_agenda_file', self.agenda, self.request)
+ render_view = view()
+ linha0 = '"Título da Agenda","Descrição da Agenda","Nome do Órgão","Nome da Autoridade",'
+ '"Data da Agenda Diária","Informações Gerais","Compromisso","Local do Compromisso",'
+ '"Horário de Inicio","Horário de Término","Outros Participantes,Pauta"'
+ linha1 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"'
+ '"01/12/2019","Atualização","Compromisso 01","Local"'
+ '"12:00","13:00","Maria","Pauta 01"'
+ linha2 = '"Agenda de Autoridade","Agenda de José","Órgão de José","José"'
+ '"25/12/2019","Atualização","Compromisso 25","Local"'
+ '"08:00","09:00","Marta","Pauta 25"'
+ self.assertIn(linha0, render_view)
+ self.assertIn(linha1, render_view)
+ self.assertIn(linha2, render_view)
+ headers = self.request.response.headers
+ self.assertEqual(headers['content-type'], 'text/csv')
+ self.assertEqual(
+ headers['content-disposition'], 'attachment; filename="agenda.csv"')
+
+
+class TestExportAgendaForm(unittest.TestCase):
+
+ layer = INTEGRATION_TESTING
+
+ def setUp(self):
+ self.portal = self.layer['portal']
+ self.request = self.layer['request']
+ setRoles(self.portal, TEST_USER_ID, ['Site Administrator'])
+ self.agenda = api.content.create(
+ self.portal,
+ 'Agenda',
+ 'agenda',
+ u'Agenda de Autoridade',
+ autoridade=u'José',
+ )
+ self.view = api.content.get_view(
+ 'export_agenda', self.agenda, self.request)
+
+ def test_fields_requires(self):
+ """Testa os campos requeridos do form."""
+ self.request.set('form.buttons.export', u'Export')
+ html = self.view()
+ self.assertIn('There were some errors', html)
+ num_requires = html.count('Required input is missing.')
+ self.assertEqual(num_requires, 3)
+
+ def test_final_greater_initial(self):
+ """Testa a validação da data final maior que a inicial."""
+ self.request.set('form.widgets.initial_date-day', u'29')
+ self.request.set('form.widgets.initial_date-month', u'12')
+ self.request.set('form.widgets.initial_date-year', u'2020')
+ self.request.set('form.widgets.final_date-day', u'01')
+ self.request.set('form.widgets.final_date-month', u'12')
+ self.request.set('form.widgets.final_date-year', u'2020')
+ self.request.set('form.widgets.review_state', u'private')
+ self.request.set('form.buttons.export', u'Export')
+ html = self.view()
+ self.assertIn('There were some errors', html)
+ self.assertIn('Final date less than initial date', html)
+
+ def test_final_greater_year(self):
+ """Testa a validação da data final maior que 1 ano da inicial."""
+ self.request.set('form.widgets.initial_date-day', u'01')
+ self.request.set('form.widgets.initial_date-month', u'12')
+ self.request.set('form.widgets.initial_date-year', u'2019')
+ self.request.set('form.widgets.final_date-day', u'02')
+ self.request.set('form.widgets.final_date-month', u'12')
+ self.request.set('form.widgets.final_date-year', u'2020')
+ self.request.set('form.widgets.review_state', u'private')
+ self.request.set('form.buttons.export', u'Export')
+ html = self.view()
+ self.assertIn('There were some errors', html)
+ self.assertIn('Final date greater than 1 year after the initial date', html)
+
+ def test_form_export_redirect(self):
+ """Testa o form redireciona para a view que gera o arquivo."""
+ self.request.set('form.widgets.initial_date-day', u'29')
+ self.request.set('form.widgets.initial_date-month', u'11')
+ self.request.set('form.widgets.initial_date-year', u'2019')
+ self.request.set('form.widgets.final_date-day', u'25')
+ self.request.set('form.widgets.final_date-month', u'12')
+ self.request.set('form.widgets.final_date-year', u'2019')
+ self.request.set('form.widgets.review_state', u'private')
+ self.request.set('form.buttons.export', u'Export')
+ self.view()
+ location = self.request.response.getHeader('location')
+ self.assertEqual(
+ 'http://nohost/plone/agenda/export_agenda_file?'
+ 'initial_date=2019-11-29&final_date=2019-12-25'
+ '&review_state=private',
+ location,
+ )
diff --git a/src/brasil/gov/agenda/tests/test_setup.py b/src/brasil/gov/agenda/tests/test_setup.py
index 53dc40f..517b891 100644
--- a/src/brasil/gov/agenda/tests/test_setup.py
+++ b/src/brasil/gov/agenda/tests/test_setup.py
@@ -40,7 +40,7 @@ def test_installed(self):
def test_version(self):
self.assertEqual(
- self.st.getLastVersionForProfile(self.profile), (u'4104',))
+ self.st.getLastVersionForProfile(self.profile), (u'4105',))
def test_agenda_not_searched(self):
pp = getattr(self.portal, 'portal_properties')
diff --git a/src/brasil/gov/agenda/tests/test_upgrades.py b/src/brasil/gov/agenda/tests/test_upgrades.py
index 9d8521a..b1b592d 100644
--- a/src/brasil/gov/agenda/tests/test_upgrades.py
+++ b/src/brasil/gov/agenda/tests/test_upgrades.py
@@ -163,3 +163,48 @@ def test_deprecate_resource_registries(self):
self.assertNotIn(js, js_tool.getResourceIds())
for css in STYLES:
self.assertNotIn(css, css_tool.getResourceIds())
+
+
+class to4105TestCase(UpgradeTestCaseBase):
+
+ def setUp(self):
+ UpgradeTestCaseBase.setUp(self, u'4104', u'4105')
+
+ def test_registrations(self):
+ version = self.setup.getLastVersionForProfile(self.profile_id)[0]
+ self.assertGreaterEqual(int(version), int(self.to_version))
+ self.assertEqual(self.total_steps, 3)
+
+ def test_add_export_agenda_action(self):
+ # check if the upgrade step is registered
+ title = u'Adiciona action Exportar Agenda'
+ step = self.get_upgrade_step(title)
+ self.assertIsNotNone(step)
+
+ portal_actions = api.content.portal.get_tool('portal_actions')
+ object_buttons = portal_actions.object_buttons
+ object_buttons.manage_delObjects(['export_agenda'])
+ action = object_buttons.listActions()[-1]
+ self.assertNotEqual(action.title, u'Export Schedule')
+
+ # Executa upgrade.
+ self.execute_upgrade_step(step)
+
+ action = object_buttons.listActions()[-1]
+ self.assertEqual(action.title, u'Export Schedule')
+
+ def test_permission(self):
+ permission = 'brasil.gov.agenda: Exportar Agenda'
+ roles = self.portal.rolesOfPermission(permission)
+ roles = [r['name'] for r in roles if r['selected']]
+ expected = ['Manager', 'Site Administrator']
+ self.assertListEqual(roles, expected)
+
+ def test_setup_catalog(self):
+ catalog = api.portal.get_tool('portal_catalog')
+ self.assertIn('date', catalog.indexes())
+
+ metadatas = ['date', 'autoridade', 'attendees']
+ idsMetadatas = catalog.schema()
+ for metadata in metadatas:
+ self.assertIn(metadata, idsMetadatas)
diff --git a/src/brasil/gov/agenda/upgrades/configure.zcml b/src/brasil/gov/agenda/upgrades/configure.zcml
index f673c33..fcac8dd 100644
--- a/src/brasil/gov/agenda/upgrades/configure.zcml
+++ b/src/brasil/gov/agenda/upgrades/configure.zcml
@@ -4,4 +4,5 @@
+
diff --git a/src/brasil/gov/agenda/upgrades/v4105/__init__.py b/src/brasil/gov/agenda/upgrades/v4105/__init__.py
new file mode 100644
index 0000000..40a96af
--- /dev/null
+++ b/src/brasil/gov/agenda/upgrades/v4105/__init__.py
@@ -0,0 +1 @@
+# -*- coding: utf-8 -*-
diff --git a/src/brasil/gov/agenda/upgrades/v4105/configure.zcml b/src/brasil/gov/agenda/upgrades/v4105/configure.zcml
new file mode 100644
index 0000000..608e2d5
--- /dev/null
+++ b/src/brasil/gov/agenda/upgrades/v4105/configure.zcml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/brasil/gov/agenda/upgrades/v4105/reindex.py b/src/brasil/gov/agenda/upgrades/v4105/reindex.py
new file mode 100644
index 0000000..ee50184
--- /dev/null
+++ b/src/brasil/gov/agenda/upgrades/v4105/reindex.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+from brasil.gov.agenda.setuphandlers import setup_catalog
+from plone import api
+
+import transaction
+
+
+def reindex_catalog(context):
+ """ Cria e reindexa o indice date e os metadados autoridade, update e attendees
+ Segue orientação:
+ https://community.plone.org/t/best-practices-on-reindexing-the-catalog/4157/14
+ """
+ setup_catalog(context)
+ catalog = api.portal.get_tool('portal_catalog')
+
+ # Agendas diárias
+ n = 0
+ agendas = catalog(portal_type='AgendaDiaria')
+ for agenda in agendas:
+ obj_agenda = agenda.getObject()
+ catalog.catalog_object(obj_agenda, idxs=['date'], update_metadata=True)
+ n += 1
+ if n % 1000 == 0:
+ transaction.commit()
+
+ # Compromissos
+ n = 0
+ compromissos = catalog(portal_type='Compromisso')
+ for compromisso in compromissos:
+ obj_compromisso = compromisso.getObject()
+ catalog.catalog_object(obj_compromisso, idxs=[], update_metadata=True)
+ n += 1
+ if n % 1000 == 0:
+ transaction.commit()