예제 #1
0
class VideoEditForm(Form):
    title = wtf.TextField(
        u"Title",
        validators=[wtf.Required()],
        description=u"Video title, without the speakers’ names")
    description = RichTextField(u'Description',
                                description=u"Summary of this video's content")
예제 #2
0
class ParticipantForm(Form):
    skill_levels = [('Beginner', 'Beginner'), ('Intermediate', 'Intermediate'),
                    ('Advanced', 'Advanced')]

    reason_to_join = RichTextField(
        "Reason To Join",
        description="Why would you love to join Hacknight",
        validators=[wtf.Required()],
        content_css="/static/css/editor.css")
    phone_no = wtf.TextField(
        "Telephone No",
        description="Telephone No",
        validators=[wtf.Required(),
                    wtf.validators.length(max=15)])
    email = wtf.html5.EmailField(
        "Email",
        description="Email Address, We will never spam you .",
        validators=[wtf.Required(),
                    wtf.validators.length(max=80)])
    job_title = wtf.TextField(
        "Job Title",
        description="What is your job title? E.G: Senior Software "
        "Engineer at Awesome company",
        validators=[wtf.Required(),
                    wtf.validators.length(max=120)])
    company = wtf.TextField(
        "Company",
        description="Company Name",
        validators=[wtf.Optional(),
                    wtf.validators.length(max=1200)])
    skill_level = wtf.RadioField("Skill Level",
                                 description="What is your skill level?",
                                 choices=skill_levels)
예제 #3
0
class SponsorForm(Form):
    title = wtforms.TextField(
        "Title",
        description="Title of the project",
        validators=[
            wtforms.validators.Required("A title is required"),
            wtforms.validators.length(max=250)
        ])
    description = RichTextField(
        u"Description",
        description="Detailed description of your project",
        content_css="/static/css/editor.css")
    website = wtforms.fields.html5.URLField(
        "Home Page",
        description="URL to the home page",
        validators=[
            wtforms.validators.Optional(),
            wtforms.validators.length(max=250)
        ])
    image_url = wtforms.fields.html5.URLField(
        "Image URL",
        description="URL to the image",
        validators=[
            wtforms.validators.Required("An image is required."),
            wtforms.validators.length(max=250)
        ])
예제 #4
0
class VenueForm(Form):
    title = wtf.TextField("Name",
                          description="Name of the venue",
                          validators=[wtf.Required()])
    description = RichTextField("Notes",
                                description="Notes about the venue",
                                content_css="/static/css/editor.css")
    address1 = wtf.TextField("Address (line 1)", validators=[wtf.Required()])
    address2 = wtf.TextField("Address (line 2)", validators=[wtf.Optional()])
    city = wtf.TextField("City", validators=[wtf.Required()])
    state = wtf.TextField("State", validators=[wtf.Optional()])
    postcode = wtf.TextField("Post code", validators=[wtf.Optional()])
    country = wtf.SelectField("Country",
                              validators=[wtf.Required()],
                              choices=country_codes,
                              default="IN")
    latitude = wtf.DecimalField(
        "Latitude",
        places=None,
        validators=[wtf.Optional(), wtf.NumberRange(-90, 90)])
    longitude = wtf.DecimalField(
        "Longitude",
        places=None,
        validators=[wtf.Optional(), wtf.NumberRange(-180, 180)])
    profile_id = wtf.SelectField("Owner",
                                 description="The owner of this listing",
                                 coerce=int,
                                 validators=[wtf.Required()])
예제 #5
0
class BoardForm(Form):
    """
    Edit a board.
    """
    description = RichTextField(
        "Description",
        validators=[
            validators.Required("A description of the job board is required"),
            AllUrlsValid()
        ])
예제 #6
0
class ProjectForm(Form):
    title = wtf.TextField("Title", description="Title of the project", validators=[wtf.Required("A title is required"), wtf.validators.length(max=250)])
    blurb = wtf.TextField("Blurb", description="A single-line summary of the project",
        validators=[wtf.Required("A blurb is required"), wtf.validators.length(max=250)])
    description = RichTextField(u"Description",
        description="Detailed description of your project",
        content_css="/static/css/editor.css")
    participating = wtf.RadioField("Will you be participating?", default=1, coerce=getbool,
        choices=[(1,  u"I will be working on this project"),
                 (0, u"I’m proposing an idea for others to take up")])
예제 #7
0
class SendEmailForm(Form):
    subject = wtf.TextField(
        "Subject",
        description="Subject for the email",
        validators=[wtf.Required(),
                    wtf.validators.length(max=250)])
    message = RichTextField(
        "Message",
        description=
        "Email message, only `FULLNAME` will be replaced with participant fullname",
        validators=[wtf.Required()])
    send_to = wtf.RadioField("Send email to", default=2, coerce=int)
예제 #8
0
class EmailEventParticipantsForm(Form):
    pending_message = RichTextField(
        "Pending Message",
        description=
        "Message to be sent for pending participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtf.Optional()])
    confirmation_message = RichTextField(
        "Confirmation Message",
        description=
        "Message to be sent for confirmed participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtf.Optional()])
    rejected_message = RichTextField(
        "Rejected Message",
        description=
        "Message to be sent for rejected participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtf.Optional()])
    waitlisted_message = RichTextField(
        "Waitlisted Message",
        description=
        "Message to be sent for waitlisted participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtf.Optional()])
예제 #9
0
class EventForm(Form):
    title = wtf.TextField(
        "Title",
        description="Name of the Event",
        validators=[wtf.Required(), wtf.NoneOf(values=["new"])])
    name = wtf.TextField(
        "URL name",
        validators=[
            wtf.Optional(),
            ValidName(),
            AvailableName(u"There’s another event with the same name")
        ],
        description="URL identifier, leave blank to autogenerate")
    blurb = wtf.TextField(
        "Blurb", description="Single line blurb introducing the event")
    description = RichTextField(
        "Description",
        description="Detailed description of the event",
        content_css="/static/css/editor.css")
    venue = wtf.QuerySelectField(
        "Venue",
        description=Markup(
            'Venue for this event (<a href="/venue/new">make new</a>)'),
        query_factory=lambda: Venue.query,
        get_label='title',
    )
    start_datetime = DateTimeField(
        "Start date/time",
        description="The date and time at which this event begins",
        validators=[wtf.Required()])
    end_datetime = DateTimeField(
        "End date/time",
        description="The date and time at which this event ends",
        validators=[wtf.Required()])
    ticket_price = wtf.TextField(
        "Ticket price",
        description="Entry fee, if any, to be paid at the venue")
    total_participants = wtf.IntegerField(
        "Venue capacity",
        description=
        "The number of people this venue can accommodate. Registrations will be closed after that. Use 0 to indicate unlimited capacity",
        default=50,
        validators=[wtf.Required()])
    website = wtf.TextField("Website",
                            description="Related Website (Optional)",
                            validators=[wtf.Optional()])

    def validate_end_datetime(self, field):
        if field.data < self.start_datetime.data:
            raise wtf.ValidationError(
                u"Your event can’t end before it starts.")
예제 #10
0
class ExpenseReportForm(Form):
    """
    Create or edit an expense report.
    """
    title = wtforms.TextField(u"Title", validators=[wtforms.validators.Required()],
        description=u"What are these expenses for?")
    description = RichTextField(u"Description", validators=[wtforms.validators.Optional()],
        description=u"Notes on the expenses")
    currency = wtforms.SelectField(u"Currency", validators=[wtforms.validators.Required()],
        description=u"Currency for expenses in this report",
        choices=CURRENCIES)
    budget = QuerySelectField(u"Budget", validators=[wtforms.validators.Optional()],
        query_factory=sorted_budgets, get_label='title', allow_blank=True,
        description=u"The budget source for these expenses")
예제 #11
0
class EmailEventParticipantsForm(Form):
    pending_message = RichTextField(
        "Pending Message",
        description=
        "Message to be sent for pending participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtforms.validators.Optional()],
        tinymce_options={
            'convert_urls': False,
            'remove_script_host': False
        })
    confirmation_message = RichTextField(
        "Confirmation Message",
        description=
        "Message to be sent for confirmed participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtforms.validators.Optional()],
        tinymce_options={
            'convert_urls': False,
            'remove_script_host': False
        })
    rejected_message = RichTextField(
        "Rejected Message",
        description=
        "Message to be sent for rejected participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtforms.validators.Optional()],
        tinymce_options={
            'convert_urls': False,
            'remove_script_host': False
        })
    waitlisted_message = RichTextField(
        "Waitlisted Message",
        description=
        "Message to be sent for waitlisted participants. '*|FULLNAME|*' will be replaced with user's fullname.",
        validators=[wtforms.validators.Optional()],
        tinymce_options={
            'convert_urls': False,
            'remove_script_host': False
        })
예제 #12
0
class BudgetForm(Form):
    """
    Create or edit a budget.
    """
    title = wtforms.TextField(u"Budget title", validators=[wtforms.validators.Required()],
        description=u"The name of your project or other budget source")
    description = RichTextField(u"Description",
        description=u"Description of the budget")

    def validate_title(self, field):
        """
        If the title is already in use, refuse to add this one.
        """
        existing = set([simplify_text(b.title) for b in
            Budget.query.filter_by(workspace=g.workspace).all() if b != self.edit_obj])
        if simplify_text(field.data) in existing:
            raise wtforms.ValidationError("You have an existing budget with the same name")
예제 #13
0
class SendEmailForm(Form):
    subject = wtforms.TextField("Subject",
                                description="Subject for the email",
                                validators=[
                                    wtforms.validators.Required(),
                                    wtforms.validators.length(max=250)
                                ])
    message = RichTextField(
        "Message",
        description=
        "Email message, only *|FULLNAME|* will be replaced with participant fullname",
        validators=[wtforms.validators.Required()],
        tinymce_options={
            'convert_urls': False,
            'remove_script_host': False
        })
    send_to = wtforms.RadioField("Send email to", default=2, coerce=int)
예제 #14
0
class WorkspaceForm(Form):
    """
    Manage workspace settings.
    """
    description = RichTextField(
        u"Usage notes",
        description=
        u"Notes for your organization members on how to use this expense reporting tool"
    )
    timezone = wtforms.SelectField(
        u"Timezone",
        validators=[wtforms.validators.Required("Select a timezone")],
        choices=[(tz, tz) for tz in common_timezones],
        description=u"The primary timezone in which your organization is based"
    )
    access_teams = QuerySelectMultipleField(
        u"Access Teams",
        validators=[
            wtforms.validators.Required("You need to select at least one team")
        ],
        get_label='title',
        description=u"Teams that can submit expense reports")
    review_teams = QuerySelectMultipleField(
        u"Review Teams",
        validators=[
            wtforms.validators.Required("You need to select at least one team")
        ],
        get_label='title',
        description=u"Teams that can review and act on expense reports")
    admin_teams = QuerySelectMultipleField(
        u"Admin Teams",
        validators=[
            wtforms.validators.Required("You need to select at least one team")
        ],
        get_label='title',
        description=u"Teams with administrative access to this workspace. "
        u"Admin access is required to create or edit budgets and categories")

    def validate_admin_teams(self, field):
        if self.edit_obj.owners not in field.data:
            field.data.append(self.edit_obj.owners)
예제 #15
0
class ParticipantForm(Form):
    reason_to_join = RichTextField(
        "Reason To Join",
        description="Why would you love to join Hacknight",
        validators=[wtf.Required()],
        content_css="/static/css/editor.css")
    phone_no = wtf.TextField("Telephone No",
                             description="Telephone No",
                             validators=[wtf.Required()])
    email = wtf.html5.EmailField(
        "Email",
        description="Email Address, We will never spam you .",
        validators=[wtf.Required()])
    job_title = wtf.TextField(
        "Job Title",
        description="What is your job title? E.G: Senior Software "
        "Engineer at Awesome company",
        validators=[wtf.Required()])
    company = wtf.TextField("Company",
                            description="Company Name",
                            validators=[wtf.Optional()])
예제 #16
0
class PlaylistForm(Form):
    title = wtf.TextField(u"Title",
                          validators=[wtf.Required()],
                          description=u"The name of your playlist")
    short_title = wtf.TextField(
        u"Short title",
        validators=[wtf.Optional()],
        description=
        u"Shorter title, displayed next to the channel's name when viewing a video"
    )
    name = wtf.TextField(
        u"URL Name",
        validators=[wtf.Optional()],
        description=u"Optional. Will be automatically generated if left blank")
    description = RichTextField(u"Description")
    recorded_date = wtf.DateField(
        u"Recorded date",
        validators=[wtf.Optional()],
        description=
        u"Date on which the videos in this playlist were recorded, if applicable"
    )
    published_date = wtf.DateField(
        u"Published date",
        validators=[wtf.Required()],
        default=date.today(),
        description=u"Date on which this playlist was created or made public")
    public = wtf.BooleanField(u"This playlist is public", default=True)

    def validate_name(self, field):
        if invalid_name.search(field.data):
            raise wtf.ValidationError(
                "The name cannot have spaces or non-alphanumeric characters")
        existing = Playlist.query.filter_by(channel=self.channel,
                                            name=field.data).first()
        if existing and existing.id != self.edit_id:
            raise wtf.ValidationError("That name is already in use")
예제 #17
0
class ReviewForm(Form):
    """
    Reviewer notes on expense reports.
    """
    notes = RichTextField(u"Notes", validators=[wtforms.validators.Required()])
예제 #18
0
class ProfileForm(Form):
    type = wtf.SelectField(u"Profile type",
                           coerce=int,
                           validators=[wtf.Required()])
    description = RichTextField(u"Description/Bio",
                                content_css="/static/css/editor.css")
예제 #19
0
class ApplicationResponseForm(Form):
    response_message = RichTextField("")
예제 #20
0
class ListingForm(Form):
    """Form for new job posts"""
    job_headline = TextField(
        "Headline",
        description=
        "A single-line summary. This goes to the front page and across the network",
        validators=[
            validators.Required("A headline is required"),
            validators.Length(min=1,
                              max=100,
                              message="%(max)d characters maximum")
        ])
    job_type = RadioField(
        "Type",
        coerce=int,
        validators=[validators.Required("The job type must be specified")])
    job_category = RadioField(
        "Category",
        coerce=int,
        validators=[validators.Required("Select a category")])
    job_location = TextField(
        "Location",
        description=
        u'“Bangalore”, “Chennai”, “Pune”, etc or “Anywhere” (without quotes)',
        validators=[
            validators.Required(
                u"If this job doesn’t have a fixed location, use “Anywhere”"),
            validators.Length(min=3,
                              max=80,
                              message="%(max)d characters maximum")
        ])
    job_relocation_assist = BooleanField("Relocation assistance available")
    job_description = RichTextField(
        "Description",
        description=
        u"Don’t just describe the job, tell a compelling story for why someone should work for you",
        validators=[
            validators.Required("A description of the job is required"),
            AllUrlsValid()
        ],
        tinymce_options={'convert_urls': True})
    job_perks = BooleanField("Job perks are available")
    job_perks_description = RichTextField(
        "Describe job perks",
        description=u"Stock options, free lunch, free conference passes, etc",
        validators=[AllUrlsValid()])
    job_how_to_apply = TextAreaField(
        "What should a candidate submit when applying for this job?",
        description=u"Example: “Include your LinkedIn and GitHub profiles.” "
        u"We now require candidates to apply through the job board only. "
        u"Do not include any contact information here. Candidates CANNOT "
        u"attach resumes or other documents, so do not ask for that",
        validators=[
            validators.Required(
                u"HasGeek does not offer screening services. "
                u"Please specify what candidates should submit")
        ])
    company_name = TextField(
        "Name",
        description=u"The name of the organization where the position is. "
        u"No intermediaries or unnamed stealth startups. Use your own real name if the company isn’t named "
        u"yet. We do not accept listings from third parties such as recruitment consultants. Such listings "
        u"may be removed without notice",
        validators=[
            validators.Required(
                u"This is required. Posting any name other than that of the actual organization is a violation of the ToS"
            ),
            validators.Length(
                min=4,
                max=80,
                message="The name must be within %(min)d to %(max)d characters"
            )
        ])
    company_logo = FileField(
        "Logo",
        description=
        u"Optional — Your company logo will appear at the top of your listing. "
        u"170px wide is optimal. We’ll resize automatically if it’s wider",
    )  # validators=[file_allowed(uploaded_logos, "That image type is not supported")])
    company_logo_remove = BooleanField("Remove existing logo")
    company_url = TextField("URL",
                            description=u"Example: http://www.google.com",
                            validators=[optional_url,
                                        AllUrlsValid()])
    hr_contact = RadioField(
        u"Is it okay for recruiters and other "
        u"intermediaries to contact you about this listing?",
        coerce=getbool,
        description=u"We’ll display a notice to this effect on the listing",
        default=0,
        choices=[(0, u"No, it is NOT OK"),
                 (1, u"Yes, recruiters may contact me")])
    # Deprecated 2013-11-20
    # poster_name = TextField("Name",
    #     description=u"This is your name, for our records. Will not be revealed to applicants",
    #     validators=[validators.Required("We need your name")])
    poster_email = EmailField(
        "Email",
        description=
        u"This is where we’ll send your confirmation email and all job applications. "
        u"We recommend using a shared email address such as [email protected]. "
        u"Listings are classified by your email domain. "
        u"Your email address will not be revealed to applicants until you respond",
        validators=[
            validators.Required(
                "We need to confirm your email address before the job can be listed"
            ),
            validators.Length(min=5,
                              max=80,
                              message="%(max)d characters maximum"),
            validators.Email(
                "That does not appear to be a valid email address"),
            ValidEmailDomain()
        ])
    collaborators = HiddenMultiField(
        u"Collaborators",
        description=
        u"If someone is helping you evaluate candidates, type their names here. "
        u"They must have a HasGeek account. They will not receive email notifications "
        u"— use a shared email address above for that — but they will be able to respond "
        u"to candidates who apply")

    def validate_company_name(form, field):
        if len(field.data) > 5:
            caps = len(CAPS_RE.findall(field.data))
            small = len(SMALL_RE.findall(field.data))
            if small == 0 or caps / float(small) > 0.8:
                raise ValidationError(
                    "Surely your company isn't named in uppercase?")

    def validate_company_logo(form, field):
        if not request.files['company_logo']:
            return
        try:
            g.company_logo = process_image(request.files['company_logo'])
        except IOError, e:
            raise ValidationError(e.message)
        except KeyError, e:
            raise ValidationError("Unknown file format")
예제 #21
0
class ChannelForm(Form):
    type = wtf.SelectField(u"Channel type", coerce=int, validators=[wtf.Required()])
    description = RichTextField(u"Description")
예제 #22
0
class ApplicationForm(Form):
    apply_email = RadioField(
        "Email",
        validators=[validators.Required("Pick an email address")],
        description="Add new email addresses from your profile")
    apply_phone = TextField(
        "Phone",
        validators=[
            validators.Required("Specify a phone number"),
            validators.Length(min=1,
                              max=15,
                              message="%(max)d characters maximum")
        ],
        description="A phone number the employer can reach you at")
    apply_message = RichTextField(
        "Job application",
        validators=[
            validators.Required("You need to say something about yourself"),
            AllUrlsValid()
        ],
        description="Please provide all details the employer has requested")

    def __init__(self, *args, **kwargs):
        super(ApplicationForm, self).__init__(*args, **kwargs)
        self.apply_email.choices = []
        if g.user:
            self.apply_email.description = Markup(
                u'Add new email addresses from <a href="{}" target="_blank">your profile</a>'
                .format(g.user.profile_url))
            self.apply_email.choices = [(e, e)
                                        for e in lastuser.user_emails(g.user)]
            if not self.apply_email.choices:
                self.apply_email.choices = [
                    ('',
                     Markup(
                         '<em>You have not verified your email address</em>'))
                ]

    def validate_apply_message(form, field):
        words = get_word_bag(field.data)
        form.words = words
        similar = False
        for oldapp in JobApplication.query.filter_by(
                response=EMPLOYER_RESPONSE.SPAM).all():
            if oldapp.words:
                s = SequenceMatcher(None, words, oldapp.words)
                if s.ratio() > 0.8:
                    similar = True
                    break

        if similar:
            raise ValidationError(
                "Your application is very similar to one previously identified as spam"
            )

        # Check for email and phone numbers in the message

        # Prepare text by replacing non-breaking spaces with spaces (for phone numbers) and removing URLs.
        # URLs may contain numbers that are not phone numbers.
        phone_search_text = URL_RE.sub(
            '',
            field.data.replace('&nbsp;',
                               ' ').replace('&#160;',
                                            ' ').replace(u'\xa0', ' '))
        if EMAIL_RE.search(field.data) is not None or PHONE_DETECT_RE.search(
                phone_search_text) is not None:
            raise ValidationError(
                "Do not include your email address or phone number in the application"
            )
예제 #23
0
class EventForm(Form):
    title = wtforms.TextField("Title",
                              description="Name of the Event",
                              validators=[
                                  wtforms.validators.Required(),
                                  wtforms.validators.NoneOf(values=["new"]),
                                  wtforms.validators.length(max=250)
                              ])
    name = wtforms.TextField(
        "URL name",
        validators=[
            wtforms.validators.Optional(),
            ValidName(),
            AvailableName(u"There’s another event with the same name",
                          scoped=True),
            wtforms.validators.length(max=250)
        ],
        description="URL identifier, leave blank to autogenerate")
    blurb = wtforms.TextField(
        "Blurb",
        description="Single line blurb introducing the event",
        validators=[wtforms.validators.length(max=250)])
    description = RichTextField(
        "Description",
        description="Detailed description of the event",
        linkify=False,
        content_css="/static/css/editor.css",
        tinymce_options={
            "valid_elements":
            "p,br,strong/b,em/i,sup,sub,h3,h4,h5,h6,ul,ol,li,a[!href|title|target|class],blockquote,pre,code,img[!src|alt|class|width|height|align]",
            "theme_advanced_buttons1":
            "bold,italic,|,sup,sub,|,bullist,numlist,|,link,unlink,|,blockquote,|,removeformat,code,image",
            "theme": "advanced"
        },
        sanitize_tags=[
            'p', 'br', 'strong', 'em', 'sup', 'sub', 'h3', 'h4', 'h5', 'h6',
            'ul', 'ol', 'li', 'a', 'span', 'blockquote', 'pre', 'code', 'img',
            'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'iframe'
        ],
        sanitize_attributes={
            'a': ['href', 'title', 'target', 'class'],
            'span': ['class'],
            'img': ['src', 'alt', 'class', 'width', 'height', 'align']
        },
    )
    apply_instructions = RichTextField(
        "Instructions for participants",
        description=
        "This will be shown to participants on the hacknight joining form",
        content_css="/static/css/editor.css")
    venue = QuerySelectField(
        "Venue",
        description=Markup(
            'Venue for this event (<a href="/venue/new">make new</a>)'),
        query_factory=lambda: Venue.query,
        get_label='title',
        allow_blank=True,
        blank_text="Online event",
    )
    start_datetime = DateTimeField(
        "Start date/time",
        description="The date and time at which this event begins",
        validators=[wtforms.validators.Required()])
    end_datetime = DateTimeField(
        "End date/time",
        description="The date and time at which this event ends",
        validators=[wtforms.validators.Required()])
    ticket_price = wtforms.TextField(
        "Ticket price",
        description="Entry fee, if any, to be paid at the venue",
        validators=[wtforms.validators.length(max=250)])
    maximum_participants = wtforms.IntegerField(
        "Venue capacity",
        description="The number of people this venue can accommodate.",
        default=50,
        validators=[wtforms.validators.Required()])
    website = wtforms.fields.html5.URLField(
        "Website",
        description="Related Website (Optional)",
        validators=[
            wtforms.validators.Optional(),
            wtforms.validators.length(max=250),
            wtforms.validators.URL()
        ])
    status = wtforms.SelectField(
        "Event status",
        description="Current status of this hacknight",
        coerce=int,
        choices=STATUS_CHOICES)
    sync_service = wtforms.SelectField(
        "Sync service name",
        description="Name of the ticket sync service like doattend",
        choices=SYNC_CHOICES,
        validators=[
            wtforms.validators.Optional(),
            wtforms.validators.length(max=100)
        ])
    sync_eventsid = wtforms.TextField(
        "Sync event ID",
        description=
        "Sync events id like DoAttend event ID. More than one event ID is allowed separated by ,.",
        validators=[
            wtforms.validators.Optional(),
            wtforms.validators.length(max=100)
        ])
    sync_credentials = wtforms.TextField(
        "Sync credentials",
        description="Sync credentials like API Key for the event",
        validators=[
            wtforms.validators.Optional(),
            wtforms.validators.length(max=100)
        ])

    def validate_end_datetime(self, field):
        if field.data < self.start_datetime.data:
            raise wtforms.ValidationError(
                u"Your event can’t end before it starts.")

    def validate_sync_credentials(self, field):
        # Remove extra space in front and end.
        # TODO: Find better way to do it, because this code doesn't validate rather sanitizes.
        field.data = field.data.strip()

    def validate_sync_eventsid(self, field):
        if self.sync_service.data == SYNC_SERVICE.DOATTEND:
            #Event id in doattend is 5 digit integer, in future it may increase or change.
            event_id_pattern = r"\d{5,}"
            events_id = field.data.strip().split(',')
            for event_id in events_id:
                if not re.match(event_id_pattern, event_id.strip()):
                    raise wtforms.ValidationError(
                        u"Event id {event_id} is invalid".format(
                            event_id=event_id))
            if events_id:
                field.data = ",".join(events_id)