Here is my py file
# -*- coding: utf-8 -*-
from plone.app.textfield import RichText
from plone.autoform import directives
from plone import schema
from plone.dexterity.content import Container
from plone.supermodel.directives import fieldset
# from plone.namedfile import field as namedfile
from plone.supermodel import model
from plone.autoform import directives
# from plone.supermodel.directives import fieldset
# from z3c.form.browser.radio import RadioFieldWidget
# from zope import schema
from zope.interface import implementer
import json
from z3c.form.interfaces import IAddForm
import datetime
from zope.interface import provider
from zope.schema.interfaces import IContextAwareDefaultFactory
from zope.interface import invariant
# from budget.site import _
#notes of things to do on wednesday apr 17, 2024
#https://4.docs.plone.org/external/plone.app.dexterity/docs/advanced/event-handlers.html
# add an object created event to calculate the object title
#add an object ioobjectaddedevent to calculate deptcode and deptname and school and total
#total has to be calculated on modified as well
def meeting_date_default_value():
return datetime.datetime.today() + datetime.timedelta(7)
def getdeptcode(deptcodename):
print("got to getdeptcode")
return deptcodename[0:5]
def getdeptinfo(deptcodename):
print(deptcodename)
deptcode=deptcodename[0:5]
dlen=len(deptcodename)-1
deptname=deptcodename[7:dlen]
deptinfo={"deptcode":deptcode,"deptname":deptname}
return deptinfo
@provider(IContextAwareDefaultFactory)
def get_container_id(context):
return context.id.upper()
MIXEDFIELD_SCHEMA = json.dumps(
{
'type': 'object',
'properties': {'items': {'type': 'array', 'items': {'type': 'object', 'properties': {}}}},
}
)
class IFulltimestaff(model.Schema):
""" Marker interface and Dexterity Python Schema for Fulltimestaff
"""
# If you want, you can load a xml model created TTW here
# and customize it in Python:
# model.load('fulltimestaff.xml')
# directives.widget(level=RadioFieldWidget)
# level = schema.Choice(
# title=_(u'Sponsoring Level'),
# vocabulary=LevelVocabulary,
# required=False
# )
# text = RichText(
# title=_(u'Text'),
# required=False
# )
# url = schema.URI(
# title=_(u'Link'),
# required=False
# )
# fieldset('Images', fields=['logo', 'advertisement'])
# logo = namedfile.NamedBlobImage(
# title=_(u'Logo'),
# required=False,
# )
# advertisement = namedfile.NamedBlobImage(
# title=_(u'Advertisement (Gold-sponsors and above)'),
# required=False,
# )
# directives.read_permission(notes='cmf.ManagePortal')
# directives.write_permission(notes='cmf.ManagePortal')
# notes = RichText(
# title=_(u'Secret Notes (only for site-admins)'),
# required=False
# )
# the object id assigned by plone
directives.omitted(IAddForm, 'budgetid') # will omit from dataentry form but show on editing form
#directives.omitted('field_1', 'field_2')
#directives.mode(additionalInfo='hidden') can be input, display or hidden this sets mode
budgetid=schema.TextLine(
title="budget id",
description="Object ID",
# values=[2024-2025],
required=False,
defaultFactory=get_container_id,
)
directives.read_permission(fiscalyear='cmf.ModifyPortalContent') #only entry user should be able to edit field.
#so change appropriately once you set up users.
#form.read_permission(secret="cmf.ManagePortal")
fiscalyear = schema.Choice(
title="Fiscalyear",
description="Fiscal Year",
vocabulary="budget.fiscalyearlist",
#values=[2024-2025],
required=False,
)
deptcodename = schema.Choice(
title="Department Code and Name",
description="Department",
vocabulary="budget.budgetcodes",
#values=["10101","10201"],
required=False,
)
division = schema.TextLine(
title="Division",
description="Division",
required=False,
)
directives.omitted(IAddForm, 'deptcode') #will omit from dataentry form but show on editing form
deptcode = schema.TextLine(
title="Department Code",
description="Department Code",
required=False,
#defaultFactory=getdeptcode(data.deptcodename), # sets the default
)
deptname = schema.TextLine(
title="Department Name",
description="Department Name",
max_length=200,
required=False,
)
Total = schema.Float(
title="Department Total",
description="Department Total",
required=False,
)
deptheadchairname = schema.TextLine(
title="deptheadchair",
description="Person that fills out form",
max_length=200,
required=False,
)
deptheadchairemail = schema.Email(
title="deptheadchair email",
description="Person that fills out form",
required=False,
)
entrydate = schema.Datetime(
title="deptheadchair entrydate",
description="Person that fills out form",
required=False,
defaultFactory=meeting_date_default_value, #sets the default date
)
deanvpname = schema.TextLine(
title="Dean-VP Approver",
description="Dean or VP name",
max_length=200,
required=False,
)
deanvpemail = schema.Email(
title="Dean-VP Email",
description="Dean or VP email",
required=False,
)
deanvpdecision = schema.Choice(
title="Dean-VP Decision",
description="Dean or VP decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
deanvpdecisiondate = schema.Datetime(
title="Dean-VP Decision Date",
description="Dean or VP Decision date",
required=False,
)
deanvpnotes = schema.TextLine(
title="Dean-VP Notes",
description="Dean or VP Notes",
max_length=2000,
required=False,
)
presprovostname = schema.TextLine(
title="President-Provost Approver",
description="President or Provost",
max_length=200,
required=False,
)
presprovostemail = schema.Email(
title="President-Provost Email",
description="President or Provost email",
required=False,
)
presprovostdecision = schema.Choice(
title="President-Provost Decision",
description="President or Provost Decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
presprovostdecisiondate = schema.Datetime(
title="President-Provost Decision Date",
description="President or Provost decision date",
required=False,
)
presprovostnotes = schema.TextLine(
title="President-Provost Notes",
description="President or Provost notes",
max_length=2000,
required=False,
)
budgetname = schema.TextLine(
title="Budget Approver",
description="Budget",
max_length=200,
required=False,
)
budgetemail = schema.Email(
title="Budget Email",
description="Budget email",
required=False,
)
budgetdecision = schema.Choice(
title="Budget Decision",
description="Budget decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
budgetdecisiondate = schema.Datetime(
title="Budget Decision Date",
description="Budget decision date",
required=False,
)
budgetnotes = schema.TextLine(
title="Budget Notes",
description="Budget Notes",
max_length=2000,
required=False,
)
allocationcommname = schema.TextLine(
title="Allocation Committee Approver",
description="Committee",
max_length=200,
required=False,
)
allocationcommemail = schema.Email(
title="Allocation Committee Email",
description="Comittee email",
required=False,
)
allocationcommdecision = schema.Choice(
title="Allocation Committee Decision",
description="Committee decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
allocationcommdecisiondate = schema.Datetime(
title="Allocation Committee Decision Date",
description="Committee",
required=False,
)
allocationcommnotes = schema.TextLine(
title="Allocation Committee Notes",
description="Committee",
max_length=2000,
required=False,
)
accountmname = schema.TextLine(
title="Account Approver",
description="Account",
max_length=200,
required=False,
)
accountmemail = schema.Email(
title="Account Email",
description="Account email",
required=False,
)
accountmdecision = schema.Choice(
title="Account Decision",
description="Account Decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
accountmdecisiondate = schema.Datetime(
title="Account Decision Date",
description="Account decision date",
required=False,
)
accountmnotes = schema.TextLine(
title="Account Notes",
description="Account Notes",
max_length=2000,
required=False,
)
establishedmname = schema.TextLine(
title="Established Approver",
description="Established",
max_length=200,
required=False,
)
establishedmemail = schema.Email(
title="Established Email",
description="Established email",
required=False,
)
establishedmdecision = schema.Choice(
title="Established Decision",
description="Established Decision",
values=["Approved", "Denied", "Pending"],
required=False,
)
establishedmdecisiondate = schema.Datetime(
title="Established Decision Date",
description="Established Decision date",
required=False,
)
establishedmnotes = schema.TextLine(
title="Established Notes",
description="Established notes",
max_length=2000,
required=False,
)
fulltime_positions = schema.JSONField(
title='Mixedfield: datagrid field for Plone',
required=False,
schema=MIXEDFIELD_SCHEMA,
widget='faculty2widget',
default={'items': []},
missing_value={'items': []},
)
@invariant
def validate(data):
print("got to validate")
if data.deptcodename is not None:
print("got to validate")
deptinfo=getdeptinfo(data.deptcodename)
#data.deptcode=deptinfo["deptcode"]
#data.deptname=deptinfo["deptname"]
@implementer(IFulltimestaff)
class Fulltimestaff(Container):
""" Content-type class for IFulltimestaff
"""
Here is my View
import React from 'react';
import { DefaultView } from '@plone/volto/components';
import { Container } from 'semantic-ui-react';
const FacultyBudget = props => {
const { content } = props;
return (
<>
<DefaultView {...props} />
<Container>
<h1 className="documentFirstHeading">
{content.title}
</h1>
{content.description && (
<p className="documentDescription">{content.description}</p>
)}
{<Table celled className="Fulltime positions list">
<Table.Header>
<Table.Row>
<Table.HeaderCell>Position</Table.HeaderCell>
<Table.HeaderCell>Salary</Table.HeaderCell>
<Table.HeaderCell>Justification</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{content?.items?.map((item) => (
<Table.Row>
<Table.Cell>{item.positiontype}</Table.Cell>
<Table.Cell>{item.salary}</Table.Cell>
<Table.Cell>{item.justification}</Table.Cell>
</Table.Row>
))}
</Table.Body>
</Table>}
<div dangerouslySetInnerHTML={{ __html: content.details.data }} />
</Container>
</>
);
};
const FacultyBudgetView = ({ content }) => {
return (
<Container>
<h2>Faculty View</h2>
<h3>Faculty LIst</h3>
<FacultyBudget mybudget={content.faculty2widget} />
</Container>
);
};
export default FacultyBudgetView;
Here is my widget
import React from 'react';
import { ReactTableWidget } from '@eeacms/volto-react-table-widget';
const ItemSchema = () => ({
title: 'Faculty-List',
properties: {
positiontype: {
title: 'Position Type',
type: 'string',
},
salary: {
title: 'Salary',
type:'number',
},
justification: {
title: 'Justification',
type: 'string',
},
},
fieldsets: [
{
id: 'default',
title: 'Faculty-List',
fields: [
'positiontype',
'salary',
'justification',
],
},
],
required: [],
});
const Faculty2Widget = (props) => {
return (
<ReactTableWidget
schema={ItemSchema()}
{...props}
csvexport={false}
csvimport={false}
value={props.value?.items || props.default?.items || []}
onChange={(id, value) => props.onChange(id, { items: value })}
/>
);
};
export default Faculty2Widget;****strong text