a
    Dg%/                     @   s  d dl Z d dlZd dlmZ d dlmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZmZ ddlmZmZ dedfdedfdedfdedfdedfdedfdedfdedfded fd!ed"fd#ed$fd%ed&fd'ed(ffZG d)d* d*ejZG d+d, d,eZ G d-d. d.eZ!G d/d0 d0Z"d1d2 Z#G d3d4 d4e"eZ$G d5d6 d6ejZ%G d7d8 d8e%e"eZ&dS )9    N)DjangoJSONEncoder)validate_email)models)TemplateResponse)date_format)gettext_lazy)	send_mail)
FieldPanel)APIField)get_field_clean_name)	OrderablePage   )FormBuilderWagtailAdminFormPageFormZ
singlelinezSingle line text	multilinezMulti-line textemailZEmailnumberNumberurlURLZcheckboxZCheckboxZ
checkboxesZ
CheckboxesZdropdownz	Drop downZmultiselectzMultiple selectZradiozRadio buttonsdateDatedatetimez	Date/timehiddenzHidden fieldc                   @   s\   e Zd ZdZejedZeje	ej
dZejedddZdd Zd	d
 ZG dd dZdS )AbstractFormSubmissionz
    Data for a form submission.

    You can create custom submission model based on this abstract model.
    For example, if you need to save additional data or a reference to a user.
    )encoder)Z	on_deletezsubmit timeT)verbose_nameZauto_now_addc                 C   s   i | j d| jiS )zl
        Returns dict with form data.

        You can override this method to add additional data.
        submit_time)	form_datar   self r"   [/var/www/lab.imftr.de/x/nb_venv/lib/python3.9/site-packages/wagtail/contrib/forms/models.pyget_data1   s
    zAbstractFormSubmission.get_datac                 C   s   | j  S N)r   r    r"   r"   r#   __str__=   s    zAbstractFormSubmission.__str__c                   @   s    e Zd ZdZedZedZdS )zAbstractFormSubmission.MetaTzform submissionzform submissionsN)__name__
__module____qualname__abstract_r   Zverbose_name_pluralr"   r"   r"   r#   Meta@   s   r,   N)r'   r(   r)   __doc__r   Z	JSONFieldr   r   Z
ForeignKeyr   ZCASCADEpageZDateTimeFieldr+   r   r$   r&   r,   r"   r"   r"   r#   r   $   s   r   c                   @   s   e Zd ZdZdS )FormSubmissionzData for a Form submission.N)r'   r(   r)   r-   r"   r"   r"   r#   r/   F   s   r/   c                	       s6  e Zd ZdZejeddddeddZejedded	d
Zejedde	dZ
ejedddZejeddeddZejeddeddZejeddddZededededddedddedddgZedededededededgZdd  Z fd!d"ZG d#d$ d$Z  ZS )%AbstractFormFieldzD
    Database Fields required for building a Django Form field.
    name   T zDSafe name of the form field, the label converted to ascii_snake_case)r   
max_lengthblankdefault	help_textlabelzThe label of the form field)r   r4   r7   z
field type   )r   r4   choicesrequired)r   r6   r:   z_Comma or new line separated list of choices. Only applicable in checkboxes, radio and dropdown.)r   r5   r7   zdefault valuezKDefault value. Comma or new line separated values supported for checkboxes.z	help textr   r4   r5   r7   
field_typezformbuilder-type)	classnamezformbuilder-choicesdefault_valuezformbuilder-default
clean_namec                 C   s
   t | jS )a  
        Prepare an ascii safe lower_snake_case variant of the field name to use as the field key.
        This key is used to reference the field responses in the JSON store and as the field name in forms.
        Called for new field creation, validation of duplicate labels and form previews.
        When called, does not have access to the Page, nor its own id as the record is not yet created.
        )r   r8   r    r"   r"   r#   r      s    z&AbstractFormField.get_field_clean_namec                    s2   | j du }|r|  }|| _t j|i | dS )a  
        When new fields are created, generate a template safe ascii name to use as the
        JSON storage reference for this field. Previously created fields will be updated
        to use the legacy unidecode method via checks & _migrate_legacy_clean_name.
        We do not want to update the clean name on any subsequent changes to the label
        as this would invalidate any previously submitted data.
        N)pkr   r@   supersave)r!   argskwargsZis_newr@   	__class__r"   r#   rC      s
    	
zAbstractFormField.savec                   @   s   e Zd ZdZdgZdS )zAbstractFormField.MetaTZ
sort_orderN)r'   r(   r)   r*   Zorderingr"   r"   r"   r#   r,      s   r,   )r'   r(   r)   r-   r   	CharFieldr+   r@   r8   FORM_FIELD_CHOICESr=   ZBooleanFieldr;   Z	TextFieldr:   r?   r7   r	   Zpanelsr
   Z
api_fieldsr   rC   r,   __classcell__r"   r"   rF   r#   r0   J   sl   	







r0   c                       s   e Zd ZdZeZeZdZ fddZ	dd Z
dd Zd	d
 Zdd Zdd Zdd Zdd Zdd Zdd Zd%ddZdd Zdd Zdedfded fgZ fd!d"Z fd#d$Z  ZS )&	FormMixinz9A mixin that adds form builder functionality to the page.Nc                    s@   t  j|i | t| ds<tj| j\}}|d | | _d S )Nlanding_page_templateZ_landing)rB   __init__hasattrospathsplitexttemplaterL   )r!   rD   rE   r1   extrF   r"   r#   rM      s    
zFormMixin.__init__c                 C   s
   | j  S )z
        Form page expects `form_fields` to be declared.
        If you want to change backwards relation name,
        you need to override this method.
        )Zform_fieldsallr    r"   r"   r#   get_form_fields   s    zFormMixin.get_form_fieldsc                 C   s(   dt dfg}|dd |  D 7 }|S )zJ
        Returns a list of tuples with (field_name, field_label).
        r   zSubmission datec                 S   s   g | ]}|j |jfqS r"   )r@   r8   ).0fieldr"   r"   r#   
<listcomp>   s   z-FormMixin.get_data_fields.<locals>.<listcomp>)r+   rU   )r!   Zdata_fieldsr"   r"   r#   get_data_fields   s    
zFormMixin.get_data_fieldsc                 C   s   |  |  }| S r%   )form_builderrU   get_form_class)r!   Zfbr"   r"   r#   r[      s    zFormMixin.get_form_classc                 C   s   i S r%   r"   r    r"   r"   r#   get_form_parameters   s    zFormMixin.get_form_parametersc                 O   s(   |   }|  }|| ||i |S r%   )r[   r\   update)r!   rD   rE   Z
form_classZform_paramsr"   r"   r#   get_form   s    
zFormMixin.get_formc                 O   s   | j S r%   )rL   )r!   rD   rE   r"   r"   r#   get_landing_page_template   s    z#FormMixin.get_landing_page_templatec                 C   s   t S )z
        Returns submission class.

        You can override this method to provide custom submission class.
        Your class must be inherited from AbstractFormSubmission.
        )r/   r    r"   r"   r#   get_submission_class   s    zFormMixin.get_submission_classc                 C   s   ddl m} | jp|S )Nr   )SubmissionsListView)Zviewsra   submissions_list_view_class)r!   ra   r"   r"   r#   get_submissions_list_view_class   s    z)FormMixin.get_submissions_list_view_classc                 C   s   |   jj|j| dS )z
        Accepts form instance with submitted data, user and page.
        Creates submission instance.

        You can override this method if you want to have custom creation logic.
        For example, if you want to save reference to a user.
        )r   r.   )r`   Zobjectscreatecleaned_data)r!   formr"   r"   r#   process_form_submission   s    	
z!FormMixin.process_form_submissionc                 O   s$   |  |}||d< t|| ||S )z
        Renders the landing page.

        You can override this method to return a different HttpResponse as
        landing page. E.g. you could return a redirect to a separate page.
        form_submission)get_contextr   r_   )r!   requestrh   rD   rE   contextr"   r"   r#   render_landing_page   s
    
zFormMixin.render_landing_pagec                 O   s6   | dd}|  j|d}||g|R d| i|S )z
        Returns list submissions view for admin.

        `list_submissions_view_class` can be set to provide custom view class.
        Your class must be inherited from SubmissionsListView.
        results_onlyF)rm   Z	form_page)poprc   Zas_view)r!   rj   rD   rE   rm   viewr"   r"   r#   serve_submissions_list_view  s    z%FormMixin.serve_submissions_list_viewc                 O   s   |j dkrP| j|j|j| |jd}| r`| |}| j||g|R i |S n| j| |jd}| |}||d< t	|| 
||S )NPOSTr.   userrf   )methodr^   rq   ZFILESrs   Zis_validrg   rl   ri   r   Zget_template)r!   rj   rD   rE   rf   rh   rk   r"   r"   r#   serve  s"    


zFormMixin.serverf   ZFormlandingzLanding pagec                    s$   |dkr|  |S t ||S d S )Nrv   )rl   rB   serve_preview)r!   rj   	mode_namerF   r"   r#   rw   (  s    
zFormMixin.serve_previewc                    s&   t  ||}| j| |jd|d< |S )Nrr   rf   )rB   get_preview_contextr^   rs   )r!   rj   rx   rk   rF   r"   r#   ry   .  s    zFormMixin.get_preview_context)N)r'   r(   r)   r-   r   Zbase_form_classr   rZ   rb   rM   rU   rY   r[   r\   r^   r_   r`   rc   rg   rl   rp   ru   r+   Zpreview_modesrw   ry   rJ   r"   r"   rF   r#   rK      s,   	



rK   c                 C   s    |  dD ]}t|  q
d S )N,)splitr   strip)valueaddressr"   r"   r#   validate_to_address4  s    r   c                   @   s   e Zd ZdZG dd dZdS )AbstractFormz>A Form Page. Pages implementing a form should inherit from it.c                   @   s   e Zd ZdZdS )zAbstractForm.MetaTNr'   r(   r)   r*   r"   r"   r"   r#   r,   <  s   r,   Nr'   r(   r)   r-   r,   r"   r"   r"   r#   r   9  s   r   c                       s   e Zd ZdZejedddedegdZej	eddddZ
ejed	dddZ fd
dZdd Zdd ZG dd dZ  ZS )EmailFormMixinz:A mixin that adds email sending functionality to the form.z
to addressr2   TzeOptional - form submissions will be emailed to these addresses. Separate multiple addresses by comma.)r   r4   r5   r7   Z
validatorszfrom addressr<   subjectc                    s    t  |}| jr| | |S r%   )rB   rg   
to_addressr   )r!   rf   Z
submissionrF   r"   r#   rg   R  s    
z&EmailFormMixin.process_form_submissionc                 C   s2   dd | j dD }t| j| ||| j d S )Nc                 S   s   g | ]}|  qS r"   )r|   )rV   xr"   r"   r#   rX   Y      z,EmailFormMixin.send_mail.<locals>.<listcomp>rz   )r   r{   r   r   render_emailfrom_address)r!   rf   	addressesr"   r"   r#   r   X  s    zEmailFormMixin.send_mailc                 C   s   g }|j }|D ]t}|j|vrq||j}t|tr>d|}t|tjrVt|d}nt|tjrlt|d}|	|j
 d|  qd|S )Nz, ZSHORT_DATETIME_FORMATZSHORT_DATE_FORMATz: 
)re   r1   get
isinstancelistjoinr   r   r   appendr8   )r!   rf   contentre   rW   r}   r"   r"   r#   r   a  s    



zEmailFormMixin.render_emailc                   @   s   e Zd ZdZdS )zEmailFormMixin.MetaTNr   r"   r"   r"   r#   r,   x  s   r,   )r'   r(   r)   r-   r   rH   r+   r   r   Z
EmailFieldr   r   rg   r   r   r,   rJ   r"   r"   rF   r#   r   @  s$   

	r   c                   @   s   e Zd ZdZG dd dZdS )AbstractEmailFormzT
    A Form Page that sends email. Inherit from it if your form sends an email.
    c                   @   s   e Zd ZdZdS )zAbstractEmailForm.MetaTNr   r"   r"   r"   r#   r,     s   r,   Nr   r"   r"   r"   r#   r   |  s   r   )'r   rO   Zdjango.core.serializers.jsonr   Zdjango.core.validatorsr   Z	django.dbr   Zdjango.template.responser   Zdjango.utils.formatsr   Zdjango.utils.translationr   r+   Zwagtail.admin.mailr   Zwagtail.admin.panelsr	   Zwagtail.apir
   Zwagtail.contrib.forms.utilsr   Zwagtail.modelsr   r   Zformsr   r   rI   ZModelr   r/   r0   rK   r   r   r   r   r"   r"   r"   r#   <module>   sH   












"[ <