archiveunit.py 44.8 KB
Newer Older
1
# copyright 2016-2021 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# contact http://www.logilab.fr -- mailto:contact@logilab.fr
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Lesser General Public License as published by the Free
# Software Foundation, either version 2.1 of the License, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
"""cubicweb-seda views for ArchiveUnit"""

18
from logilab.mtconverter import xml_escape
19
from logilab.common.registry import objectify_predicate
20
from logilab.common.decorators import monkeypatch
21

Sylvain Thénault's avatar
Sylvain Thénault committed
22
from cubicweb import tags, _
23
from cubicweb.predicates import is_instance, match_form_params, specified_etype_implements
24
from cubicweb.view import EntityView
25
from cubicweb.web.views import autoform, baseviews, tabs, uicfg
26

27
from cubicweb_compound import views as compound
28
from cubicweb_relationwidget import views as rwdg
29

30
from ..xsd import un_camel_case
31
32
from ..entities import (is_full_seda2_profile, full_seda2_profile,
                        simplified_profile, parent_and_container)
33
from ..entities.itree import parent_archive_unit
34
from . import (CONTENT_ETYPE, add_subobject_link,
35
               rtags_from_xsd_element, rtags_from_rtype_role_targets, has_rel_perm)
36
from . import clone, viewlib, widgets
37
from . import uicfg as sedauicfg  # noqa - ensure those rules are defined first
38
39


40
41
42
43
44
def add_links_with_custom_arguments(seq, rtype, role, extraurlparams, sub_unit_types):
    """Return a list of links to be inserted in dropdown button to add subobjects through `rtype`
    and `role` but with an extra argument in url params, given through the `param_defs` list of
    3-uple defining argument's (name, value, link label).
    """
45
    _ = seq._cw._
46
47
48
49
50
    links = []
    urlparams = extraurlparams.copy()
    for argument, value, label in sub_unit_types:
        urlparams[argument] = value
        link = add_subobject_link(seq, rtype, role, urlparams,
51
                                  msg=_(label), klass='')
52
53
54
55
56
        if link:
            links.append(link)
    return links


57
58
@objectify_predicate
def is_archive_unit_ref(cls, req, rset=None, entity=None, **kwargs):
Sylvain Thénault's avatar
Sylvain Thénault committed
59
    """Return 1 if a unit_type value is specified in kwargs or in form parameters, and its value is
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    'unit_ref'
    """
    try:
        # first check for unit_type specified in form params
        unit_type = req.form['unit_type']
        return int(unit_type == 'unit_ref')
    except KeyError:
        # if it's not, look if we're in the context of a archive unit or its first level choice
        if entity is None:
            assert rset is not None, \
                ('is_archive_unit_ref can only be used in the context of a SEDAArchiveUnit '
                 'or SEDAAltArchiveUnitArchiveUnitRefId entity, but no context entity specified')
            entity = rset.get_entity(0, 0)
        if entity.cw_etype == 'SEDAArchiveUnit':
            entity = entity.first_level_choice
75
        elif entity.cw_etype == 'SEDAArchiveUnitRefId':
76
77
            if not entity.seda_archive_unit_ref_id_from:
                return 0  # other kind of reference
78
79
80
            entity = entity.seda_archive_unit_ref_id_from[0]
            if entity.cw_etype != 'SEDAAltArchiveUnitArchiveUnitRefId':
                return 0  # other kind of reference
81
        assert entity.cw_etype == 'SEDAAltArchiveUnitArchiveUnitRefId', \
82
83
            ('is_archive_unit_ref can only be used in the context of a SEDAArchiveUnit, '
             'SEDAArchiveUnitRefId or SEDAAltArchiveUnitArchiveUnitRefId entity, not %s' % entity)
84
85
86
        return 0 if entity.content_sequence else 1


87
88
89
90
91
92
93
94
95
96
@objectify_predicate
def is_simple_keyword(cls, req, rset=None, entity=None, **kwargs):
    """Return 1 if a keyword_type value is specified in kwargs or in form parameters, and its value is
    'simple_keyword', or if given entity is not linked to a keyword reference.
    """
    try:
        # first check for unit_type specified in form params
        unit_type = req.form['keyword_type']
        return int(unit_type == 'simple_keyword')
    except KeyError:
97
        if entity is not None and not entity.reverse_seda_keyword_reference_from:
98
99
100
101
            return 1
        return 0


102
@objectify_predicate
103
104
105
def typed_reference(cls, req, entity=None, **kwargs):
    """Return positive score for content's typed data object references (IsPartOf, VersionOf, etc.),
    not those starting directly from archive unit.
106
    """
107
108
109
110
111
    # code below don't handle properly the case where entity isn't yet created while rtype isn't
    # specified (e.g. because it's an inlined form). To avoid false positive, we've to also ensure
    # we're within a full seda 2 profile (typed references aren't allowed in simplified profiles)
    if not is_full_seda2_profile(entity, kwargs.get('rset')):
        return 0
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
    if entity is None or not entity.has_eid():
        try:
            rtype, eid, role = req.form['__linkto'].split(':')
        except KeyError:
            pass
        else:
            if rtype == 'seda_data_object_reference':
                entity = req.entity_from_eid(eid)
            else:
                return 0
    else:
        entity = entity.seda_data_object_reference[0]
    if entity is not None and entity.cw_etype == CONTENT_ETYPE:
        return 0
    return 1


afs = uicfg.autoform_section
affk = uicfg.autoform_field_kwargs
pvs = uicfg.primaryview_section
pvdc = uicfg.primaryview_display_ctrl
rec = uicfg.reledit_ctrl


136
137
138
139
140
141
142
def unit_ref_vocabulary(form, field):
    """Form vocabulary function for archive unit references, necessary to get parent container while
    the entity is being created.
    """
    req = form._cw
    parent, container = parent_and_container(form.edited_entity)
    assert container is not None
143
144
    rset = req.execute('Any X, XUA ORDERBY XUA WHERE '
                       'X is SEDAArchiveUnit, X user_annotation XUA, X container R, R eid %(root)s',
145
                       {'root': container.eid})
146
    return [(entity.dc_title(), str(entity.eid)) for entity in rset.entities()]
147

148

149
150
151
152
affk.tag_subject_of(('SEDAArchiveUnitRefId', 'seda_archive_unit_ref_id_to', '*'),
                    {'choices': unit_ref_vocabulary})


153
154
155
156
157
158
159
def do_ref_vocabulary(form, field):
    """Form vocabulary function for data object references, necessary to get parent container while
    the entity is being created.
    """
    req = form._cw
    parent, container = parent_and_container(form.edited_entity)
    assert container is not None
160
161
    rset = req.execute('Any X, XUA ORDERBY XUA WHERE '
                       'X is IN(SEDABinaryDataObject, SEDAPhysicalDataObject), '
162
                       'X user_annotation XUA, X container R, R eid %(root)s',
163
                       {'root': container.eid})
164
    return [(entity.dc_title(), str(entity.eid)) for entity in rset.entities()]
165
166
167
168
169
170


for rtype in ('seda_data_object_reference_id', 'seda_target'):
    affk.tag_subject_of(('*', rtype, '*'), {'choices': do_ref_vocabulary})


171
172
173
174
175
pvs.tag_subject_of(
    ('SEDAArchiveUnit', 'seda_alt_archive_unit_archive_unit_ref_id', '*'),
    'hidden')


176
177
178
179
180
class SkipIBreadCrumbsAdapter(compound.IContainedBreadcrumbsAdapter):
    """IBreadCrumbsAdapter for entities which should not appears in breadcrumb, we want to go back to
    the parent
    """
    __select__ = is_instance('SEDAAltArchiveUnitArchiveUnitRefId',
181
                             CONTENT_ETYPE)
182
183
184
185
186
187
188
189
190
191

    def breadcrumbs(self, view=None, recurs=None):
        parent = self.parent_entity()
        adapter = parent.cw_adapt_to('IBreadCrumbs')
        return adapter.breadcrumbs(view, recurs)


class SkipInContextView(baseviews.InContextView):
    """Custom incontext view, for use in title of creation form, among others"""
    __select__ = is_instance('SEDAAltArchiveUnitArchiveUnitRefId',
192
                             CONTENT_ETYPE)
193
194
195

    def cell_call(self, row, col):
        entity = self.cw_rset.get_entity(row, col)
196
        parent_archive_unit(entity).view('incontext', w=self.w)
197
198


199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
class ArchiveUnitSubObjectsTab(viewlib.SubObjectsTab):
    """Abstract subobjects tab specific to archive unit to handle subentities below choice>sequence
    child transparently.
    """

    __abstract__ = True
    __select__ = is_instance('SEDAArchiveUnit') & ~is_archive_unit_ref()

    def entity_call(self, entity):
        seq = entity.first_level_choice.content_sequence
        self.display_add_button(seq)
        self.display_subobjects_list(seq)

    def url_params(self, entity):
        archive_unit = parent_archive_unit(entity)
        return {'__redirectparams': 'tab=' + self.__regid__,
                '__redirectpath': archive_unit.rest_path()}

    def parent(self, entity):
        return parent_archive_unit(entity)


class ArchiveUnitContentTab(tabs.TabsMixin, EntityView):
    """Base class for tabs whose content is generated by redirecting to a view on archive unit's
    content.
    """

    __abstract__ = True
    __select__ = ArchiveUnitSubObjectsTab.__select__
    content_vid = None  # set in concrete class

    def entity_call(self, entity):
        seq = entity.first_level_choice.content_sequence
        seq.view(self.content_vid, w=self.w)


class ContentSubObjectsView(viewlib.SubObjectsTab):
    """Base class to display subobjects of archive unit's content as if they were directly linked
    to it.
    """

    __abstract__ = True
    __select__ = is_instance(CONTENT_ETYPE)
    tabid = None  # set in concrete class

    def url_params(self, entity):
        params = super(ContentSubObjectsView, self).url_params(entity)
        params['__redirectpath'] = self.parent(entity).rest_path()
        return params

    def parent(self, entity):
        return (entity
                .reverse_seda_seq_alt_archive_unit_archive_unit_ref_id_management[0]
                .reverse_seda_alt_archive_unit_archive_unit_ref_id[0])


255
class ArchiveUnitTabbedPrimaryView(tabs.TabbedPrimaryView):
256
    __select__ = is_instance('SEDAArchiveUnit')
257
258
259

    tabs = [
        'main_tab',
260
        _('seda_management_tab'),
261
        _('seda_archive_units_tab'),
262
        _('seda_data_objects_tab'),
263
        # Content tabs
264
265
266
267
268
269
        _('seda_identification_tab'),
        _('seda_dates_tab'),
        _('seda_gps_tab'),
        _('seda_services_tab'),
        _('seda_agents_tab'),
        _('seda_coverage_tab'),
270
        _('seda_indexation_tab'),
271
272
        _('seda_relations_tab'),
        _('seda_events_tab'),
273
274
        _('seda_history_tab'),

275
276
    ]

277
278
    def entity_call(self, entity, **kwargs):
        super(ArchiveUnitTabbedPrimaryView, self).entity_call(entity, **kwargs)
279
        rwdg.bootstrap_dialog(self.w, self._cw._, clone._import_div_id(entity))
280
281


Sylvain Thénault's avatar
Sylvain Thénault committed
282
# main tab for archive unit reference ##########################################
283

284
285
au_ref_pvs = pvs.derive(__name__,
                        is_instance('SEDAArchiveUnit') & is_archive_unit_ref())
286
au_ref_pvs.tag_subject_of(
287
288
289
290
    ('SEDAArchiveUnit', 'seda_alt_archive_unit_archive_unit_ref_id', '*'),
    'attributes')
rec.tag_subject_of(('SEDAArchiveUnit', 'seda_alt_archive_unit_archive_unit_ref_id', '*'),
                   {'rvid': 'seda.reledit.simplelink',
291
                    'novalue_label': ' '})
292
293
294
295
296
297
298
299
300
301
302
303


class RefArchiveUnitSimpleLinkToEntityAttributeView(EntityView):
    __regid__ = 'seda.reledit.simplelink'
    __select__ = is_instance('SEDAAltArchiveUnitArchiveUnitRefId') & is_archive_unit_ref()

    def entity_call(self, entity):
        entity.reference.view('seda.reledit.complexlink',
                              initargs={'rtype': 'seda_archive_unit_ref_id_from'},
                              w=self.w)


304
305
# management tab ###############################################################

306
class ArchiveUnitManagementTab(viewlib.PrimaryTabWithoutBoxes):
307
308
    """Display management information about an archive unit."""

309
    __regid__ = 'seda_management_tab'
310
    __select__ = is_instance('SEDAArchiveUnit') & ~is_archive_unit_ref()
311
312
313
314
315
316
317
318
319
320

    rtype_role_targets = [
        ('seda_storage_rule', 'object', None),
        ('seda_appraisal_rule', 'object', None),
        ('seda_access_rule', 'object', None),
        ('seda_dissemination_rule', 'object', None),
        ('seda_reuse_rule', 'object', None),
        ('seda_classification_rule', 'object', None),
        ('seda_need_authorization', 'object', None),
    ]
321
    rsection, display_ctrl = rtags_from_rtype_role_targets(
322
        CONTENT_ETYPE, rtype_role_targets
323
    )
324

325
    def entity_call(self, entity, **kwargs):
326
        seq = entity.first_level_choice.content_sequence
327
        super(ArchiveUnitManagementTab, self).entity_call(seq, **kwargs)
328
329


330
331
332
333
334
335
336
337
class SimplifiedArchiveUnitManagementTab(ArchiveUnitManagementTab):
    __select__ = ArchiveUnitManagementTab.__select__ & simplified_profile()

    rtype_role_targets = [
        ('seda_appraisal_rule', 'object', None),
        ('seda_access_rule', 'object', None),
    ]
    rsection, display_ctrl = rtags_from_rtype_role_targets(
338
        CONTENT_ETYPE, rtype_role_targets
339
340
341
    )


342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
# identification tab ###########################################################

class ArchiveUnitIdentificationTab(ArchiveUnitContentTab):
    """Display identification information about a full seda2 archive unit."""

    __regid__ = 'seda_identification_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_identification'


class ContentIdentificationView(viewlib.PrimaryTabWithoutBoxes):
    """Display identification information about an archive unit content."""

    __regid__ = 'seda_content_identification'
    __select__ = is_instance(CONTENT_ETYPE)

    rtype_role_targets = [
        ('seda_source', 'object', None),
        ('seda_file_plan_position', 'object', None),
        ('seda_system_id', 'object', None),
        ('seda_originating_system_id', 'object', None),
        ('seda_archival_agency_archive_unit_identifier', 'object', None),
        ('seda_originating_agency_archive_unit_identifier', 'object', None),
        ('seda_transferring_agency_archive_unit_identifier', 'object', None),
    ]
    rsection, display_ctrl = rtags_from_rtype_role_targets(CONTENT_ETYPE, rtype_role_targets)


# dates tab ####################################################################

class ArchiveUnitDatesTab(ArchiveUnitContentTab):
    """Display dates information about a full seda2 archive unit."""

    __regid__ = 'seda_dates_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_dates'


class ContentDatesView(viewlib.PrimaryTabWithoutBoxes):
    """Display dates information about an archive unit content."""

    __regid__ = 'seda_content_dates'
    __select__ = is_instance(CONTENT_ETYPE)

    rtype_role_targets = [
        ('seda_created_date', 'object', None),
        ('seda_transacted_date', 'object', None),
        ('seda_acquired_date', 'object', None),
        ('seda_sent_date', 'object', None),
        ('seda_received_date', 'object', None),
        ('seda_registered_date', 'object', None),
        ('seda_start_date', 'object', None),
        ('seda_end_date', 'object', None),
    ]
    rsection, display_ctrl = rtags_from_rtype_role_targets(CONTENT_ETYPE, rtype_role_targets)


# GPS tab ######################################################################

class ArchiveUnitGPSTab(ArchiveUnitContentTab):
    """Display GPS information about a full seda2 archive unit."""

    __regid__ = 'seda_gps_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_gps'


class ContentGPSView(viewlib.PrimaryTabWithoutBoxes):
    """Display GPS information about an archive unit content."""

    __regid__ = 'seda_content_gps'
    __select__ = is_instance(CONTENT_ETYPE)

    rsection, display_ctrl = rtags_from_xsd_element(CONTENT_ETYPE, 'Gps')


# services tab #################################################################

class ArchiveUnitServicesTab(ArchiveUnitContentTab):
    """Display services related to a full seda2 archive unit."""

    __regid__ = 'seda_services_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_services'


class ContentServicesView(viewlib.PrimaryTabWithoutBoxes):
    """Display services related to an archive unit content."""

    __regid__ = 'seda_content_services'
    __select__ = is_instance(CONTENT_ETYPE)

    rtype_role_targets = [
        ('seda_originating_agency_from', 'object', None),
        ('seda_submission_agency_from', 'object', None),
        ('seda_authorized_agent_from', 'object', None),
    ]
    rsection, display_ctrl = rtags_from_rtype_role_targets(CONTENT_ETYPE, rtype_role_targets)


# agents tab ###################################################################

class ArchiveUnitAgentsTab(ArchiveUnitContentTab):
    """Display agents related to a full seda2 archive unit."""

    __regid__ = 'seda_agents_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_agents'


452
class ContentAgentsView(ContentSubObjectsView):
453
454
455
456
    """Display agents related to an archive unit content."""

    __regid__ = 'seda_content_agents'
    __select__ = is_instance(CONTENT_ETYPE)
457
    tabid = ArchiveUnitAgentsTab.__regid__
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

    rtype_role_targets = [
        ('seda_writer_from', 'object', None),
        ('seda_addressee_from', 'object', None),
        ('seda_recipient_from', 'object', None),
    ]

    _('creating SEDAWriter (SEDAWriter seda_writer_from '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDAAddressee (SEDAAddressee seda_addressee_from '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDARecipient (SEDARecipient seda_recipient_from '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linto)s)')


# coverage tab #################################################################

class ArchiveUnitCoverageTab(ArchiveUnitContentTab):
    """Display coverage information about a full seda2 archive unit."""

    __regid__ = 'seda_coverage_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_coverage'


483
class ContentCoverageView(ContentSubObjectsView):
484
485
486
487
    """Display coverage information about an archive unit content."""

    __regid__ = 'seda_content_coverage'
    __select__ = is_instance(CONTENT_ETYPE)
488
    tabid = ArchiveUnitCoverageTab.__regid__
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512

    rtype_role_targets = [('seda_spatial', 'object', None),
                          ('seda_temporal', 'object', None),
                          ('seda_juridictional', 'object', None)]

    _('creating SEDASpatial (SEDASpatial seda_spatial '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDATemporal (SEDATemporal seda_temporal '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDAJuridictional (SEDAJuridictional seda_juridictional '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')


class TypeListItemContentView(viewlib.ListItemContentView):
    """Extended list item content view including the entity's type (for case where the list may
    include entities of different types).
    """
    __select__ = is_instance('SEDAWriter', 'SEDAAddressee', 'SEDARecipient',
                             'SEDASpatial', 'SEDATemporal', 'SEDAJuridictional')

    def entity_call(self, entity):
        entity.view('seda.type_meta', w=self.w)


513
# indexation tab ###############################################################
514

515
516
class ArchiveUnitIndexationTab(ArchiveUnitContentTab):
    """Display content's indexation about an archive unit."""
517

518
519
    __regid__ = 'seda_indexation_tab'
    content_vid = 'seda_content_indexation'
520
521


522
523
class ContentIndexationView(ContentSubObjectsView):
    """Display indexation (keywords and tags) about an archive unit content."""
524

525
526
    __regid__ = 'seda_content_indexation'
    tabid = ArchiveUnitIndexationTab.__regid__
527

528
529
530
531
    rtype_role_targets = [
        ('seda_keyword', 'object', 'SEDAKeyword'),
        ('seda_tag', 'object', 'SEDATag'),
    ]
532
533
    keyword_custom_arguments = [
        ('keyword_type', 'concept_keyword', _('keyword concept')),
534
        ('keyword_type', 'simple_keyword', _('keyword simple')),
535
    ]
536

537
538
539
540
    _('creating SEDAKeyword (SEDAKeyword seda_keyword '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDATag (SEDATag seda_tag '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
541

542
543
544
545
546
547
548
549
550
    def display_add_button(self, entity):
        urlparams = self.url_params(entity)
        links = add_links_with_custom_arguments(entity, 'seda_keyword', 'object', urlparams,
                                                self.keyword_custom_arguments)
        rtype_roles = [(rtype, role) for rtype, role, _ in self.rtype_role_targets
                       if rtype != 'seda_keyword']
        links += viewlib.add_links_from_rtype_roles(entity, rtype_roles, urlparams)
        viewlib.display_add_button(self.w, links, entity._cw.__('add'))

551

552
class SimplifiedArchiveUnitContentIndexationView(ContentIndexationView):
553

554
    __select__ = ContentIndexationView.__select__ & simplified_profile()
555

556
    rtype_role_targets = [('seda_keyword', 'object', 'SEDAKeyword')]
557
558


559
560
561
562
563
564
565
566
567
class KeywordBusinessValueEntityView(viewlib.ListItemContentView):

    __select__ = viewlib.ListItemContentView.__select__ & is_instance('SEDAKeyword')

    def entity_call(self, entity):
        if entity.reverse_seda_keyword_reference_from:
            kwr = entity.reverse_seda_keyword_reference_from[0]
            if kwr.concept:
                kwr_value = kwr.concept.view('oneline')
568
                msg = xml_escape(self._cw._('keyword concept: {0}')).format(kwr_value)
569
570
571
572
            elif kwr.scheme:
                kwr_value = kwr.scheme.view('oneline')
                msg = xml_escape(self._cw._('keyword scheme: {0}')).format(kwr_value)
            else:
573
                msg = xml_escape(self._cw._('<no keyword scheme specified>'))
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
        else:
            if entity.keyword_content:
                content = entity.keyword_content
            else:
                content = self._cw._('<no value specified>')
            msg = xml_escape(self._cw._('keyword: {0}').format(content))
        self.w(u'<span class="value">{0} {1}</span>'.format(msg, entity.view('seda.xsdmeta')))

        if entity.reverse_seda_keyword_type_from:
            kwt = entity.reverse_seda_keyword_type_from[0]
            if kwt.seda_keyword_type_to:
                kwt_value = kwt.seda_keyword_type_to[0].label()
            else:
                kwt_value = self._cw._('<no type specified>')
            msg = xml_escape(self._cw._('keyword type: {0}').format(kwt_value))
            self.w(u'<br/><span>{0} {1}</span>'.format(msg, kwt.view('seda.xsdmeta')))
590
591
592
593


afs.tag_subject_of(('SEDAKeywordReference', 'seda_keyword_reference_to_scheme', '*'),
                   'main', 'attributes')
594
595
affk.set_field_kwargs('SEDAKeywordReference', 'seda_keyword_reference_to_scheme',
                      help=_('select a type to filter out unrelated vocabularies'))
596
affk.set_field_kwargs('SEDAKeywordReference', 'seda_keyword_reference_to',
597
                      help=_('select first a vocabulary then type here to prompt auto-completion'),
598
599
600
601
602
603
604
                      widget=widgets.ConceptAutoCompleteWidget(
                          slave_name='seda_keyword_reference_to',
                          master_name='seda_keyword_reference_to_scheme'))
affk.set_fields_order('SEDAKeywordReference', ['user_cardinality',
                                               'seda_keyword_reference_to_scheme',
                                               'seda_keyword_reference_to'])

605
606
607
608
# add rule in afs for 'complex keyword'
afs.tag_attribute(('SEDAKeyword', 'keyword_content'), 'main', 'hidden')
afs.tag_attribute(('SEDAKeywordReference', 'user_cardinality'), 'main', 'hidden')
# custom afs to handle 'simple keyword'
609
610
kw_simple_afs = afs.derive(__name__,
                           is_instance('SEDAKeyword') & is_simple_keyword())
611
612
613
614
615
kw_simple_afs.tag_attribute(('SEDAKeyword', 'keyword_content'), 'main', 'attributes')
kw_simple_afs.tag_object_of(
    ('*', 'seda_keyword_reference_from', 'SEDAKeyword'),
    'main', 'hidden')
# but one ordering is enough to rule them all
616
617
618
affk.set_fields_order('SEDAKeyword', [('seda_keyword_type_from', 'object'),
                                      'keyword_content',
                                      ('seda_keyword_reference_from', 'object')])
619

620
621
622
623
affk.set_field_kwargs('SEDAKeywordType', 'seda_keyword_type_to',
                      widget=widgets.KeywordTypeMasterWidget(
                          slave_base_name='seda_keyword_reference_to_scheme'))

624
625
626
627
628

class ComplexKeywordAutomaticEntityForm(autoform.AutomaticEntityForm):
    __select__ = (is_instance('SEDAKeyword') & ~is_simple_keyword())

    def should_display_inline_creation_form(self, rschema, existing, card):
629
630
        # force display of type and keyword
        if not existing and rschema in ('seda_keyword_type_from', 'seda_keyword_reference_from'):
631
            return True
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
        return False

    def should_display_add_new_relation_link(self, rschema, existing, card):
        return False


class ComplexKeywordEditionFormView(autoform.InlineEntityEditionFormView):
    __select__ = (autoform.InlineEntityEditionFormView.__select__
                  & is_instance('SEDAKeywordType', 'SEDAKeywordReference')
                  & ~is_simple_keyword())
    removejs = None


class ComplexKeywordCreationFormView(autoform.InlineEntityCreationFormView):
    __select__ = (autoform.InlineEntityCreationFormView.__select__
                  & specified_etype_implements('SEDAKeywordType', 'SEDAKeywordReference')
                  & ~is_simple_keyword())
    removejs = None
650

651
652
653
654
655
656
657

# relations tab ################################################################

class ArchiveUnitRelationsTab(ArchiveUnitContentTab):
    """Display content's relations about a full seda2  archive unit."""

    __regid__ = 'seda_relations_tab'
658
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
    content_vid = 'seda_content_relations'


class ContentRelationsView(ContentSubObjectsView):
    """Display relation information about an archive unit content."""

    __regid__ = 'seda_content_relations'
    tabid = ArchiveUnitRelationsTab.__regid__

    rtype_role_targets = [('seda_is_version_of', 'object', None),
                          ('seda_replaces', 'object', None),
                          ('seda_requires', 'object', None),
                          ('seda_is_part_of', 'object', None),
                          ('seda_references', 'object', None)]

    _('creating SEDAIsVersionOf (SEDAIsVersionOf seda_is_version_of '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDAReplaces (SEDAReplaces seda_replaces '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDARequires (SEDARequires seda_requires '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDAIsPartOf (SEDAIsPartOf seda_is_part_of '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
    _('creating SEDAReferences (SEDAReferences seda_references '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')


class ReferenceListItemContentView(viewlib.ListItemContentView):
    __select__ = is_instance('SEDAIsVersionOf', 'SEDAReplaces', 'SEDARequires', 'SEDAIsPartOf',
                             'SEDAReferences')

    def entity_call(self, entity):
        self.w(u'<b>{} '.format(entity.dc_type()))
        entity.view('seda.xsdmeta')
        self.w(u'</b> :')
        alt_rtype = 'seda_alt_{}_archive_unit_ref_id'.format(un_camel_case(entity.cw_etype[4:]))
        alt = entity.related(alt_rtype).one()
        alternatives = viewlib.alternative_values(alt, alt_rtype)
        self.w(u'<div class="value alternative">')
        if alternatives:
            self.w(alternatives)
        else:
            self.wdata(self._cw._('<no value specified>'))
        self.w(u'</div>')
        self.w(u'<div class="clearfix"/>')


706
707
do_ref_afs = afs.derive(__name__,
                        is_instance('SEDADataObjectReference') & typed_reference())
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
do_ref_afs.tag_attribute(('SEDADataObjectReference', 'user_cardinality'), 'main', 'hidden')

for etype in ('SEDAAltIsPartOfArchiveUnitRefId',
              'SEDAAltIsVersionOfArchiveUnitRefId',
              'SEDAAltReferencesArchiveUnitRefId',
              'SEDAAltReplacesArchiveUnitRefId',
              'SEDAAltRequiresArchiveUnitRefId'):
    affk.set_fields_order(etype, [('seda_data_object_reference', 'object'),
                                  ('seda_repository_object_pid', 'object'),
                                  ('seda_archive_unit_ref_id_from', 'object'),
                                  ('seda_repository_archive_unit_pid', 'object')])


# event tab ####################################################################

class ArchiveUnitEventsTab(ArchiveUnitContentTab):
    """Display content's relations about a full seda2 archive unit."""

    __regid__ = 'seda_events_tab'
    __select__ = ArchiveUnitContentTab.__select__ & full_seda2_profile()
    content_vid = 'seda_content_events'


class ContentEventsView(ContentSubObjectsView):
    """Display events about an archive unit content."""

    __regid__ = 'seda_content_events'
    tabid = ArchiveUnitEventsTab.__regid__

    rtype_role_targets = [
        ('seda_event', 'object', None),
    ]

    _('creating SEDAEvent (SEDAEvent seda_event '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')


class EventListItemContentView(viewlib.ListItemContentView):

    __select__ = viewlib.ListItemContentView.__select__ & is_instance('SEDAEvent')

    def entity_call(self, entity):
        entity.view('seda.xsdmeta', w=self.w, skip_one_card=True, with_annotation=False)
        attrs = []
        for rtype in ['seda_event_type_from',
                      'seda_event_identifier',
                      'seda_event_detail']:
            related = getattr(entity, 'reverse_' + rtype)
            if related:
                if related[0].user_cardinality == '1':
                    card = self._cw._('mandatory')
                else:
                    card = self._cw._('optional')
                value = ''
                if rtype == 'seda_event_type_from':
                    value = related[0].seda_event_type_to
                    if value:
                        value = value[0].label()
                attrs.append(u'{rtype} {value} {card}'.format(rtype=self._cw.__(rtype + '_object'),
                                                              value=value,
                                                              card=card))
        if attrs:
            self.w(u' ({0})'.format(', '.join(attrs)))
        description = getattr(entity, 'user_annotation', None)
        if description:
            self.w(u' <div class="description text-muted">%s</div>' % description)


affk.set_fields_order('SEDAEvent', ['user_cardinality',
                                    ('seda_event_type_from', 'object'),
                                    ('seda_event_identifier', 'object'),
                                    ('seda_event_detail', 'object')])


782
# history tab ##################################################################
783

784
785
class ArchiveUnitHistoryTab(ArchiveUnitContentTab):
    """Display content's custodial history about an archive unit."""
786

787
788
    __regid__ = 'seda_history_tab'
    content_vid = 'seda_content_history'
789
790


791
792
793
794
795
796
797
798
799
800
class ContentHistoryView(ContentSubObjectsView):
    """Display custodial history information about an archive unit content."""

    __regid__ = 'seda_content_history'
    tabid = ArchiveUnitHistoryTab.__regid__

    rtype_role_targets = [('seda_custodial_history_item', 'object', None)]

    _('creating SEDACustodialHistoryItem (SEDACustodialHistoryItem seda_custodial_history_item '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')
801
802


803
804
805
806
807
808
809
810
811
class CustodialHistoryItemListItemContentView(viewlib.ListItemContentView):

    __select__ = viewlib.ListItemContentView.__select__ & is_instance('SEDACustodialHistoryItem')

    def entity_call(self, entity):
        super(CustodialHistoryItemListItemContentView, self).entity_call(entity)
        if entity.reverse_seda_when:
            when = entity.reverse_seda_when[0]
            if when.user_cardinality == '1':
812
                self.w(u' ({})'.format(self._cw._('mandatory timestamp')))
813
            else:
814
                self.w(u' ({})'.format(self._cw._('optional timestamp')))
815
816


817
# main tab for archive unit content ############################################
818

819
820
821
822
class ArchiveUnitPrimaryTab(tabs.PrimaryTab):
    """Overriden primary tab to display attributes from both the archive unit and it's content
    sequence.
    """
823

824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
    __select__ = is_instance('SEDAArchiveUnit') & ~is_archive_unit_ref()

    def render_entity_attributes(self, entity):
        """Renders all attributes and relations in the 'attributes' section.
        """
        display_attributes = list(self._display_attributes(entity))
        seq = entity.first_level_choice.content_sequence
        view = self._cw.vreg['views'].select('seda_content_main', self._cw, rset=seq.as_rset())
        display_attributes += view._display_attributes(seq)
        if display_attributes:
            self.w(u'<table class="table cw-table-primary-entity">')
            for rschema, role, dispctrl, value in display_attributes:
                label = self._rel_label(entity, rschema, role, dispctrl)
                self.render_attribute(label, value, table=True)
            self.w(u'</table>')


# add as a monkey patch the first step of original 'render_entity_attributes'
# method, which is unfortunatly monolitic in cubicweb. We need this so we can
# have attributes from two distinct entities as if it was only one.

@monkeypatch(tabs.PrimaryTab)
def _display_attributes(self, entity):
    for rschema, targets, role, dispctrl in self._section_def(entity, 'attributes'):
        vid = dispctrl.get('vid', 'reledit')
        if rschema.final or vid == 'reledit' or dispctrl.get('rtypevid'):
            value = entity.view(vid, rtype=rschema.type, role=role,
                                initargs={'dispctrl': dispctrl})
        else:
            rset = self._relation_rset(entity, rschema, role, dispctrl)
            if rset:
                value = self._cw.view(vid, rset)
            else:
                value = None
        if value is not None and value != '':
            yield (rschema, role, dispctrl, value)


content_ordered_fields = [
863
    ('seda_description_level_from', 'object'),
864
    ('seda_title', 'object'),
865
866
    ('seda_start_date', 'object'),
    ('seda_end_date', 'object'),
867
    ('seda_description', 'object'),
868
869
870
    ('seda_originating_agency_from', 'object'),
    ('seda_transferring_agency_archive_unit_identifier', 'object'),
    ('seda_system_id', 'object'),
871
872
873
874
875
876
877
    ('seda_version', 'object'),
    ('seda_type_from', 'object'),
    ('seda_document_type', 'object'),
    ('seda_status', 'object'),
    ('seda_language_from', 'object'),
    ('seda_description_language_from', 'object'),
]
878
879
880
881
882
883
884
885


class ContentMainView(viewlib.PrimaryTabWithoutBoxes):
    """Display content information which are not in a dedicated tab."""

    __regid__ = 'seda_content_main'
    __select__ = is_instance(CONTENT_ETYPE)

886
887
888
    rtype_role_targets = [field_def + (None,) for field_def in content_ordered_fields]
    rsection, display_ctrl = rtags_from_rtype_role_targets(CONTENT_ETYPE, rtype_role_targets)

889
890
891
892
893
894
895

class SimplifiedContentMainView(ContentMainView):
    """Display content information which are not in a dedicated tab for a simplified archive unit.
    """
    __select__ = ContentMainView.__select__ & simplified_profile()

    rtype_role_targets = [
896
        ('seda_description_level_from', 'object', None),
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
        ('seda_title', 'object', None),
        ('seda_start_date', 'object', None),
        ('seda_end_date', 'object', None),
        ('seda_description', 'object', None),
        ('seda_originating_agency_from', 'object', None),
        ('seda_transferring_agency_archive_unit_identifier', 'object', None),
        ('seda_system_id', 'object', None),
        ('seda_language_from', 'object', None),
    ]
    rsection, display_ctrl = rtags_from_rtype_role_targets(CONTENT_ETYPE, rtype_role_targets)


for rtype, role in content_ordered_fields:
    if role == 'subject':
        pvs.tag_subject_of((CONTENT_ETYPE, rtype, '*'), 'attributes')
    else:
        pvs.tag_object_of(('*', rtype, CONTENT_ETYPE), 'attributes')
914
    if rtype == 'seda_description_level_to':
915
916
        novalue_label = _('<no value specified>')
    else:
917
        novalue_label = ' '
918
    vid = 'seda.reledit.complexlink' if rtype.endswith('_from') else 'seda.reledit.text'
919
920
921
922
923
924
925
926
927
    if role == 'subject':
        rec.tag_subject_of((CONTENT_ETYPE, rtype, '*'),
                           {'rvid': vid, 'novalue_label': novalue_label})
    else:
        rec.tag_object_of(('*', rtype, CONTENT_ETYPE),
                          {'rvid': vid, 'novalue_label': novalue_label})

pvs.tag_object_of(('*', 'seda_seq_alt_archive_unit_archive_unit_ref_id_management', '*'), 'hidden')

928
for rtype in ('seda_description_level_to', 'seda_language_to', 'seda_description_language_to',
929
930
931
932
933
934
              'seda_archival_agency', 'seda_transferring_agency',
              'seda_originating_agency_to', 'seda_submission_agency_to',
              'seda_authorized_agent_to',
              'seda_writer_to', 'seda_addressee_to', 'seda_recipient_to'):
    affk.tag_subject_of(('*', rtype, '*'),
                        {'widget': rwdg.RelationFacetWidget})
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956

affk.set_fields_order(CONTENT_ETYPE,
                      ['user_cardinality', 'user_annotation'] + content_ordered_fields)
pvdc.set_fields_order(CONTENT_ETYPE,
                      ['user_cardinality', 'user_annotation'] + content_ordered_fields)

# remove from relations section and autoform what is shown in tabs
for cls in (ContentIdentificationView,
            ContentDatesView,
            ContentServicesView,
            ContentAgentsView,
            ContentIndexationView,
            ContentEventsView):
    for rtype, role, target in cls.rtype_role_targets:
        if role == 'object':
            pvs.tag_object_of(('*', rtype, CONTENT_ETYPE), 'hidden')
            afs.tag_object_of(('*', rtype, CONTENT_ETYPE), 'main', 'hidden')
        else:
            pvs.tag_subject_of((CONTENT_ETYPE, rtype, '*'), 'hidden')
            afs.tag_subject_of((CONTENT_ETYPE, rtype, '*'), 'main', 'hidden')


957
# archive units tab ############################################################
958

959
class ArchiveUnitArchiveUnitsTab(ArchiveUnitSubObjectsTab):
960
    """Tab for sub-archive units of an archive unit"""
961

962
    __regid__ = 'seda_archive_units_tab'
963
964
965

    rtype = 'seda_archive_unit'
    role = 'object'
966
967
968
969
    unit_custom_arguments = [
        ('unit_type', 'unit_content', _('archive unit (content)')),
        ('unit_type', 'unit_ref', _('archive unit (reference)')),
    ]
970
971
972
973

    _('creating SEDAArchiveUnit (SEDAArchiveUnit seda_archive_unit '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')

974
975
    def display_add_button(self, entity):
        urlparams = self.url_params(entity)
976
977
        links = add_links_with_custom_arguments(entity, self.rtype, self.role, urlparams,
                                                self.unit_custom_arguments)
978
979
980
        if links:
            import_url = clone.import_unit_url(self._cw, parent_archive_unit(entity))
            links.append(tags.a(self._cw._('import_unit'), href=import_url))
981
        viewlib.display_add_button(self.w, links, self._cw.__('add'))
982
983
984

    def display_subobjects_list(self, entity):
        rset = entity.related(self.rtype, self.role)
985
986
        if rset:
            subvid = 'seda.listitem'
987
988
            self._cw.view('list', rset=rset, w=self.w, subvid=subvid,
                          parent=self.parent(entity), tabid=self.__regid__)
989
990


991
992
993
994
class SimplifiedArchiveUnitArchiveUnitsTab(ArchiveUnitArchiveUnitsTab):

    __select__ = ArchiveUnitArchiveUnitsTab.__select__ & simplified_profile()

995
996
997
    unit_custom_arguments = [
        ('unit_type', 'unit_content', _('archive unit (content)')),
    ]
998
999


1000
1001
# data objects tab #############################################################

1002
class ArchiveUnitDataObjectReferencesTab(ArchiveUnitSubObjectsTab):
1003
    """Tab for data object references of an archive unit"""
1004

1005
    __regid__ = 'seda_data_objects_tab'
1006
1007
1008
1009
1010
1011
1012

    rtype_role_targets = [('seda_data_object_reference', 'object', None)]

    _('creating SEDADataObjectReference (SEDADataObjectReference seda_data_object_reference '
      'SEDASeqAltArchiveUnitArchiveUnitRefIdManagement %(linkto)s)')


1013
1014
1015
1016
1017
1018
1019
1020
class SimplifiedArchiveUnitDataObjectReferencesTab(ArchiveUnitDataObjectReferencesTab):
    """Tab for data object references of an archive unit within a simplified transfer: see
    referenced data object as if they were children of the archive unit referencing them (only one
    reference is allowed in such case, so this is fine).
    """

    __select__ = ArchiveUnitDataObjectReferencesTab.__select__ & simplified_profile()

1021
1022
    rtype_role_targets = [('seda_binary_data_object', 'object', 'SEDABinaryDataObject')]

1023
    def display_add_button(self, entity):
1024
        rtype_roles = [(rtype, role) for rtype, role, _ in self.rtype_role_targets]
1025
        params = self.url_params(entity)
Noé Gaumont's avatar
Noé Gaumont committed
1026
        params['referenced_by'] = str(entity.eid)
1027
        transfer = entity.container[0]
1028
        links = []
1029
        if transfer.cw_etype == 'SEDAArchiveTransfer':
1030
            links = viewlib.add_links_from_rtype_roles(transfer, rtype_roles, params)
1031
            label = self._cw.__('add')
1032
1033
1034
1035
1036
        else:
            if has_rel_perm('add', entity, 'seda_data_object_reference', 'object'):
                vreg = self._cw.vreg
                url = vreg['etypes'].etype_class('SEDABinaryDataObject').cw_create_url(
                    self._cw, **params)
1037
1038
1039
                label = self._cw.__('seda_binary_data_object_object')
                links = [tags.a(label, href=url, title=self._cw.__('New SEDABinaryDataObject'))]
        viewlib.display_add_button(self.w, links, self._cw.__('add'))
1040
1041

    def display_subobjects_list(self, entity):
1042
        rset = self._cw.execute(
1043
1044
            'Any DO, DOUA, DOUC ORDERBY DOUA WHERE '
            'DO user_annotation DOUA, DO user_cardinality DOUC, '
1045
1046
1047
1048
1049
            'REF seda_data_object_reference_id DO, REF seda_data_object_reference SEQ, '
            'SEQ eid %(x)s', {'x': entity.eid})
        if rset:
            self._cw.view('list', rset=rset, parent=self.parent(entity), w=self.w,
                          subvid=self.subvid, tabid=self.tabid)
1050
1051


1052
1053
# reference / content archive unit forms #######################################

1054
1055
1056
1057
# Top level ArchiveUnit form: create to distinct forms, one form archive unit reference and the
# other for archive unit content. This is done by a mix of uicfg, form and renderer customization
# depending on a 'unit_type' parameter in form params.

1058
pvs.tag_object_of(('*', 'seda_data_object_reference', CONTENT_ETYPE),
1059
                  'hidden')
1060
afs.tag_object_of(('*', 'seda_data_object_reference', CONTENT_ETYPE),
1061
1062
                  'main', 'hidden')

1063
1064
1065
1066
1067
1068
1069
1070
# add rtags for content archive unit in default afs
afs.tag_object_of(
    ('*', 'seda_archive_unit_ref_id_from', 'SEDAAltArchiveUnitArchiveUnitRefId'),
    'inlined', 'hidden')
afs.tag_subject_of(
    ('SEDAAltArchiveUnitArchiveUnitRefId',
     'seda_seq_alt_archive_unit_archive_unit_ref_id_management', '*'),
    'inlined', 'inlined')
1071

1072
# and create a custom one for reference archive unit
1073
1074
1075
au_ref_afs = afs.derive(__name__,
                        is_instance('SEDAAltArchiveUnitArchiveUnitRefId')
                        & is_archive_unit_ref())
1076
1077
1078
1079
1080
1081
1082
1083
1084
au_ref_afs.tag_object_of(
    ('*', 'seda_archive_unit_ref_id_from', 'SEDAAltArchiveUnitArchiveUnitRefId'),
    'inlined', 'inlined')
au_ref_afs.tag_subject_of(
    ('SEDAAltArchiveUnitArchiveUnitRefId',
     'seda_seq_alt_archive_unit_archive_unit_ref_id_management', '*'),
    'inlined', 'hidden')


1085
1086
class AltArchiveUnitRefIdSimplifiedAutomaticEntityForm(widgets.SimplifiedAutomaticEntityForm):
    """Force display of AltArchiveUnitArchiveUnitRefId's sub-ArchiveUnitRefId or
1087
1088
    SeqAltArchiveUnitArchiveUnitRefIdManagement (uicfg will control which of them is displayed).
    """
1089

1090
    __select__ = (widgets.SimplifiedAutomaticEntityForm.__select__
1091
1092
1093
                  & is_instance('SEDAAltArchiveUnitArchiveUnitRefId'))


1094
1095
1096
1097
class ArchiveUnitNoTitleEntityInlinedFormRenderer(widgets.NoTitleEntityInlinedFormRenderer):
    """Don't display any title nor remove link for AltArchiveUnitArchiveUnitRefId,
    SeqAltArchiveUnitArchiveUnitRefIdManagement or ArchiveUnitRefId in the context of an archive
    unit reference.
1098
    """
1099

1100
    __select__ = (widgets.NoTitleEntityInlinedFormRenderer.__select__
1101
                  & (is_instance('SEDAAltArchiveUnitArchiveUnitRefId',
1102
                                 CONTENT_ETYPE)
1103
1104
                     | (is_instance('SEDAArchiveUnitRefId')
                        & is_archive_unit_ref())))
1105

1106

1107
copy_afs = afs.derive(__name__, afs.__select__ & match_form_params(vid='copy'))
1108
copy_afs.tag_subject_of(('*', 'seda_alt_archive_unit_archive_unit_ref_id', '*'), 'main', 'hidden')