scinote-web/config/initializers/constants.rb

487 lines
17 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class Constants
#=============================================================================
# String lengths
#=============================================================================
# Min characters for short text fields
NAME_MIN_LENGTH = 2
# Max characters for short text fields
NAME_MAX_LENGTH = 255
# Max characters for short text fields, after which they get truncated
NAME_TRUNCATION_LENGTH = 25
# Max edge length
MAX_EDGE_LENGTH = 75
# Max character for listing projects in dropdown
MAX_NAME_TRUNCATION = 150
# Max characters for short text fields, in dropdownList
NAME_TRUNCATION_LENGTH_DROPDOWN = 20
# Max characters for long text fields
TEXT_MAX_LENGTH = 10000
# Max characters for rich text fields (in html format)
RICH_TEXT_MAX_LENGTH = 1000000
# Max characters for color field (given in HEX format)
COLOR_MAX_LENGTH = 7
# Max characters for text in dropdown list element
DROPDOWN_TEXT_MAX_LENGTH = 15
# Max characters for text in modal list element
MODAL_TEXT_MAX_LENGTH = 55
# Max characters limit for (on most operating systems, it's ~255 characters,
# but this is with a bit more safety margin)
FILENAME_MAX_LENGTH = 100
# Max characters for filenames, after which they get truncated
FILENAME_TRUNCATION_LENGTH = 50
# Max characters for names of exported files and folders, after which they get
# truncated
EXPORTED_FILENAME_TRUNCATION_LENGTH = 20
USER_INITIALS_MAX_LENGTH = 4
# Password 'key stretching' factor
PASSWORD_STRETCH_FACTOR = 10
# Standard max length for email
EMAIL_MAX_LENGTH = 254
# Some big value which is still supported by all databases, no matter what
# data type is used
INFINITY = ((2**32) / 2) - 1
# Prevents integer overflow for reminder delta seconds
MAX_NUMBER_OF_REMINDER_WEEKS = 816
#=============================================================================
# Query/display limits
#=============================================================================
# General limited/unlimited query/display elements for pages
SEARCH_LIMIT = 20
# General global search limit for object groups
GLOBAL_SEARCH_PREVIEW_LIMIT = 4
SEARCH_NO_LIMIT = -1
# General limited query/display elements for popup modals
MODAL_SEARCH_LIMIT = 5
# Comments limited query/display elements for pages
COMMENTS_SEARCH_LIMIT = 10
# Activity limited query/display elements for pages
ACTIVITY_AND_NOTIF_SEARCH_LIMIT = 20
# Infinite Scroll load limit (elements per page)
INFINITE_SCROLL_LIMIT = 20
# Maximum number of users that can be invited in a single action
INVITE_USERS_LIMIT = 20
# Maximum nr. of search results for atwho (smart annotations)
ATWHO_SEARCH_LIMIT = 10
# Max characters for repository name in Atwho modal
ATWHO_REP_NAME_LIMIT = 16
# Results limited query/display elements for pages
RESULTS_PER_PAGE_LIMIT = 10
#Experiments more button appears
EXPERIMENT_LONG_DESCRIPTION = 80
# Infinite scroll default elements per page
DEFAULT_ELEMENTS_PER_PAGE = 20
# Default navigator width
DEFAULT_NAV_WIDTH = 208
#=============================================================================
# File and data memory size
#=============================================================================
# Max table JSON size in MB
TABLE_JSON_MAX_SIZE_MB = 20
# Max uploaded user picture avatar size in MB
AVATAR_MAX_SIZE_MB = 0.2
# PDF preview file limit in MB
PDF_PREVIEW_MAX_SIZE_MB = 10
#=============================================================================
# Application space
#=============================================================================
# Minimal space needed for team (in B)
MINIMAL_TEAM_SPACE_TAKEN = 1.megabyte
# Additional space of each file is added to its estimated size to account for
# DB indexes size etc.
ASSET_ESTIMATED_SIZE_FACTOR = 1.1
#=============================================================================
# Format sizes
#=============================================================================
# Picture size formats
LARGE_PIC_FORMAT = [800, 600].freeze
MEDIUM_PIC_FORMAT = [300, 300].freeze
THUMB_PIC_FORMAT = [100, 100].freeze
ICON_PIC_FORMAT = [40, 40].freeze
ICON_SMALL_PIC_FORMAT = [30, 30].freeze
# Hands-on-table number of starting columns and rows
HANDSONTABLE_INIT_COLS_CNT = 5
HANDSONTABLE_INIT_ROWS_CNT = 5
# Word reports format. All units in Twips.
# A twip is 1/20 of a point. Word documents are printed at 72dpi. 1in == 72pt == 1440 twips.
# Here is default A4
REPORT_DOCX_WIDTH = 12240
REPORT_DOCX_HEIGHT = 15840
REPORT_DOCX_MARGIN_TOP = 720
REPORT_DOCX_MARGIN_RIGHT = 720
REPORT_DOCX_MARGIN_BOTTOM = 720
REPORT_DOCX_MARGIN_LEFT = 720
# Word borders in eighth point units.
# A eighth point is 1/8 of a point. A border size of 4 is equivalent to 0.5pt.
REPORT_DOCX_TABLE_BORDER_SIZE = 4
# All font size in half points
REPORT_DOCX_REPORT_TITLE_SIZE = 36
REPORT_DOCX_EXPERIMENT_TITLE_SIZE = 32
REPORT_DOCX_MY_MODULE_TITLE_SIZE = 28
REPORT_DOCX_STEP_TITLE_SIZE = 22
REPORT_DOCX_STEP_ELEMENTS_TITLE_SIZE = 20
#=============================================================================
# Styling
#=============================================================================
# Dropdown top offset from the parent
DROPDOWN_TOP_OFFSET_PX = 20
#=============================================================================
# Date and time
#=============================================================================
# URL expire time, used for presigned file URLs, because outsiders shouldn't
# have access to them, but some buffer time is needed for file to be loaded
URL_SHORT_EXPIRE_TIME = 30
# Same as URL_EXPIRE_TIME, except for cases where the URL migth be used in
# another page, and hence the URL mustn't expire by then (e.g. when generating
# report and than using same HTML code in PDF, and consequently same file
# URL); it expires in exactly one day
URL_LONG_EXPIRE_TIME = 86_400
DEFAULT_DATE_FORMAT = '%m/%d/%Y'.freeze
SUPPORTED_DATE_FORMATS = [
# US formats
'%m/%d/%Y', '%m.%d.%Y', '%m. %d. %Y', '%m-%d-%Y', '%-m/%-d/%Y',
'%-m.%-d.%Y', '%-m. %-d. %Y', '%-m-%-d-%Y',
# European formats
'%d/%m/%Y', '%d.%m.%Y', '%d. %m. %Y', '%d-%b-%Y', '%Y-%m-%d',
'%d.%b.%Y', '%Y/%b/%d', '%d, %B, %Y', '%B, %d, %Y', '%-d/%-m/%Y',
'%-d.%-m.%Y', '%-d. %-m. %Y', '%d-%m-%Y', '%Y-%-m-%-d', '%-d-%b-%Y',
'%Y-%b-%-d', '%-d, %B, %Y', '%B, %-d, %Y'
].freeze
#=============================================================================
# Application colors
#
# NOTE: Don't use shortened syntax, e.g. #000 for #000000, as some Gems need
# full syntax!
#=============================================================================
TAG_COLORS = %i(
#C4D3A0
#5EC66F
#46C3C8
#A3CCE4
#3B99FD
#104DA9
#6F2DC1
#FF69B4
#DF3562
#AD0015
#FF5C00
#E9A845
#B06500
#663300
#1D2939
#98A2B3
#DCE0E7
).freeze
# Theme colors
BRAND_PRIMARY = '#104da9'.freeze # $brand-primary
# Grayscale colors
COLOR_WHITE = '#ffffff'.freeze # $color-white
COLOR_CONCRETE = '#f0f0f6'.freeze # $color-concrete
COLOR_ALTO = '#d0d0d8'.freeze # $color-alto
COLOR_SILVER_CHALICE = '#a0a0a8'.freeze # $color-silver-chalice
COLOR_VOLCANO = '#404048'.freeze # $color-volcano
COLOR_BLACK = '#231f20'.freeze # $color-black
# Fonts
FONT_FAMILY_BASE = 'Inter,"Open Sans",Arial,Helvetica,sans-serif;'.freeze # $font-family-base
#=============================================================================
# External URLs
#=============================================================================
HTTP = 'http://'.freeze
TUTORIALS_URL = ENV.fetch('VIDEO_TUTORIALS_URL', "#{HTTP}goo.gl/YH3fXA").freeze
SUPPORT_URL = ENV.fetch('KNOWLEDGE_CENTER_URL', 'https://scinote-3850750.hs-sites.com/en/knowledge').freeze
FREE_TRIAL_URL = 'https://www.scinote.net/free-trial/?utm_source=SciNoteShare&utm_medium=FreeTrialButton&utm_campaign=Q3_2023'.freeze
# Default user picture avatar
DEFAULT_AVATAR_URL = '/images/:style/missing.svg'.freeze
ACADEMY_BL_LINK = 'https://scinote.net/academy/?utm_source=SciNote%20software%20BL&utm_medium=SciNote%20software%20BL'.freeze
PWA_URL = 'https://:pwa_domain/teams/:team_id/projects/:project_id/experiments/:experiment_id/tasks/:task_id/protocol/:protocol_id/:step_id?domain=:domain'.freeze
TWO_FACTOR_URL = {
google: {
android: 'https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2',
ios: 'https://apps.apple.com/us/app/google-authenticator/id388497605'
},
microsoft: {
android: 'https://play.google.com/store/apps/details?id=com.azure.authenticator',
ios: 'https://apps.apple.com/us/app/microsoft-authenticator/id983156458'
},
two_fa: {
android: 'https://play.google.com/store/apps/details?id=com.twofasapp',
ios: 'https://apps.apple.com/us/app/2fa-authenticator-2fas/id1217793794'
},
}
SCINOTE_FLUICS_URL = 'https://www.scinote.net/fluics/'.freeze
SCINOTE_ZEBRA_DOWNLOAD_URL = 'https://www.zebra.com/us/en/software/printer-software/browser-print.html'.freeze
SCINOTE_ZEBRA_BLOG_URL = 'https://www.scinote.net/blog/connect-zebra-printers/'.freeze
SCINOTE_ZEBRA_SUPPORT_URL = 'https://www.zebra.com/us/en/about-zebra/contact-zebra/contact-tech-support.html'.freeze
TWO_FACTOR_RECOVERY_CODE_COUNT = 6
TWO_FACTOR_RECOVERY_CODE_LENGTH = 12
API_KEY_EXPIRES_IN = 1.year
#=============================================================================
# Protocol importers
#=============================================================================
PROTOCOLS_ENDPOINTS = {
protocolsio: {
v3: 'ProtocolsIo::V3'
}
}.freeze
PROTOCOLS_IO_URL = 'https://www.protocols.io/'.freeze
PROTOCOLS_IO_V3_API = {
base_uri: 'https://www.protocols.io/api/v3/',
default_timeout: 10,
debug_level: :debug,
sort_mappings: {
alpha_asc: { order_field: :name, order_dir: :asc },
alpha_desc: { order_field: :name, order_dir: :desc },
newest: { order_field: :date, order_dir: :desc },
oldest: { order_field: :date, order_dir: :asc }
},
endpoints: {
protocols: {
default_query_params: {
filter: :public,
key: '',
order_field: :activity,
order_dir: :desc,
page_size: 50,
page_id: 0,
fields: 'id,title,authors,created_on,uri,stats,published_on'
}
},
publications: {
default_query_params: {
latest: 20
}
}
},
source_id: 'protocolsio/v3'
}.freeze
PROTOCOLS_DESC_TAGS = %w(a img i br).freeze
#=============================================================================
# Other
#=============================================================================
FILE_TEXT_FORMATS = %w(doc docm docx dot dotm dotx odt rtf).freeze
FILE_TABLE_FORMATS = %w(csv ods xls xlsb xlsm xlsx).freeze
FILE_PRESENTATION_FORMATS =
%w(odp pot potm potx pps ppsm ppsx ppt pptm pptx).freeze
WOPI_EDITABLE_FORMATS = %w(
docx docm odt xlsx xlsm xlsb ods pptx ppsx odp
).freeze
TEXT_EXTRACT_FILE_TYPES = [
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
'application/pdf',
'application/rtf',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'application/vnd.oasis.opendocument.presentation',
'application/vnd.oasis.opendocument.spreadsheet',
'application/vnd.oasis.opendocument.text',
'application/vnd.ms-excel',
'application/vnd.ms-powerpoint',
'application/vnd.ms-word',
'text/plain'
].freeze
PREVIEWABLE_FILE_TYPES = TEXT_EXTRACT_FILE_TYPES
WHITELISTED_IMAGE_TYPES = [
'gif', 'jpeg', 'pjpeg', 'png', 'x-png', 'svg+xml', 'bmp', 'tiff', 'jpg'
].freeze
WHITELISTED_IMAGE_TYPES_EDITABLE = %w(
jpeg pjpeg png
).freeze
config = Sanitize::Config::RELAXED.deep_dup
config[:attributes][:all] << 'id'
config[:attributes][:all] << 'contenteditable'
config[:attributes]['img'] << 'data-mce-token'
config[:attributes]['img'] << 'data-source-type'
config[:attributes]['a'] << 'data-turbolinks'
config[:protocols]['img']['src'] << 'data'
INPUT_SANITIZE_CONFIG = Sanitize::Config.freeze_config(config)
REPOSITORY_DEFAULT_PAGE_SIZE = 10
REPOSITORY_LIST_ITEMS_PER_COLUMN = 500
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN = 50
REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN = 50
REPOSITORY_NUMBER_TYPE_DEFAULT_DECIMALS = 2
REPOSITORY_NUMBER_TYPE_MAX_DECIMALS = 10
REPOSITORY_DATETIME_REMINDER_PRESET = 10
# Repository default table state
REPOSITORY_TABLE_DEFAULT_STATE = {
'time' => 0,
'start' => 0,
'length' => REPOSITORY_DEFAULT_PAGE_SIZE,
'order' => [[3, 'asc']], # Default sorting by 'name' column
'columns' => [],
'assigned' => 'assigned',
'ColReorder' => [*0..10]
}
11.times do |i|
REPOSITORY_TABLE_DEFAULT_STATE['columns'] << {
'visible' => (i < 7 && i != 4), # relationship column is hidden by default
'searchable' => (i >= 1 && i != 4), # Checkboxes and relationship column is not searchable
'search' => { 'search' => '',
'smart' => true,
'regex' => false,
'caseInsensitive' => true }
}
end
REPOSITORY_TABLE_DEFAULT_STATE.freeze
# Repository default table state
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE = {
'time' => 0,
'start' => 0,
'length' => REPOSITORY_DEFAULT_PAGE_SIZE,
'order' => [[1, 'asc']], # Default sorting by 'ID' column
'columns' => [],
'assigned' => 'assigned',
'ColReorder' => [*0..4]
}
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['columns'] = REPOSITORY_TABLE_DEFAULT_STATE['columns'][0..4].deep_dup
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE['columns'][4]['visible'] = true
REPOSITORY_SNAPSHOT_TABLE_DEFAULT_STATE.freeze
# For default custom column template, any searchable default
# column can be reused
REPOSITORY_TABLE_STATE_CUSTOM_COLUMN_TEMPLATE =
REPOSITORY_TABLE_DEFAULT_STATE['columns'][1].deep_dup
.freeze
EXPORTABLE_ZIP_EXPIRATION_DAYS = 7
REPOSITORY_LIST_ITEMS_DELIMITERS_MAP = {
return: "\n",
comma: ',',
semicolon: ';',
space: ' '
}.freeze
REPOSITORY_LIST_ITEMS_DELIMITERS_ICON_MAP = {
auto: "",
return: "",
comma: ',',
semicolon: ';',
space: '⎵'
}.freeze
IMPORT_REPOSITORY_ITEMS_LIMIT = 2000
IMPORT_REPOSITORY_ITEMS_MIN_LIMIT = 2
DEFAULT_TEAM_REPOSITORIES_LIMIT = 6
# Very basic regex to check for validity of emails
BASIC_EMAIL_REGEX = URI::MailTo::EMAIL_REGEXP
TINY_MCE_ASSET_REGEX = /data-mce-token="(\w+)"/
# Team name for default admin user
DEFAULT_PRIVATE_TEAM_NAME = 'My projects'.freeze
TEMPLATES_PROJECT_NAME = 'SciNote Examples'.freeze
# Interval time for polling status state
FAST_STATUS_POLLING_INTERVAL = 5000
SLOW_STATUS_POLLING_INTERVAL = 10000
# Interval time for polling asset changes when editing with SciNote Edit
ASSET_POLLING_INTERVAL = 5000
ASSET_SYNC_TOKEN_EXPIRATION = 1.year
ASSET_SYNC_URL = ENV['ASSET_SYNC_URL'].freeze
# Grover timeout in ms
GROVER_TIMEOUT_MS = 450000
# SciNote Edit supported versions
MIN_SCINOTE_EDIT_VERSION = ENV['MIN_SCINOTE_EDIT_VERSION'].freeze
MAX_SCINOTE_EDIT_VERSION = ENV['MAX_SCINOTE_EDIT_VERSION'].freeze
# quick search
QUICK_SEARCH_LIMIT = 5
QUICK_SEARCH_SEARCHABLE_OBJECTS = %w(project experiment my_module protocol repository_row
report project_folder result label_template).freeze
# ) \ / (
# /|\ )\_/( /|\
# * / | \ (/\|/\) / | \ *
# |`.____________________/__|__o____\`|'/___o__|__\___________________.'|
# | '^` \|/ '^` |
# | V |
# | _____ _ _ __ |
# | |_ _| |__ __ _ _ __ | | __ _ _ ___ _ _ ( | |
# | | | | '_ \ / _` | '_ \| |/ / | | | |/ _ \| | | | | ) |
# | | | | | | | (_| | | | | < | |_| | ( | | |_| | \_/ |
# | |_| |_| |_|\__,_|_| |_|_|\_\ \__, |\___/ \_,|_| _ |
# | |___/ (_) |
# | |
# | Special Thank You for supporting SciNote on Kicstarter goes |
# | to the following supporters |
# | ._________________________________________________________________. |
# |' l /\ / \\ \ /\ l `|
# * l / V )) V \ l *
# l/ // \I
KICKSTARTER_SUPPORTERS = [
'Manuela Lanzafame',
'Fluckiger Rudolf',
'Emily Gleason',
'Benjamin E Doremus',
'Chord Pet Wearable',
'Chris Taylor',
'Abraham White',
'Ryotaro Eguchi',
'Simon Waldherr',
'Isaac Sandaljian',
'Markus Rademacher'
].freeze
end