mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-09-20 14:45:56 +08:00
Basic OVE editor implementation [SCI-8929]
This commit is contained in:
parent
a6c2a3aa59
commit
76a0f433cd
2
app/assets/javascripts/i18n_bundle.js
Normal file
2
app/assets/javascripts/i18n_bundle.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
//= require i18n.js
|
||||
//= require i18n/translations
|
21
app/assets/javascripts/sitewide/iframe_modal.js
Normal file
21
app/assets/javascripts/sitewide/iframe_modal.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* global iFrameModal */
|
||||
// General-purpose iframe modal. For closing the modal, you need will to take care of triggering
|
||||
// the 'hide' event on the modal itself, example from inside the iframe:
|
||||
// parent.document.getElementById('iFrameModal').dispatchEvent(new Event('hide'));
|
||||
|
||||
$(document).on('turbolinks:load', function() {
|
||||
window.iFrameModal = document.getElementById('iFrameModal');
|
||||
let iFrameModalFrame = document.getElementById('iFrameModalFrame');
|
||||
|
||||
window.showIFrameModal = (url) => {
|
||||
iFrameModalFrame.setAttribute('src', url);
|
||||
iFrameModal.classList.remove('hidden');
|
||||
iFrameModal.dispatchEvent(new Event('shown'));
|
||||
};
|
||||
|
||||
iFrameModal.addEventListener('hide', () => {
|
||||
iFrameModal.classList.add('hidden');
|
||||
iFrameModalFrame.removeAttribute('src');
|
||||
iFrameModal.dispatchEvent(new Event('hidden'));
|
||||
});
|
||||
});
|
4
app/assets/stylesheets/sn_icon_font.css
Normal file
4
app/assets/stylesheets/sn_icon_font.css
Normal file
|
@ -0,0 +1,4 @@
|
|||
/*
|
||||
*= require sn-icon-font
|
||||
*= require sn-inter-font
|
||||
*/
|
123
app/controllers/gene_sequence_assets_controller.rb
Normal file
123
app/controllers/gene_sequence_assets_controller.rb
Normal file
|
@ -0,0 +1,123 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class GeneSequenceAssetsController < ApplicationController
|
||||
include ActiveStorage::SetCurrent
|
||||
|
||||
skip_before_action :verify_authenticity_token
|
||||
|
||||
before_action :load_vars, except: %i(new create)
|
||||
before_action :load_create_vars, only: %i(new create)
|
||||
|
||||
before_action :check_read_permission
|
||||
before_action :check_manage_permission, only: %i(new update create)
|
||||
|
||||
def new
|
||||
render :edit, layout: false
|
||||
end
|
||||
|
||||
def edit
|
||||
@file_url = rails_representation_url(@asset.file)
|
||||
@file_name = @asset.render_file_name
|
||||
render :edit, layout: false
|
||||
end
|
||||
|
||||
def create
|
||||
save_asset!
|
||||
head :ok
|
||||
end
|
||||
|
||||
def update
|
||||
save_asset!
|
||||
head :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def save_asset!
|
||||
ActiveRecord::Base.transaction do
|
||||
ensure_asset!
|
||||
|
||||
@asset.file.purge
|
||||
@asset.preview_image.purge
|
||||
|
||||
@asset.file.attach(
|
||||
io: StringIO.new(params[:sequence_data].to_json),
|
||||
filename: "#{params[:sequence_name]}.json"
|
||||
)
|
||||
|
||||
@asset.preview_image.attach(
|
||||
io: StringIO.new(Base64.decode64(params[:base64_image].split(',').last)),
|
||||
filename: "#{params[:sequence_name]}.png"
|
||||
)
|
||||
|
||||
file = @asset.file
|
||||
|
||||
file.blob.metadata['asset_type'] = 'gene_sequence'
|
||||
file.blob.metadata['name'] = params[:sequence_name]
|
||||
file.save!
|
||||
|
||||
@asset.save!
|
||||
end
|
||||
end
|
||||
|
||||
def ensure_asset!
|
||||
return if @asset
|
||||
return unless @parent
|
||||
|
||||
@asset = @parent.assets.create!(last_modified_by: current_user, team: current_team)
|
||||
end
|
||||
|
||||
def load_vars
|
||||
@asset = current_team.assets.find_by(id: params[:id])
|
||||
return render_404 unless @asset
|
||||
|
||||
@parent ||= @asset.step
|
||||
@parent ||= @asset.result
|
||||
|
||||
case @parent
|
||||
when Step
|
||||
@protocol = @parent.protocol
|
||||
when Result
|
||||
@my_module = @parent.my_module
|
||||
end
|
||||
end
|
||||
|
||||
def load_create_vars
|
||||
@parent = case params[:parent_type]
|
||||
when 'Step'
|
||||
Step.find_by(id: params[:parent_id])
|
||||
when 'Result'
|
||||
Result.find_by(id: params[:parent_id])
|
||||
end
|
||||
|
||||
case @parent
|
||||
when Step
|
||||
@protocol = @parent.protocol
|
||||
when Result
|
||||
@result = @parent
|
||||
end
|
||||
end
|
||||
|
||||
def check_read_permission
|
||||
case @parent
|
||||
when Step
|
||||
return render_403 unless can_read_protocol_in_module?(@protocol) ||
|
||||
can_read_protocol_in_repository?(@protocol)
|
||||
when Result
|
||||
return render_403 unless can_read_my_module?(@my_module)
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
|
||||
def check_manage_permission
|
||||
case @parent
|
||||
when Step
|
||||
return render_403 unless can_manage_step?(@parent)
|
||||
when Result
|
||||
return render_403 unless can_manage_my_module?(@parent)
|
||||
else
|
||||
render_403
|
||||
end
|
||||
end
|
||||
end
|
2
app/javascript/packs/open_vector_editor.js
Normal file
2
app/javascript/packs/open_vector_editor.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
import './ove/script.js';
|
||||
import './ove/style.css';
|
222154
app/javascript/packs/ove/script.js
Normal file
222154
app/javascript/packs/ove/script.js
Normal file
File diff suppressed because one or more lines are too long
12005
app/javascript/packs/ove/style.css
Normal file
12005
app/javascript/packs/ove/style.css
Normal file
File diff suppressed because one or more lines are too long
11
app/javascript/packs/vue/open_vector_editor.js
Normal file
11
app/javascript/packs/vue/open_vector_editor.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
import TurbolinksAdapter from 'vue-turbolinks';
|
||||
import Vue from 'vue/dist/vue.esm';
|
||||
import OpenVectorEditor from '../../vue/ove/OpenVectorEditor.vue';
|
||||
|
||||
Vue.use(TurbolinksAdapter);
|
||||
Vue.prototype.i18n = window.I18n;
|
||||
|
||||
new Vue({
|
||||
el: '#open-vector-editor',
|
||||
components: { OpenVectorEditor }
|
||||
});
|
106
app/javascript/vue/ove/OpenVectorEditor.vue
Normal file
106
app/javascript/vue/ove/OpenVectorEditor.vue
Normal file
|
@ -0,0 +1,106 @@
|
|||
<template>
|
||||
<div class="ove-wrapper flex flex-col h-screen">
|
||||
<div class="ove-header flex justify-between">
|
||||
<span class="file-name flex items-center ml-3">
|
||||
<div class="sci-input-container">
|
||||
<input v-model="sequenceName" class="sci-input-field" type="text" />
|
||||
</div>
|
||||
</span>
|
||||
<div class="ove-buttons">
|
||||
<button @click="saveAndClose" class="btn btn-light">
|
||||
<i class="sn-icon sn-icon-save"></i>
|
||||
{{ i18n.t('SaveClose') }}
|
||||
</button>
|
||||
<button @click="closeModal" class="preview-close btn btn-light icon-btn">
|
||||
<i class="sn-icon sn-icon-close"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="container" class="ove-container w-full h-full">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import { blobToBase64 } from '../shared/blobToBase64.js'
|
||||
|
||||
export default {
|
||||
name: 'OpenVectorEditor',
|
||||
props: {
|
||||
fileUrl: { type: String },
|
||||
fileName: { type: String },
|
||||
updateUrl: { type: String }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editor: null,
|
||||
sequenceName: null,
|
||||
closeAfterSave: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
sequenceName() {
|
||||
if (this.editor && this.editor.getState()) {
|
||||
this.editor.updateEditor({
|
||||
sequenceData: { ...this.editor.getState().sequenceData, name: this.sequenceName }
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.editor = window.createVectorEditor(this.$refs.container, {
|
||||
onSave: this.saveFile,
|
||||
generatePng: true
|
||||
});
|
||||
this.sequenceName = this.fileName || this.i18n.t('open_vector_editor.default_sequence_name');
|
||||
|
||||
if (this.fileUrl) {
|
||||
this.loadFile();
|
||||
} else {
|
||||
this.editor.updateEditor(
|
||||
{
|
||||
sequenceData: { circular: true, name: this.sequenceName },
|
||||
readOnly: false
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadFile() {
|
||||
fetch(this.fileUrl).then((response) => response.json()).then(
|
||||
(json) => this.editor.updateEditor(
|
||||
{
|
||||
sequenceData: json,
|
||||
readOnly: false
|
||||
}
|
||||
)
|
||||
);
|
||||
},
|
||||
saveAndClose() {
|
||||
this.closeAfterSave = close;
|
||||
document.querySelector('[data-test=saveTool]').click();
|
||||
},
|
||||
saveFile(opts, sequenceDataToSave, editorState, onSuccessCallback) {
|
||||
blobToBase64(opts.pngFile).then((base64image) => {
|
||||
(this.fileUrl ? axios.patch : axios.post)(
|
||||
this.updateUrl,
|
||||
{
|
||||
sequence_data: sequenceDataToSave,
|
||||
sequence_name: this.sequenceName,
|
||||
base64_image: base64image
|
||||
}
|
||||
).then(() => {
|
||||
parent.document.getElementById('iFrameModal').dispatchEvent(new Event('sequenceSaved'));
|
||||
if (this.closeAfterSave) this.closeModal();
|
||||
});
|
||||
});
|
||||
},
|
||||
closeModal() {
|
||||
if (parent !== window) {
|
||||
parent.document.getElementById('iFrameModal').dispatchEvent(new Event('hide'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -141,6 +141,7 @@
|
|||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initOVE();
|
||||
this.initMarvinJS();
|
||||
$(this.$refs.actionsDropdownButton).on('shown.bs.dropdown hidden.bs.dropdown', this.handleDropdownPosition);
|
||||
},
|
||||
|
@ -165,6 +166,9 @@
|
|||
deleteAttachment(id) {
|
||||
this.$emit('attachment:deleted', id)
|
||||
},
|
||||
initOVE() {
|
||||
$(window.iFrameModal).on('sequenceSaved', () => this.$emit('attachment:uploaded'));
|
||||
},
|
||||
initMarvinJS() {
|
||||
// legacy logic from app/assets/javascripts/sitewide/marvinjs_editor.js
|
||||
MarvinJsEditor.initNewButton(
|
||||
|
|
|
@ -20,6 +20,11 @@
|
|||
{{ attachment.attributes.wopi_context.button_text }}
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="attachment.attributes.asset_type == 'gene_sequence'">
|
||||
<a class="ove-edit-button" @click="openOVEditor(attachment.attributes.edit_url)">
|
||||
{{ i18n.t('open_vector_editor.edit_sequence') }}
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="attachment.attributes.asset_type == 'marvinjs' && attachment.attributes.urls.marvin_js_start_edit">
|
||||
<a class="marvinjs-edit-button"
|
||||
:data-sketch-id="attachment.id"
|
||||
|
@ -129,6 +134,9 @@
|
|||
deleteAttachment() {
|
||||
this.deleteModal = false
|
||||
this.$emit('attachment:delete')
|
||||
},
|
||||
openOVEditor(url) {
|
||||
window.showIFrameModal(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,11 @@
|
|||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="integration-block open-vector-editor-button">
|
||||
<a @click="openOVEditor">
|
||||
{{ i18n.t('open_vector_editor.new_sequence') }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type='button' class='btn btn-secondary' @click="cancel">
|
||||
|
@ -148,6 +153,10 @@
|
|||
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
|
||||
}
|
||||
});
|
||||
},
|
||||
openOVEditor() {
|
||||
$(this.$refs.modal).modal('hide');
|
||||
window.showIFrameModal(this.step.attributes.new_sequence_url);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
:data-preview-url="attachment.attributes.urls.preview"
|
||||
>
|
||||
<div class="attachment-preview" :class= "attachment.attributes.asset_type">
|
||||
<img v-if="attachment.attributes.medium_preview !== null"
|
||||
<img v-if="attachment.attributes.medium_preview"
|
||||
:src="attachment.attributes.medium_preview"
|
||||
@error="ActiveStoragePreviews.reCheckPreview"
|
||||
@load="ActiveStoragePreviews.showPreview"
|
||||
|
|
9
app/javascript/vue/shared/blobToBase64.js
Normal file
9
app/javascript/vue/shared/blobToBase64.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
export function blobToBase64(blob) {
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(blob);
|
||||
return new Promise(resolve => {
|
||||
reader.onloadend = () => {
|
||||
resolve(reader.result);
|
||||
};
|
||||
});
|
||||
}
|
|
@ -17,6 +17,7 @@ class Asset < ApplicationRecord
|
|||
# ActiveStorage configuration
|
||||
has_one_attached :file
|
||||
has_one_attached :file_pdf_preview
|
||||
has_one_attached :preview_image
|
||||
|
||||
# Asset validation
|
||||
# This could cause some problems if you create empty asset and want to
|
||||
|
@ -165,17 +166,21 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
|
||||
def previewable?
|
||||
return false unless file.attached?
|
||||
return false unless preview_image.attached? || file.attached?
|
||||
|
||||
previewable_document?(blob) || previewable_image?
|
||||
end
|
||||
|
||||
def preview_attachment
|
||||
preview_image.attached? ? preview_image : file
|
||||
end
|
||||
|
||||
def medium_preview
|
||||
file.representation(resize_to_limit: Constants::MEDIUM_PIC_FORMAT)
|
||||
preview_attachment.representation(resize_to_limit: Constants::MEDIUM_PIC_FORMAT)
|
||||
end
|
||||
|
||||
def large_preview
|
||||
file.representation(resize_to_limit: Constants::LARGE_PIC_FORMAT)
|
||||
preview_attachment.representation(resize_to_limit: Constants::LARGE_PIC_FORMAT)
|
||||
end
|
||||
|
||||
def file_name
|
||||
|
@ -449,6 +454,7 @@ class Asset < ApplicationRecord
|
|||
end
|
||||
|
||||
def previewable_image?
|
||||
preview_image.attached? ||
|
||||
file.blob&.content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
|
||||
end
|
||||
|
||||
|
|
|
@ -11,7 +11,9 @@ class AssetSerializer < ActiveModel::Serializer
|
|||
attributes :file_name, :view_mode, :icon, :urls, :updated_at_formatted,
|
||||
:file_size, :medium_preview, :large_preview, :asset_type, :wopi,
|
||||
:wopi_context, :pdf_previewable, :file_size_formatted, :asset_order,
|
||||
:updated_at, :metadata, :image_editable, :image_context, :pdf, :attached
|
||||
:updated_at, :metadata, :image_editable, :image_context, :pdf, :attached,
|
||||
:edit_url, :preview_image
|
||||
|
||||
|
||||
def icon
|
||||
file_fa_icon_class(object)
|
||||
|
@ -37,6 +39,10 @@ class AssetSerializer < ActiveModel::Serializer
|
|||
number_to_human_size(object.file_size)
|
||||
end
|
||||
|
||||
def preview_image
|
||||
rails_representation_url(object.preview_image) if object.preview_image.attached?
|
||||
end
|
||||
|
||||
def medium_preview
|
||||
rails_representation_url(object.medium_preview) if object.previewable?
|
||||
end
|
||||
|
@ -49,6 +55,10 @@ class AssetSerializer < ActiveModel::Serializer
|
|||
object.file.metadata&.dig(:asset_type)
|
||||
end
|
||||
|
||||
def edit_url
|
||||
edit_gene_sequence_asset_path(object.id) if object.file.metadata&.dig(:asset_type) == 'gene_sequence'
|
||||
end
|
||||
|
||||
def metadata
|
||||
object.file.metadata
|
||||
end
|
||||
|
|
|
@ -9,7 +9,8 @@ class StepSerializer < ActiveModel::Serializer
|
|||
|
||||
attributes :name, :position, :completed, :attachments_manageble, :urls, :assets_view_mode,
|
||||
:marvinjs_enabled, :marvinjs_context, :created_by, :created_at, :assets_order,
|
||||
:wopi_enabled, :wopi_context, :comments_count, :unseen_comments, :storage_limit
|
||||
:wopi_enabled, :wopi_context, :comments_count, :unseen_comments, :storage_limit,
|
||||
:new_sequence_url
|
||||
|
||||
def marvinjs_enabled
|
||||
MarvinJsService.enabled?
|
||||
|
@ -24,6 +25,10 @@ class StepSerializer < ActiveModel::Serializer
|
|||
end
|
||||
end
|
||||
|
||||
def new_sequence_url
|
||||
new_gene_sequence_asset_url(parent_type: 'Step', parent_id: object.id)
|
||||
end
|
||||
|
||||
def comments_count
|
||||
object.comments.count
|
||||
end
|
||||
|
|
26
app/views/gene_sequence_assets/edit.html.erb
Normal file
26
app/views/gene_sequence_assets/edit.html.erb
Normal file
|
@ -0,0 +1,26 @@
|
|||
<html>
|
||||
<head>
|
||||
<%= javascript_include_tag 'i18n_bundle' %>
|
||||
<%= stylesheet_link_tag 'sn_icon_font' %>
|
||||
<%= stylesheet_link_tag 'tailwind' %>
|
||||
<%= stylesheet_link_tag 'open_vector_editor' %>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="open-vector-editor" data-behaviour="vue">
|
||||
<open-vector-editor
|
||||
file-url="<%= @file_url %>"
|
||||
file-name="<%= @file_name %>"
|
||||
parent-id="<%= @parent.id %>"
|
||||
parent-type="<%= @parent.class.name %>"
|
||||
update-url="<%= @asset ? gene_sequence_asset_url(@asset) : gene_sequence_assets_url(parent_type: params[:parent_type], parent_id: params[:parent_id]) %>"
|
||||
/>
|
||||
</div>
|
||||
<%= javascript_include_tag 'open_vector_editor' %>
|
||||
<%= javascript_include_tag 'vue_components_open_vector_editor' %>
|
||||
</body>
|
||||
</html>
|
|
@ -106,6 +106,7 @@
|
|||
<%= render "shared/file_preview/modal" %>
|
||||
<%= render "shared/file_edit_modal" %>
|
||||
<%= render "shared/marvinjs_modal" %>
|
||||
<%= render "shared/iframe_modal" %>
|
||||
<%= render "users/sessions/session_expire_modal" %>
|
||||
<%= render "users/sessions/session_end_modal" %>
|
||||
<%= render "label_printers/label_printer_modal" %>
|
||||
|
|
3
app/views/shared/_iframe_modal.html.erb
Normal file
3
app/views/shared/_iframe_modal.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div id="iFrameModal" class="fixed top-0 left-0 right-0 z-[2000] w-full h-full bg-sn-white hidden">
|
||||
<iframe id="iFrameModalFrame" class="w-full h-full border-0"></iframe>
|
||||
</div>
|
|
@ -138,3 +138,9 @@ Rails.application.config.assets.precompile += %w(big.min.js)
|
|||
|
||||
# JQuery related includes
|
||||
Rails.application.config.assets.precompile += %w(jquery_bundle.js)
|
||||
|
||||
# Separate icon font file
|
||||
Rails.application.config.assets.precompile += %w(sn_icon_font.css)
|
||||
|
||||
# Separate translations file
|
||||
Rails.application.config.assets.precompile += %w(i18n_bundle.js)
|
||||
|
|
|
@ -3636,6 +3636,11 @@ en:
|
|||
checmical_drawing: "Chemical drawings"
|
||||
no_sketches_found: "No Sketches Found"
|
||||
|
||||
open_vector_editor:
|
||||
new_sequence: "New sequence"
|
||||
edit_sequence: "Edit sequence"
|
||||
default_sequence_name: "New sequence"
|
||||
|
||||
pdf_preview:
|
||||
fit_to_screen: 'Fit to screen'
|
||||
pages:
|
||||
|
|
|
@ -975,4 +975,6 @@ Rails.application.routes.draw do
|
|||
get 'wopi/files/:id', to: 'wopi#file_get_endpoint', as: 'wopi_rest_endpoint'
|
||||
post 'wopi/files/:id', to: 'wopi#post_file_endpoint'
|
||||
end
|
||||
|
||||
resources :gene_sequence_assets, only: %i(new create edit update)
|
||||
end
|
||||
|
|
|
@ -14,6 +14,7 @@ const entryList = {
|
|||
emoji_button: './app/javascript/packs/emoji_button.js',
|
||||
fontawesome: './app/javascript/packs/fontawesome.scss',
|
||||
prism: './app/javascript/packs/prism.js',
|
||||
open_vector_editor: './app/javascript/packs/open_vector_editor.js',
|
||||
tiny_mce: './app/javascript/packs/tiny_mce.js',
|
||||
tiny_mce_styles: './app/javascript/packs/tiny_mce_styles.scss',
|
||||
tui_image_editor: './app/javascript/packs/tui_image_editor.js',
|
||||
|
@ -33,7 +34,8 @@ const entryList = {
|
|||
vue_repository_assign_items_to_task_modal: './app/javascript/packs/vue/assign_items_to_task_modal.js',
|
||||
vue_navigation_top_menu: './app/javascript/packs/vue/navigation/top_menu.js',
|
||||
vue_navigation_navigator: './app/javascript/packs/vue/navigation/navigator.js',
|
||||
vue_components_action_toolbar: './app/javascript/packs/vue/action_toolbar.js'
|
||||
vue_components_action_toolbar: './app/javascript/packs/vue/action_toolbar.js',
|
||||
vue_components_open_vector_editor: './app/javascript/packs/vue/open_vector_editor.js'
|
||||
}
|
||||
|
||||
// Engine pack loading based on https://github.com/rails/webpacker/issues/348#issuecomment-635480949
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
"@joeattardi/emoji-button": "^4.6.2",
|
||||
"ajv": "6.12.6",
|
||||
"autoprefixer": "10.4.14",
|
||||
"axios": "^1.4.0",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"bootstrap-sass": "^3.3.7",
|
||||
|
|
28
yarn.lock
28
yarn.lock
|
@ -1900,6 +1900,15 @@ available-typed-arrays@^1.0.5:
|
|||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||
|
||||
axios@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.4.0.tgz#38a7bf1224cd308de271146038b551d725f0be1f"
|
||||
integrity sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==
|
||||
dependencies:
|
||||
follow-redirects "^1.15.0"
|
||||
form-data "^4.0.0"
|
||||
proxy-from-env "^1.1.0"
|
||||
|
||||
axobject-query@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-0.1.0.tgz#62f59dbc59c9f9242759ca349960e7a2fe3c36c0"
|
||||
|
@ -3601,6 +3610,11 @@ focus-trap@^5.1.0:
|
|||
tabbable "^4.0.0"
|
||||
xtend "^4.0.1"
|
||||
|
||||
follow-redirects@^1.15.0:
|
||||
version "1.15.2"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
|
||||
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
|
||||
|
||||
for-each@^0.3.3:
|
||||
version "0.3.3"
|
||||
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
|
||||
|
@ -3617,6 +3631,15 @@ form-data@^3.0.0:
|
|||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
form-data@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
|
||||
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
|
||||
dependencies:
|
||||
asynckit "^0.4.0"
|
||||
combined-stream "^1.0.8"
|
||||
mime-types "^2.1.12"
|
||||
|
||||
fraction.js@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
|
||||
|
@ -5753,6 +5776,11 @@ prop-types@^15.8.1:
|
|||
object-assign "^4.1.1"
|
||||
react-is "^16.13.1"
|
||||
|
||||
proxy-from-env@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
|
||||
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
|
||||
|
||||
pseudomap@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
|
||||
|
|
Loading…
Reference in a new issue