2025-05-15 10:43:26 +03:00
from crispy_forms . bootstrap import FormActions
from crispy_forms . helper import FormHelper
from crispy_forms . layout import Field , Layout , Submit
2020-12-15 23:33:43 +02:00
from django import forms
2025-04-05 12:44:21 +03:00
from django . conf import settings
2021-05-26 18:35:21 +03:00
from . methods import get_next_state , is_mediacms_editor
2025-05-15 10:43:26 +03:00
from . models import Category , Media , MEDIA_STATES , Subtitle
class CustomField ( Field ) :
template = ' cms/crispy_custom_field.html '
2020-12-15 23:33:43 +02:00
class MultipleSelect ( forms . CheckboxSelectMultiple ) :
input_type = " checkbox "
2025-05-15 10:43:26 +03:00
class MediaMetadataForm ( forms . ModelForm ) :
new_tags = forms . CharField ( label = " Tags " , help_text = " a comma separated list of tags. " , required = False )
2020-12-15 23:33:43 +02:00
class Meta :
model = Media
fields = (
" title " ,
" new_tags " ,
" add_date " ,
" uploaded_poster " ,
" description " ,
" enable_comments " ,
" thumbnail_time " ,
2025-05-15 10:43:26 +03:00
)
widgets = {
" new_tags " : MultipleSelect ( ) ,
" description " : forms . Textarea ( attrs = { ' rows ' : 4 } ) ,
" add_date " : forms . DateInput ( attrs = { ' type ' : ' date ' } ) ,
" thumbnail_time " : forms . NumberInput ( attrs = { ' min ' : 0 , ' step ' : 0.1 } ) ,
}
labels = {
" uploaded_poster " : " Poster Image " ,
" thumbnail_time " : " Thumbnail Time (seconds) " ,
}
help_texts = {
" title " : " " ,
" thumbnail_time " : " Select the time in seconds for the video thumbnail " ,
" uploaded_poster " : " Maximum file size: 5MB " ,
}
def __init__ ( self , user , * args , * * kwargs ) :
self . user = user
super ( MediaMetadataForm , self ) . __init__ ( * args , * * kwargs )
if self . instance . media_type != " video " :
self . fields . pop ( " thumbnail_time " )
if self . instance . media_type == " image " :
self . fields . pop ( " uploaded_poster " )
self . fields [ " new_tags " ] . initial = " , " . join ( [ tag . title for tag in self . instance . tags . all ( ) ] )
self . helper = FormHelper ( )
self . helper . form_tag = True
self . helper . form_class = ' post-form '
self . helper . form_method = ' post '
self . helper . form_enctype = " multipart/form-data "
self . helper . form_show_errors = False
self . helper . layout = Layout (
CustomField ( ' title ' ) ,
CustomField ( ' new_tags ' ) ,
CustomField ( ' add_date ' ) ,
CustomField ( ' description ' ) ,
CustomField ( ' uploaded_poster ' ) ,
CustomField ( ' enable_comments ' ) ,
)
if self . instance . media_type == " video " :
self . helper . layout . append ( CustomField ( ' thumbnail_time ' ) )
self . helper . layout . append ( FormActions ( Submit ( ' submit ' , ' Update Media ' , css_class = ' primaryAction ' ) ) )
def clean_uploaded_poster ( self ) :
image = self . cleaned_data . get ( " uploaded_poster " , False )
if image :
if image . size > 5 * 1024 * 1024 :
raise forms . ValidationError ( " Image file too large ( > 5mb ) " )
return image
def save ( self , * args , * * kwargs ) :
data = self . cleaned_data # noqa
media = super ( MediaMetadataForm , self ) . save ( * args , * * kwargs )
return media
class MediaPublishForm ( forms . ModelForm ) :
confirm_state = forms . BooleanField (
required = False ,
initial = False ,
label = " Acknowledge sharing status " ,
help_text = " "
)
create_segments = forms . BooleanField (
required = False ,
initial = False ,
label = " Create segments from video chapters " ,
help_text = " If checked, separate media files will be created for each chapter "
)
class Meta :
model = Media
fields = (
" category " ,
" state " ,
" featured " ,
2020-12-15 23:33:43 +02:00
" reported_times " ,
" is_reviewed " ,
2021-05-26 18:35:21 +03:00
" allow_download " ,
2020-12-15 23:33:43 +02:00
)
2025-05-15 10:43:26 +03:00
2020-12-15 23:33:43 +02:00
widgets = {
2025-05-15 10:43:26 +03:00
" category " : MultipleSelect ( ) ,
2020-12-15 23:33:43 +02:00
}
def __init__ ( self , user , * args , * * kwargs ) :
self . user = user
2025-05-15 10:43:26 +03:00
super ( MediaPublishForm , self ) . __init__ ( * args , * * kwargs )
2020-12-15 23:33:43 +02:00
if not is_mediacms_editor ( user ) :
2025-05-15 10:43:26 +03:00
for field in [ " featured " , " reported_times " , " is_reviewed " ] :
self . fields [ field ] . disabled = True
self . fields [ field ] . widget . attrs [ ' class ' ] = ' read-only-field '
self . fields [ field ] . widget . attrs [ ' title ' ] = " This field can only be modified by MediaCMS admins or editors "
if settings . PORTAL_WORKFLOW not in [ " public " ] :
valid_states = [ " unlisted " , " private " ]
if self . instance . state and self . instance . state not in valid_states :
valid_states . append ( self . instance . state )
self . fields [ " state " ] . choices = [ ( state , dict ( MEDIA_STATES ) . get ( state , state ) ) for state in valid_states ]
2025-04-05 12:44:21 +03:00
if getattr ( settings , ' USE_RBAC ' , False ) and ' category ' in self . fields :
if is_mediacms_editor ( user ) :
pass
else :
self . fields [ ' category ' ] . initial = self . instance . category . all ( )
non_rbac_categories = Category . objects . filter ( is_rbac_category = False )
rbac_categories = user . get_rbac_categories_as_contributor ( )
combined_category_ids = list ( non_rbac_categories . values_list ( ' id ' , flat = True ) ) + list ( rbac_categories . values_list ( ' id ' , flat = True ) )
if self . instance . pk :
instance_category_ids = list ( self . instance . category . all ( ) . values_list ( ' id ' , flat = True ) )
combined_category_ids = list ( set ( combined_category_ids + instance_category_ids ) )
self . fields [ ' category ' ] . queryset = Category . objects . filter ( id__in = combined_category_ids ) . order_by ( ' title ' )
2025-05-15 10:43:26 +03:00
self . helper = FormHelper ( )
self . helper . form_tag = True
self . helper . form_class = ' post-form '
self . helper . form_method = ' post '
self . helper . form_enctype = " multipart/form-data "
self . helper . form_show_errors = False
self . helper . layout = Layout (
CustomField ( ' category ' ) ,
CustomField ( ' state ' ) ,
CustomField ( ' featured ' ) ,
CustomField ( ' reported_times ' ) ,
CustomField ( ' is_reviewed ' ) ,
CustomField ( ' allow_download ' ) ,
)
2020-12-15 23:33:43 +02:00
2025-05-15 10:43:26 +03:00
# Only add create_segments field if the media has chapters
if self . instance . media_type == ' video ' and self . instance . chapters . exists ( ) :
self . fields [ ' create_segments ' ] = forms . BooleanField (
required = False ,
initial = False ,
label = " Create segments from video chapters " ,
help_text = " If checked, separate media files will be created for each chapter "
)
self . helper . layout . append ( CustomField ( ' create_segments ' ) )
self . helper . layout . append ( FormActions ( Submit ( ' submit ' , ' Publish Media ' , css_class = ' primaryAction ' ) ) )
def clean ( self ) :
cleaned_data = super ( ) . clean ( )
state = cleaned_data . get ( " state " )
categories = cleaned_data . get ( " category " )
if getattr ( settings , ' USE_RBAC ' , False ) and ' category ' in self . fields :
rbac_categories = categories . filter ( is_rbac_category = True ) . values_list ( ' title ' , flat = True )
if rbac_categories and state in [ ' private ' , ' unlisted ' ] :
# Make the confirm_state field visible and add it to the layout
self . fields [ ' confirm_state ' ] . widget = forms . CheckboxInput ( )
state_index = None
for i , layout_item in enumerate ( self . helper . layout ) :
if isinstance ( layout_item , CustomField ) and layout_item . fields [ 0 ] == ' state ' :
state_index = i
break
if state_index :
layout_items = list ( self . helper . layout )
layout_items . insert ( state_index + 1 , CustomField ( ' confirm_state ' ) )
self . helper . layout = Layout ( * layout_items )
if not cleaned_data . get ( ' confirm_state ' ) :
error_message = f " I understand that although media state is { state } , the media is also shared with users that have access to the following categories: { ' , ' . join ( rbac_categories ) } "
self . add_error ( ' confirm_state ' , error_message )
return cleaned_data
2020-12-15 23:33:43 +02:00
def save ( self , * args , * * kwargs ) :
data = self . cleaned_data
state = data . get ( " state " )
if state != self . initial [ " state " ] :
2021-05-26 18:35:21 +03:00
self . instance . state = get_next_state ( self . user , self . initial [ " state " ] , self . instance . state )
2020-12-15 23:33:43 +02:00
2025-05-15 10:43:26 +03:00
media = super ( MediaPublishForm , self ) . save ( * args , * * kwargs )
2020-12-15 23:33:43 +02:00
return media
class SubtitleForm ( forms . ModelForm ) :
class Meta :
model = Subtitle
fields = [ " language " , " subtitle_file " ]
def __init__ ( self , media_item , * args , * * kwargs ) :
super ( SubtitleForm , self ) . __init__ ( * args , * * kwargs )
self . instance . media = media_item
2025-03-09 20:29:26 +02:00
self . fields [ " subtitle_file " ] . help_text = " SubRip (.srt) and WebVTT (.vtt) are supported file formats. "
self . fields [ " subtitle_file " ] . label = " Subtitle or Closed Caption File "
2020-12-15 23:33:43 +02:00
def save ( self , * args , * * kwargs ) :
self . instance . user = self . instance . media . user
media = super ( SubtitleForm , self ) . save ( * args , * * kwargs )
return media
2025-03-09 20:29:26 +02:00
class EditSubtitleForm ( forms . Form ) :
subtitle = forms . CharField ( widget = forms . Textarea , required = True )
def __init__ ( self , subtitle , * args , * * kwargs ) :
super ( EditSubtitleForm , self ) . __init__ ( * args , * * kwargs )
self . fields [ " subtitle " ] . initial = subtitle . subtitle_file . read ( ) . decode ( " utf-8 " )
2020-12-15 23:33:43 +02:00
class ContactForm ( forms . Form ) :
from_email = forms . EmailField ( required = True )
name = forms . CharField ( required = False )
message = forms . CharField ( widget = forms . Textarea , required = True )
def __init__ ( self , user , * args , * * kwargs ) :
super ( ContactForm , self ) . __init__ ( * args , * * kwargs )
self . fields [ " name " ] . label = " Your name: "
self . fields [ " from_email " ] . label = " Your email: "
self . fields [ " message " ] . label = " Please add your message here and submit: "
self . user = user
if user . is_authenticated :
self . fields . pop ( " name " )
self . fields . pop ( " from_email " )