Merge pull request #6216 from scinote-eln/features/ove-integration

Features/ove integration
This commit is contained in:
Alex Kriuchykhin 2023-09-13 17:05:48 +02:00 committed by GitHub
commit 40a82f67c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 3035 additions and 107 deletions

View file

@ -0,0 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.4923 3.51517C10.0704 3.60025 8.69275 4.04129 7.48581 4.79777C6.27887 5.55426 5.28139 6.60192 4.58502 7.84452C3.88865 9.08711 3.51572 10.4848 3.50049 11.9091C3.48526 13.3335 3.82822 14.7388 4.49786 15.996" stroke="#1D2939" stroke-linecap="round"/>
<path d="M11.5501 6.51843C10.6743 6.59031 9.8284 6.87102 9.08335 7.33704C8.3383 7.80307 7.71577 8.44084 7.26789 9.19694C6.82001 9.95304 6.55984 10.8055 6.50916 11.6828C6.45847 12.5601 6.61875 13.4368 6.97658 14.2395" stroke="#1D2939" stroke-linecap="round"/>
<path d="M10.7142 14.144C11.0835 14.3654 11.5036 14.4878 11.934 14.4991C12.3644 14.5105 12.7904 14.4105 13.1708 14.2089" stroke="#1D2939" stroke-linecap="round"/>
<path d="M11.5231 9.54591C11.0365 9.64048 10.5889 9.87759 10.2374 10.2271C9.88584 10.5766 9.64613 11.0227 9.54873 11.5088" stroke="#1D2939" stroke-linecap="round"/>
<path d="M16.4528 15.2284C17.2432 14.1382 17.6062 12.7958 17.473 11.4558" stroke="#1D2939" stroke-linecap="round"/>
<path d="M8.8669 16.5204C9.66189 17.0714 10.5881 17.403 11.5522 17.4817C12.5163 17.5605 13.4841 17.3836 14.358 16.9689" stroke="#1D2939" stroke-linecap="round"/>
<path d="M19.4459 7.90013C18.6397 6.43599 17.4197 5.24203 15.9386 4.46756" stroke="#1D2939" stroke-linecap="round"/>
<path d="M6.52764 18.5041C7.79803 19.573 9.35364 20.2464 11.0024 20.4413C12.6512 20.6361 14.3209 20.3439 15.8054 19.6006C17.29 18.8573 18.5244 17.6955 19.3562 16.2587C20.188 14.8219 20.5808 13.1729 20.4862 11.5154" stroke="#1D2939" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -0,0 +1,2 @@
//= require i18n.js
//= require i18n/translations

View file

@ -58,12 +58,41 @@ function importProtocolFromFile(
}
function getAssetBytes(folder, stepGuid, fileRef) {
var stepPath = stepGuid ? stepGuid + '/' : '';
var filePath = folder + stepPath + fileRef;
var assetBytes = zipFiles.files[cleanFilePath(filePath)].asBinary();
const stepPath = stepGuid ? stepGuid + '/' : '';
const filePath = folder + stepPath + fileRef;
const assetBytes = zipFiles.files[cleanFilePath(filePath)].asBinary();
return window.btoa(assetBytes);
}
function getAssetPreview(folder, stepGuid, fileRef, fileName, fileType) {
if ($.inArray(fileType, ['image/png', 'image/jpeg', 'image/gif', 'image/bmp']) > 0) {
return {
fileName: fileName,
fileType: fileType,
bytes: getAssetBytes(folder, stepGuid, fileRef)
};
} else {
const stepPath = stepGuid ? folder + stepGuid + '/' : folder;
let baseName;
baseName = fileRef.split('.');
baseName.pop();
baseName.join('.');
let previewFileRef = zipFiles.file(new RegExp(stepPath + 'previews/' + baseName));
if (previewFileRef.length > 0) {
const previewFileExt = previewFileRef[0].name.split('.').at(-1);
let previewFileName = fileName.split('.');
previewFileName.splice(-1, 1, previewFileExt);
previewFileName.join('.');
return {
fileName: previewFileName,
fileType: `image/${previewFileExt}`,
bytes: window.btoa(previewFileRef[0].asBinary())
};
}
}
return null;
}
/* Template functions */
function newPreviewElement(name, values) {
@ -82,14 +111,14 @@ function importProtocolFromFile(
}
function newAssetElement(folder, stepGuid, fileRef, fileName, fileType) {
var html = '<li class="col-xs-12">';
var assetBytes;
if ($.inArray(fileType, ['image/png', 'image/jpeg', 'image/gif', 'image/bmp']) > 0) {
assetBytes = getAssetBytes(folder, stepGuid, fileRef);
let html = '<li class="col-xs-12">';
let assetPreview = getAssetPreview(folder, stepGuid, fileRef, fileName, fileType);
html += '<img style="max-width:300px; max-height:300px;" src="data:' + fileType + ';base64,' + assetBytes + '" />';
if (assetPreview) {
html += '<img style="max-width:300px; max-height:300px;" src="data:' + assetPreview.fileType + ';base64,' + assetPreview.bytes + '" />';
html += '<br>';
}
html += '<span>' + fileName + '</span>';
html += '</li>';
return $.parseHTML(html);
@ -708,6 +737,7 @@ function importProtocolFromFile(
var assetId = $(this).attr('id');
var fileRef = $(this).attr('fileRef');
var fileName = $(this).children('fileName').text();
stepAssetJson.id = assetId;
stepAssetJson.fileName = fileName;
stepAssetJson.fileType = $(this).children('fileType').text();
@ -723,6 +753,14 @@ function importProtocolFromFile(
fileRef
);
stepAssetJson.preview_image = getAssetPreview(
protocolFolders[index],
stepGuid,
fileRef,
fileName,
null
);
stepAssetsJson.push(stepAssetJson);
});
stepJson.assets = stepAssetsJson;

View file

@ -17,6 +17,8 @@ var ActiveStoragePreviews = (function() {
if (img.retryCount >= RETRY_COUNT) return;
$(img).css('opacity', 0);
if (!$(img).parent().hasClass('processing')) $(img).parent().addClass('processing');
setTimeout(() => {

View file

@ -0,0 +1,31 @@
/* 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'));
});
iFrameModal.addEventListener('shown', () => {
document.body.classList.add('overflow-hidden');
document.body.classList.remove('overflow-auto');
});
iFrameModal.addEventListener('hidden', () => {
document.body.classList.remove('overflow-hidden');
document.body.classList.add('overflow-auto');
});
});

View file

@ -303,6 +303,12 @@ $(document).on('click', '.marvinjs-edit-button', function() {
});
});
$(document).on('click', '.gene-sequence-edit-button', function() {
var editButton = $(this);
$('#filePreviewModal').modal('hide');
window.showIFrameModal(editButton.data('sequence-edit-url'));
});
$(document).on('turbolinks:load', function() {
MarvinJsEditor = MarvinJsEditorApi();
if (MarvinJsEditor.enabled()) {

View file

@ -67,6 +67,8 @@ label {
* Global fix for handsontable
*/
.hot-table-container {
display: flex;
overflow: auto;
.ht_master .wtHolder {
height: auto !important;
width: auto !important;

View file

@ -29,6 +29,8 @@ div.print-report {
}
.hot-table-container {
display: flex;
overflow: auto;
.ht_master .wtHolder {
overflow: hidden !important;

View file

@ -445,3 +445,15 @@
padding: 4px 8px;
white-space: nowrap;
}
.sn-file-ove {
height: 1.5rem;
width: 1.5rem;
&::before {
content: url("icon_small/sequence-editor.svg");
display: inline-block;
margin: auto;
width: 100%;
}
}

View file

@ -26,11 +26,22 @@
.file-preview-container {
align-items: center;
background-color: var(--sn-color-white);
display: flex;
height: 100%;
height: calc(100% - 4rem);
justify-content: center;
margin: 2rem;
text-align: center;
width: 100%;
width: calc(100% - 4rem);
.asset-image {
background-color: var(--sn-white);
}
.gene-sequence-asset {
height: 500px;
width: 500px;
}
&.processing {
background-image: url("/images/medium/loading_white.svg");

View file

@ -15,7 +15,7 @@
.sci-input-field {
@include font-button;
animation-timing-function: $timing-function-sharp;
border: $border-secondary;
border: 1px solid var(--sn-light-grey);
border-radius: $border-radius-default !important;
box-shadow: none;
height: 36px;
@ -24,12 +24,18 @@
transition: .3s;
width: 100%;
&:hover {
border: 1px solid var(--sn-science-blue-hover);
}
&:focus {
border: $border-focus;
}
&:disabled {
background: transparent;
background-color: var(--sn-super-light-grey);
color: var(--sn-light-grey);
border: 1px solid var(--sn-light-grey);
}
&::placeholder {

View file

@ -0,0 +1,4 @@
/*
*= require sn-icon-font
*= require sn-inter-font
*/

View file

@ -29,6 +29,16 @@
box-shadow: none;
}
.sci-input-container-v2 input:hover {
border-color: var(--sn-science-blue-hover);
}
.sci-input-container-v2 input:disabled {
background-color: var(--sn-super-light-grey);
color: var(--sn-light-grey);
border: 1px solid var(--sn-light-grey);
}
.sci-input-container-v2 .sn-icon {
@apply m-2;
color: var(--sn-black)

View file

@ -0,0 +1,176 @@
# frozen_string_literal: true
class GeneSequenceAssetsController < ApplicationController
include ActiveStorage::SetCurrent
skip_before_action :verify_authenticity_token
before_action :check_open_vector_service_enabled, except: %i(new edit)
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
log_activity('sequence_asset_edit_started')
render :edit, layout: false
end
def create
save_asset!
log_activity('sequence_asset_added')
head :ok
end
def update
save_asset!
log_activity('sequence_asset_edit_finished')
head :ok
end
def destroy
log_activity('sequence_asset_deleted')
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.view_mode = @parent.assets_view_mode
@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
@ove_enabled = OpenVectorEditorService.enabled?
@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
@ove_enabled = OpenVectorEditorService.enabled?
@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
render_403 unless asset_managable?
end
def check_open_vector_service_enabled
render_403 unless OpenVectorEditorService.enabled?
end
helper_method :asset_managable?
def asset_managable?
case @parent
when Step
can_manage_step?(@parent)
when Result
can_manage_my_module?(@parent)
else
false
end
end
def log_activity(type_of, project = nil, message_items = {})
return unless @parent.is_a?(Step)
my_module = @parent.my_module
default_items = {
protocol: @parent.protocol.id,
step: @parent.id,
asset_name: { id: @asset.id, value_for: 'file_name' },
step_position: { id: @parent.id, value_for: 'position_plus_one' }
}
if my_module
project = my_module.project
default_items[:my_module] = my_module.id
type_of = "task_#{type_of}".to_sym
else
type_of = "protocol_#{type_of}".to_sym
end
message_items = default_items.merge(message_items)
Activities::CreateActivityService.call(
activity_type: type_of,
owner: current_user,
team: @parent.protocol.team,
subject: @parent.protocol,
message_items: message_items,
project: project
)
end
end

View file

@ -697,6 +697,12 @@ class ProtocolsController < ApplicationController
asset_file_name = asset_guid.to_s + File.extname(asset.file_name).to_s
ostream.put_next_entry("#{step_dir}/#{asset_file_name}")
ostream.print(asset.file.download)
next unless asset.preview_image.attached?
asset_preview_image_name = asset_guid.to_s + File.extname(asset.preview_image_file_name).to_s
ostream.put_next_entry("#{step_dir}/previews/#{asset_preview_image_name}")
ostream.print(asset.preview_image.download)
end
end
ostream = step.tiny_mce_assets.save_to_eln(ostream, step_dir)

View file

@ -40,6 +40,8 @@ module FileIconsHelper
image_link = 'icon_small/pptx_file.svg'
elsif asset.file.attached? && asset.file.metadata['asset_type'] == 'marvinjs'
image_link = 'icon_small/marvinjs_file.svg'
elsif asset.file.attached? && asset.file.metadata['asset_type'] == 'gene_sequence'
image_link = 'icon_small/sequence-editor.svg'
end
# Now check for custom mappings or possible overrides

View file

@ -0,0 +1,2 @@
import '@teselagen/ove';
import '@teselagen/ove/style.css';

View 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 }
});

View file

@ -0,0 +1,154 @@
<template>
<div class="ove-wrapper flex flex-col h-screen">
<div class="ove-header flex justify-between h-14 px-4 py-2">
<span class="file-name flex items-center ml-3 w-56">
<div class="sci-input-container-v2 w-full">
<input v-model="sequenceName"
class="sci-input-field"
type="text"
:disabled="readOnly"
:placeholder="i18n.t('open_vector_editor.sequence_name_placeholder')"/>
</div>
</span>
<div v-if="oveEnabledDaysLeft <= 30" class="flex items-center">
<i class="mr-1 text-brand-warning sn-icon sn-icon-alert-warning"></i>
<p v-html="i18n.t('open_vector_editor.trial_expiration_warning_html', { count: oveEnabledDaysLeft })" class="mb-0"></p>
</div>
<div class="ove-buttons text-sn-blue">
<button :style="{ pointerEvents: 'all' }" @click="saveAndClose" class="btn btn-light font-sans" :disabled="this.readOnly">
<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 },
canEditFile: { type: Boolean, default: false },
oveEnabledDaysLeft: { type: Number }
},
data() {
return {
editor: null,
sequenceName: null,
closeAfterSave: false,
readOnly: !this.canEditFile
}
},
mounted() {
let editorConfig = {
onSave: this.saveFile,
generatePng: true,
showMenuBar: true,
alwaysAllowSave: true,
menuFilter: this.menuFilter,
beforeReadOnlyChange: this.readOnlyHandler,
ToolBarProps: {
toolList: [
'saveTool',
'downloadTool',
{ name: 'importTool', tooltip: I18n.t('open_vector_editor.editor.tooltips.importTool'), disabled: this.readOnly },
'undoTool',
'redoTool',
'cutsiteTool',
'featureTool',
'partTool',
'oligoTool',
'orfTool',
// Hide allignment tool
// 'alignmentTool',
'editTool',
'findTool',
'visibilityTool'
]
}
}
if (this.readOnly) {
editorConfig = {
...editorConfig,
showReadOnly: false,
ToolBarProps: {
toolList: []
}
}
}
this.editor = window.createVectorEditor(this.$refs.container, editorConfig);
this.sequenceName = this.fileName;
if (this.fileUrl) {
this.loadFile();
} else {
this.editor.updateEditor(
{
sequenceData: { circular: true, name: this.sequenceName },
readOnly: this.readOnly
}
);
}
},
methods: {
loadFile() {
fetch(this.fileUrl).then((response) => response.json()).then(
(json) => this.editor.updateEditor(
{ sequenceData: json, readOnly: this.readOnly }
)
);
},
saveAndClose() {
this.closeAfterSave = true;
document.querySelector('[data-test=saveTool]').click()
},
saveFile(opts, sequenceDataToSave, editorState, onSuccessCallback) {
if (this.readOnly) return;
blobToBase64(opts.pngFile).then((base64image) => {
(this.fileUrl ? axios.patch : axios.post)(
this.updateUrl,
{
sequence_data: sequenceDataToSave,
sequence_name: this.sequenceName || this.i18n.t('open_vector_editor.default_sequence_name'),
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'));
}
},
menuFilter(menus) {
return menus.map(menu => {
if(menu.text !== 'Help') return menu;
const menuOverride = {
...menu,
submenu: menu.submenu.filter(item => item.cmd !== 'versionNumber')
}
return menuOverride;
});
},
readOnlyHandler(val) { this.readOnly = val; return true }
}
}
</script>

View file

@ -1,5 +1,5 @@
<template>
<div class="step-attachments">
<div class="step-attachments" v-if="attachments && attachments.length">
<div class="attachments-actions">
<div class="title">
<h3>{{ i18n.t('protocols.steps.files', {count: attachments.length}) }}</h3>
@ -27,6 +27,12 @@
{{ i18n.t('protocols.steps.attachments.menu.office_file') }}
</a>
</li>
<li v-if="step.attributes.open_vector_editor_context.new_sequence_asset_url">
<a @click="openOVEditor" class="open-vector-editor-button" tabindex="0" @keyup.enter="openOVEditor">
<img :src="step.attributes.open_vector_editor_context.icon"/>
{{ i18n.t('open_vector_editor.new_sequence_file') }}
</a>
</li>
<li v-if="step.attributes.marvinjs_enabled">
<a
class="new-marvinjs-upload-button"
@ -36,7 +42,7 @@
:data-sketch-container="`.attachments[data-step-id=${step.id}]`"
>
<span class="new-marvinjs-upload-icon">
<img :src="step.attributes.marvinjs_context.icon">
<i class="sn-icon sn-icon-marvinjs"></i>
</span>
{{ i18n.t('protocols.steps.attachments.menu.chemical_drawing') }}
</a>
@ -68,8 +74,9 @@
</div>
</div>
<div class="attachments">
<template v-for="(attachment, index) in attachmentsOrdered">
<template >
<component
v-for="(attachment, index) in attachmentsOrdered"
:is="attachment_view_mode(attachmentsOrdered[index])"
:key="attachment.id"
:attachment="attachment"
@ -150,6 +157,7 @@
}
},
mounted() {
this.initOVE(this);
this.initMarvinJS();
$(this.$refs.actionsDropdownButton).on('shown.bs.dropdown hidden.bs.dropdown', this.handleDropdownPosition);
},
@ -174,6 +182,11 @@
deleteAttachment(id) {
this.$emit('attachment:deleted', id)
},
initOVE(component) {
$(window.iFrameModal).on('sequenceSaved', function() {
component.$emit('attachment:uploaded');
});
},
initMarvinJS() {
// legacy logic from app/assets/javascripts/sitewide/marvinjs_editor.js
MarvinJsEditor.initNewButton(
@ -190,6 +203,9 @@
}
});
},
openOVEditor() {
window.showIFrameModal(this.step.attributes.open_vector_editor_context.new_sequence_asset_url);
},
handleDropdownPosition() {
this.$refs.actionsDropdownButton.classList.toggle("dropup", !this.isInViewport(this.$refs.actionsDropdown));
},

View file

@ -140,8 +140,8 @@
<div class="collapse in" :id="'stepBody' + step.id">
<div class="step-elements">
<div class="step-timestamp">{{ i18n.t('protocols.steps.timestamp', {date: step.attributes.created_at, user: step.attributes.created_by}) }}</div>
<template v-for="(element, index) in orderedElements">
<component
v-for="(element, index) in orderedElements"
:is="elements[index].attributes.orderable_type"
:key="index"
:element.sync="elements[index]"
@ -154,17 +154,16 @@
@reorder="openReorderModal"
@component:insert="insertElement"
/>
</template>
<Attachments v-if="attachments.length"
:step="step"
:attachments="attachments"
:attachmentsReady="attachmentsReady"
@attachments:openFileModal="showFileModal = true"
@attachment:deleted="attachmentDeleted"
@attachment:uploaded="loadAttachments"
@attachments:order="changeAttachmentsOrder"
@attachments:viewMode="changeAttachmentsViewMode"
@attachment:viewMode="updateAttachmentViewMode"/>
<Attachments
:step="step"
:attachments="attachments"
:attachmentsReady="attachmentsReady"
@attachments:openFileModal="showFileModal = true"
@attachment:deleted="attachmentDeleted"
@attachment:uploaded="loadAttachments"
@attachments:order="changeAttachmentsOrder"
@attachments:viewMode="changeAttachmentsViewMode"
@attachment:viewMode="updateAttachmentViewMode"/>
</div>
</div>
<deleteStepModal v-if="confirmingDelete" @confirm="deleteStep" @cancel="closeDeleteModal"/>
@ -308,7 +307,6 @@
$.get(this.urls.attachments_url, (result) => {
this.attachments = result.data
if (this.attachments.findIndex((e) => e.attributes.attached === false) >= 0) {
setTimeout(() => {
this.loadAttachments()

View file

@ -20,6 +20,12 @@
{{ attachment.attributes.wopi_context.button_text }}
</a>
</li>
<li v-if="attachment.attributes.asset_type == 'gene_sequence' && attachment.attributes.urls.open_vector_editor_edit">
<a class="ove-edit-button" @click="openOVEditor(attachment.attributes.urls.open_vector_editor_edit)">
<span class="sn-icon sn-icon-sequence-editor"></span>
{{ 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"
@ -28,7 +34,7 @@
:data-sketch-name="attachment.attributes.metadata.name"
:data-sketch-description="attachment.attributes.metadata.description"
>
<img :src="attachment.attributes.urls.marvin_js_icon"/>
<span class="sn-icon sn-icon-marvinjs"></span>
{{ i18n.t('assets.file_preview.edit_in_marvinjs') }}
</a>
</li>
@ -129,6 +135,9 @@
deleteAttachment() {
this.deleteModal = false
this.$emit('attachment:delete')
},
openOVEditor(url) {
window.showIFrameModal(url);
}
}
}

View file

@ -34,7 +34,7 @@
{{ i18n.t("protocols.steps.attachments.file_modal.drag_zone_notification", {position: step.attributes.position + 1}) }}
</div>
</div>
<div class="divider" v-if="step.attributes.marvinjs_enabled || step.attributes.wopi_enabled">
<div class="divider" v-if="step.attributes.marvinjs_enabled || step.attributes.wopi_enabled || step.attributes.open_vector_editor_context.new_sequence_asset_url">
{{ i18n.t("protocols.steps.attachments.file_modal.or") }}
</div>
<div class="integrations-container">
@ -44,6 +44,12 @@
{{ i18n.t('assets.create_wopi_file.button_text') }}
</a>
</div>
<div class="integration-block" v-if="step.attributes.open_vector_editor_context.new_sequence_asset_url">
<a @click="openOVEditor" class="open-vector-editor-button btn btn-light">
<img :src="step.attributes.open_vector_editor_context.icon"/>
{{ i18n.t('open_vector_editor.new_sequence') }}
</a>
</div>
<div class="integration-block marvinjs" v-if="step.attributes.marvinjs_enabled">
<a
class="new-marvinjs-upload-button btn btn-light"
@ -57,7 +63,7 @@
<span class="new-marvinjs-upload-icon">
<img :src="step.attributes.marvinjs_context.icon"/>
</span>
{{ i18n.t('marvinjs.new_button') }}
{{ i18n.t('marvinjs.new_li_button') }}
</a>
</div>
</div>
@ -148,6 +154,10 @@
HelperModule.flashAlertMsg(this.i18n.t('errors.general'), 'danger');
}
});
},
openOVEditor() {
$(this.$refs.modal).modal('hide');
window.showIFrameModal(this.step.attributes.open_vector_editor_context.new_sequence_asset_url);
}
}
}

View file

@ -2,6 +2,7 @@
<div class="list-attachment-container asset"
:data-asset-id="attachment.id"
>
<div v-html="attachment.attributes.icon"></div>
<i class="fas asset-icon" :class="attachment.attributes.icon"></i>
<a :href="attachment.attributes.urls.blob"
class="file-preview-link file-name"

View file

@ -10,13 +10,15 @@
:data-gallery-view-id="stepId"
:data-preview-url="attachment.attributes.urls.preview"
>
<div class="attachment-preview" :class= "attachment.attributes.asset_type">
<img v-if="attachment.attributes.medium_preview !== null"
<div v-if="attachment.attributes.medium_preview" class="attachment-preview" :class= "attachment.attributes.asset_type">
<img
:src="attachment.attributes.medium_preview"
@error="ActiveStoragePreviews.reCheckPreview"
@load="ActiveStoragePreviews.showPreview"
style='opacity: 0' />
<i v-else class="fas" :class="attachment.attributes.icon"></i>
</div>
<div v-else class="attachment-preview flex">
<span class="fa fa-paperclip m-auto text-4xl"></span>
</div>
<div class="attachment-label"
data-toggle="tooltip"

View 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);
};
});
}

View file

@ -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
@ -184,6 +189,12 @@ class Asset < ApplicationRecord
file.blob&.filename&.sanitized
end
def preview_image_file_name
return '' unless preview_image.attached?
preview_image.blob&.filename&.sanitized
end
def render_file_name
if file.attached? && file.metadata['asset_type']
file.metadata['name']
@ -221,6 +232,18 @@ class Asset < ApplicationRecord
to_blob = ActiveStorage::Blob.create_and_upload!(io: tmp_file, filename: blob.filename, metadata: blob.metadata)
to_asset.file.attach(to_blob)
end
if preview_image.attached?
preview_image.blob.open do |tmp_preview_image|
to_blob = ActiveStorage::Blob.create_and_upload!(
io: tmp_preview_image,
filename: blob.filename,
metadata: blob.metadata
)
to_asset.preview_image.attach(to_blob)
end
end
to_asset.post_process_file(to_asset.team)
end
@ -449,7 +472,8 @@ class Asset < ApplicationRecord
end
def previewable_image?
file.blob&.content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
preview_image.attached? ||
file.blob&.content_type =~ %r{^image/#{Regexp.union(Constants::WHITELISTED_IMAGE_TYPES)}}
end
def step_or_result_or_repository_asset_value

View file

@ -14,11 +14,11 @@ class AssetSerializer < ActiveModel::Serializer
:updated_at, :metadata, :image_editable, :image_context, :pdf, :attached
def icon
file_fa_icon_class(object)
file_extension_icon_html(object)
end
def file_name
escape_input(object.render_file_name)
object.render_file_name
end
def updated_at
@ -127,6 +127,7 @@ class AssetSerializer < ActiveModel::Serializer
delete: asset_destroy_path(object)
)
end
urls[:open_vector_editor_edit] = edit_gene_sequence_asset_path(object.id) if can_manage_asset?(user, object)
urls[:wopi_action] = object.get_action_url(user, 'embedview') if wopi && can_manage_asset?(user, object)
urls[:blob] = rails_blob_path(object.file, disposition: 'attachment') if object.file.attached?

View file

@ -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,
:open_vector_editor_context
def marvinjs_enabled
MarvinJsService.enabled?
@ -24,6 +25,15 @@ class StepSerializer < ActiveModel::Serializer
end
end
def open_vector_editor_context
if can_manage_step?(object)
{
new_sequence_asset_url: new_gene_sequence_asset_url(parent_type: 'Step', parent_id: object.id),
icon: image_path('icon_small/sequence-editor.svg')
}
end
end
def comments_count
object.comments.count
end

View file

@ -0,0 +1,23 @@
# frozen_string_literal: true
class OpenVectorEditorService
class << self
def enabled?
ove_enabled_until = ENV.fetch('SCINOTE_OVE_ENABLED_UNTIL', nil)
return false if ove_enabled_until.blank?
DateTime.now.utc.to_date < DateTime.strptime(ove_enabled_until, '%d-%m-%Y').utc.to_date
end
def evaluation_period_left
return 0 unless enabled?
ove_enabled_until = ENV.fetch('SCINOTE_OVE_ENABLED_UNTIL', nil)
return 0 if ove_enabled_until.blank?
(DateTime.strptime(ove_enabled_until, '%d-%m-%Y').utc.to_date - DateTime.now.utc.to_date).to_i
end
end
end

View file

@ -115,6 +115,11 @@ class ProtocolsImporterV2
filename: asset_json['fileName'],
content_type: asset_json['fileType'],
metadata: JSON.parse(asset_json['fileMetadata'] || '{}'))
if asset_json['preview_image'].present?
asset.preview_image.attach(io: StringIO.new(Base64.decode64(asset_json.dig('preview_image', 'bytes'))),
filename: asset_json.dig('preview_image', 'fileName'))
end
asset.save!
asset_ids << asset.id

View file

@ -0,0 +1,30 @@
<html>
<head>
<%= csp_meta_tag %>
<%= javascript_include_tag 'i18n_bundle' %>
<%= stylesheet_link_tag 'sn_icon_font' %>
<%= stylesheet_link_tag 'application' %>
<%= stylesheet_link_tag 'tailwind' %>
<%= stylesheet_link_tag 'open_vector_editor' %>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<% if @ove_enabled %>
<div id="open-vector-editor" data-behaviour="vue">
<open-vector-editor
file-url="<%= @file_url %>"
file-name="<%= @file_name %>"
update-url="<%= @asset ? gene_sequence_asset_url(@asset) : gene_sequence_assets_url(parent_type: params[:parent_type], parent_id: params[:parent_id]) %>"
:can-edit-file="<%= asset_managable? %>"
:ove-enabled-days-left="<%= OpenVectorEditorService.evaluation_period_left %>"
/>
</div>
<%= javascript_include_tag 'open_vector_editor' %>
<%= javascript_include_tag 'vue_components_open_vector_editor' %>
<% end %>
</body>
</html>

View file

@ -109,6 +109,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" %>

View file

@ -1,7 +1,9 @@
<% @asset_results.each do |asset| %>
<h5>
<h5 class="flex flex-row flex-nowrap items-center gap-1">
<% if asset.blob.metadata["asset_type"] == 'marvinjs' %>
<span class="mce-i-marvinjs"></span>
<% elsif asset.blob.metadata["asset_type"] == 'gene_sequence' %>
<span class="sn-file-ove"></span>
<% else %>
<% if wopi_file?(asset) %>
<%= file_extension_icon(asset) %>

View file

@ -6,7 +6,7 @@
</span>
</div>
<div class="my-5 flex-1 bg-sn-white">
<div class="my-5 max-w-4xl flex-1 bg-sn-white">
<div class="content-pane flexible">
<%= render partial: 'shareable_links/my_modules/header_actions' %>
<div class="px-4">

View file

@ -2,13 +2,13 @@
<div class="comment-container">
<div class="avatar-placehodler">
<span class='global-avatar-container'>
<%= image_tag avatar_path(comment.user, :icon_small), class: 'avatar' %>
<%= image_tag user_avatar_absolute_url(comment.user, :icon_small, true), class: 'user-avatar' %>
</span>
</div>
<div class="content-placeholder">
<div class="comment-name"><%= comment.user.full_name %></div>
<div class="comment-right !w-fit">
<div class="comment-datetime !w-fit"><%= comment.created_at.iso8601 %></div>
<div class="comment-datetime !w-fit"><%= l(comment.created_at, format: :full) %></div>
</div>
<div class="comment-message">
<div class="view-mode"><%= smart_annotation_text(comment.message) %></div>

View file

@ -4,7 +4,7 @@
<% if element.name.present? %>
<div class="step-element-name">
<%= render partial: "shareable_links/my_modules/inline_view", locals: { text: element.name, smart_annotation_enabled: false } %>
</div>
</div>
<% end %>
</div>
<div class="step-table view locked" tabindex="0">

View 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>

View file

@ -22,6 +22,14 @@
<%= t('assets.file_preview.edit_in_marvinjs') %>
</button>
<% elsif asset.blob.metadata["asset_type"] == 'gene_sequence' %>
<button class="btn btn-light gene-sequence-edit-button"
data-sequence-edit-url="<%= edit_gene_sequence_asset_path(asset) %>"
>
<span class="sn-icon sn-icon-sequence-editor"></span>
<%= t('open_vector_editor.edit_sequence') %>
</button>
<% elsif asset.editable_image? %>
<button class="btn btn-light image-edit-button"
data-image-id="<%= asset.id %>"
@ -54,8 +62,8 @@
<%= render partial: 'shared/pdf_viewer', locals: { asset: asset, report_document: false } %>
<% else %>
<%= image_tag asset.large_preview,
class: 'asset-image',
style: 'opacity: 0' %>
class: class_names('asset-image', 'gene-sequence-asset': asset.blob&.metadata["asset_type"] == 'gene_sequence'),
style: 'opacity: 0' %>
<% end %>
<% else %>
<%= render partial: 'shared/file_preview/file_icon', locals: { asset: asset } %>

View file

@ -131,5 +131,11 @@ 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)
# Add stuff installed by yarn
Rails.application.config.assets.paths << Rails.root.join('node_modules')

View file

@ -449,7 +449,15 @@ class Extends
team_sharing_tasks_disabled: 245,
task_link_sharing_enabled: 246,
task_link_sharing_disabled: 247,
shared_task_message_edited: 248
shared_task_message_edited: 248,
task_sequence_asset_added: 249,
task_sequence_asset_edit_started: 250,
task_sequence_asset_edit_finished: 251,
task_sequence_asset_deleted: 252,
protocol_sequence_asset_added: 253,
protocol_sequence_asset_edit_started: 254,
protocol_sequence_asset_edit_finished: 255,
protocol_sequence_asset_deleted: 256
}
ACTIVITY_GROUPS = {
@ -458,7 +466,7 @@ class Extends
task: [8, 58, 9, 59, *10..14, 35, 36, 37, 53, 54, *60..63, 138, 139, 140, 64, 66, 106, 126, 120, 132,
*146..148, 166, 246, 247, 248],
task_protocol: [15, 22, 16, 18, 19, 20, 21, 17, 38, 39, 100, 111, 45, 46, 47, 121, 124, 115, 118, 127, 130, 137,
217, 168, 171, 177, 184, 185, 188, 189, *192..203, 222, 224, 225, 226, 236],
217, 168, 171, 177, 184, 185, 188, 189, *192..203, 222, 224, 225, 226, 236, *249..252],
task_inventory: [55, 56, 146, 147, 183],
experiment: [*27..31, 57, 141, 165],
reports: [48, 50, 49, 163, 164],
@ -466,7 +474,7 @@ class Extends
78, 96, 107, 113, 114, *133..136, 180, 181, 182],
protocol_repository: [80, 103, 89, 87, 79, 90, 91, 88, 85, 86, 84, 81, 82,
83, 101, 112, 123, 125, 117, 119, 129, 131, 170, 173, 179, 187, 186,
190, 191, *204..215, 220, 221, 223, 227, 228, 229, *230..235, *237..240],
190, 191, *204..215, 220, 221, 223, 227, 228, 229, *230..235, *237..240, *253..256],
team: [92, 94, 93, 97, 104, 244, 245],
label_templates: [*216..219]
}

View file

@ -3097,7 +3097,7 @@ en:
drag_zone_title: "Upload a file from your PC"
drag_zone_description: "You can also drag & drop files to here or into steps to upload"
drag_zone_notification: "Drop files to add to step %{position}"
or: "OR"
or: "or create new"
new:
description: 'New'
uploading: 'Uploading'
@ -3277,7 +3277,7 @@ en:
wopi_supported_table_formats_title: 'Only .xlsx, .xlsm, .xlsb, .ods file formats are supported for editing in Excel Online.'
wopi_supported_presentation_formats_title: 'Only .pptx, ppsx, .odp file formats are supported for editing in PowerPoint Online.'
create_wopi_file:
button_text: 'Create an MS Office file'
button_text: 'MS Office file'
li_text: "Office file"
modal_title: 'Create new Microsoft Office Online document'
text_field_label: 'Document name'
@ -3701,9 +3701,18 @@ en:
new_li_button: "Chemical drawing"
structure_placeholder: "Click here to enter Chemical Drawing name"
modal_name_title: "Chemical Drawing name:"
checmical_drawing: "Chemical drawings"
chemical_drawing: "Chemical drawings"
no_sketches_found: "No Sketches Found"
open_vector_editor:
new_sequence: "Sequence"
new_sequence_file: "New sequence"
default_sequence_name: "New sequence"
edit_sequence: "Edit in Sequence editor"
sequence_name_placeholder: "Click here to enter sequence name"
editor:
tooltips:
importTool: "Click or drag to import and view files (.fasta .gb .dna .json)"
pdf_preview:
fit_to_screen: 'Fit to screen'
pages:

View file

@ -273,6 +273,14 @@ en:
task_link_sharing_enabled_html: "%{user} enabled link sharing for task %{my_module}."
task_link_sharing_disabled_html: "%{user} disabled link sharing for task %{my_module}."
shared_task_message_edited_html: "%{user} edited message for shared task %{my_module}."
task_sequence_asset_added_html: "%{user} created sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> on task <strong>%{my_module}</strong>."
task_sequence_asset_edit_started_html: "%{user} edited sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> on task <strong>%{my_module}</strong>: editing started."
task_sequence_asset_edit_finished_html: "%{user} edited sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> on task <strong>%{my_module}</strong>: editing finished."
task_sequence_asset_deleted_html: "%{user} deleted sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> on task <strong>%{my_module}</strong>."
protocol_sequence_asset_added_html: "%{user} created sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> in Protocol repository."
protocol_sequence_asset_edit_started_html: "%{user} edited sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> in Protocol repository: editing started."
protocol_sequence_asset_edit_finished_html: "%{user} edited sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> in Protocol repository: editing finished."
protocol_sequence_asset_deleted_html: "%{user} deleted sequence <strong>%{asset_name}</strong> on protocols step <strong>%{step_position}</strong> <strong>%{step}</strong> in Protocol repository."
activity_name:
create_project: "Project created"
rename_project: "Project renamed"
@ -500,6 +508,14 @@ en:
task_link_sharing_enabled: "Task link sharing enabled"
task_link_sharing_disabled: "Task link sharing disabled"
shared_task_message_edited: "Shared task message edited"
task_sequence_asset_added: "Task sequence asset added"
task_sequence_asset_edit_started: "Task sequence asset editing started"
task_sequence_asset_edit_finished: "Task sequence asset editing finished"
task_sequence_asset_deleted: "Task sequence asset deleted"
protocol_sequence_asset_added: "Protocol sequence asset added"
protocol_sequence_asset_edit_started: "Protocol sequence asset editing started"
protocol_sequence_asset_edit_finished: "Protocol sequence asset editing finished"
protocol_sequence_asset_deleted: "Protocol sequence asset deleted"
activity_group:
projects: "Projects"
task_results: "Task results"

View file

@ -991,4 +991,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

View file

@ -19,7 +19,10 @@ module.exports = {
},
colors: {
transparent: 'transparent',
current: 'currentColor'
current: 'currentColor',
'brand-warning': '#f0ad4e',
'sn-blue': '#104DA9',
'sn-grey': '#98a2b3'
}
}
},

View file

@ -16,6 +16,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',
@ -36,8 +37,9 @@ const entryList = {
vue_share_task_container: './app/javascript/packs/vue/share_task_container.js',
vue_navigation_top_menu: './app/javascript/packs/vue/navigation/top_menu.js',
vue_navigation_navigator: './app/javascript/packs/vue/navigation/navigator.js',
vue_navigation_breadcrumbs: './app/javascript/packs/vue/navigation/breadcrumbs.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',
vue_navigation_breadcrumbs: './app/javascript/packs/vue/navigation/breadcrumbs.js',
vue_protocol_file_import_modal: './app/javascript/packs/vue/protocol_file_import_modal.js'
}

View file

@ -49,8 +49,10 @@
"@babel/preset-env": "^7.20.2",
"@fortawesome/fontawesome-free": "^5.2.0",
"@joeattardi/emoji-button": "^4.6.2",
"@teselagen/ove": "^0.3.15",
"ajv": "6.12.6",
"autoprefixer": "10.4.14",
"axios": "^1.4.0",
"babel-loader": "^8.2.5",
"babel-plugin-macros": "^3.1.0",
"bootstrap": "^3.4.1",

View file

@ -0,0 +1,10 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.4923 3.51517C10.0704 3.60025 8.69275 4.04129 7.48581 4.79777C6.27887 5.55426 5.28139 6.60192 4.58502 7.84452C3.88865 9.08711 3.51572 10.4848 3.50049 11.9091C3.48526 13.3335 3.82822 14.7388 4.49786 15.996" stroke="#1D2939" stroke-linecap="round"/>
<path d="M11.5501 6.51843C10.6743 6.59031 9.8284 6.87102 9.08335 7.33704C8.3383 7.80307 7.71577 8.44084 7.26789 9.19694C6.82001 9.95304 6.55984 10.8055 6.50916 11.6828C6.45847 12.5601 6.61875 13.4368 6.97658 14.2395" stroke="#1D2939" stroke-linecap="round"/>
<path d="M10.7142 14.144C11.0835 14.3654 11.5036 14.4878 11.934 14.4991C12.3644 14.5105 12.7904 14.4105 13.1708 14.2089" stroke="#1D2939" stroke-linecap="round"/>
<path d="M11.5231 9.54591C11.0365 9.64048 10.5889 9.87759 10.2374 10.2271C9.88584 10.5766 9.64613 11.0227 9.54873 11.5088" stroke="#1D2939" stroke-linecap="round"/>
<path d="M16.4528 15.2284C17.2432 14.1382 17.6062 12.7958 17.473 11.4558" stroke="#1D2939" stroke-linecap="round"/>
<path d="M8.8669 16.5204C9.66189 17.0714 10.5881 17.403 11.5522 17.4817C12.5163 17.5605 13.4841 17.3836 14.358 16.9689" stroke="#1D2939" stroke-linecap="round"/>
<path d="M19.4459 7.90013C18.6397 6.43599 17.4197 5.24203 15.9386 4.46756" stroke="#1D2939" stroke-linecap="round"/>
<path d="M6.52764 18.5041C7.79803 19.573 9.35364 20.2464 11.0024 20.4413C12.6512 20.6361 14.3209 20.3439 15.8054 19.6006C17.29 18.8573 18.5244 17.6955 19.3562 16.2587C20.188 14.8219 20.5808 13.1729 20.4862 11.5154" stroke="#1D2939" stroke-linecap="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

View file

@ -10,9 +10,9 @@
"description": "SN icon font\nFont generated by IcoMoon.",
"copyright": "SciNote LLC",
"majorVersion": 1,
"minorVersion": 12,
"minorVersion": 14,
"fontURL": "https://www.scinote.net",
"version": "Version 1.12",
"version": "Version 1.14",
"fontId": "SN-icon-font",
"psName": "SN-icon-font",
"subFamily": "Regular",
@ -64,19 +64,19 @@
<glyph unicode="&#xe923;" glyph-name="resize" data-tags="resize" d="M725.76 618.24l-29.867-29.867 140.373-140.373h-648.533l140.8 140.8-29.867 29.867-192-192 192-192 29.867 29.867-140.8 140.8h648.533l-140.8-140.8 29.867-29.867 192 192-191.573 191.573z" />
<glyph unicode="&#xe924;" glyph-name="reset-password" data-tags="reset-password" d="M512 768c-128.853 0-240.64-71.68-298.667-176.64v91.307h-42.667v-170.667h170.667v42.667h-98.987c48.213 100.693 150.613 170.667 269.653 170.667 164.693 0 298.667-133.973 298.667-298.667s-133.973-298.667-298.667-298.667c-134.827 0-249.173 90.027-286.293 213.333h-43.947c37.973-147.2 171.093-256 330.24-256 188.587 0 341.333 152.747 341.333 341.333s-152.747 341.333-341.333 341.333zM597.333 469.334v42.667c0 46.933-38.4 85.333-85.333 85.333s-85.333-38.4-85.333-85.333v-42.667c-23.467 0-42.667-19.2-42.667-42.667v-128c0-23.467 19.2-42.667 42.667-42.667h170.667c23.467 0 42.667 19.2 42.667 42.667v128c0 23.467-19.2 42.667-42.667 42.667zM512 554.667c23.467 0 42.667-19.2 42.667-42.667v-42.667h-85.333v42.667c0 23.467 19.2 42.667 42.667 42.667z" />
<glyph unicode="&#xe925;" glyph-name="reports" data-tags="reports" d="M762.027 725.334c29.013 0 48.213-21.76 48.213-42.667v-512c0-20.907-18.773-42.667-48.213-42.667h-500.48c-29.013 0-48.213 21.76-48.213 42.667v512c0 20.907 18.773 42.667 48.213 42.667h500.907zM261.973 768c-50.347 0-90.88-38.4-90.88-85.333v-512c0-46.933 40.96-85.333 90.88-85.333h500.48c50.347 0 90.88 38.4 90.88 85.333v512c0 46.933-40.96 85.333-90.88 85.333h-500.907zM682.667 618.667c0 11.947 9.387 21.333 21.333 21.333s21.333-9.387 21.333-21.333v-384c0-11.947-9.387-21.333-21.333-21.333s-21.333 9.387-21.333 21.333v384zM554.667 362.667c0 11.947 9.387 21.333 21.333 21.333s21.333-9.387 21.333-21.333v-128c0-11.947-9.387-21.333-21.333-21.333s-21.333 9.387-21.333 21.333v128zM426.667 533.334c0 11.947 9.387 21.333 21.333 21.333s21.333-9.387 21.333-21.333v-298.667c0-11.947-9.387-21.333-21.333-21.333s-21.333 9.387-21.333 21.333v298.667zM298.667 448c0 11.947 9.387 21.333 21.333 21.333s21.333-9.387 21.333-21.333v-213.333c0-11.947-9.387-21.333-21.333-21.333s-21.333 9.387-21.333 21.333v213.333z" />
<glyph unicode="&#xe926;" glyph-name="relationships" data-tags="relationships" d="M810.667 490.667v298.667h-298.667v-128h-256v128h-42.667v-597.333h298.667v-128h298.667v298.667h-298.667v-128h-256v384h256v-128h298.667zM554.667 320h213.333v-213.333h-213.333v213.333zM554.667 746.667h213.333v-213.333h-213.333v213.333z" />
<glyph unicode="&#xe927;" glyph-name="relationships-solid" data-tags="relationships-solid" d="M810.667 490.667v298.667h-298.667v-128h-256v128h-42.667v-597.333h298.667v-128h298.667v298.667h-298.667v-128h-256v384h256v-128h298.667z" />
<glyph unicode="&#xe926;" glyph-name="navigator-light" data-tags="relationships" d="M810.667 490.667v298.667h-298.667v-128h-256v128h-42.667v-597.333h298.667v-128h298.667v298.667h-298.667v-128h-256v384h256v-128h298.667zM554.667 320h213.333v-213.333h-213.333v213.333zM554.667 746.667h213.333v-213.333h-213.333v213.333z" />
<glyph unicode="&#xe927;" glyph-name="navigator" data-tags="relationships-solid" d="M810.667 490.667v298.667h-298.667v-128h-256v128h-42.667v-597.333h298.667v-128h298.667v298.667h-298.667v-128h-256v384h256v-128h298.667z" />
<glyph unicode="&#xe928;" glyph-name="read-more" data-tags="read-more" d="M432.213 570.454c-4.267-4.267-6.4-9.813-5.547-16.213s3.84-12.373 9.387-17.92l88.32-88.32h-353.707v-42.667h353.707l-87.893-87.893c-5.547-5.547-8.533-11.52-9.387-17.92s0.853-11.947 5.547-16.213c4.267-4.267 9.813-6.4 16.213-5.547s12.373 3.84 17.92 9.387l125.44 125.44s2.987 4.267 3.84 6.4c0.853 2.133 1.28 4.693 1.28 7.68s0 5.12-1.28 7.253c-0.853 2.56-2.133 4.693-3.84 6.4l-125.867 125.867c-5.547 5.547-11.52 8.533-17.92 9.387s-11.947-0.853-16.213-5.547v0zM640 576h213.333v-42.667h-213.333v42.667zM725.333 448h128v-42.667h-128v42.667zM640 320h213.333v-42.667h-213.333v42.667z" />
<glyph unicode="&#xe929;" glyph-name="protocols-templates" data-tags="protocols-templates" d="M512 45.227c-86.187 24.747-157.44 76.8-213.76 155.307s-84.907 166.827-84.907 264.96v230.4l298.667 112.213 298.667-112.213v-230.4c0-98.133-28.16-186.453-84.907-264.96-56.32-78.507-128-130.133-213.76-155.307zM512 90.027c73.813 23.467 135.253 70.4 183.467 140.8s72.533 148.48 72.533 234.667v201.813l-256 94.72-256-94.72v-201.813c0-86.187 24.32-164.267 72.533-234.667s109.653-117.333 183.467-140.8zM640 555.094h-256v42.667h256v-42.667zM640 427.094h-256v42.667h256v-42.667zM640 299.094h-256v42.667h256v-42.667z" />
<glyph unicode="&#xe92a;" glyph-name="projects" data-tags="projects" d="M853.333 42.667h-256c-23.467 0-42.667 19.2-42.667 42.667v256c0 23.467 19.2 42.667 42.667 42.667h256c23.467 0 42.667-19.2 42.667-42.667v-256c0-23.467-19.2-42.667-42.667-42.667zM597.333 341.334v-256h256v256h-256zM299.093 42.667c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667-76.373-170.667-170.667-170.667zM299.093 341.334c-70.4 0-128-57.6-128-128s57.6-128 128-128 128 57.6 128 128-57.6 128-128 128zM725.76 469.334c-94.293 0-170.667 76.373-170.667 170.667s76.373 170.667 170.667 170.667 170.667-76.373 170.667-170.667-76.373-170.667-170.667-170.667zM725.76 768c-70.4 0-128-57.6-128-128s57.6-128 128-128 128 57.6 128 128-57.6 128-128 128zM427.093 469.334h-256c-23.467 0-42.667 19.2-42.667 42.667v256c0 23.467 19.2 42.667 42.667 42.667h256c23.467 0 42.667-19.2 42.667-42.667v-256c0-23.467-19.2-42.667-42.667-42.667zM171.093 768v-256h256v256h-256z" />
<glyph unicode="&#xe92b;" glyph-name="project-member-access" data-tags="project-member-access" d="M170.667 85.334v42.667h85.333v570.88c0 20.053 6.4 36.267 19.627 49.493s29.867 19.627 49.493 19.627h373.333c20.053 0 36.267-6.4 49.493-19.627s19.627-29.867 19.627-49.493v-570.88h85.333v-42.667h-682.24zM298.667 128h426.667v570.88c0 7.253-2.56 13.227-8.107 18.773-5.12 5.547-11.52 8.107-18.773 8.107h-373.333c-7.253 0-13.227-2.56-18.773-8.107-5.547-5.12-8.107-11.52-8.107-18.773v-570.88zM456.107 397.227c-8.533-8.533-18.347-13.227-29.44-13.227-11.947 0-22.187 4.267-30.293 13.227-8.107 8.533-12.373 18.347-12.373 29.44s4.267 20.907 12.373 29.44c8.107 8.533 18.347 13.227 30.293 13.227 11.093 0 20.907-4.267 29.44-13.227 8.533-8.533 13.227-18.773 13.227-29.44s-4.267-20.907-13.227-29.44z" />
<glyph unicode="&#xe92c;" glyph-name="printer" data-tags="printer" d="M874.667 533.334c0 23.467-19.2 42.667-42.667 42.667h-85.333v170.667h-469.333v-170.667h-85.333c-23.467 0-42.667-19.2-42.667-42.667v-256h128v-170.667h469.333v170.667h128v256zM320 149.334v213.333h384v-213.333h-384zM277.333 405.334v-85.333h-85.333v213.333h640v-213.333h-85.333v85.333h-469.333zM320 704h384v-128h-384v128z" />
<glyph unicode="&#xe92d;" glyph-name="open-show" data-tags="open-show" d="M512 298.667l-213.333 225.28 28.16 30.72 185.173-195.413 185.173 195.413 28.16-30.72-213.333-225.28z" />
<glyph unicode="&#xe92d;" glyph-name="down" data-tags="open-show" d="M512 298.667l-213.333 225.28 28.16 30.72 185.173-195.413 185.173 195.413 28.16-30.72-213.333-225.28z" />
<glyph unicode="&#xe92e;" glyph-name="notifications" data-tags="notifications" d="M512 768c-35.413 0-64-28.587-64-64v-21.333h128v21.333c0 35.413-28.587 64-64 64zM746.667 213.334v281.173c0 55.467-17.92 104.107-54.613 145.92-34.133 39.68-77.653 64.427-128.853 75.947-41.387 8.533-78.507 4.693-100.693 0.427-52.48-11.093-96-36.267-130.987-76.373-36.267-41.813-54.613-90.453-54.613-145.92v-281.173h-84.907v-42.667h640v42.667h-85.333zM704 213.334h-384v281.173c0 52.053 18.773 96 55.893 132.267 37.547 36.267 82.773 54.613 136.107 54.613s98.56-18.347 136.107-54.613c37.12-36.267 55.893-80.64 55.893-132.267v-281.173zM467.2 97.28c12.8-8.107 27.733-11.947 44.8-11.947 18.347 0 33.707 3.84 45.653 11.947s18.347 18.347 18.347 30.72h-128c0-12.373 6.4-22.613 19.2-30.72z" />
<glyph unicode="&#xe92f;" glyph-name="notes" data-tags="notes" d="M282.453 42.667c-20.053 0-36.267 6.4-49.493 19.627s-19.627 29.867-19.627 49.493v629.76c0 20.053 6.4 36.267 19.627 49.493s29.867 19.627 49.493 19.627h336.213l192-192v-506.88c0-20.053-6.4-36.267-19.627-49.493s-29.867-19.627-49.493-19.627h-459.093zM597.333 597.334v170.667h-314.88c-7.253 0-13.227-2.56-18.773-8.107-5.547-5.12-8.107-11.52-8.107-18.773v-629.333c0-7.253 2.56-13.227 8.107-18.773 5.12-5.547 11.52-8.107 18.773-8.107h458.667c7.253 0 13.227 2.56 18.773 8.107 5.547 5.12 8.107 11.52 8.107 18.773v485.547h-170.667zM682.667 256v-42.667h-341.333v42.667h341.333zM682.667 384v-42.667h-341.333v42.667h341.333zM512 554.667v-42.667h-170.667v42.667h170.667z" />
<glyph unicode="&#xe930;" glyph-name="new-task" data-tags="new-task" d="M490.667 149.334v554.667h42.667v-554.667h-42.667zM789.333 405.334h-554.667v42.667h554.667v-42.667z" />
<glyph unicode="&#xe931;" glyph-name="navigate-next" data-tags="navigate-next" d="M406.187 667.734l-29.867-29.867 211.627-211.627-211.627-211.2 29.867-29.867 241.493 241.067-241.493 241.493z" />
<glyph unicode="&#xe932;" glyph-name="navigate-before" data-tags="navigate-before" d="M617.813 667.734l29.867-29.867-211.627-211.627 211.627-211.2-29.867-29.867-241.493 241.067 241.493 241.493z" />
<glyph unicode="&#xe931;" glyph-name="right" data-tags="navigate-next" d="M406.187 667.734l-29.867-29.867 211.627-211.627-211.627-211.2 29.867-29.867 241.493 241.067-241.493 241.493z" />
<glyph unicode="&#xe932;" glyph-name="left" data-tags="navigate-before" d="M617.813 667.734l29.867-29.867-211.627-211.627 211.627-211.2-29.867-29.867-241.493 241.067 241.493 241.493z" />
<glyph unicode="&#xe933;" glyph-name="move" data-tags="move" d="M309.333 106.667l-29.44 29.44 84.053 84.053c-76.8 1.28-142.507 26.453-197.12 75.947-54.187 49.493-81.493 111.787-81.493 187.307s25.6 135.68 76.373 186.88c51.2 50.773 113.493 76.373 186.88 76.373h101.547v-40.533h-101.547c-61.44 0-113.92-21.76-157.44-65.28s-65.28-96-65.28-157.44 22.187-114.773 66.56-155.307c44.373-40.96 101.547-63.147 171.947-67.413l-84.053 84.053 29.44 29.44 132.693-133.547-132.693-133.547zM896 704v-170.667h-256v170.667h256zM640 746.667c-23.467 0-42.667-19.2-42.667-42.667v-170.667c0-23.467 19.2-42.667 42.667-42.667h256c23.467 0 42.667 19.2 42.667 42.667v170.667c0 23.467-19.2 42.667-42.667 42.667h-256zM597.333 362.667c0 23.467 19.2 42.667 42.667 42.667h256c23.467 0 42.667-19.2 42.667-42.667v-170.667c0-23.467-19.2-42.667-42.667-42.667h-256c-23.467 0-42.667 19.2-42.667 42.667v170.667z" />
<glyph unicode="&#xe934;" glyph-name="more-vert" data-tags="more-vert" d="M542.293 140.8c8.107 8.533 12.373 18.347 12.373 29.867 0 11.947-4.267 22.187-12.373 30.293s-18.347 12.373-30.293 12.373-22.187-4.267-30.293-12.373c-8.107-8.107-12.373-18.347-12.373-30.293 0-11.52 4.267-21.333 12.373-29.867s18.347-12.8 30.293-12.8 22.187 4.267 30.293 12.8zM542.293 396.8c8.107 8.533 12.373 18.347 12.373 29.867 0 11.947-4.267 22.187-12.373 30.293s-18.347 12.373-30.293 12.373-22.187-4.267-30.293-12.373-12.373-18.347-12.373-30.293c0-11.52 4.267-21.333 12.373-29.867s18.347-12.8 30.293-12.8 22.187 4.267 30.293 12.8zM542.293 652.8c8.107 8.533 12.373 18.347 12.373 29.867 0 11.947-4.267 22.187-12.373 30.293s-18.347 12.373-30.293 12.373-22.187-4.267-30.293-12.373c-8.107-8.107-12.373-18.347-12.373-30.293 0-11.52 4.267-21.333 12.373-29.867s18.347-12.8 30.293-12.8 22.187 4.267 30.293 12.8z" />
<glyph unicode="&#xe935;" glyph-name="more-hori" data-tags="more-hori" d="M226.133 396.374c8.533-8.107 18.347-12.373 29.867-12.373 11.947 0 22.187 4.267 30.293 12.373s12.373 18.347 12.373 30.293-4.267 22.187-12.373 30.293c-8.107 8.107-18.347 12.373-30.293 12.373-11.52 0-21.333-4.267-29.867-12.373s-12.8-18.347-12.8-30.293 4.267-22.187 12.8-30.293zM482.133 396.374c8.533-8.107 18.347-12.373 29.867-12.373 11.947 0 22.187 4.267 30.293 12.373s12.373 18.347 12.373 30.293-4.267 22.187-12.373 30.293-18.347 12.373-30.293 12.373c-11.52 0-21.333-4.267-29.867-12.373s-12.8-18.347-12.8-30.293 4.267-22.187 12.8-30.293zM738.133 396.374c8.533-8.107 18.347-12.373 29.867-12.373 11.947 0 22.187 4.267 30.293 12.373s12.373 18.347 12.373 30.293-4.267 22.187-12.373 30.293c-8.107 8.107-18.347 12.373-30.293 12.373-11.52 0-21.333-4.267-29.867-12.373s-12.8-18.347-12.8-30.293 4.267-22.187 12.8-30.293z" />
@ -93,7 +93,7 @@
<glyph unicode="&#xe940;" glyph-name="import" data-tags="import" d="M533.333 21.334v472.747l89.6-89.6 29.867 30.72-140.8 140.8-140.8-140.8 29.867-30.72 89.6 89.6v-472.747h42.667zM789.333 277.334h-128v42.667h117.333c5.973 0 10.667 4.693 10.667 10.667v448c0 5.973-4.693 10.667-10.667 10.667h-533.333c-5.973 0-10.667-4.693-10.667-10.667v-448c0-5.973 4.693-10.667 10.667-10.667h117.333v-42.667h-128c-23.467 0-42.667 19.2-42.667 42.667v469.333c0 23.467 19.2 42.667 42.667 42.667h554.667c23.467 0 42.667-19.2 42.667-42.667v-469.333c0-23.467-19.2-42.667-42.667-42.667z" />
<glyph unicode="&#xe941;" glyph-name="help" data-tags="help" d="M512 42.667c-53.333 0-103.253 10.24-149.76 30.293-46.507 20.48-87.040 47.787-121.6 82.347s-61.867 75.093-82.347 121.6c-20.053 46.507-30.293 96.427-30.293 149.76s10.24 103.253 30.293 149.76c20.48 46.507 47.787 87.040 82.347 121.6s75.093 61.867 121.6 82.347c46.507 20.053 96.427 30.293 149.76 30.293s103.253-10.24 149.76-30.293c46.507-20.48 87.040-47.787 121.6-82.347s61.867-75.093 81.92-121.6c20.053-46.507 30.293-96.427 30.293-149.76s-10.24-103.253-30.293-149.76c-20.48-46.507-47.787-87.040-81.92-121.6s-75.093-61.867-121.6-82.347c-46.507-20.053-96.427-30.293-149.76-30.293zM512 85.334c95.147 0 175.787 32.853 241.92 99.413 66.133 66.133 99.413 146.773 99.413 241.92s-32.853 175.787-99.413 242.347c-66.133 66.133-146.773 98.987-241.92 98.987s-175.787-33.28-242.347-98.987c-66.133-66.133-98.987-146.773-98.987-242.347s33.28-175.787 98.987-241.92c66.133-66.133 146.773-99.413 242.347-99.413zM512 341.334h-42.667c3.413 25.173 9.387 32.427 13.653 42.667 7.68 15.787 36.267 45.653 61.013 68.267 12.8 11.947 23.040 23.893 31.147 34.987s11.52 24.32 11.52 39.68c0 18.347-6.4 34.987-19.2 49.92s-33.28 22.613-61.013 22.613c-23.467 0-41.813-5.973-54.187-17.493-12.8-11.947-22.613-25.6-29.867-40.96l-38.4 16.213c9.813 22.187 25.6 41.387 46.933 58.027s47.36 25.173 77.653 25.173 59.733-9.813 83.627-29.867c23.893-20.053 35.84-46.933 35.84-81.067 0-20.053-4.693-37.547-14.080-52.053-9.387-14.933-23.467-32-42.667-51.2-18.347-17.92-30.72-31.573-40.533-41.813-8.107-9.813-18.347-20.48-19.2-42.667zM520.533 225.707c-8.533-8.107-18.773-12.373-30.293-12.373s-21.76 4.267-29.867 12.373-12.373 17.92-12.373 29.867c0 12.8 4.267 23.040 12.373 31.147s17.92 12.373 29.867 12.373 21.76-4.267 30.293-12.373c8.533-8.107 12.8-18.347 12.8-31.147 0-11.947-4.267-21.76-12.8-29.867z" />
<glyph unicode="&#xe942;" glyph-name="help-s" data-tags="help-s" d="M514.987 240.64c7.253 0 13.653 2.56 18.773 7.68s7.68 11.52 7.68 18.773-2.56 13.653-7.68 18.773c-5.12 5.12-11.52 7.68-18.773 7.68s-13.653-2.56-18.773-7.68c-5.12-5.12-7.68-11.52-7.68-18.773s2.56-13.653 7.68-18.773c5.12-5.12 11.52-7.68 18.773-7.68zM496.64 357.547h33.28c0.853 17.92 3.413 30.72 7.68 37.973 4.267 7.68 11.093 16.213 20.48 26.027 21.333 20.48 35.413 37.547 42.24 50.347s10.24 26.453 10.24 40.533c0 27.307-8.96 50.773-26.453 69.973s-40.533 29.013-68.693 29.013c-22.187 0-42.667-5.973-61.44-18.347-19.2-11.947-32.853-28.587-41.813-48.64l32-14.507c8.107 18.773 17.92 31.573 29.867 38.4s24.747 9.813 38.827 9.813c20.48 0 37.12-5.973 48.64-17.493 11.947-11.947 17.92-26.88 17.92-44.8 0-14.080-4.267-26.027-13.227-36.267-8.533-9.813-18.773-20.48-29.867-31.573-15.36-14.933-25.6-29.013-31.147-42.667s-8.107-29.44-8.107-48.213zM512.427 120.747c-41.813 0-81.493 8.107-118.613 23.893s-69.547 37.973-97.707 65.707c-27.733 27.733-49.92 60.587-65.707 97.707s-23.893 76.8-23.893 118.613 8.107 82.347 23.893 119.040c15.787 36.693 37.973 69.12 65.707 97.28 27.733 27.733 60.587 49.92 97.707 65.707s76.8 23.893 118.613 23.893 82.347-8.107 119.040-23.893 69.12-37.973 97.28-65.707c27.733-27.733 49.92-60.16 65.707-97.28 15.787-36.693 23.893-76.373 23.893-119.040s-8.107-81.493-23.893-118.613c-15.787-37.12-37.973-69.547-65.707-97.707-27.733-27.733-60.16-49.92-97.28-65.707-36.693-15.787-76.373-23.893-119.040-23.893zM512.427 149.334c77.227 0 142.507 26.88 196.267 81.067 53.76 53.76 81.067 119.467 81.067 196.267s-26.88 142.507-81.067 196.267c-53.76 53.76-119.467 81.067-196.267 81.067s-142.507-26.88-196.267-81.067c-53.76-53.76-81.067-119.467-81.067-196.267s26.88-142.507 81.067-196.267c53.76-53.76 119.467-81.067 196.267-81.067z" />
<glyph unicode="&#xe943;" glyph-name="hamburger-menu" data-tags="hamburger-menu" d="M853.333 597.334h-682.667v-42.667h682.667v42.667zM853.333 298.667h-682.667v-42.667h682.667v42.667z" />
<glyph unicode="&#xe943;" glyph-name="hamburger" data-tags="hamburger-menu" d="M853.333 597.334h-682.667v-42.667h682.667v42.667zM853.333 298.667h-682.667v-42.667h682.667v42.667z" />
<glyph unicode="&#xe944;" glyph-name="hamburger-big" data-tags="hamburger-big" d="M597.333 661.334h-426.667v-42.667h426.667v42.667zM853.333 447.574h-682.667v-42.667h682.667v42.667zM597.333 234.667h-426.667v-42.667h426.667v42.667z" />
<glyph unicode="&#xe945;" glyph-name="grid-view" data-tags="grid-view" d="M170.667 469.334v256c0 23.467 19.2 42.667 42.667 42.667h256v-298.667h-298.667zM213.333 85.334c-23.467 0-42.667 19.2-42.667 42.667v256h298.667v-298.667h-256zM554.667 469.334v298.667h256c23.467 0 42.667-19.2 42.667-42.667v-256h-298.667zM554.667 85.334v298.667h298.667v-256c0-23.467-19.2-42.667-42.667-42.667h-256zM213.333 512h213.333v213.333h-213.333v-213.333zM597.333 512h213.333v213.333h-213.333v-213.333zM597.333 128h213.333v213.333h-213.333v-213.333zM213.333 128h213.333v213.333h-213.333v-213.333z" />
<glyph unicode="&#xe946;" glyph-name="folder" data-tags="folder" d="M876.8 641.707c-13.227 13.227-29.867 19.627-49.493 19.627h-314.027l-42.667 42.667h-273.067c-19.627 0-36.267-6.4-49.493-19.627s-19.627-29.44-19.627-48.64v-417.28c0-20.053 6.4-36.267 19.627-49.493s29.867-19.627 49.493-19.627h629.333c20.053 0 36.267 6.4 49.493 19.627s19.627 29.867 19.627 49.493v373.76c0 20.053-6.4 36.267-19.627 49.493h0.427zM853.76 218.88c0-7.68-2.56-14.080-7.253-19.2s-11.52-7.253-19.2-7.253h-630.187c-7.68 0-14.080 2.56-19.2 7.253-5.12 5.12-7.253 11.52-7.253 19.2v416.853c0 7.253 2.56 13.227 7.253 17.92s11.52 7.68 19.2 7.68h255.147l42.667-42.667h331.947c7.68 0 14.080-2.56 19.2-7.253s7.253-11.52 7.253-19.2v-373.76z" />
@ -117,9 +117,9 @@
<glyph unicode="&#xe958;" glyph-name="courses" data-tags="courses" d="M506.027 745.387c2.987 1.707 6.827 1.707 9.813 0l368.64-214.613c7.253-3.84 10.667-11.093 10.667-18.773v-170.667c0-11.947-8.96-21.333-20.053-21.333s-20.053 9.387-20.053 21.333v134.4l-80.64-46.933v-172.8c0-8.107-4.267-15.787-11.093-19.2l-242.347-128c-5.547-2.987-12.373-2.987-17.92 0l-242.347 128c-6.827 3.84-11.093 11.093-11.093 19.2v172.8l-110.933 64.427c-14.080 8.107-14.080 29.44 0 37.547l368.64 214.613zM190.72 512l321.707-187.307 321.707 187.307-321.707 187.307-321.707-187.307zM734.72 405.334l-217.6-126.72c-2.987-1.707-6.827-1.707-9.813 0l-217.6 126.72v-136.107l222.293-117.333 222.293 117.333v136.107z" />
<glyph unicode="&#xe959;" glyph-name="comments" data-tags="comments" d="M128 62.294v659.2c0 20.053 6.4 36.267 19.627 49.493s29.867 19.627 49.493 19.627h629.333c20.053 0 36.267-6.4 49.493-19.627s19.627-29.867 19.627-49.493v-458.667c0-20.053-6.4-36.267-19.627-49.493s-29.867-19.627-49.493-19.627h-567.467l-130.987-131.413zM170.667 165.974l70.4 70.4h585.387c7.68 0 14.080 2.56 19.2 7.68s7.253 11.52 7.253 19.2v458.24c0 7.68-2.56 14.080-7.253 19.2-5.12 5.12-11.52 7.68-19.2 7.68h-629.333c-7.68 0-14.080-2.56-19.2-7.68s-7.68-11.52-7.68-19.2v-555.52zM170.667 721.494v0zM725.333 535.040h-426.667v42.667h426.667v-42.667zM725.333 407.040h-426.667v42.667h426.667v-42.667z" />
<glyph unicode="&#xe95a;" glyph-name="collapse" data-tags="collapse" d="M810.667 426.667v42.667h-256v256h-42.667v-298.667h298.667zM823.040 768l-283.733-283.733 30.293-30.293 283.733 283.733-30.293 30.293zM213.333 426.667v-42.667h256v-256h42.667v298.667h-298.667zM453.973 399.36l-283.733-283.733 30.293-30.293 283.733 283.733-30.293 30.293z" />
<glyph unicode="&#xe95b;" glyph-name="close-remove" data-tags="close-remove" d="M273.067 157.867l-29.867 29.867 238.933 238.933-238.933 238.933 29.867 29.867 238.933-238.933 238.933 238.933 29.867-29.867-238.933-238.933 238.933-238.933-29.867-29.867-238.933 238.933-238.933-238.933z" />
<glyph unicode="&#xe95c;" glyph-name="close-remove-small" data-tags="close-remove-small" d="M331.093 637.867l-30.293-30.293 392.107-392.107 30.293 30.293-392.107 392.107zM300.8 245.76l30.293-30.293 392.107 392.107-30.293 30.293-392.107-392.107z" />
<glyph unicode="&#xe95d;" glyph-name="close-hide" data-tags="close-hide" d="M512 554.667l213.333-225.28-28.16-30.72-185.173 195.413-185.173-195.413-28.16 30.72 213.333 225.28z" />
<glyph unicode="&#xe95b;" glyph-name="close" data-tags="close-remove" d="M273.067 157.867l-29.867 29.867 238.933 238.933-238.933 238.933 29.867 29.867 238.933-238.933 238.933 238.933 29.867-29.867-238.933-238.933 238.933-238.933-29.867-29.867-238.933 238.933-238.933-238.933z" />
<glyph unicode="&#xe95c;" glyph-name="close-small" data-tags="close-remove-small" d="M331.093 637.867l-30.293-30.293 392.107-392.107 30.293 30.293-392.107 392.107zM300.8 245.76l30.293-30.293 392.107 392.107-30.293 30.293-392.107-392.107z" />
<glyph unicode="&#xe95d;" glyph-name="up" data-tags="close-hide" d="M512 554.667l213.333-225.28-28.16-30.72-185.173 195.413-185.173-195.413-28.16 30.72 213.333 225.28z" />
<glyph unicode="&#xe95e;" glyph-name="checkllist" data-tags="checkllist" d="M281.6 541.44l-68.267 68.267 30.293 30.293 37.973-38.4 123.733 123.733 30.293-30.293-154.027-153.6zM810.667 640h-298.667v-42.667h298.667v42.667zM810.667 256h-298.667v-42.667h298.667v42.667zM324.267 298.667c35.413 0 64-28.587 64-64s-28.587-64-64-64-64 28.587-64 64 28.587 64 64 64zM324.267 341.334c-58.88 0-106.667-47.787-106.667-106.667s47.787-106.667 106.667-106.667 106.667 47.787 106.667 106.667-47.787 106.667-106.667 106.667z" />
<glyph unicode="&#xe95f;" glyph-name="check" data-tags="check" d="M407.467 200.96l-212.053 211.2 30.72 31.147 181.333-181.333 390.4 390.4 30.72-30.72-421.547-420.267z" />
<glyph unicode="&#xe960;" glyph-name="card-view" data-tags="card-view" d="M832 704h-640c-23.467 0-42.667-19.2-42.667-42.667v-469.333c0-23.467 19.2-42.667 42.667-42.667h640c23.467 0 42.667 19.2 42.667 42.667v469.333c0 23.467-19.2 42.667-42.667 42.667zM661.333 661.334v-128h-128v128h128zM533.333 490.667h128v-128h-128v128zM490.667 362.667h-128v128h128v-128zM490.667 661.334v-128h-128v128h128zM192 661.334h128v-128h-128v128zM192 490.667h128v-128h-128v128zM192 192v128h128v-128h-128zM362.667 192v128h128v-128h-128zM533.333 192v128h128v-128h-128zM832 192h-128v128h128v-128zM832 362.667h-128v128h128v-128zM832 533.334h-128v128h128v-128z" />
@ -146,4 +146,8 @@
<glyph unicode="&#xe975;" glyph-name="file-pdf" data-tags="file-pdf" d="M234.667 64c-29.867 0-55.111 10.313-75.733 30.933s-30.933 45.867-30.933 75.733v554.667c0 29.867 10.311 55.111 30.933 75.733s45.867 30.933 75.733 30.933h554.667c29.867 0 55.113-10.311 75.733-30.933s30.933-45.867 30.933-75.733v-554.667c0-29.867-10.313-55.113-30.933-75.733s-45.867-30.933-75.733-30.933h-554.667zM234.667 106.667h554.667c17.779 0 32.883 6.229 45.312 18.688 12.459 12.429 18.688 27.533 18.688 45.312v554.667c0 17.778-6.229 32.882-18.688 45.312-12.429 12.459-27.533 18.688-45.312 18.688h-554.667c-17.778 0-32.882-6.229-45.312-18.688-12.459-12.43-18.688-27.534-18.688-45.312v-554.667c0-17.779 6.229-32.883 18.688-45.312 12.43-12.459 27.534-18.688 45.312-18.688zM256 330.308v203.025h76.134c15.597 0 28.683-2.91 39.257-8.725 10.64-5.815 18.67-13.811 24.089-23.987 5.486-10.112 8.228-21.611 8.228-34.5 0-13.018-2.743-24.585-8.228-34.697s-13.581-18.074-24.288-23.889c-10.706-5.751-23.891-8.627-39.554-8.627h-50.459v30.238h45.502c9.12 0 16.588 1.583 22.404 4.757 5.816 3.17 10.112 7.535 12.887 13.086 2.842 5.551 4.263 11.93 4.263 19.132s-1.421 13.547-4.263 19.034c-2.776 5.487-7.104 9.749-12.986 12.787-5.816 3.106-13.317 4.659-22.503 4.659h-33.705v-172.292h-36.779zM504.452 330.308h-68.796v203.025h70.187c20.156 0 37.47-4.066 51.942-12.194 14.541-8.064 25.711-19.661 33.51-34.795 7.795-15.134 11.695-33.242 11.695-54.327 0-21.146-3.93-39.322-11.797-54.524-7.795-15.198-19.063-26.863-33.805-34.991-14.669-8.128-32.316-12.194-52.937-12.194zM472.435 362.129h30.234c14.144 0 25.941 2.577 35.392 7.731 9.451 5.222 16.555 12.988 21.312 23.3 4.757 10.372 7.138 23.326 7.138 38.857s-2.381 28.42-7.138 38.665c-4.757 10.308-11.797 18.010-21.116 23.095-9.25 5.158-20.753 7.735-34.496 7.735h-31.326v-139.383zM637.935 330.308v203.025h130.065v-30.831h-93.286v-55.117h84.365v-30.831h-84.365v-86.246h-36.779z" />
<glyph unicode="&#xe976;" glyph-name="save" data-tags="save" d="M707.2 789.125h-467.627c-19.627 0-35.84-6.4-49.067-19.627s-19.627-29.44-19.627-49.067v-544.854c0-19.627 6.4-35.84 19.627-49.067s29.44-19.627 49.067-19.627h544.853c19.627 0 35.84 6.4 49.067 19.627s19.627 29.44 19.627 49.067v467.628l-145.92 145.92zM298.453 746.458h298.667v-106.667c0-11.947-9.387-21.333-21.333-21.333h-256c-11.947 0-21.333 9.387-21.333 21.333v106.667zM810.453 175.578c0-7.68-2.56-14.080-7.253-18.773-5.12-5.12-11.093-7.253-18.773-7.253h-544.853c-7.68 0-14.080 2.56-18.773 7.253-5.12 5.12-7.253 11.093-7.253 18.773v544.428c0 7.68 2.56 14.080 7.253 18.773 5.12 5.12 11.093 7.253 18.773 7.253h16.213v-127.573c0-23.467 19.2-42.667 42.667-42.667h298.667c23.467 0 42.667 19.2 42.667 42.667v128h49.067l121.6-121.6v-449.281zM511.787 447.791c-23.467 0-43.52-8.533-60.16-25.173s-25.173-36.693-25.173-60.16c0-23.467 8.533-43.52 25.173-60.16s36.693-25.173 60.16-25.173c23.467 0 43.52 8.533 60.16 25.173s25.173 36.693 25.173 60.16c0 23.467-8.533 43.52-25.173 60.16s-36.693 25.173-60.16 25.173z" />
<glyph unicode="&#xe977;" glyph-name="archived" data-tags="archived" d="M240 106.667c-19.911 0-36.437 6.571-49.579 19.712-13.17 13.171-19.755 29.709-19.755 49.621v457.6c0 7.111 0.882 13.696 2.645 19.755 1.792 6.030 4.466 11.534 8.021 16.512l53.333 62.933c4.978 4.978 10.667 8.533 17.067 10.667s13.155 3.2 20.267 3.2h480c7.113 0 13.867-0.711 20.267-2.133s12.087-5.333 17.067-11.733l51.2-62.933c4.979-4.978 8.363-10.482 10.155-16.512 1.762-6.059 2.645-12.643 2.645-19.755v-457.6c0-19.913-6.571-36.45-19.712-49.621-13.171-13.141-29.709-19.712-49.621-19.712h-544zM230.4 661.333h563.2l-36.267 42.667h-490.667l-36.267-42.667zM213.333 618.667v-442.667c0-7.113 2.674-13.325 8.021-18.645 5.319-5.346 11.534-8.021 18.645-8.021h544c7.113 0 13.325 2.675 18.645 8.021 5.346 5.321 8.021 11.533 8.021 18.645v442.667h-597.333zM298.667 277.333h426.667v-42.667h-426.667v42.667z" />
<glyph unicode="&#xe978;" glyph-name="star" data-tags="star" horiz-adv-x="983" d="M391.569 280.412l99.951 76.407 99.951-76.407-37.482 125.968 93.704 66.077h-116.609l-39.563 128.033-39.563-128.033h-116.611l93.706-66.077-37.483-125.968zM312.039 169.058l67.196 220.164-174.435 124.539h217.203l69.517 228.739 69.517-228.739h217.203l-174.436-124.539 67.195-220.164-179.479 135.34-179.481-135.34z" />
<glyph unicode="&#xe979;" glyph-name="star-filled" data-tags="star-filled" horiz-adv-x="983" d="M778.24 513.942h-217.088l-69.632 228.558-69.632-228.558h-217.088l174.49-124.518-67.174-220.365 179.405 135.168 179.405-135.168-67.174 220.365 174.49 124.518z" />
<glyph unicode="&#xe97a;" glyph-name="marvinjs" data-tags="marvinjs" horiz-adv-x="983" d="M491.52 777.123l285.639-160.672v-321.343l-285.639-160.674-285.639 160.674v321.343l285.639 160.672zM819.2 640.1l-327.68 184.32-327.68-184.32v-368.642l327.68-184.32 327.68 184.32v368.642zM484.835 688.801l203.817-124.109-22.282-34.736-203.817 124.11 22.282 34.734zM344.375 578.66v-245.762h-42.041v245.762h42.041zM688.652 346.866l-203.817-124.109-22.282 34.734 203.817 124.109 22.282-34.734z" />
<glyph unicode="&#xe97b;" glyph-name="sequence-editor" data-tags="sequence-editor" horiz-adv-x="983" d="M317.364 734.104c46.285 29.082 99.94 46.285 154.417 49.562 11.469 0.819 20.070 10.24 19.251 21.709-0.819 11.059-9.421 19.661-21.709 19.251-61.438-3.686-121.649-22.938-173.668-55.706s-95.846-78.643-125.747-132.301c-30.31-53.658-46.285-114.687-47.104-176.127s14.336-122.88 43.418-177.357c3.686-6.963 10.65-10.65 18.022-10.65 3.277 0 6.554 0.819 9.83 2.458 9.83 5.325 13.926 17.613 8.602 27.853-25.805 48.333-38.912 102.81-38.502 157.696s15.155 108.952 41.779 156.876c26.624 47.923 65.536 88.474 111.821 117.555l-0.41-0.819zM285.825 344.166c2.867 0 5.734 0.41 8.192 1.638 10.24 4.506 15.155 16.794 10.24 27.034-13.107 29.901-19.251 62.669-17.613 95.437 2.048 32.768 11.469 64.717 28.262 92.568 16.794 28.262 40.141 52.019 67.584 69.222 27.441 17.203 59.39 27.853 91.748 30.31 11.469 0.819 19.661 10.65 18.842 22.118s-11.878 19.661-22.118 18.842c-38.912-3.277-77.003-15.974-110.18-36.454-33.178-20.89-61.030-49.562-81.101-83.149s-31.539-72.088-33.997-111 4.915-78.643 20.89-114.278c3.277-7.782 11.059-12.288 18.842-12.288h0.41zM449.253 385.946c-9.83 5.734-22.118 2.867-28.262-6.963-5.734-9.83-2.867-22.118 6.963-28.262 18.022-11.059 38.912-16.794 59.802-17.613 1.229 0 2.048 0 3.277 0 20.070 0 39.731 4.915 57.344 14.336 9.83 5.325 13.926 17.613 8.602 27.853s-17.613 13.926-27.853 8.602c-12.288-6.554-26.624-9.83-40.55-9.421-13.926 0-27.853 4.506-39.731 11.469h0.41zM386.996 456.397c0 0 2.867 0 4.096 0 9.421 0 18.022 6.554 20.068 16.384 3.277 15.974 11.059 30.31 22.528 42.189 11.469 11.469 26.214 19.251 42.189 22.528 11.059 2.048 18.432 13.106 16.384 24.165s-13.107 18.022-24.166 16.384c-23.757-4.506-45.875-16.384-63.076-33.586-17.203-17.203-29.082-38.912-33.997-63.078-2.048-11.059 4.915-21.709 15.974-24.166v-0.819zM661.836 307.302c3.686-2.458 7.782-4.096 11.878-4.096 6.144 0 12.698 2.867 16.384 8.602 35.226 48.742 51.61 108.544 45.466 168.755-1.229 11.059-10.24 18.842-22.528 18.432-11.059-1.229-19.251-11.059-18.432-22.528 4.915-49.971-8.602-99.942-38.093-140.493-6.554-9.011-4.506-22.118 4.506-28.672h0.819zM474.649 252.006c-36.045 2.867-70.449 15.565-99.94 36.045-9.421 6.554-22.118 4.096-28.672-5.325s-4.096-22.118 5.325-28.672c35.635-24.576 77.003-39.322 120.011-43.008 6.554-0.41 13.107-0.819 19.661-0.819 36.454 0 72.499 8.192 105.677 23.757 10.24 4.915 14.746 17.203 9.83 27.443s-17.203 14.746-27.443 9.83c-32.358-15.565-68.813-22.118-104.448-19.251zM643.404 746.802c57.344-29.901 104.038-75.776 135.168-132.301 3.686-6.963 10.65-10.65 18.022-10.65 3.277 0 6.963 0.819 9.83 2.458 9.83 5.325 13.517 18.022 8.192 27.853-35.226 63.898-87.654 115.098-151.962 149.094-9.83 5.325-22.118 1.229-27.443-8.602s-1.229-22.528 8.602-27.853h-0.41zM837.964 496.538c-11.469-0.819-20.070-10.24-19.251-21.709 3.686-64.307-11.469-127.386-43.418-183.091s-79.462-100.352-136.806-129.024c-57.344-28.672-121.651-39.731-185.139-32.358-63.486 7.373-123.288 33.587-172.44 74.547-8.602 7.373-21.709 6.144-29.082-2.458s-6.144-21.709 2.458-29.082c55.296-46.694 122.47-75.776 194.148-83.968 14.336-1.638 29.082-2.458 43.418-2.458 56.934 0 113.050 13.107 164.659 38.912 64.717 32.358 117.965 82.33 154.010 144.998s53.248 133.53 49.152 206.029c-0.41 11.469-8.602 19.661-21.709 19.251v0.41z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,10 +1,11 @@
@font-face {
font-family: 'SN-icon-font';
src: url('fonts/SN-icon-font.eot?n7qhkp');
src: url('fonts/SN-icon-font.eot?n7qhkp#iefix') format('embedded-opentype'),
url('fonts/SN-icon-font.ttf?n7qhkp') format('truetype'),
url('fonts/SN-icon-font.woff?n7qhkp') format('woff'),
url('fonts/SN-icon-font.svg?n7qhkp#SN-icon-font') format('svg');
src: url('fonts/SN-icon-font.eot?x922k8');
src: url('fonts/SN-icon-font.eot?x922k8#iefix') format('embedded-opentype'),
url('fonts/SN-icon-font.woff2?x922k8') format('woff2'),
url('fonts/SN-icon-font.ttf?x922k8') format('truetype'),
url('fonts/SN-icon-font.woff?x922k8') format('woff'),
url('fonts/SN-icon-font.svg?x922k8#SN-icon-font') format('svg');
font-weight: normal;
font-style: normal;
font-display: block;
@ -25,14 +26,6 @@
-moz-osx-font-smoothing: grayscale;
}
.sn-icon {
font-size: 24px !important;
}
.sn-icon.mini {
font-size: 16px !important;
}
.sn-icon-info:before {
content: "\e900";
}
@ -279,10 +272,10 @@
.sn-icon-drag:before {
content: "\e951";
}
.sn-icon-double-left:before {
.sn-icon-double-navigate-before:before {
content: "\e952";
}
.sn-icon-double-right:before {
.sn-icon-double-navigate-after:before {
content: "\e953";
}
.sn-icon-dot-small:before {
@ -393,3 +386,15 @@
.sn-icon-archived:before {
content: "\e977";
}
.sn-icon-star:before {
content: "\e978";
}
.sn-icon-star-filled:before {
content: "\e979";
}
.sn-icon-marvinjs:before {
content: "\e97a";
}
.sn-icon-sequence-editor:before {
content: "\e97b";
}

2272
yarn.lock

File diff suppressed because it is too large Load diff