diff options
author | Bryan Newbold <bnewbold@robocracy.org> | 2019-04-04 11:21:41 -0700 |
---|---|---|
committer | Bryan Newbold <bnewbold@robocracy.org> | 2019-04-04 11:21:41 -0700 |
commit | c4591cd12298cc03cd96af829a9a007d83d4e537 (patch) | |
tree | 1a5e47037bb2294a34841f0a7f7b04da3fccc369 /python/fatcat_web/forms.py | |
parent | 005236655dec1cb3f7409724a711a19b52aa9108 (diff) | |
parent | edb9c1b85f367a50957dc0423c3104b900c7e92c (diff) | |
download | fatcat-c4591cd12298cc03cd96af829a9a007d83d4e537.tar.gz fatcat-c4591cd12298cc03cd96af829a9a007d83d4e537.zip |
Merge branch 'bnewbold-forms'
Diffstat (limited to 'python/fatcat_web/forms.py')
-rw-r--r-- | python/fatcat_web/forms.py | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/python/fatcat_web/forms.py b/python/fatcat_web/forms.py new file mode 100644 index 00000000..776812ae --- /dev/null +++ b/python/fatcat_web/forms.py @@ -0,0 +1,315 @@ + +""" +Note: in thoery could use, eg, https://github.com/christabor/swagger_wtforms, +but can't find one that is actually maintained. +""" + +from flask_wtf import FlaskForm +from wtforms import SelectField, DateField, StringField, IntegerField, \ + HiddenField, FormField, FieldList, validators + +from fatcat_client import ContainerEntity, CreatorEntity, FileEntity, \ + ReleaseEntity, ReleaseContrib, FileEntityUrls + +release_type_options = [ + ('', 'Unknown'), + ('article-journal', 'Journal Article'), + ('paper-conference', 'Conference Proceeding'), + ('article', 'Article (non-journal)'), + ('book', 'Book'), + ('chapter', 'Book Chapter'), + ('dataset', 'Dataset'), + ('stub', 'Invalid/Stub'), +] +release_status_options = [ + ('', 'Unknown'), + ('draft', 'Draft'), + ('submitted', 'Submitted'), + ('accepted', 'Accepted'), + ('published', 'Published'), + ('updated', 'Updated'), +] +role_type_options = [ + ('author', 'Author'), + ('editor', 'Editor'), + ('translator', 'Translator'), +] + +class EntityEditForm(FlaskForm): + editgroup_id = StringField('Editgroup ID', + [validators.Optional(True), + validators.Length(min=26, max=26)]) + editgroup_description = StringField('Editgroup Description', + [validators.Optional(True)]) + edit_description = StringField('Description of Changes', + [validators.Optional(True)]) + +class ReleaseContribForm(FlaskForm): + class Meta: + # this is a sub-form, so disable CSRF + csrf = False + + #surname + #given_name + #creator_id (?) + #orcid (for match?) + prev_index = HiddenField('prev_revision index', default=None) + raw_name = StringField('Display Name', + [validators.DataRequired()]) + role = SelectField( + [validators.DataRequired()], + choices=role_type_options, + default='author') + +RELEASE_SIMPLE_ATTRS = ['title', 'original_title', 'work_id', 'container_id', + 'release_type', 'release_status', 'release_date', 'doi', 'wikidata_qid', + 'isbn13', 'pmid', 'pmcid', 'volume', 'issue', 'pages', 'publisher', + 'language', 'license_slug'] + +class ReleaseEntityForm(EntityEditForm): + """ + TODO: + - field types: fatcat id + - date + """ + title = StringField('Title', + [validators.DataRequired()]) + original_title = StringField('Original Title') + work_id = StringField('Work FCID', + [validators.Optional(True), + validators.Length(min=26, max=26)]) + container_id = StringField('Container FCID', + [validators.Optional(True), + validators.Length(min=26, max=26)]) + release_type = SelectField('Release Type', + [validators.DataRequired()], + choices=release_type_options, + default='') + release_status = SelectField(choices=release_status_options) + release_date = DateField('Release Date', + [validators.Optional(True)]) + #release_year + doi = StringField('DOI', + [validators.Regexp('^10\..*\/.*', message="DOI must be valid"), + validators.Optional(True)]) + wikidata_qid = StringField('Wikidata QID') + isbn13 = StringField('ISBN-13') + pmid = StringField('PubMed Id') + pmcid = StringField('PubMed Central Id') + #core_id + #arxiv_id + #jstor_id + volume = StringField('Volume') + issue = StringField('Issue') + pages = StringField('Pages') + publisher = StringField('Publisher (optional)') + language = StringField('Language (code)') + license_slug = StringField('License (slug)') + contribs = FieldList(FormField(ReleaseContribForm)) + #refs + #abstracts + + @staticmethod + def from_entity(re): + """ + Initializes form with values from an existing release entity. + """ + ref = ReleaseEntityForm() + for simple_attr in RELEASE_SIMPLE_ATTRS: + a = getattr(ref, simple_attr) + a.data = getattr(re, simple_attr) + for i, c in enumerate(re.contribs): + rcf = ReleaseContribForm() + rcf.prev_index = i + rcf.role = c.role + rcf.raw_name = c.raw_name + ref.contribs.append_entry(rcf) + return ref + + def to_entity(self): + assert(self.title.data) + entity = ReleaseEntity(title=self.title.data) + self.update_entity(entity) + return entity + + def update_entity(self, re): + """ + Mutates a release entity in place, updating fields with values from + this form. + + Form must be validated *before* calling this function. + """ + for simple_attr in RELEASE_SIMPLE_ATTRS: + a = getattr(self, simple_attr).data + # special case blank strings + if a == '': + a = None + setattr(re, simple_attr, a) + # bunch of complexity here to preserve old contrib metadata (eg, + # affiliation and extra) not included in current forms + # TODO: this may be broken; either way needs tests + if re.contribs: + old_contribs = re.contribs.copy() + re.contribs = [] + else: + old_contribs = [] + re.contribs = [] + for c in self.contribs: + if c.prev_index.data not in ('', None): + rc = old_contribs[int(c.prev_index.data)] + rc.role = c.role.data or None + rc.raw_name = c.raw_name.data or None + else: + rc = ReleaseContrib( + role=c.role.data or None, + raw_name=c.raw_name.data or None, + ) + re.contribs.append(rc) + if self.edit_description.data: + re.edit_extra = dict(description=self.edit_description.data) + +container_type_options = ( + ('journal', 'Journal'), + ('proceedings', 'Conference Proceedings'), + ('blog', 'Blog'), +) + +CONTAINER_SIMPLE_ATTRS = ['name', 'container_type', 'publisher', 'issnl', + 'wikidata_qid'] + +class ContainerEntityForm(EntityEditForm): + name = StringField('Name/Title', + [validators.DataRequired()]) + container_type = SelectField('Container Type', + [validators.Optional(True)], + choices=container_type_options, + default='') + publisher = StringField("Publisher") + issnl = StringField("ISSN-L") + wikidata_qid = StringField('Wikidata QID') + + @staticmethod + def from_entity(re): + """ + Initializes form with values from an existing container entity. + """ + ref = ContainerEntityForm() + for simple_attr in CONTAINER_SIMPLE_ATTRS: + a = getattr(ref, simple_attr) + a.data = getattr(re, simple_attr) + return ref + + def to_entity(self): + assert(self.name.data) + entity = ContainerEntity(name=self.name.data) + self.update_entity(entity) + return entity + + def update_entity(self, ce): + """ + Mutates a container entity in place, updating fields with values from + this form. + + Form must be validated *before* calling this function. + """ + for simple_attr in CONTAINER_SIMPLE_ATTRS: + a = getattr(self, simple_attr).data + # special case blank strings + if a == '': + a = None + setattr(ce, simple_attr, a) + if self.edit_description.data: + ce.edit_extra = dict(description=self.edit_description.data) + +url_rel_options = [ + ('web', 'Public Web'), + ('webarchive', 'Web Archive'), + ('repository', 'Repository'), + ('social', 'Academic Social Network'), + ('publisher', 'Publisher'), + ('dweb', 'Decentralized Web'), +] + +FILE_SIMPLE_ATTRS = ['size', 'md5', 'sha1', 'sha256', 'mimetype'] + +class FileUrlForm(FlaskForm): + class Meta: + # this is a sub-form, so disable CSRF + csrf = False + + url = StringField('Display Name', + [validators.DataRequired(), + validators.URL(require_tld=False)]) + rel = SelectField( + [validators.DataRequired()], + choices=url_rel_options, + default='web') + +class FileEntityForm(EntityEditForm): + size = IntegerField('Size (bytes)', + [validators.DataRequired()]) + # TODO: positive definite + md5 = StringField("MD5", + [validators.Optional(True), + validators.Length(min=32, max=32)]) + sha1 = StringField("SHA-1", + [validators.DataRequired(), + validators.Length(min=40, max=40)]) + sha256 = StringField("SHA-256", + [validators.Optional(True), + validators.Length(min=64, max=64)]) + urls = FieldList(FormField(FileUrlForm)) + mimetype = StringField("Mimetype") + release_ids = FieldList( + StringField("Release FCID", + [validators.DataRequired(), + validators.Length(min=26, max=26)])) + + @staticmethod + def from_entity(fe): + """ + Initializes form with values from an existing file entity. + """ + ref = FileEntityForm() + for simple_attr in FILE_SIMPLE_ATTRS: + a = getattr(ref, simple_attr) + a.data = getattr(fe, simple_attr) + for i, c in enumerate(fe.urls): + ruf = FileUrlForm() + ruf.rel = c.rel + ruf.url = c.url + ref.urls.append_entry(ruf) + for r in fe.release_ids: + ref.release_ids.append_entry(r) + return ref + + def to_entity(self): + assert(self.sha1.data) + entity = FileEntity() + self.update_entity(entity) + return entity + + def update_entity(self, fe): + """ + Mutates in place, updating fields with values from this form. + + Form must be validated *before* calling this function. + """ + for simple_attr in FILE_SIMPLE_ATTRS: + a = getattr(self, simple_attr).data + # special case blank strings + if a == '': + a = None + setattr(fe, simple_attr, a) + fe.urls = [] + for u in self.urls: + fe.urls.append(FileEntityUrls( + rel=u.rel.data or None, + url=u.url.data or None, + )) + fe.release_ids = [] + for ri in self.release_ids: + fe.release_ids.append(ri.data) + if self.edit_description.data: + fe.edit_extra = dict(description=self.edit_description.data) + |