Volto development concern. Loading classic plone addons into volto

Good morning, Plone community!

I am in the process of getting my python plone addons ready to work on Volto. I am running into an issue however with the individual content types. The full traceback is below:

    /Users/rhennebrown/Plone522py37/zinstance/bin/python /Users/rhennebrown/Plone522py37/zinstance/bin/instance fg
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/Products.CMFFormController-4.1.2-py3.7.egg/Products/CMFFormController/ControllerPythonScript.py:41: DeprecationWarning: the imp module is deprecated in favour of importlib; see the module's documentation for alternative uses
  import imp
2021-02-10 12:01:40,442 WARNING [Init:89][MainThread] Class Products.CMFFormController.ControllerPythonScript.ControllerPythonScript has a security declaration for nonexistent method 'ZPythonScriptHTML_changePrefs'
2021-02-10 12:01:40,450 WARNING [Init:89][MainThread] Class Products.CMFFormController.ControllerValidator.ControllerValidator has a security declaration for nonexistent method 'ZPythonScriptHTML_changePrefs'
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/Products.CMFPlacefulWorkflow-2.0.2-py3.7.egg/Products/CMFPlacefulWorkflow/permissions.py:5: DeprecationWarning: setDefaultRoles is deprecated. Please use addPermission from AccessControl.Permission.
  from Products.CMFCore.permissions import setDefaultRoles
2021-02-10 12:01:41,238 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied sql_quote patch
2021-02-10 12:01:41,291 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied in_portal patch
2021-02-10 12:01:41,294 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied password_validation patch
2021-02-10 12:01:41,314 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied pac patch
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/Products.PloneHotfix20200121-1.1-py3.7.egg/Products/PloneHotfix20200121/utils.py:4: DeprecationWarning: getSiteEncoding: `getSiteEncoding` is deprecated. Plone only supports UTF-8 currently. This method always returns "utf-8"
  from Products.CMFPlone.utils import *
2021-02-10 12:01:41,382 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied content patch
2021-02-10 12:01:41,411 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied layout patch
2021-02-10 12:01:41,566 INFO    [Products.PloneHotfix20200121:49][MainThread] Applied restapi_local_roles patch
2021-02-10 12:01:41,566 INFO    [Products.PloneHotfix20200121:57][MainThread] Hotfix installed
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/Products.PortalTransforms-3.1.8-py3.7.egg/Products/PortalTransforms/transforms/text_to_html.py:2: DeprecationWarning: html_quote is deprecated. Please import from DocumentTemplate.html_quote. These shims will go away in DocumentTemplate 4.0.
  from DocumentTemplate.DT_Util import html_quote
2021-02-10 12:01:42,065 WARNING [TemporaryStorage:93][MainThread] DEPRECATED: Usage of the package tempstorage is deprecated, as it is known to randomly lose data.
Especially on Zope 4. For details see https://github.com/zopefoundation/tempstorage/issues/8
and https://github.com/zopefoundation/tempstorage

/Users/rhennebrown/Plone522py37/buildout-cache/eggs/tempstorage-5.1-py3.7.egg/tempstorage/TemporaryStorage.py:94: DeprecationWarning: DEPRECATED: Usage of the package tempstorage is deprecated, as it is known to randomly lose data.
Especially on Zope 4. For details see https://github.com/zopefoundation/tempstorage/issues/8
and https://github.com/zopefoundation/tempstorage

  warnings.warn(deprecation_warning, DeprecationWarning)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.app.textfield-1.3.4-py3.7.egg/plone/app/textfield/utils.py:10: DeprecationWarning: ComponentLookupError is deprecated. Import from zope.interface.interfaces
  from zope.component.interfaces import ComponentLookupError
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.app.upgrade-2.0.34-py3.7.egg/plone/app/upgrade/__init__.py:167: DeprecationWarning: LockItem is deprecated. Please import from OFS.LockItem.
  from webdav.LockItem import LockItem
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.subrequest-1.9.2-py3.7.egg/plone/subrequest/__init__.py:18: DeprecationWarning: zope.site.hooks has moved to zope.component.hooks. Import of zope.site.hooks will become unsupported in Version 5.0
  from zope.site.hooks import getSite
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.scale-3.1.1-py3.7.egg/plone/scale/storage.py:5: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
  from collections import MutableMapping
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.configuration-4.4.0-py3.7.egg/zope/configuration/config.py:241: DeprecationWarning: IObjectEvent is deprecated. Import from zope.interface.interfaces
  obj = getattr(mod, oname)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.app.content-3.8.6-py3.7.egg/plone/app/content/browser/vocabulary.py:10: DeprecationWarning: IFieldPermissionChecker is deprecated. Import IFieldPermissionChecker from plone.app.z3cform.interfaces instead
  from plone.app.widgets.interfaces import IFieldPermissionChecker
2021-02-10 12:01:44,479 INFO    [chameleon.config:38][MainThread] directory cache: /Users/rhennebrown/Plone522py37/zinstance/var/cache.
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.configuration-4.4.0-py3.7.egg/zope/configuration/config.py:241: DeprecationWarning: IComponentRegistry is deprecated. Import from zope.interface.interfaces
  obj = getattr(mod, oname)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.configuration-4.4.0-py3.7.egg/zope/configuration/config.py:241: DeprecationWarning: LockableItem is deprecated. Please import from OFS.Lockable.
  obj = getattr(mod, oname)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.schemaeditor-3.0.1-py3.7.egg/plone/schemaeditor/utils.py:6: DeprecationWarning: ObjectEvent is deprecated. Import from zope.interface.interfaces
  from zope.component.interfaces import ObjectEvent
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.configuration-4.4.0-py3.7.egg/zope/configuration/config.py:241: DeprecationWarning: LazyMap is deprecated. Please import from ZTUtils.Lazy.
  obj = getattr(mod, oname)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.configuration-4.4.0-py3.7.egg/zope/configuration/config.py:241: DeprecationWarning: LazyCat is deprecated. Please import from ZTUtils.Lazy.
  obj = getattr(mod, oname)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/plone.app.upgrade-2.0.34-py3.7.egg/plone/app/upgrade/v50/betas.py:8: DeprecationWarning: ILanguageSchema is deprecated. It has been moved to plone.i18n.interfaces, import from there instead.
  from Products.CMFPlone.interfaces import ILanguageSchema
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/calmjs.parse-1.2.4-py3.7.egg/calmjs/parse/io.py:7: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3,and in 3.9 it will stop working
  from collections import Iterable
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/pyScss-1.3.7-py3.7.egg/scss/namespace.py:172: DeprecationWarning: inspect.getargspec() is deprecated since Python 3.0, use inspect.signature() or inspect.getfullargspec()
  argspec = inspect.getargspec(function)
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/pyScss-1.3.7-py3.7.egg/scss/selector.py:54: FutureWarning: Possible nested set at position 329
  ''', re.VERBOSE | re.MULTILINE)
2021-02-10 12:01:52,745 INFO    [Zope:45][MainThread] Ready to handle requests
Starting server in PID 23101.
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/waitress-1.4.4-py3.7.egg/waitress/adjustments.py:445: DeprecationWarning: In future versions of Waitress clear_untrusted_proxy_headers will be set to True by default. You may opt-out by setting this value to False, or opt-in explicitly by setting this to True.
  DeprecationWarning,
Serving on http://0.0.0.0:8080
/Users/rhennebrown/Plone522py37/buildout-cache/eggs/zope.deprecation-4.4.0-py3.7.egg/zope/deprecation/deprecation.py:88: DeprecationWarning: isDefaultPage is deprecated. Import from Products.CMFPlone.defaultpage instead
  name)
2021-02-10 12:03:06,554 ERROR   [Zope.SiteErrorLog:252][waitress-1] 1612976586.5404280.6398224715325398 http://localhost:3000/api/admissions/POST_application_json_
Traceback (innermost last):
  Module ZPublisher.WSGIPublisher, line 162, in transaction_pubevents
  Module ZPublisher.WSGIPublisher, line 359, in publish_module
  Module ZPublisher.WSGIPublisher, line 262, in publish
  Module ZPublisher.mapply, line 85, in mapply
  Module ZPublisher.WSGIPublisher, line 63, in call_object
  Module plone.rest.service, line 22, in __call__
  Module plone.restapi.services, line 21, in render
  Module plone.restapi.services.content.add, line 54, in reply
  Module plone.restapi.services.content.utils, line 63, in create
  Module plone.dexterity.factory, line 45, in __call__
ValueError: Error whilst constructing content for admissions_docs using class yc.documents.content.admissions_docs.AdmissionsDocs: setTitle() takes 1 positional argument but 2 were given

My question is where do I need to start regarding solving this error? I have made attempts to create views and addons yet the problem still persists. I appreciate any help that can be provided regarding this problem.

Sincerely,

rbrown12

I'm not an expert in plone.restapi stuff, but that setTitle thing is weird. Could you paste some of the code of yc.documents.content.admissions_docs.AdmissionsDocs ? Does it define a setTitle method?

Here is some of the code containing the setTitle method:

@implementer(IAdmissionsDocs)
class AdmissionsDocs(Item):
    """
    """

def setTitle(self):
    self.setTitle = self.computeTitle()

def Title(self):
    return self.computeTitle()

def computeTitle(self):
    return str(self.last_name) + ', ' + str(self.first_name) + ' - ' + str(self.employeeID)

def setDescription(self):
    self.setDescription = self.computeDescription()

def Description(self):
    return self.computeDescription()

def computeDescription(self):
    return str(self.employeeID)

the style of this seems wrong, it seems to overwrite itself? Why are setTitle and setDescription needed? Who uses them?

@tiberiuichim, I was using this to get information from member fields defined in the userschema in the Plone classic backend. I did notice that it worked when i commented out the setTitle and setDescription in the code. However, I didn't see any content published in Volto even when I created it there. Would I need to make a whole addon for this to work or can I just use views and have the content types display through them in volto?

Thanks for responding.

Sincerely,

rbrown12

To view the fields of your content type you'll have to write a new view component for Volto. Check the NewsItem view component for a simple example, see how it's registered.

Thanks. However, I wasn't able to get the views to display the content. I don't remember seeing this in the tutorial. Is this a newer way of adding views for Volto? I currently have been going through the tutorials but so far i have not successfully gotten the views to work. Are the tutorials in Volto currently relevant? Do they still apply today in 2021?

Volto itself doesn't need you to declare any Plone views, to be able to show your content. If you have a content type implemented, you can configure your component to match the content type. See volto/Views.jsx at master · plone/volto · GitHub

Maybe this would help? 26. Volto View Components: A Listing View for Talks — Plone Training 2021 documentation

Thanks for your reply. Using the examples provided, I was able to successfully create the views, however, I still am running into problems with the setTitle and setDescription. I am required to use the setTitle and setDescription and cannot get rid of it. Is there a way for me to implement it in Volto? Would I need to modify the backend code or can I just implement something in the Volto views?

You may want to see plonecli · PyPI for how schema, fields and their getters and setters could look like.

plonecli create addon src/collective.todo
cd src/collective.todo/
plonecli add behavior

This creates a behavior with a starter of a schema with a dummy field and its getter and setter in src/collective/todo/behaviors/ .

class IMoreFieldsForEuropeMarker(Interface):
    pass


@provider(IFormFieldProvider)
class IMoreFieldsForEurope(model.Schema):
    """
    """

    project = schema.TextLine(
        title=_(u'Project'),
        description=_(u'Give in a project name'),
        required=False,
    )


@implementer(IMoreFieldsForEurope)
@adapter(IMoreFieldsForEuropeMarker)
class MoreFieldsForEurope(object):
    def __init__(self, context):
        self.context = context

    @property
    def project(self):
        if safe_hasattr(self.context, 'project'):
            return self.context.project
        return None

    @project.setter
    def project(self, value):
        self.context.project = value

Good morning, Plone community!

When I reloaded and installed Volto this morning, I noticed that my views didn't display or render anymore.

I thank you kindly.

Sincerely,

rbrown12

@rbrown12 There's been another release of Volto that fixes the problem. Upgrade to latest Volto and it should be fine.

Good evening, Plone community!

I have a question regarding Volto. I am planning on building a table that filters search results based on the data in the table like DataTables in JQuery. Is there a way to do this using Volto and react without implementing JQuery?

I thank you for your time.

Sincerely,

rbrown12

@rbrown12 It's relatively simple if you know React. There's no getting around that, though, even if you were to integrate one of the many React libraries that provide data tables.

I am getting an error saying nothing was returned from the render even though I have a return function.

Here is the full error:

FinAidView(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.


in FinAidView (at View.jsx:242)
in div (at View.jsx:226)
in View (created by ConnectFunction)
in ConnectFunction (created by Context.Consumer)
in injectIntl(Connect(View)) (created by Context.Consumer)
in Route (created by App)
in Switch (created by App)
in main (at App.jsx:137)
in div (created by Segment)
in Segment (at App.jsx:136)
in MultilingualRedirector (at App.jsx:135)
in App (created by ConnectFunction)
in ConnectFunction (created by ConnectFunction)
in ConnectFunction (created by Context.Consumer)
in Route (created by Context.Consumer)
in Switch (created by Context.Consumer)
in Route (at AsyncConnect.jsx:89)
in AsyncConnect (at AsyncConnect.jsx:129)
in AsyncConnectWithContext (created by Context.Consumer)
in withRouter(AsyncConnectWithContext) (created by ConnectFunction)
in ConnectFunction (at start-client.jsx:51)
in ScrollToTop (created by Context.Consumer)
in withRouter(ScrollToTop) (at start-client.jsx:50)
in Router (created by ConnectedRouter)
in ConnectedRouter (created by Context.Consumer)
in ConnectedRouterWithContext (created by ConnectFunction)
in ConnectFunction (at start-client.jsx:49)
in IntlProvider (created by ConnectFunction)
in ConnectFunction (at start-client.jsx:48)
in Provider (at start-client.jsx:47)

And this is the code I was using:

import React from 'react';
import { Container, Table, Popup, Grid, Image, Menu } from 'semantic-ui-react';
import { FormattedMessage } from 'react-intl';
import moment from 'moment';
import { Helmet } from '@plone/volto/helpers';
import open from './show.svg';
import check from './check.svg';
import history from './clock.svg';
import right from './right-key.svg';
import left from './left-key.svg';

const FinAidView = (props) => {
  const { content } = props;
  const results = content.items;

  for (let number = 1; number < results.length; number++)
return (
  <Container className="view-wrapper">
    <Helmet className={content.title} />
    <article id="content">
      <header>
        {content.title && (
          <h1 className="documentFirstHeading">{content.title}</h1>
        )}
        {content.description && (
          <p className="documentDescription">{content.description}</p>
        )}
      </header>
      <section id="content-core">
        <Table celled sortable striped>
          <Table.Header>
            <Table.Row id="headerRow">
              <Table.HeaderCell>
                <FormattedMessage id="#" defaultMessage="#" />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage id="Created" defaultMessage="Created" />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage id="empID" defaultMessage="empID" />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage
                  id="Firstname"
                  defaultMessage="Firstname"
                />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage id="Lastname" defaultMessage="Lastname" />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage
                  id="Documents"
                  defaultMessage="Documents"
                />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage id="State" defaultMessage="State" />
              </Table.HeaderCell>
              <Table.HeaderCell>
                <FormattedMessage id="Action" defaultMessage="Action" />
              </Table.HeaderCell>
            </Table.Row>
          </Table.Header>
          <Table.Body key="table-body">
            {results &&
              results.map((item) => (
                <Table.Row key={item.title}>
                  <Table.Cell key="number">
                    <div>
                      <span>{number++}</span>
                    </div>
                  </Table.Cell>
                  <Table.Cell key="created">
                    <div>{moment(item.created).format('ll')}</div>
                  </Table.Cell>
                  <Table.Cell key="employeeID">
                    <div>{item.employeeID}</div>
                  </Table.Cell>
                  <Table.Cell key="first_name">
                    <div>{item.first_name}</div>
                  </Table.Cell>
                  <Table.Cell key="last_name">
                    <div>{item.last_name}</div>
                  </Table.Cell>
                  <Table.Cell key="documents">
                    <ol>
                      {item.attachment_type && (
                        <li>
                          <Popup
                            trigger={
                              <a href={item.attachment_file.download}>
                                {item.attachment_type.title}
                              </a>
                            }
                          >
                            <Grid>
                              <Image
                                src={item.attachment_file.download}
                                size="small"
                                floated="right"
                                alt={item.attachment_file.filename}
                              />
                            </Grid>
                          </Popup>
                        </li>
                      )}
                      {item.attachment_type1 && (
                        <li>
                          <Popup
                            trigger={
                              <a href={item.attachment_file1.download}>
                                {item.attachment_type1.title}
                              </a>
                            }
                          >
                            <Grid>
                              <Image
                                src={item.attachment_file1.download}
                                size="small"
                                floated="right"
                                alt={item.attachment_file1.filename}
                              />
                            </Grid>
                          </Popup>
                        </li>
                      )}
                      {item.attachment_type2 && (
                        <li>
                          <Popup
                            trigger={
                              <a href={item.attachment_file2.download}>
                                {item.attachment_type2.title}
                              </a>
                            }
                          >
                            <Grid>
                              <Image
                                src={item.attachment_file2.download}
                                size="small"
                                floated="right"
                                alt={item.attachment_file2.filename}
                              />
                            </Grid>
                          </Popup>
                        </li>
                      )}
                      {item.attachment_type3 && (
                        <li>
                          <Popup
                            trigger={
                              <a href={item.attachment_file3.download}>
                                {item.attachment_type3.title}
                              </a>
                            }
                          >
                            <Grid>
                              <Image
                                src={item.attachment_file3.download}
                                size="small"
                                floated="right"
                                alt={item.attachment_file3.filename}
                              />
                            </Grid>
                          </Popup>
                        </li>
                      )}
                      {item.attachment_type4 && (
                        <li>
                          <Popup
                            trigger={
                              <a href={item.attachment_file4.download}>
                                {item.attachment_type4.title}
                              </a>
                            }
                          >
                            <Grid>
                              <Image
                                src={item.attachment_file4.download}
                                size="small"
                                floated="right"
                                alt={item.attachment_file4.filename}
                              />
                            </Grid>
                          </Popup>
                        </li>
                      )}
                    </ol>
                  </Table.Cell>
                  <Table.Cell key="review_state">
                    <div>{item.review_state}</div>
                  </Table.Cell>
                  <Table.Cell key="actions">
                    <div>
                      <a href={item.url}>
                        <span>
                          <Image src={open} size="mini" alt={open} />
                        </span>
                      </a>
                      <a href={item['@id'] + '/content_status_history'}>
                        <span>
                          <Image src={check} size="mini" alt={check} />
                        </span>
                      </a>
                      <a href={item.url + '/history'}>
                        <span>
                          <Image src={history} size="mini" alt={history} />
                        </span>
                      </a>
                    </div>
                  </Table.Cell>
                </Table.Row>
              ))}
          </Table.Body>
          <Table.Footer>
            <Table.Row>
              <Table.HeaderCell colSpan="3">
                <Menu pagination>
                  <Menu.Item as="a" icon>
                    <span>
                      <Image src={left} size="mini" alt={left} />
                    </span>
                  </Menu.Item>
                  <Menu.Item as="a">1</Menu.Item>
                  <Menu.Item as="a">2</Menu.Item>
                  <Menu.Item as="a">3</Menu.Item>
                  <Menu.Item as="a">4</Menu.Item>
                  <Menu.Item as="a" icon>
                    <span>
                      <Image src={right} size="mini" alt={right} />
                    </span>
                  </Menu.Item>
                </Menu>
              </Table.HeaderCell>
            </Table.Row>
          </Table.Footer>
        </Table>
      </section>
    </article>
  </Container>
);
};

export default FinAidView;

What is it that I need to fix? I recently updated to Volto 12.2.0 and Plone 5.2.4, however I am still having trouble loading the views in Volto after creating a new content type.

I thank you kindly.

Sincerely,

rbrown12

See the React docs on how to render multiple components: https://reactjs.org/docs/lists-and-keys.html#rendering-multiple-components

The return statement exits the function, you're trying to aggregate that list of results into a list of articles. So you shouldn't use the for loop, you need to structure your code to work in a functional pattern. Also, React expects that you return a single component.

So your code should look something like this:

const FinAidView = (props) => {
    return <div>
       {props.content.items.map(item => (<article><h1>{item.title}</h1></article>))}
    </div>
}

It was working fine in Plone Classic because there were default factories set for "employeeID", "first_name", and "last_name" in the admissions_docs content type. Is there a way to render the "implementers" from Plone Classic Items into Volto?