mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-09-29 00:14:41 +08:00
Merge branch 'develop' into features/native-tables-revamp
This commit is contained in:
commit
ace4139a84
35 changed files with 286 additions and 109 deletions
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
1.39.0
|
||||
1.39.1.1
|
||||
|
|
|
@ -81,16 +81,19 @@
|
|||
dropdownSelector.init(myModuleUserSelector, {
|
||||
closeOnSelect: true,
|
||||
labelHTML: true,
|
||||
tagClass: 'my-module-user-tags',
|
||||
tagLabel: (data) => {
|
||||
return `<img class="img-responsive block-inline" src="${data.params.avatar_url}" alt="${data.label}"/>
|
||||
<span class="user-full-name block-inline">${data.label}</span>`;
|
||||
return `<div class="flex items-center gap-2">
|
||||
<img class="img-responsive block-inline" src="${data.params.avatar_url}" alt="${data.label}"/>
|
||||
<span class="user-full-name block-inline">${data.label}</span>
|
||||
</div>`;
|
||||
},
|
||||
optionLabel: (data) => {
|
||||
if (data.params.avatar_url) {
|
||||
return `<span class="global-avatar-container" style="margin-top: 10px">
|
||||
<img src="${data.params.avatar_url}" alt="${data.label}"/></span>
|
||||
<span style="margin-left: 10px">${data.label}</span>`;
|
||||
return `<div class="flex items-center gap-2">
|
||||
<span class="global-avatar-container">
|
||||
<img src="${data.params.avatar_url}" alt="${data.label}"/></span>
|
||||
<span style="margin-left: 10px">${data.label}</span>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
return data.label;
|
||||
|
|
|
@ -747,7 +747,7 @@ var MyModuleRepositories = (function() {
|
|||
|
||||
function openUpdateRecordsModal(downstream) {
|
||||
var updateUrl = FULL_VIEW_MODAL.data('update-url-modal');
|
||||
$.get(updateUrl, { selected_rows: SELECTED_ROWS, downstream: downstream }, function(data) {
|
||||
$.post(updateUrl, { selected_rows: SELECTED_ROWS, downstream: downstream }, function(data) {
|
||||
var assignList;
|
||||
var assignListScrollbar;
|
||||
var unassignList;
|
||||
|
@ -766,7 +766,7 @@ var MyModuleRepositories = (function() {
|
|||
|
||||
function openAssignRecordsModal(downstream) {
|
||||
var assignUrl = FULL_VIEW_MODAL.data('assign-url-modal');
|
||||
$.get(assignUrl, { selected_rows: Object.keys(SELECTED_ROWS), downstream: downstream }, function(data) {
|
||||
$.post(assignUrl, { selected_rows: Object.keys(SELECTED_ROWS), downstream: downstream }, function(data) {
|
||||
UPDATE_REPOSITORY_MODAL.find('.modal-content').html(data.html);
|
||||
UPDATE_REPOSITORY_MODAL.data('update-url', data.update_url);
|
||||
UPDATE_REPOSITORY_MODAL.modal('show');
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
const GLOBAL_CONSTANTS = {
|
||||
NAME_TRUNCATION_LENGTH: <%= Constants::NAME_TRUNCATION_LENGTH %>,
|
||||
NAME_MAX_LENGTH: <%= Constants::NAME_MAX_LENGTH %>,
|
||||
NAME_MIN_LENGTH: <%= Constants::NAME_MIN_LENGTH %>,
|
||||
TEXT_MAX_LENGTH: <%= Constants::TEXT_MAX_LENGTH %>,
|
||||
TABLE_CARD_MIN_WIDTH: 340, <%# pixels %>
|
||||
TABLE_CARD_GAP: 16, <%# pixels %>
|
||||
FILENAME_TRUNCATION_LENGTH: <%= Constants::FILENAME_TRUNCATION_LENGTH %>,
|
||||
FILE_MAX_SIZE_MB: parseInt($('meta[name="max-file-size"]').attr('content'), 10),
|
||||
IS_SAFARI: /^((?!chrome|android).)*safari/i.test(navigator.userAgent),
|
||||
REPOSITORY_LIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN %>,
|
||||
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN %>,
|
||||
REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN: <%= Constants::REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN %>,
|
||||
HAS_UNSAVED_DATA_CLASS_NAME: 'has-unsaved-data',
|
||||
DEFAULT_ELEMENTS_PER_PAGE: <%= Constants::DEFAULT_ELEMENTS_PER_PAGE %>,
|
||||
FILENAME_MAX_LENGTH: <%= Constants::FILENAME_MAX_LENGTH %>,
|
||||
FAST_STATUS_POLLING_INTERVAL: <%= Constants::FAST_STATUS_POLLING_INTERVAL %>,
|
||||
SLOW_STATUS_POLLING_INTERVAL: <%= Constants::SLOW_STATUS_POLLING_INTERVAL %>,
|
||||
ASSET_POLLING_INTERVAL: <%= Constants::ASSET_POLLING_INTERVAL %>,
|
||||
ASSET_SYNC_URL: '<%= Constants::ASSET_SYNC_URL %>',
|
||||
GLOBAL_SEARCH_PREVIEW_LIMIT: <%= Constants::GLOBAL_SEARCH_PREVIEW_LIMIT %>,
|
||||
SEARCH_LIMIT: <%= Constants::SEARCH_LIMIT %>,
|
||||
SCINOTE_EDIT_RESTRICTED_EXTENSIONS: <%= Constants::SCINOTE_EDIT_RESTRICTED_EXTENSIONS %>
|
||||
};
|
|
@ -182,7 +182,7 @@ var zebraPrint = (function() {
|
|||
repository_id: int
|
||||
}
|
||||
*/
|
||||
print: function(modalUrl, progressModal, printModal, printData) {
|
||||
print: function(modalUrl, progressModal, printModal, printData, finishedCallback = null) {
|
||||
var modal = $(progressModal);
|
||||
$.ajax({
|
||||
method: 'GET',
|
||||
|
@ -224,7 +224,7 @@ var zebraPrint = (function() {
|
|||
}
|
||||
}).fail(() => {
|
||||
HelperModule.flashAlertMsg(I18n.t('repository_row.modal_print_label.general_error'), 'danger');
|
||||
});
|
||||
}).always(() => { if (finishedCallback) finishedCallback(); });
|
||||
}
|
||||
};
|
||||
}());
|
||||
|
|
|
@ -36,3 +36,9 @@ table.dataTable.table--resizable-columns {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
div.dataTables_wrapper div.dataTables_processing {
|
||||
// This overrides default library behaviour, where the 'Processing' element
|
||||
// can go off-screen on large tables due to top: 50% positioning.
|
||||
top: 150px !important;
|
||||
}
|
||||
|
|
38
app/controllers/global_constants_controller.rb
Normal file
38
app/controllers/global_constants_controller.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GlobalConstantsController < ApplicationController
|
||||
before_action :load_global_constants
|
||||
skip_before_action :authenticate_user!, only: :index
|
||||
skip_before_action :verify_authenticity_token, only: :index
|
||||
|
||||
def index; end
|
||||
|
||||
private
|
||||
|
||||
def load_global_constants
|
||||
@global_constants = {
|
||||
NAME_TRUNCATION_LENGTH: Constants::NAME_TRUNCATION_LENGTH,
|
||||
NAME_MAX_LENGTH: Constants::NAME_MAX_LENGTH,
|
||||
NAME_MIN_LENGTH: Constants::NAME_MIN_LENGTH,
|
||||
TEXT_MAX_LENGTH: Constants::TEXT_MAX_LENGTH,
|
||||
TABLE_CARD_MIN_WIDTH: 340,
|
||||
TABLE_CARD_GAP: 16,
|
||||
FILENAME_TRUNCATION_LENGTH: Constants::FILENAME_TRUNCATION_LENGTH,
|
||||
FILE_MAX_SIZE_MB: Rails.configuration.x.file_max_size_mb,
|
||||
REPOSITORY_LIST_ITEMS_PER_COLUMN: Constants::REPOSITORY_LIST_ITEMS_PER_COLUMN,
|
||||
REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN: Constants::REPOSITORY_CHECKLIST_ITEMS_PER_COLUMN,
|
||||
REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN: Constants::REPOSITORY_STOCK_UNIT_ITEMS_PER_COLUMN,
|
||||
HAS_UNSAVED_DATA_CLASS_NAME: 'has-unsaved-data',
|
||||
DEFAULT_ELEMENTS_PER_PAGE: Constants::DEFAULT_ELEMENTS_PER_PAGE,
|
||||
FILENAME_MAX_LENGTH: Constants::FILENAME_MAX_LENGTH,
|
||||
FAST_STATUS_POLLING_INTERVAL: Constants::FAST_STATUS_POLLING_INTERVAL,
|
||||
SLOW_STATUS_POLLING_INTERVAL: Constants::SLOW_STATUS_POLLING_INTERVAL,
|
||||
ASSET_POLLING_INTERVAL: Constants::ASSET_POLLING_INTERVAL,
|
||||
ASSET_SYNC_URL: Constants::ASSET_SYNC_URL,
|
||||
GLOBAL_SEARCH_PREVIEW_LIMIT: Constants::GLOBAL_SEARCH_PREVIEW_LIMIT,
|
||||
SEARCH_LIMIT: Constants::SEARCH_LIMIT,
|
||||
SCINOTE_EDIT_RESTRICTED_EXTENSIONS: Constants::SCINOTE_EDIT_RESTRICTED_EXTENSIONS,
|
||||
SCINOTE_EDIT_LATEST_JSON_URL: Constants::SCINOTE_EDIT_LATEST_JSON_URL
|
||||
}
|
||||
end
|
||||
end
|
|
@ -9,15 +9,16 @@ class RepositoriesController < ApplicationController
|
|||
include RepositoriesDatatableHelper
|
||||
include MyModulesHelper
|
||||
|
||||
before_action :switch_team_with_param, only: %i(index)
|
||||
before_action :load_repository, except: %i(index create create_modal sidebar archive restore actions_toolbar
|
||||
export_modal export_repositories list)
|
||||
export_repositories list)
|
||||
before_action :load_repositories, only: %i(index list)
|
||||
before_action :load_repositories_for_archiving, only: :archive
|
||||
before_action :load_repositories_for_restoring, only: :restore
|
||||
before_action :check_view_all_permissions, only: %i(index sidebar list)
|
||||
before_action :check_view_permissions, except: %i(index create_modal create update destroy parse_sheet
|
||||
import_records sidebar archive restore actions_toolbar
|
||||
export_modal export_repositories list)
|
||||
export_repositories list)
|
||||
before_action :check_manage_permissions, only: %i(rename_modal update)
|
||||
before_action :check_delete_permissions, only: %i(destroy destroy_modal)
|
||||
before_action :check_archive_permissions, only: %i(archive restore)
|
||||
|
@ -83,7 +84,6 @@ class RepositoriesController < ApplicationController
|
|||
def show
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
current_team_switch(@repository.team) unless @repository.shared_with?(current_team)
|
||||
@display_edit_button = can_create_repository_rows?(@repository)
|
||||
@display_delete_button = can_delete_repository_rows?(@repository)
|
||||
@display_duplicate_button = can_create_repository_rows?(@repository)
|
||||
|
@ -470,7 +470,7 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def load_repository
|
||||
repository_id = params[:id] || params[:repository_id]
|
||||
@repository = Repository.viewable_by_user(current_user).find_by(id: repository_id)
|
||||
@repository = Repository.viewable_by_user(current_user, current_user.teams).find_by(id: repository_id)
|
||||
render_404 unless @repository
|
||||
end
|
||||
|
||||
|
@ -515,6 +515,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def check_view_permissions
|
||||
current_team_switch(@repository.team) unless @repository.shared_with?(current_team)
|
||||
render_403 unless can_read_repository?(@repository)
|
||||
end
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
class ResultsController < ApplicationController
|
||||
include Breadcrumbs
|
||||
include TeamsHelper
|
||||
|
||||
before_action :load_my_module
|
||||
before_action :load_vars, only: %i(destroy elements assets upload_attachment archive restore destroy
|
||||
update_view_state update_asset_view_mode update duplicate)
|
||||
|
|
|
@ -114,7 +114,7 @@ class SearchController < ApplicationController
|
|||
return
|
||||
when 'repository_rows'
|
||||
@model = RepositoryRow
|
||||
search_by_name(RepositoryRow)
|
||||
search_by_name
|
||||
|
||||
render json: @records,
|
||||
each_serializer: GlobalSearch::RepositoryRowSerializer,
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<div v-if="!loading && actions.length === 0" class="sn-action-toolbar__message">
|
||||
{{ i18n.t('action_toolbar.no_actions') }}
|
||||
</div>
|
||||
<div v-for="action in actions" :key="action.name" class="sn-action-toolbar__action shrink-0">
|
||||
<div v-for="action in actions" :key="action.name" class="sn-action-toolbar__action shrink-0" :class="{ 'disable-click': disabledActions[action.name] }">
|
||||
<div v-if="action.type === 'group' && Array.isArray(action.actions) && action.actions.length > 1" class="export-actions-dropdown sci-dropdown dropup">
|
||||
<button class="btn btn-primary dropdown-toggle single-object-action rounded" type="button" id="exportDropdown" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true" data-e2e="e2e-DD-actionToolbar-export">
|
||||
<i class="sn-icon sn-icon-export"></i>
|
||||
|
@ -75,6 +75,7 @@
|
|||
|
||||
<script>
|
||||
import { debounce } from '../shared/debounce.js';
|
||||
import axios from '../../packs/custom_axios.js';
|
||||
|
||||
export default {
|
||||
name: 'ActionToolbar',
|
||||
|
@ -95,7 +96,8 @@ export default {
|
|||
bottomOffset: 0,
|
||||
leftOffset: 0,
|
||||
buttonOverflow: false,
|
||||
submitting: false
|
||||
submitting: false,
|
||||
disabledActions: {}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
|
@ -105,8 +107,8 @@ export default {
|
|||
this.debouncedFetchActions = debounce((params) => {
|
||||
this.params = params;
|
||||
|
||||
$.get(`${this.actionsUrl}?${new URLSearchParams(this.params).toString()}`, (data) => {
|
||||
this.actions = data.actions;
|
||||
axios.post(this.actionsUrl, this.params).then((response) => {
|
||||
this.actions = response.data.actions;
|
||||
this.loading = false;
|
||||
this.setButtonOverflow();
|
||||
if (this.actionsLoadedCallback) this.$nextTick(this.actionsLoadedCallback);
|
||||
|
@ -168,6 +170,12 @@ export default {
|
|||
this.actionsLoadedCallback = func;
|
||||
},
|
||||
doAction(action, event) {
|
||||
this.disabledActions[action.name] = true;
|
||||
|
||||
setTimeout(() => {
|
||||
delete this.disabledActions[action.name];
|
||||
}, 1000); // enable action after one second, to prevent multi-clicks
|
||||
|
||||
switch (action.type) {
|
||||
case 'legacy':
|
||||
// do nothing, this is handled by legacy code based on the button class
|
||||
|
|
|
@ -367,6 +367,7 @@ export default {
|
|||
deleteSteps() {
|
||||
$.post(this.urls.delete_steps_url, () => {
|
||||
this.steps = [];
|
||||
this.refreshProtocolDropdownOptions();
|
||||
}).fail(() => {
|
||||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
});
|
||||
|
|
|
@ -238,6 +238,9 @@ export default {
|
|||
label_template_id: this.selectedTemplate.id,
|
||||
row_ids: this.row_ids,
|
||||
repository_id: this.repository_id
|
||||
},
|
||||
() => {
|
||||
this.submitting = false;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="p-4 w-full rounded bg-sn-light-grey min-h-[68px]" :class="{ 'disable-click': submitting }" data-e2e="e2e-CO-actionToolbar">
|
||||
<div class="p-4 w-full rounded bg-sn-light-grey min-h-[68px]" data-e2e="e2e-CO-actionToolbar">
|
||||
<div class="flex gap-4 items-center h-full">
|
||||
<div v-if="loading && !actions.length" class="sn-action-toolbar__action">
|
||||
<a class="rounded flex items-center py-1.5 px-2.5 bg-transparent text-transparent no-underline"></a>
|
||||
|
@ -7,7 +7,7 @@
|
|||
<div v-if="!loading && actions.length === 0" class="text-sn-grey-grey">
|
||||
{{ i18n.t('action_toolbar.no_actions') }}
|
||||
</div>
|
||||
<div v-for="action in actions" :key="action.name" class="sn-action-toolbar__action shrink-0">
|
||||
<div v-for="action in actions" :key="action.name" class="sn-action-toolbar__action shrink-0" :class="{ 'disable-click': disabledActions[action.name] }">
|
||||
<a :class="`rounded flex gap-2 items-center py-1.5 px-1.5 xl:px-2.5 hover:text-sn-white hover:bg-sn-blue
|
||||
bg-sn-white color-sn-blue hover:no-underline focus:no-underline ${action.button_class}`"
|
||||
:href="(['link', 'remote-modal']).includes(action.type) ? action.path : '#'"
|
||||
|
@ -32,7 +32,7 @@ export default {
|
|||
name: 'ActionToolbar',
|
||||
props: {
|
||||
actionsUrl: { type: String, required: true },
|
||||
actionsMethod: { type: String, default: 'get' },
|
||||
actionsMethod: { type: String, default: 'post' },
|
||||
params: { type: Object },
|
||||
},
|
||||
data() {
|
||||
|
@ -42,7 +42,7 @@ export default {
|
|||
reloadCallback: null,
|
||||
loaded: false,
|
||||
loading: true,
|
||||
submitting: false
|
||||
disabledActions: {}
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
|
@ -70,10 +70,15 @@ export default {
|
|||
});
|
||||
},
|
||||
doAction(action, event) {
|
||||
this.disabledActions[action.name] = true;
|
||||
|
||||
setTimeout(() => {
|
||||
delete this.disabledActions[action.name];
|
||||
}, 1000); // enable action after one second, to prevent multi-clicks
|
||||
|
||||
switch (action.type) {
|
||||
case 'emit':
|
||||
event.preventDefault();
|
||||
this.submitting = true;
|
||||
this.$emit('toolbar:action', action);
|
||||
break;
|
||||
case 'modal':
|
||||
|
|
|
@ -50,7 +50,7 @@ export default {
|
|||
methods: {
|
||||
loadActions() {
|
||||
if (this.actionsMenu.length > 0) return;
|
||||
axios.get(this.params.data.urls.actions)
|
||||
axios.post(this.params.data.urls.actions)
|
||||
.then((response) => {
|
||||
this.actionsMenu = response.data.actions;
|
||||
});
|
||||
|
|
|
@ -114,7 +114,7 @@ export default {
|
|||
},
|
||||
methods: {
|
||||
fetchData() {
|
||||
$.get('https://extras.scinote.net/scinote-edit/latest.json', (result) => {
|
||||
$.get(GLOBAL_CONSTANTS.SCINOTE_EDIT_LATEST_JSON_URL, (result) => {
|
||||
this.responseData = result;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
require 'caxlsx'
|
||||
|
||||
class FormResponsesZipExportJob < ZipExportJob
|
||||
include StringUtility
|
||||
|
||||
private
|
||||
|
||||
# Override
|
||||
|
@ -11,7 +13,7 @@ class FormResponsesZipExportJob < ZipExportJob
|
|||
|
||||
exported_data = to_xlsx(form)
|
||||
|
||||
File.binwrite("#{dir}/#{form.name}.xlsx", exported_data)
|
||||
File.binwrite("#{dir}/#{to_filesystem_name(form.name)}.xlsx", exported_data)
|
||||
end
|
||||
|
||||
def failed_notification_title
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RepositoryItemDateReminderJob < ApplicationJob
|
||||
BUFFER_DAYS = 2
|
||||
|
||||
queue_as :default
|
||||
|
||||
def perform
|
||||
|
@ -11,33 +13,37 @@ class RepositoryItemDateReminderJob < ApplicationJob
|
|||
|
||||
private
|
||||
|
||||
def process_repository_values(model, comparison_value)
|
||||
def repository_values_due(model, comparison_value)
|
||||
model
|
||||
.joins(repository_cell: [:repository_row, { repository_column: :repository }])
|
||||
.where(
|
||||
notification_sent: false,
|
||||
repositories: { type: 'Repository', archived: false },
|
||||
repository_rows: { archived: false }
|
||||
).where('repository_date_time_values.updated_at >= ?', 2.days.ago)
|
||||
.where( # date(time) values that are within the reminder range
|
||||
"data <= " \
|
||||
"(?::timestamp + CAST(((repository_columns.metadata->>'reminder_unit')::int * " \
|
||||
).where( # date(time) values that are within the reminder range including buffer
|
||||
"(data > (:comparison_value::timestamp - (INTERVAL ':buffer_days DAY'))) AND data <= " \
|
||||
"(:comparison_value::timestamp + CAST(((repository_columns.metadata->>'reminder_unit')::int * " \
|
||||
"(repository_columns.metadata->>'reminder_value')::int) || ' seconds' AS Interval))",
|
||||
comparison_value
|
||||
).find_each do |value|
|
||||
repository_row = RepositoryRow.find(value.repository_cell.repository_row_id)
|
||||
repository_column = RepositoryColumn.find(value.repository_cell.repository_column_id)
|
||||
buffer_days: BUFFER_DAYS,
|
||||
comparison_value: comparison_value
|
||||
)
|
||||
end
|
||||
|
||||
RepositoryItemDateNotification
|
||||
.send_notifications({
|
||||
"#{value.class.name.underscore}_id": value.id,
|
||||
repository_row_id: repository_row.id,
|
||||
repository_row_name: repository_row.name,
|
||||
repository_column_id: repository_column.id,
|
||||
repository_column_name: repository_column.name,
|
||||
reminder_unit: repository_column.metadata['reminder_unit'],
|
||||
reminder_value: repository_column.metadata['reminder_value']
|
||||
})
|
||||
end
|
||||
def process_repository_values(model, comparison_value)
|
||||
repository_values_due(model, comparison_value).find_each do |value|
|
||||
repository_row = RepositoryRow.find(value.repository_cell.repository_row_id)
|
||||
repository_column = RepositoryColumn.find(value.repository_cell.repository_column_id)
|
||||
|
||||
RepositoryItemDateNotification
|
||||
.send_notifications({
|
||||
"#{value.class.name.underscore}_id": value.id,
|
||||
repository_row_id: repository_row.id,
|
||||
repository_row_name: repository_row.name,
|
||||
repository_column_id: repository_column.id,
|
||||
repository_column_name: repository_column.name,
|
||||
reminder_unit: repository_column.metadata['reminder_unit'],
|
||||
reminder_value: repository_column.metadata['reminder_value']
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -299,13 +299,13 @@ class Asset < ApplicationRecord
|
|||
|
||||
# Extract only the licenced user flag parameter
|
||||
is_licenced_user = ENV['WOPI_BUSINESS_USERS'] == 'true' && action_url.include?('IsLicensedUser=BUSINESS_USER')
|
||||
action_url = action_url.split('?').first + "?IsLicencedUser=#{is_licenced_user ? 1 : 0}&"
|
||||
action_url = action_url.split(/<.*>/).first + "IsLicencedUser=#{is_licenced_user ? 1 : 0}"
|
||||
|
||||
rest_url = Rails.application.routes.url_helpers.wopi_rest_endpoint_url(
|
||||
host: ENV['WOPI_ENDPOINT_URL'],
|
||||
id: id
|
||||
)
|
||||
action_url += "WOPISrc=#{rest_url}"
|
||||
action_url += "&WOPISrc=#{rest_url}"
|
||||
if with_tokens
|
||||
token = user.get_wopi_token
|
||||
action_url + "&access_token=#{token.token}"\
|
||||
|
|
|
@ -137,11 +137,7 @@ class RepositoryRow < ApplicationRecord
|
|||
teams = options[:teams] || current_team || user.teams.select(:id)
|
||||
searchable_row_fields = [RepositoryRow::PREFIXED_ID_SQL, 'repository_rows.name', 'users.full_name']
|
||||
|
||||
readable_rows =
|
||||
distinct
|
||||
.joins(:repository, :created_by)
|
||||
.where(repositories: { id: Repository.with_granted_permissions(user, RepositoryPermissions::READ).select(:id),
|
||||
team_id: teams })
|
||||
readable_rows = distinct.joins(:repository, :created_by).viewable_by_user(user, teams)
|
||||
readable_rows = readable_rows.active unless include_archived
|
||||
repository_rows = readable_rows.where_attributes_like_boolean(searchable_row_fields, query, options)
|
||||
|
||||
|
|
|
@ -273,8 +273,8 @@ class TeamImporter
|
|||
updated = true
|
||||
end
|
||||
end
|
||||
text.scan(/\[@[\w+-@?! ]+~\w+\]/).each do |user_match|
|
||||
orig_id_encoded = user_match.match(/\[@[\w+-@?! ]+~(\w+)\]/)[1]
|
||||
text.scan(SmartAnnotations::TagToText::USER_REGEX).each do |user_match|
|
||||
orig_id_encoded = user_match[1]
|
||||
orig_id = orig_id_encoded.base62_decode
|
||||
next unless @user_mappings[orig_id]
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<html>
|
||||
<head>
|
||||
<%= csp_meta_tag %>
|
||||
<%= csrf_meta_tags %>
|
||||
<%= javascript_include_tag 'i18n_bundle' %>
|
||||
<%= javascript_include_tag 'jquery_bundle' %>
|
||||
<%= stylesheet_link_tag 'sn_icon_font' %>
|
||||
|
|
1
app/views/global_constants/index.js.erb
Normal file
1
app/views/global_constants/index.js.erb
Normal file
|
@ -0,0 +1 @@
|
|||
const GLOBAL_CONSTANTS = <%= @global_constants.to_json.html_safe %>;
|
|
@ -5,7 +5,6 @@
|
|||
<meta data-hook="head-js">
|
||||
<title><%=t "head.title", title: (yield :head_title) %></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<meta name="max-file-size" content="<%= Rails.configuration.x.file_max_size_mb %>">
|
||||
<meta name="tiny-mce-assets-url" content="<%= tiny_mce_assets_path %>">
|
||||
<% if user_signed_in? %>
|
||||
<meta name="expiration-url" content="<%= users_expire_in_path %>">
|
||||
|
@ -18,6 +17,8 @@
|
|||
<% if ::NewRelic::Agent.instance.started? %>
|
||||
<%= ::NewRelic::Agent.browser_timing_header(controller.request.content_security_policy_nonce) %>
|
||||
<% end %>
|
||||
<script src="<%= global_constants_path(format: :js) %>"></script>
|
||||
|
||||
<%= javascript_include_tag 'jquery_bundle' %>
|
||||
<%= javascript_include_tag 'application_pack' %>
|
||||
|
||||
|
@ -79,7 +80,6 @@
|
|||
data-datetime-picker-format-vue="<%= datetime_picker_format_date_only_vue %>"
|
||||
<% end %>
|
||||
>
|
||||
|
||||
<span style="display: none;" data-hook="body-js"></span>
|
||||
<span style="display: none;" data-hook="application-body-html"></span>
|
||||
|
||||
|
@ -140,6 +140,5 @@
|
|||
|
||||
<%= javascript_include_tag 'prism' %>
|
||||
<%= javascript_include_tag "vue_components_repository_item_sidebar" %>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
<meta data-hook="head-js">
|
||||
<title><%=t "head.title", title: (yield :head_title) %></title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<script src="<%= global_constants_path(format: :js) %>"></script>
|
||||
|
||||
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag 'bootstrap_pack', media: 'all' %>
|
||||
<%= stylesheet_link_tag 'application', media: 'all' %>
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
<style media="all">
|
||||
html, body { height: 100%; min-height: 100%; }
|
||||
</style>
|
||||
<script src="<%= global_constants_path(format: :js) %>"></script>
|
||||
|
||||
<%= stylesheet_link_tag "tailwind", "data-turbo-track": "reload" %>
|
||||
<%= stylesheet_link_tag 'bootstrap_pack', media: 'all' %>
|
||||
<%= stylesheet_link_tag 'application_pack_styles', media: 'all' %>
|
||||
|
|
|
@ -458,6 +458,8 @@ class Constants
|
|||
JSE LNK MSC MSI MSP MST PAF PIF PS1 REG RGS SCR SCT SHB SHS U3P VB VBE VBS VBSCRIPT WS WSF WSH
|
||||
).freeze
|
||||
|
||||
SCINOTE_EDIT_LATEST_JSON_URL = ENV['SCINOTE_EDIT_LATEST_JSON_URL'].freeze
|
||||
|
||||
# quick search
|
||||
QUICK_SEARCH_LIMIT = 5
|
||||
QUICK_SEARCH_SEARCHABLE_OBJECTS = %w(project experiment my_module protocol repository_row
|
||||
|
|
|
@ -4196,8 +4196,8 @@ en:
|
|||
body: "This file type appears to be executable and can potentially harm your computer. It cannot be opened with SciNote Edit. To open the file please download it manually."
|
||||
action: "I understand"
|
||||
update_version_modal:
|
||||
title: "Update required"
|
||||
body_text_html: "The current version of the SciNote Edit application is no longer supported. To ensure a seamless and secure user experience, we recommend updating to the latest version."
|
||||
title: "Incompatible SciNote Edit version"
|
||||
body_text_html: "Your current version of the SciNote Edit application is no longer supported. To ensure a seamless and secure experience, download the appropriate version by clicking the Download button below — it will automatically provide the correct version for you."
|
||||
edit_launching_application_modal:
|
||||
title: "Launching application"
|
||||
description: "%{file_name} will now open in %{application}. Saved changes in %{application} will automatically be synced in SciNote."
|
||||
|
|
|
@ -7,6 +7,8 @@ Rails.application.routes.draw do
|
|||
get 'api/health', to: 'api/api#health', as: 'api_health'
|
||||
get 'api/status', to: 'api/api#status', as: 'api_status'
|
||||
|
||||
get '/global_constants', to: 'global_constants#index', as: 'global_constants'
|
||||
|
||||
post 'access_tokens/revoke', to: 'doorkeeper/access_tokens#revoke'
|
||||
|
||||
# Addons
|
||||
|
@ -64,7 +66,7 @@ Rails.application.routes.draw do
|
|||
get :template_tags
|
||||
get :zpl_preview
|
||||
post :sync_fluics_templates
|
||||
get :actions_toolbar
|
||||
post :actions_toolbar
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -208,7 +210,7 @@ Rails.application.routes.draw do
|
|||
defaults: { format: 'json' }
|
||||
get 'create_modal', to: 'repositories#create_modal',
|
||||
defaults: { format: 'json' }
|
||||
get 'actions_toolbar'
|
||||
post 'actions_toolbar'
|
||||
get :list
|
||||
get :rows_list
|
||||
end
|
||||
|
@ -285,7 +287,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
collection do
|
||||
get :project_contents
|
||||
get 'actions_toolbar'
|
||||
post 'actions_toolbar'
|
||||
end
|
||||
end
|
||||
get 'reports/datatable', to: 'reports#datatable'
|
||||
|
@ -393,7 +395,7 @@ Rails.application.routes.draw do
|
|||
get 'users_filter'
|
||||
post 'archive_group'
|
||||
post 'restore_group'
|
||||
get 'actions_toolbar'
|
||||
post 'actions_toolbar'
|
||||
get :user_roles
|
||||
end
|
||||
end
|
||||
|
@ -418,7 +420,7 @@ Rails.application.routes.draw do
|
|||
get 'inventory_assigning_experiment_filter'
|
||||
get 'clone_modal', action: :clone_modal
|
||||
get 'move_modal', action: :move_modal
|
||||
get 'actions_toolbar'
|
||||
post 'actions_toolbar'
|
||||
get 'move_modal' # return modal with move options
|
||||
post 'move' # move experiment
|
||||
end
|
||||
|
@ -464,7 +466,7 @@ Rails.application.routes.draw do
|
|||
post 'save_table_state', on: :collection, defaults: { format: 'json' }
|
||||
|
||||
collection do
|
||||
get 'actions_toolbar'
|
||||
post 'actions_toolbar'
|
||||
get 'inventory_assigning_my_module_filter'
|
||||
end
|
||||
|
||||
|
@ -503,8 +505,8 @@ Rails.application.routes.draw do
|
|||
get :full_view_table
|
||||
post :index_dt, defaults: { format: 'json' }
|
||||
post :export_repository
|
||||
get :assign_repository_records_modal, as: :assign_modal
|
||||
get :update_repository_records_modal, as: :update_modal
|
||||
post :assign_repository_records_modal, as: :assign_modal
|
||||
post :update_repository_records_modal, as: :update_modal
|
||||
get :consume_modal
|
||||
post :update_consumption
|
||||
end
|
||||
|
@ -709,7 +711,7 @@ Rails.application.routes.draw do
|
|||
post 'protocolsio_import_save', to: 'protocols#protocolsio_import_save'
|
||||
get 'export', to: 'protocols#export'
|
||||
get 'protocolsio', to: 'protocols#protocolsio_index'
|
||||
get 'actions_toolbar', to: 'protocols#actions_toolbar'
|
||||
post 'actions_toolbar', to: 'protocols#actions_toolbar'
|
||||
get 'user_roles', to: 'protocols#user_roles'
|
||||
end
|
||||
end
|
||||
|
@ -775,7 +777,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
collection do
|
||||
get :actions_toolbar
|
||||
post :actions_toolbar
|
||||
end
|
||||
|
||||
resources :repository_row_connections, only: %i(create destroy) do
|
||||
|
@ -845,7 +847,7 @@ Rails.application.routes.draw do
|
|||
|
||||
resources :storage_locations, only: %i(index create destroy update show) do
|
||||
collection do
|
||||
get :actions_toolbar
|
||||
post :actions_toolbar
|
||||
get :tree
|
||||
end
|
||||
member do
|
||||
|
@ -875,7 +877,7 @@ Rails.application.routes.draw do
|
|||
end
|
||||
|
||||
collection do
|
||||
get :actions_toolbar
|
||||
post :actions_toolbar
|
||||
post :archive
|
||||
post :restore
|
||||
get :user_roles
|
||||
|
|
|
@ -19,6 +19,10 @@ describe ReportsController, type: :controller do
|
|||
|
||||
describe 'POST create' do
|
||||
context 'in JSON format' do
|
||||
before do
|
||||
allow(Reports::PdfJob).to receive(:perform_later)
|
||||
end
|
||||
|
||||
let(:action) { post :create, params: params, format: :json }
|
||||
let(:params) do
|
||||
{ project_id: project.id,
|
||||
|
@ -42,11 +46,14 @@ describe ReportsController, type: :controller do
|
|||
.to(change { Activity.count })
|
||||
end
|
||||
end
|
||||
# Temporary disabled due to webpack problems
|
||||
end if false
|
||||
end
|
||||
|
||||
describe 'PUT update' do
|
||||
context 'in JSON format' do
|
||||
before do
|
||||
allow(Reports::PdfJob).to receive(:perform_later)
|
||||
end
|
||||
|
||||
let(:action) { put :update, params: params, format: :json }
|
||||
let(:params) do
|
||||
{ project_id: project.id,
|
||||
|
@ -69,8 +76,7 @@ describe ReportsController, type: :controller do
|
|||
.to(change { Activity.count })
|
||||
end
|
||||
end
|
||||
# Temporary disabled due to webpack problems
|
||||
end if false
|
||||
end
|
||||
|
||||
describe 'DELETE destroy' do
|
||||
let(:action) { delete :destroy, params: params }
|
||||
|
|
|
@ -45,11 +45,11 @@ describe RepositoryRowsController, type: :controller do
|
|||
end
|
||||
|
||||
it 'successful response' do
|
||||
allow_any_instance_of(ActionView::Helpers::AssetUrlHelper).to receive(:asset_path)
|
||||
get :show, format: :json, params: { repository_id: repository.id, id: repository_row.id }
|
||||
expect(response).to have_http_status(:success)
|
||||
end
|
||||
# Temporary disabled due to webpack problems
|
||||
end if false
|
||||
end
|
||||
|
||||
context '#index' do
|
||||
before do
|
||||
|
|
|
@ -9,6 +9,18 @@ describe TeamsController, type: :controller do
|
|||
let(:team) { create :team, created_by: user }
|
||||
|
||||
describe 'POST export_projects' do
|
||||
before do
|
||||
view_response = '<div class="content-pane" id="report-new"><div class="report-container"><div id="report-content"></div></div></div>'
|
||||
proxy_manager = Warden::Manager.new({})
|
||||
proxy = Warden::Proxy.new({}, proxy_manager)
|
||||
renderer_double = double('Renderer', render: view_response.dup)
|
||||
|
||||
allow(Warden::Manager).to receive(:new).and_return(proxy_manager)
|
||||
allow(Warden::Proxy).to receive(:new).with({}, proxy_manager).and_return(proxy)
|
||||
allow(ApplicationController.renderer).to receive(:new).with({ warden: proxy }).and_return(renderer_double)
|
||||
allow(ApplicationController).to receive(:render)
|
||||
end
|
||||
|
||||
let!(:first_project) { create :project, team: team, created_by: user }
|
||||
let!(:second_project) { create :project, team: team, created_by: user }
|
||||
let(:params) do
|
||||
|
@ -31,6 +43,5 @@ describe TeamsController, type: :controller do
|
|||
expect { action }
|
||||
.to(change { Activity.count })
|
||||
end
|
||||
# Temporary disabled due to webpack problems
|
||||
end if false
|
||||
end
|
||||
end
|
||||
|
|
87
spec/jobs/repository_item_date_reminder_job_spec.rb
Normal file
87
spec/jobs/repository_item_date_reminder_job_spec.rb
Normal file
|
@ -0,0 +1,87 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
describe RepositoryItemDateReminderJob, type: :job do
|
||||
around do |example|
|
||||
Timecop.freeze(Time.utc(2025, 1, 15, 0, 0, 0)) do
|
||||
example.run
|
||||
end
|
||||
end
|
||||
|
||||
let(:user) { create :user }
|
||||
let(:team) { create :team, created_by: user }
|
||||
let!(:owner_role) { UserRole.find_by(name: I18n.t('user_roles.predefined.owner')) }
|
||||
let!(:team_assignment) { create_user_assignment(team, owner_role, user) }
|
||||
let(:repository) { create :repository, team: team, created_by: user }
|
||||
|
||||
let!(:date_column_with_reminder) do
|
||||
create :repository_column, repository: repository,
|
||||
created_by: user,
|
||||
name: 'Custom items',
|
||||
data_type: 'RepositoryDateValue',
|
||||
metadata: {"reminder_unit"=>"86400", "reminder_value"=>"5", "reminder_message"=>""}
|
||||
end
|
||||
|
||||
let!(:repository_date_value_due) do
|
||||
row = create :repository_row, name: "row 1",
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
|
||||
create(
|
||||
:repository_date_value,
|
||||
data: Date.parse('20-1-2025'),
|
||||
repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder }
|
||||
)
|
||||
end
|
||||
|
||||
let!(:repository_date_value_due_outside_buffer) do
|
||||
row = create :repository_row, name: "row 1",
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
|
||||
create(
|
||||
:repository_date_value,
|
||||
data: Date.parse('15-1-2025') - (RepositoryItemDateReminderJob::BUFFER_DAYS + 1).days,
|
||||
repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder }
|
||||
)
|
||||
end
|
||||
|
||||
let!(:repository_date_value_due_inside_buffer) do
|
||||
row = create :repository_row, name: "row 1",
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
|
||||
create(
|
||||
:repository_date_value,
|
||||
data: Date.parse('15-1-2025') - (RepositoryItemDateReminderJob::BUFFER_DAYS - 1).days,
|
||||
repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder }
|
||||
)
|
||||
end
|
||||
|
||||
let!(:repository_date_value_not_due) do
|
||||
row = create :repository_row, name: "row 1",
|
||||
repository: repository,
|
||||
created_by: user,
|
||||
last_modified_by: user
|
||||
|
||||
create(
|
||||
:repository_date_value,
|
||||
data: Date.parse('10-10-2025'),
|
||||
repository_cell_attributes: { repository_row: row, repository_column: date_column_with_reminder }
|
||||
)
|
||||
end
|
||||
|
||||
describe '#repository_values_due' do
|
||||
it "returns repository values that are due with a #{RepositoryItemDateReminderJob::BUFFER_DAYS} day buffer" do
|
||||
values = described_class.new.send(:repository_values_due, RepositoryDateValue, Date.current)
|
||||
expect(values).to include(repository_date_value_due)
|
||||
expect(values).to_not include(repository_date_value_not_due)
|
||||
expect(values).to include(repository_date_value_due_inside_buffer)
|
||||
expect(values).to_not include(repository_date_value_due_outside_buffer)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -228,11 +228,8 @@
|
|||
<glyph unicode="" glyph-name="text-fields" data-tags="text-fields" d="M336.406 144.414v554.668h-213.333v52.523h479.188v-52.523h-213.332v-554.668h-52.523zM720.405 144.414v341.333h-128v52.524h308.523v-52.524h-128v-341.333h-52.523z" />
|
||||
<glyph unicode="" glyph-name="merge-cells" data-tags="merge-cells" d="M149.333 85.333v213.333h42.667v-170.667h170.667v-42.667h-213.333zM661.333 85.333v42.667h170.667v170.667h42.667v-213.333h-213.333zM306.133 315.157l-30.443 29.376 82.133 82.133h-251.157v42.667h251.157l-82.133 82.133 30.443 29.376 132.843-132.843-132.843-132.843zM717.867 315.157l-132.843 132.843 132.843 132.843 30.443-29.376-82.133-82.133h251.157v-42.667h-251.157l82.133-82.133-30.443-29.376zM149.333 597.333v213.333h213.333v-42.667h-170.667v-170.667h-42.667zM832 597.333v170.667h-170.667v42.667h213.333v-213.333h-42.667z" />
|
||||
<glyph unicode="" glyph-name="text-Italic" data-tags="text-Italic" d="M246.976 181.333v47.595h155.072l148.514 438.144h-155.074v47.595h354.464v-47.595h-150.153l-148.514-438.144h150.157v-47.595h-354.466z" />
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
<glyph unicode="" glyph-name="forms" data-tags="forms" d="M320 256h256v42.667h-256v-42.667zM320 426.667h384v42.667h-384v-42.667zM320 597.333h384v42.667h-384v-42.667zM239.595 106.667c-19.641 0-36.039 6.579-49.195 19.733s-19.733 29.555-19.733 49.195v544.811c0 19.641 6.578 36.039 19.733 49.195s29.554 19.733 49.195 19.733h544.811c19.639 0 36.041-6.578 49.195-19.733s19.733-29.554 19.733-49.195v-544.811c0-19.639-6.579-36.041-19.733-49.195s-29.555-19.733-49.195-19.733h-544.811zM239.595 149.333h544.811c6.571 0 12.591 2.735 18.057 8.205 5.47 5.466 8.205 11.486 8.205 18.057v544.811c0 6.571-2.735 12.59-8.205 18.059-5.466 5.469-11.486 8.203-18.057 8.203h-544.811c-6.571 0-12.59-2.734-18.059-8.203s-8.203-11.488-8.203-18.059v-544.811c0-6.571 2.734-12.591 8.203-18.057 5.469-5.47 11.488-8.205 18.059-8.205z" />
|
||||
<glyph unicode="" glyph-name="value" data-tags="value" d="M512.141 64c-53.103 0-103.024 10.078-149.773 30.229-46.741 20.151-87.403 47.501-121.984 82.048s-61.955 75.17-82.123 121.877c-20.174 46.699-30.261 96.602-30.261 149.705s10.077 103.024 30.229 149.773c20.153 46.741 47.502 87.403 82.048 121.984s75.171 61.955 121.877 82.123c46.699 20.174 96.602 30.261 149.705 30.261s103.023-10.077 149.773-30.229c46.741-20.153 87.403-47.502 121.984-82.048s61.956-75.171 82.125-121.877c20.173-46.699 30.259-96.602 30.259-149.705s-10.078-103.023-30.229-149.773c-20.151-46.741-47.501-87.403-82.048-121.984s-75.17-61.956-121.877-82.125c-46.699-20.173-96.602-30.259-149.705-30.259zM512 106.667c95.287 0 176 33.067 242.133 99.2s99.2 146.846 99.2 242.133c0 95.289-33.067 176-99.2 242.133s-146.846 99.2-242.133 99.2c-95.289 0-176-33.067-242.133-99.2s-99.2-146.845-99.2-242.133c0-95.287 33.067-176 99.2-242.133s146.845-99.2 242.133-99.2zM512 256h42.667v384h-128v-42.667h85.333v-341.333z" />
|
||||
<glyph unicode="" glyph-name="choice-multiple" data-tags="choice-multiple" d="M170.667 746.667c0 23.564 19.103 42.667 42.667 42.667h597.333c23.565 0 42.667-19.103 42.667-42.667v-597.333c0-23.565-19.102-42.667-42.667-42.667h-597.333c-23.564 0-42.667 19.102-42.667 42.667v597.333zM810.667 746.667h-597.333v-597.333h597.333v597.333z" />
|
||||
<glyph unicode="" glyph-name="choice-single" data-tags="choice-single" d="M853.333 448c0-188.514-152.819-341.333-341.333-341.333s-341.333 152.819-341.333 341.333c0 188.513 152.82 341.333 341.333 341.333s341.333-152.82 341.333-341.333zM512 149.333c164.949 0 298.667 133.717 298.667 298.667s-133.717 298.667-298.667 298.667c-164.949 0-298.667-133.718-298.667-298.667s133.718-298.667 298.667-298.667z" />
|
||||
>>>>>>> develop
|
||||
</font></defs></svg>
|
Before Width: | Height: | Size: 149 KiB After Width: | Height: | Size: 149 KiB |
21
yarn.lock
21
yarn.lock
|
@ -5681,11 +5681,32 @@ tiny-emitter@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
tiny-invariant@^1.0.2, tiny-invariant@^1.0.6:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642"
|
||||
integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==
|
||||
|
||||
tiny-warning@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||
|
||||
tinycolor2@^1.4.1:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
|
||||
integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
|
||||
tinymce@^6.8.5:
|
||||
version "6.8.5"
|
||||
resolved "https://registry.yarnpkg.com/tinymce/-/tinymce-6.8.5.tgz#aa9a711c4e0b59d506dd281bade857d35a7b3c59"
|
||||
integrity sha512-qAL/FxL7cwZHj4BfaF818zeJJizK9jU5IQzTcSLL4Rj5MaJdiVblEj7aDr80VCV1w9h4Lak9hlnALhq/kVtN1g==
|
||||
|
||||
tippy.js@^6.3.7:
|
||||
version "6.3.7"
|
||||
resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-6.3.7.tgz#8ccfb651d642010ed9a32ff29b0e9e19c5b8c61c"
|
||||
integrity sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.9.0"
|
||||
|
||||
to-fast-properties@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||
|
|
Loading…
Add table
Reference in a new issue