From c980d256bf4d83f6a22b1ecdc81d6228e35faafb Mon Sep 17 00:00:00 2001 From: samoel-silva Date: Tue, 17 Sep 2024 16:11:32 -0300 Subject: [PATCH] =?UTF-8?q?Excerc=C3=ADcio=2028:=20cria=20o=20tipo=20Pesso?= =?UTF-8?q?a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/portal/governo/content/pessoa.py | 12 +++ backend/src/portal/governo/permissions.zcml | 5 ++ .../governo/profiles/default/metadata.xml | 2 +- .../governo/profiles/default/rolemap.xml | 8 ++ .../portal/governo/profiles/default/types.xml | 4 + .../governo/profiles/default/types/Pessoa.xml | 45 +++++++++++ .../portal/governo/upgrades/configure.zcml | 22 ++++++ .../src/portal/governo/utils/validadores.py | 3 +- backend/tests/content/test_ct_pessoa.py | 76 +++++++++++++++++++ backend/tests/setup/test_setup_install.py | 2 +- .../src/components/Contato/Contato.jsx | 26 +++++++ .../src/components/Endereco/Endereco.jsx | 41 +++++++--- .../src/components/Views/PessoaView.jsx | 61 +++++++++++++++ .../volto-portal-governo/src/index.js | 2 + 14 files changed, 294 insertions(+), 15 deletions(-) create mode 100644 backend/src/portal/governo/content/pessoa.py create mode 100644 backend/src/portal/governo/profiles/default/types/Pessoa.xml create mode 100644 backend/tests/content/test_ct_pessoa.py create mode 100644 frontend/packages/volto-portal-governo/src/components/Contato/Contato.jsx create mode 100644 frontend/packages/volto-portal-governo/src/components/Views/PessoaView.jsx diff --git a/backend/src/portal/governo/content/pessoa.py b/backend/src/portal/governo/content/pessoa.py new file mode 100644 index 0000000..127b754 --- /dev/null +++ b/backend/src/portal/governo/content/pessoa.py @@ -0,0 +1,12 @@ +from plone.dexterity.content import Container +from plone.supermodel import model +from zope.interface import implementer + + +class IPessoa(model.Schema): + """Definição de uma pessoa.""" + + +@implementer(IPessoa) +class Pessoa(Container): + """Uma pessoa.""" diff --git a/backend/src/portal/governo/permissions.zcml b/backend/src/portal/governo/permissions.zcml index 3cefc3f..895683c 100644 --- a/backend/src/portal/governo/permissions.zcml +++ b/backend/src/portal/governo/permissions.zcml @@ -11,6 +11,11 @@ title="portal.governo: Add Secretaria" /> + + diff --git a/backend/src/portal/governo/profiles/default/metadata.xml b/backend/src/portal/governo/profiles/default/metadata.xml index 6b1b251..e78048f 100644 --- a/backend/src/portal/governo/profiles/default/metadata.xml +++ b/backend/src/portal/governo/profiles/default/metadata.xml @@ -1,6 +1,6 @@ - 1002 + 1004 profile-plone.volto:default diff --git a/backend/src/portal/governo/profiles/default/rolemap.xml b/backend/src/portal/governo/profiles/default/rolemap.xml index 1b9af8f..32846c3 100644 --- a/backend/src/portal/governo/profiles/default/rolemap.xml +++ b/backend/src/portal/governo/profiles/default/rolemap.xml @@ -7,5 +7,13 @@ + + + + + + diff --git a/backend/src/portal/governo/profiles/default/types.xml b/backend/src/portal/governo/profiles/default/types.xml index 45ae25f..9d57ede 100644 --- a/backend/src/portal/governo/profiles/default/types.xml +++ b/backend/src/portal/governo/profiles/default/types.xml @@ -7,4 +7,8 @@ name="Secretaria" /> + + diff --git a/backend/src/portal/governo/profiles/default/types/Pessoa.xml b/backend/src/portal/governo/profiles/default/types/Pessoa.xml new file mode 100644 index 0000000..92270d3 --- /dev/null +++ b/backend/src/portal/governo/profiles/default/types/Pessoa.xml @@ -0,0 +1,45 @@ + + + + + Pessoa + Uma Pessoa dentro da estrutura de governo + + False + Pessoa + + + False + + True + + + portal.governo.pessoa.add + portal.governo.content.pessoa.Pessoa + portal.governo.content.pessoa.IPessoa + + + + + + + + + + + + + + + + diff --git a/backend/src/portal/governo/upgrades/configure.zcml b/backend/src/portal/governo/upgrades/configure.zcml index e9d8965..cfda9f1 100644 --- a/backend/src/portal/governo/upgrades/configure.zcml +++ b/backend/src/portal/governo/upgrades/configure.zcml @@ -25,4 +25,26 @@ /> + + + + + + + + diff --git a/backend/src/portal/governo/utils/validadores.py b/backend/src/portal/governo/utils/validadores.py index 3cd9c22..1fd579b 100644 --- a/backend/src/portal/governo/utils/validadores.py +++ b/backend/src/portal/governo/utils/validadores.py @@ -3,7 +3,8 @@ def is_valid_email(value: str) -> bool: """Validar se o email é @rs.gov.br.""" - return value.endswith("@rs.gov.br") if value else True + pattern = re.compile(r"^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)?rs\.gov\.br$") + return True if re.match(pattern, value) else False def is_valid_telefone(value: str) -> bool: diff --git a/backend/tests/content/test_ct_pessoa.py b/backend/tests/content/test_ct_pessoa.py new file mode 100644 index 0000000..d81ef33 --- /dev/null +++ b/backend/tests/content/test_ct_pessoa.py @@ -0,0 +1,76 @@ +from AccessControl import Unauthorized +from plone import api +from plone.dexterity.fti import DexterityFTI +from portal.governo.content.pessoa import Pessoa +from zope.component import createObject + +import pytest + + +CONTENT_TYPE = "Pessoa" + + +@pytest.fixture +def pessoa_payload() -> dict: + """Return a payload to create a new secretaria.""" + return { + "type": "Pessoa", + "id": "fulano", + "title": "Fulano da Silva", + "description": ("Essa é a ágina do fulano," "nascido em ananindeua"), + "email": "fulano@rs.gov.br", + "telefone": "(51) 3210.4193", + } + + +class TestPessoa: + @pytest.fixture(autouse=True) + def _setup(self, get_fti, portal): + self.fti = get_fti(CONTENT_TYPE) + self.portal = portal + + def test_fti(self): + assert isinstance(self.fti, DexterityFTI) + + def test_factory(self): + factory = self.fti.factory + obj = createObject(factory) + assert obj is not None + assert isinstance(obj, Pessoa) + + @pytest.mark.parametrize( + "behavior", + [ + "plone.basic", + "plone.namefromtitle", + "plone.shortname", + "plone.excludefromnavigation", + "plone.versioning", + "plone.constraintypes", + "plone.leadimage", + "volto.preview_image", + "portal.governo.behavior.contato", + "portal.governo.behavior.endereco", + ], + ) + def test_has_behavior(self, get_behaviors, behavior): + assert behavior in get_behaviors(CONTENT_TYPE) + + @pytest.mark.parametrize( + "role, allowed", + [ + ["Manager", True], + ["Site Administrator", True], + ["Member", False], + ["Editor", False], + ], + ) + def test_create(self, pessoa_payload, role, allowed): + if allowed: + with api.env.adopt_roles(role): + content = api.content.create(container=self.portal, **pessoa_payload) + assert content.portal_type == CONTENT_TYPE + assert isinstance(content, Pessoa) + else: + with pytest.raises(Unauthorized): + content = api.content.create(container=self.portal, **pessoa_payload) diff --git a/backend/tests/setup/test_setup_install.py b/backend/tests/setup/test_setup_install.py index 7945f4c..6b0dcb4 100644 --- a/backend/tests/setup/test_setup_install.py +++ b/backend/tests/setup/test_setup_install.py @@ -14,4 +14,4 @@ def test_browserlayer(self, browser_layers): def test_latest_version(self, profile_last_version): """Test latest version of default profile.""" - assert profile_last_version(f"{PACKAGE_NAME}:default") == "1002" + assert profile_last_version(f"{PACKAGE_NAME}:default") == "1004" diff --git a/frontend/packages/volto-portal-governo/src/components/Contato/Contato.jsx b/frontend/packages/volto-portal-governo/src/components/Contato/Contato.jsx new file mode 100644 index 0000000..6628f58 --- /dev/null +++ b/frontend/packages/volto-portal-governo/src/components/Contato/Contato.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Container } from '@plone/components'; +import PropTypes from 'prop-types'; + +const Contato = (props) => { + const { email, telefone } = props.content; + return ( + + + Telefone: {telefone} + + + E-mail: {email} + + + ); +}; + +Contato.propTypes = { + content: PropTypes.shape({ + telefone: PropTypes.string, + endereco: PropTypes.string, + }).isRequired, +}; + +export default Contato; diff --git a/frontend/packages/volto-portal-governo/src/components/Endereco/Endereco.jsx b/frontend/packages/volto-portal-governo/src/components/Endereco/Endereco.jsx index de6b6ce..cd47b69 100644 --- a/frontend/packages/volto-portal-governo/src/components/Endereco/Endereco.jsx +++ b/frontend/packages/volto-portal-governo/src/components/Endereco/Endereco.jsx @@ -1,29 +1,46 @@ import React from 'react'; +import PropTypes from 'prop-types'; import { Container } from '@plone/components'; const Endereco = (props) => { const { endereco, complemento, cidade, estado, cep } = props.content; return ( - - - Endereço: {endereco} - - - Complemento: {complemento} - - - Cidade: {cidade} + + {endereco && ( + + {endereco} + + )} + {complemento && ( + + {complemento} + + )} + + {cidade} {estado && ( <> - {estado.token} )} - - CEP: {cep} - + {cep && ( + + {cep} + + )} ); }; +Endereco.propTypes = { + content: PropTypes.shape({ + endereco: PropTypes.string, + complemento: PropTypes.string, + cidade: PropTypes.string, + estado: PropTypes.string, + cep: PropTypes.string, + }).isRequired, +}; + export default Endereco; diff --git a/frontend/packages/volto-portal-governo/src/components/Views/PessoaView.jsx b/frontend/packages/volto-portal-governo/src/components/Views/PessoaView.jsx new file mode 100644 index 0000000..3f8d628 --- /dev/null +++ b/frontend/packages/volto-portal-governo/src/components/Views/PessoaView.jsx @@ -0,0 +1,61 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Container } from '@plone/components'; +import { Image } from '@plone/volto/components'; +import Contato from '../Contato/Contato'; +import Endereco from '../Endereco/Endereco'; + +const PessoaView = (props) => { + const { content } = props; + return ( + + {content.image && ( + + {content.title} + + )} + {content.cargo && {content.cargo}} +

{content.title}

+ {content.description && ( +

{content.description}

+ )} + + +
+ ); +}; + +/** + * Property types. + * @property {Object} propTypes Property types. + * @static + */ +PessoaView.propTypes = { + content: PropTypes.shape({ + title: PropTypes.string, + description: PropTypes.string, + image: PropTypes.shape({ + scales: PropTypes.shape({ + preview: PropTypes.shape({ + download: PropTypes.string, + }), + }), + }), + email: PropTypes.string, + telefone: PropTypes.string, + endereco: PropTypes.string, + complemento: PropTypes.string, + cidade: PropTypes.string, + estado: PropTypes.string, + cep: PropTypes.string, + }).isRequired, +}; + +export default PessoaView; diff --git a/frontend/packages/volto-portal-governo/src/index.js b/frontend/packages/volto-portal-governo/src/index.js index 8300582..e96d6f8 100644 --- a/frontend/packages/volto-portal-governo/src/index.js +++ b/frontend/packages/volto-portal-governo/src/index.js @@ -1,5 +1,6 @@ // Views import SecretariaView from './components/Views/SecretariaView'; +import PessoaView from './components/Views/PessoaView'; const applyConfig = (config) => { config.settings = { @@ -12,6 +13,7 @@ const applyConfig = (config) => { config.views.contentTypesViews = { ...config.views.contentTypesViews, Secretaria: SecretariaView, + Pessoa: PessoaView, }; return config; };