Initial commit

This commit is contained in:
Senad Uka
2020-05-31 22:38:19 +02:00
commit 858fafc3c5
1280 changed files with 65918 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
module AccountManagementHelper
def roles_by_power
AccountAuth.roles.sort_by { |key, value| -value }.map(&:first)
end
def options_for_role_select
AccountAuth.roles.map { |role, _| [role.titleize, role] }
end
end

View File

@@ -0,0 +1,45 @@
module AnalyticsHelper
def javascript_include_analytics_js
return unless analytics_enabled?
if segment_client_key.present?
javascript_tag analytics_js_snippet, nonce: true
end
end
def identify_user_for_analytics(user)
return unless analytics_enabled?
if user.present?
javascript_tag identify_user_snippet(user.id, user.email, user.full_name), nonce: true
end
end
private
def analytics_enabled?
ENV["ENABLE_ANALYTICS"] == "true"
end
def segment_client_key
ENV["SEGMENT_CLIENT_KEY"]
end
def analytics_js_snippet
<<~SNIPPET
!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var t=analytics.methods[e];analytics[t]=analytics.factory(t)}analytics.load=function(e,t){var n=document.createElement("script");n.type="text/javascript";n.async=!0;n.src="https://cdn.segment.com/analytics.js/v1/"+e+"/analytics.min.js";var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(n,a);analytics._loadOptions=t};analytics.SNIPPET_VERSION="4.1.0";
analytics.load("#{segment_client_key}");
analytics.page();
}}();
SNIPPET
end
def identify_user_snippet(id, email, name)
<<~SNIPPET
analytics.identify('#{id}', {
email: '#{email}',
name: '#{name}'
});
SNIPPET
end
end

View File

@@ -0,0 +1,27 @@
module ApplicationHelper
def sidenav_files_nav_link_active?(project)
release_controller_names = available_release_types_model_names.map(&:plural)
current_page?(project_path(project)) || controller_name.in?(release_controller_names) || controller_name == "reports"
end
def project_feature(project, name)
if project.feature_enabled?(name)
yield
end
end
def options_for_predefined_client_name_select
[
["Discovery", :discovery],
["Nat Geo", :nat_geo],
["Other", :other],
]
end
def options_for_graphic_types_select
[
"Titlecard", "Logo", "Lower Third", "Upper Third", "Subtitle", "Graphic", "Credits", "Other",
]
end
end

View File

@@ -0,0 +1,200 @@
module ButtonsHelper
def button_to_release_report(video, content: "", disabled: false)
if disabled
t(".generating")
else
ReleaseReportButton.build_for_client(self, video, content).to_html
end
end
def button_to_video_release_confirmation(video, releasable, classes: "btn-no-style border cursor-copy p-2", additional_video_release_params: {}, &block)
if releasable.uses_edl?
route = [:new, video, releasable, :video_release_confirmation]
method = :get
else
route = [video, releasable, :video_release_confirmations]
method = :post
end
button_to \
route,
method: method,
remote: true,
class: classes,
data: { toggle: "tooltip", disable: true },
title: "Add to Report",
form: { data: { ujs_target: "video-release-confirmation-form" } },
params: { video_release_confirmation: { time_elapsed: "" }.merge(additional_video_release_params) },
&block
end
def link_to_edl_file_download(video)
video_presenter = VideoPresenter.new(video)
if video_presenter.edl_download_disabled?
content_tag("a", fa_icon("file-excel-o", text: t(".video.edl_download")), class: "dropdown-item" )
else
link_to(fa_icon("file-excel-o", text: t(".video.edl_download")), video_presenter.edl_file_path, class: "dropdown-item", target: "_blank")
end
end
def link_to_graphics_only_edl_file_download(video)
video_presenter = VideoPresenter.new(video)
if video_presenter.graphics_edl_download_disabled?
content_tag("a", fa_icon("file-excel-o", text: t(".video.graphics_only_edl_download")), class: "dropdown-item" )
else
link_to(fa_icon("file-excel-o", text: t(".video.graphics_only_edl_download")), video_presenter.graphics_only_edl_file_path, class: "dropdown-item", target: "_blank")
end
end
def link_to_audio_only_edl_file_download(video)
video_presenter = VideoPresenter.new(video)
if video_presenter.audio_edl_download_disabled?
content_tag("a", fa_icon("file-excel-o", text: t(".video.audio_only_edl_download")), class: "dropdown-item" )
else
link_to(fa_icon("file-excel-o", text: t(".video.audio_only_edl_download")), video_presenter.audio_only_edl_file_path, class: "dropdown-item", target: "_blank")
end
end
class ReleaseReportButton
def self.build_for_client(view, video, content)
client_name = video.project.client_name.parameterize.underscore
klass = begin
"buttons_helper/#{client_name}_report_button".classify.constantize
rescue NameError
DiscoveryReportButton
end
klass.new(view, video, content)
end
def initialize(view, video, content)
@view = view
@video = video
@content = content
end
def to_html
content_tag(:div, class: "btn-group") do
concat main_button
concat dropdown_menu
end
end
private
attr_reader :view, :video, :content
delegate :button_tag, :concat, :content_tag, :fa_icon, :link_to, :link_to_if, :policy, :t, to: :view
def main_button
button_tag content, class: "btn btn-sm btn-success dropdown-toggle", data: { toggle: "dropdown", boundary: "window" }, aria: { haspopup: true, expanded: false }
end
def dropdown_header(content, css_class: nil)
css = css_class.to_s + " dropdown-header"
content_tag(:h6, content, class: css)
end
def dropdown_menu
end
def dropdown_divider
content_tag(:div, nil, class: "dropdown-divider")
end
def link_to_big_music_cue_sheet
link_to build_report_path(:audio_reports, "xlsx", type: "big"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "BiG Music Cue Sheet"
end
end
def link_to_issues_and_concerns
link_to build_report_path(:issues_and_concerns_reports, "xlsx"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Issues and Concerns Report"
end
end
def build_report_path(type, format, options = {})
# TODO: Use Current for locale
[video, type, { format: format, locale: I18n.locale }.merge(options)]
end
end
class DiscoveryReportButton < ReleaseReportButton
def dropdown_menu
content_tag(:div, class: "dropdown-menu dropdown-menu-right") do
concat dropdown_header("Download Discovery Documents", css_class: "text-uppercase")
concat dropdown_divider
concat dropdown_header("Video")
concat link_to_production_elements_log
concat dropdown_header("Graphics")
concat link_to_gfx_cue_list
concat dropdown_header("Audio")
concat link_to_music_cue_sheet
concat link_to_big_music_cue_sheet
concat dropdown_header("Other")
concat link_to_issues_and_concerns
end
end
def link_to_production_elements_log
link_to build_report_path(:video_reports, "xlsx", type: "discovery"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Production Elements Log"
end
end
def link_to_gfx_cue_list
link_to build_report_path(:graphic_reports, "xlsx", type: "discovery"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "GFX Cue List"
end
end
def link_to_music_cue_sheet
link_to build_report_path(:audio_reports, "xlsx", type: "discovery"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Music Cue Sheet"
end
end
end
class NatGeoReportButton < ReleaseReportButton
def dropdown_menu
content_tag(:div, class: "dropdown-menu dropdown-menu-right") do
concat dropdown_header("Download Nat Geo Documents", css_class: "text-uppercase")
concat dropdown_divider
concat dropdown_header("Video")
concat link_to_legal_binder_log
concat dropdown_header("Graphics")
concat link_to_text_graphics_log
concat dropdown_header("Audio")
concat link_to_music_cue_sheet
concat link_to_original_music_cue_sheet
concat link_to_big_music_cue_sheet
concat dropdown_header("Other")
concat link_to_issues_and_concerns
end
end
def link_to_legal_binder_log
link_to build_report_path(:video_reports, "xlsx", type: "nat_geo"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Legal Binder Log"
end
end
def link_to_text_graphics_log
link_to build_report_path(:graphic_reports, "xlsx", type: "nat_geo"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Text Graphics Log"
end
end
def link_to_music_cue_sheet
link_to build_report_path(:audio_reports, "xlsx", type: "nat_geo"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Music Cue Sheet"
end
end
def link_to_original_music_cue_sheet
link_to build_report_path(:audio_reports, "xlsx", type: "nat_geo-original"), class: "dropdown-item", target: "_blank" do
fa_icon "file-excel-o", text: "Original Music Log"
end
end
end
end

View File

@@ -0,0 +1,22 @@
module CardsHelper
def card_header(text: "", subtext: "", close_action_path: nil)
heading =
content_tag(:div, class: "d-flex flex-row justify-content-between align-items-center") do
concat content_tag(:h1, text, class: "h3")
if close_action_path.present?
concat link_to(t("shared.close"), close_action_path, class: "font-weight-bold small text-uppercase text-more-muted")
end
end
content_tag(:div, class: "card-header") do
concat heading
if subtext.present?
concat content_tag(:small, subtext, class: "text-muted")
end
end
end
def card_field_set_tag(text, &block)
field_set_tag content_tag(:span, text, class: "h6 text-muted text-uppercase"), &block
end
end

View File

@@ -0,0 +1,91 @@
module CarouselHelper
def carousel_for(images, options = {}, &block)
Carousel.new(self, images, options, block).html
end
class Carousel
def initialize(view, images, options, block)
@view = view
@images = images
@options = options
@block = block
end
def html
css = ["carousel", "slide"] << options[:class].to_s.split(" ")
content = [].tap do |content|
content << indicators if show_indicators?
content << slides
content << controls if show_controls?
end
content_tag(:div, safe_join(content), id: uid, class: css)
end
private
attr_accessor :view, :images, :options, :block
delegate :link_to, :content_tag, :image_tag, :safe_join, :concat, :capture, to: :view
def show_controls?
options.fetch(:controls, true)
end
def show_indicators?
options.fetch(:indicators, true)
end
def uid
@uid ||= "carousel_#{SecureRandom.hex(6)}"
end
def indicators
items = images.count.times.map { |index| indicator_tag(index) }
content_tag(:ol, safe_join(items), class: 'carousel-indicators')
end
def indicator_tag(index)
options = {
class: (index.zero? ? 'active' : ''),
data: {
target: "##{uid}",
slide_to: index
}
}
content_tag(:li, '', options)
end
def slides
items = images.map.with_index { |image, index| slide_tag(image, index.zero?) }
content_tag(:div, safe_join(items), class: 'carousel-inner')
end
def slide_tag(image, is_active)
options = {
class: (is_active ? 'carousel-item active' : 'carousel-item'),
}
slide_content = @block.present? ? capture(image, &@block) : image_tag(image)
content_tag(:div, slide_content, options)
end
def controls
safe_join([control_tag('prev'), control_tag('next')])
end
def control_tag(direction)
options = {
class: "carousel-control-#{direction}",
data: { slide: direction },
role: "button"
}
link_to "##{uid}", options do
concat content_tag(:span, '', class: "carousel-control-#{direction}-icon", aria: { hidden: true })
concat content_tag(:span, direction.titleize, class: "sr-only")
end
end
end
end

View File

@@ -0,0 +1,50 @@
module ContactInfoHelper
def contact_info_for(contactable)
contact_info(
name: contactable.name,
address: contactable.address,
phone: contactable.phone,
email: contactable.email,
)
end
def contact_info(name: nil, address: nil, phone: nil, email: nil)
content_tag :address do
if name.present?
concat content_tag(:strong, name)
concat tag(:br)
end
if address.present?
concat format_address(address)
concat tag(:br)
end
if phone.present?
concat phone_abbr(phone)
concat tag(:br)
end
if email.present?
concat email_abbr(email)
concat tag(:br)
end
end
end
private
def format_address(address)
case address
when Address
simple_format address.to_s(format: :condensed), {}, wrapper_tag: "span"
else
address.to_s
end
end
def email_abbr(email)
content_tag(:abbr, "E: ", title: "Email") + mail_to(email)
end
def phone_abbr(phone)
content_tag(:abbr, "P: ", title: "Phone") + phone
end
end

View File

@@ -0,0 +1,22 @@
module DescriptionListHelper
def description_list_pair(term, definition, append: nil)
tags = [
content_tag(:dt, "#{term}#{append}"),
content_tag(:dd, definition),
]
safe_join(tags)
end
def description_list_pair_for(record, attribute, append: nil)
term = translation_for(record, attribute)
definition = record.send(attribute)
description_list_pair(term, definition, append: append)
end
private
def translation_for(record, attribute)
record.class.human_attribute_name(attribute).titleize
end
end

View File

@@ -0,0 +1,37 @@
module DropzoneHelper
def dropzone_placeholder_message_for(releasable)
case releasable.model_name.param_key
when "acquired_media_release"
"To Add Photos & Videos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera"
when "music_release"
"To Add Audio Files to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
when "directory"
"To Add Files to the Folder:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse files"
else
"To Add Photos to the release:<br>Drag & Drop Files<br>or<br>Click or Tap here to browse photos and connect to Camera"
end
end
def dropzone_accepted_files_for(releasable)
case releasable.model_name.param_key
when "appearance_release", "talent_release", "location_release", "material_release"
"image/*"
when "music_release"
"audio/*"
else
nil
end
end
def mock_photos_json(photos)
photos.map do |photo|
{ name: photo.filename, size: photo.blob.byte_size, type: photo.content_type, dataURL: rails_blob_path(photo) }
end.to_json
end
def mock_file_infos_json(file_infos)
file_infos.map do |file_info|
{ name: file_info.filename, size: file_info.byte_size, type: file_info.content_type }
end.to_json
end
end

View File

@@ -0,0 +1,11 @@
# frozen_string_literal: true
module DummyImagesHelper
def dummy_signature
'data:image/png;base64,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'
end
def dummy_photo
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAPFBMVEXMzMzl5eXg4ODv7+/R0dHU1NTb29vt7e3Z2dno6Ojx8fHi4uLs7Ozq6urj4+PPz8/e3t7W1tby8vL09PQMHpbdAAADDUlEQVR42u3dWZLsKAwFUDEYD/UAw93/XvuTj46OLrsgJdXT2cGNRAxOEZAxxhhjjDHGGGOMMcYYYwy/2u6ScweAnnO5W9UY4ig7/mUvR1WVImX8p5y0ZEkn/seZSLzqA74h+EqSRYdvc5Gkqg6PuEoi+Y6Huid5WsALoZEsteClUkmQbcdr+0ZiJPxIIiEKfqiQCA4/5pTnGJzyHIOTkUN/koRpEjHaOqbpG/HZMdFObG5MdROT2jFVr8TDYzJPPDom68xTr/YpOGO6TAwiFoi6597h5htZ+scWlqCPa1iica2G+tfEE0ucnBtf3VtgLMK0HOpfEhsWaRbkHY9FvAWxIBbEglgQC2JBLIgFsd2vBbEgXEHs44MFsSAWxIL8FUEylsj0WWnHInti79JS2LlVsFRR/pfCEHWfDgeve8IaMldXkNYuISxnQaQFsWJ/5sRiJ0enluaurQ2LbfQhAUsF+hTPsEPRuGuMdh55rF5Y5qosXdjqu7Gd8oE1fGGJL/q4I2C6cEi9vq7kgvsXw7BSUPKO+NSAaUIlRg3TNLviKmqzclVi5hm27oJPWYH4NeWVPmSG7z9Sz4uRRPDKK30Iuit9aMorffDKB9bwB6/9IUnihZeuSKJsvN95+T8QJRIn8eXgX00CSVTYmjX4630jkS48dJFMjumczj9vJZIp8hxD+IvkIqkyywGXfzfvSaoDjxwkVcMjjaSqeKSSWHiELIisnXwgoeK945H9jiTO5ne8sPtNVIoS8Foom7AUqrMcrmOK7g79KUYW1hSqs2ylY5FeNh3VzV/7Y9WbgHutTCem4Xs2ZnMdH9XdRtPVeweD/a4MP4b4nyVlsMqJJqi+g133ddIzSPxcpPfaCUHO9jZGhjC5ccXgjxIzhMqRrcear1/77hCt3/QdbYd4e2MYVTzjqwUoEdqkF9v4lfrgxTZG71+Jax3K9Paxq8QM15MdVHJrcvAncVDLzc/BnyRBtTQ6xpTbxtU1xcaFuQL1yuiyUi6OGUs3N34Q5SJ5/AqeAn6FQPglLIg0/wCowqSZm6rQPwAAAABJRU5ErkJggg=='
end
end

View File

@@ -0,0 +1,18 @@
module DurationHelper
MINUTES_IN_HOUR = 60
SECONDS_IN_MINUTE = 60
def convert_duration(value, from:, to:)
value_in_seconds = case from.to_s
when "seconds" then value
when "minutes" then value * SECONDS_IN_MINUTE
when "hours" then value * SECONDS_IN_MINUTE * MINUTES_IN_HOUR
end
result = case to.to_s
when "seconds" then value_in_seconds
when "minutes" then value_in_seconds / SECONDS_IN_MINUTE
when "hours" then value_in_seconds / SECONDS_IN_MINUTE / MINUTES_IN_HOUR
end
end
end

View File

@@ -0,0 +1,80 @@
module ErrorsHelper
# Displays an alert containing a list of error messages for a given model attribute
def errors_for(model, attribute)
ErrorsList.new(self, model, attribute).to_html
end
# Displays an alert containing a list of all the error messages for a given model
def errors_summary_for(model)
ErrorsSummary.new(self, model).to_html
end
private
class ErrorsList
def initialize(view, model, attribute)
@view = view
@model = model
@attribute = attribute
end
def to_html
return if errors.empty?
error_list_items = errors.map { |error| content_tag(:li, error) }
content_tag(:div, class: "alert alert-danger text-left") do
concat content_tag(:p, message)
concat content_tag(:ul, safe_join(error_list_items))
end
end
private
attr_reader :view, :model, :attribute
delegate :concat, :content_tag, :safe_join, to: :view
def errors
@errors ||= errors = model.errors[attribute]
end
def message
"#{attribute.to_s.humanize} is not valid."
end
end
class ErrorsSummary
def initialize(view, model)
@view = view
@model = model
end
def to_html
return if errors.empty?
content_tag(:div, class: "alert alert-danger text-left") do
concat content_tag(:p, translate("errors_helper.failure_message", model_name: name))
concat content_tag(:ul, safe_join(error_list_items))
end
end
private
attr_reader :view, :model
delegate :concat, :content_tag, :safe_join, :translate, to: :view
def errors
@errors ||= model.errors.full_messages
end
def error_list_items
errors.map { |error| content_tag(:li, error) }
end
def name
model.model_name.human.downcase
end
end
end

View File

@@ -0,0 +1,40 @@
module ImagesHelper
def thumbnail_variant(attachment)
attachment.variant(
gravity: "center",
resize: "75x75>",
extent: "75x75",
background: "#fff",
)
end
def medium_variant(attachment)
attachment.variant(
gravity: "center",
resize: "100x100>",
extent: "100x100",
background: "#fff",
)
end
def large_variant(attachment)
attachment.variant(
gravity: "center",
resize: "150x150>",
extent: "150x150",
background: "#fff",
)
end
def account_logo_variant(attachment)
attachment.variant(resize_to_fit: [200, 200])
end
def profile_variant(attachment)
attachment.variant(resize_to_fill: [100, 100, { gravity: "north" }])
end
def tiny_variant(attachment)
attachment.variant(resize_to_fill: [40, 40, { gravity: "north" }])
end
end

View File

@@ -0,0 +1,11 @@
module MailHelper
def mail_to_for_multiple_edls(content, project)
subject = "Multiple Adobe Premiere EDLs needed for #{project.account.name}'s #{project.name} project"
body =
"INSTRUCTIONS\n\n" \
"1. Tell us the name of the video: \n\n" \
"2. Attach each EDL to this email. Please make sure to indicate whether the EDL is a Video Only, Graphics Only, or Audio Only EDL."
mail_to "info@bigmedia.ai", content, subject: subject, body: body
end
end

View File

@@ -0,0 +1,45 @@
module MembershipsHelper
def get_name_or_email(user)
user.full_name.present? ? user.full_name : user.email
end
def image_or_text_avatar(user)
if user.avatar.attached?
image_avatar(user)
else
text_avatar(user)
end
end
def image_avatar(user)
image_tag(tiny_variant(user.avatar), class: "rounded-circle", alt: "User Avatar")
end
def text_avatar(user, size: 2.5)
font_size = size / 2.5
if user.first_name.present? && user.last_name.present?
initials = (user.first_name.first + user.last_name.first).upcase
else
initials = user.email.first(2).upcase
end
content_tag(:div,
class: "bg-light border rounded-circle d-inline-flex justify-content-center align-items-center",
style: "width:#{size}rem;height:#{size}rem;") do
content_tag(:span, initials, class: "h-5 m-0 p-0 text-muted no-line-height", style: "font-size:#{font_size}rem")
end
end
def team_member_list(members)
list_classes = "list-unstyled d-flex flex-row justify-content-start align-items-center flex-nowrap overflow-hidden"
content_tag(:ul, class: list_classes) do
members.each.with_index do |member, index|
concat content_tag(:li, image_or_text_avatar(member),
class: class_string("rounded-circle border border-white border-thicker", "ml-n3" => !index.zero?),
style: "z-index:#{100-index}")
end
end
end
end

View File

@@ -0,0 +1,18 @@
module NoteCategoriesHelper
MAPPINGS = {
other: "Other",
missing_talent_release: "Missing talent release",
missing_appearance_release: "Missing appearance release",
missing_location_release: "Missing location release",
missing_acquired_media_license: "Missing acquired media license",
missing_materials_release: "Missing materials release",
missing_music_license: "Missing music license",
logo_may_require_blurring: "Logo may require blurring",
}
def options_for_note_category_select(unreleased_appearance)
note_categories = UnreleasedAppearance.note_categories
note_categories = note_categories.map { |category, value| [category.humanize, category.to_s] }
options_for_select(note_categories, unreleased_appearance.note_category.to_s)
end
end

View File

@@ -0,0 +1,72 @@
module NotesHelper
def notes_preview(notes)
NotePreview.new(self, notes).to_html
end
class NotePreview
def initialize(view, notes)
@view = view
@notes = notes
end
def to_html
return if notes.empty?
safe_join [
content,
tag(:br),
timestamp_with_author,
link_to_additional_notes,
]
end
private
attr_reader :view, :notes
delegate :content_tag, :link_to, :mail_to, :pluralize, :safe_join, :tag, :time_ago_in_words, to: :view
def first_note
notes.first
end
def additional_notes
notes.drop(1)
end
def content
first_note.content
end
def link_to_additional_notes
return if additional_notes.empty?
badge = link_to([first_note.notable, :notes, locale: I18n.locale], remote: true, class: "badge badge-primary") do
pluralize(additional_notes.size, "more note")
end
safe_join [
tag(:br),
badge,
]
end
def timestamp_with_author
content_tag(:small) do
safe_join [timestamp, author]
end
end
def timestamp
time_ago_in_words(first_note.created_at) + " ago "
end
def author_email
first_note.email
end
def author
safe_join ["(", mail_to(author_email), ")"]
end
end
end

View File

@@ -0,0 +1,17 @@
module PlansHelper
def options_for_account_plan_select
[
["ME Suite", "me_suite"],
["DeliverME", "deliverme"],
["ReleaseME", "releaseme"],
]
end
def lock_icon_for(account, plan_uid, text: nil)
if account.try("#{plan_uid}_enabled?")
fa_icon("unlock fw", text: text)
else
fa_icon("lock fw", text: text)
end
end
end

View File

@@ -0,0 +1,14 @@
module ProjectClientHelper
def selected_project_client_value(project)
client_name = project.client_name
case client_name
when "Discovery", "Nat Geo"
val = client_name
else
val = "Other"
end
val.parameterize(separator: '_')
end
end

View File

@@ -0,0 +1,29 @@
module ReleaseTypesHelper
def options_for_release_type_select(project = nil, release_type = "talent")
release_types = Project::SIGNABLE_RELEASE_TYPES
if project
release_types = release_types.select { |type| project.feature_enabled?("#{type}_release") }
end
release_types = release_types.map { |type| [ "#{release_type_title(type)} Release", type ] }
options_for_select(release_types, release_type)
end
def release_type_title(releasable_type)
releasable_type.titleize
end
def releasable_type_heading(releasable_type)
releasable_type.titleize.pluralize
end
def available_release_types
Project::AVAILABLE_RELEASE_TYPES.map { |release| "#{release}_release"}
end
def available_release_types_model_names
available_release_types.map(&:classify).map(&:constantize).map(&:model_name)
end
end

View File

@@ -0,0 +1,90 @@
module TagsHelper
def button_to_bulk_tagging(project)
content = fa_icon("tags", text: t("shared.tag_multiple_releases"))
disabled_content = fa_icon("spinner spin", text: t("shared.tag_multiple_releases"))
route = [:new, :bulk_tagging]
options = {
id: "tag_all",
class: "btn btn-light border mr-2 mb-2",
method: :get,
remote: true,
disabled: true,
params: {
project_id: project,
},
data: {
disable_with: disabled_content,
},
form: {
data: {
releasable_ids: [],
},
},
}
button_to(route, options) { content }
end
def tags_preview(taggable, tags)
TagPreview.new(self, tags, taggable).to_html
end
class TagPreview
def initialize(view, tags, taggable)
@view = view
@tags = tags
@taggable = taggable
end
def to_html
return if tags.empty?
safe_join [
names,
link_to_additional_tags,
]
end
private
attr_reader :view, :tags, :taggable
delegate :content_tag, :link_to, :pluralize, :safe_join, :tag, to: :view
def two_tags
tags.first(2)
end
def additional_tags
tags.drop(2)
end
def names
content_tag(:ul, class: "list-inline list-comma-separated fa-ul m-0") do
two_tags.each do |tag|
link = link_to_manage_tags(tag.name, class: "small text-nowrap")
view.concat content_tag(:li, link, class: "list-inline-item")
end
end
end
def link_to_additional_tags
return if additional_tags.empty?
link_to_manage_tags(pluralize(additional_tags.size, "more tag"), class: "badge badge-primary")
end
def link_to_manage_tags(content, options = {})
route = [:new, taggable, :acts_as_taggable_on_tag, locale: I18n.locale]
opts = {
remote: true,
data: {
disable_with: content
}
}.update(options)
link_to(content.html_safe, route, opts)
end
end
end

View File

@@ -0,0 +1,8 @@
module TooltipHelper
def tooltip_template(css_class: nil)
tag.div class: "tooltip #{css_class}", role: "tooltip" do
concat tag.div(class: "arrow")
concat tag.div(class: "tooltip-inner")
end
end
end

View File

@@ -0,0 +1,22 @@
module WordmarkHelper
def suite_wordmark(additional_classes="")
content_tag(:div, class: "suite-wordmark #{additional_classes}") do
safe_join [
content_tag(:span, t("shared.me")),
content_tag(:span, t("shared.suite"))
]
end
end
def product_wordmark(product_name, options = {})
css = "product-wordmark #{product_name.to_s.dasherize} "
css += options[:class].to_s
content_tag(:div, class: css) do
safe_join [
content_tag(:span, t("shared.#{product_name}")),
content_tag(:span, t("shared.me"))
]
end
end
end