Merge branch 'ux-release-1' of https://github.com/biosistemika/scinote-web into zd_SCI_2218_2219

This commit is contained in:
zmagod 2018-04-04 16:06:38 +02:00
commit 0c05c60ebf
77 changed files with 1533 additions and 828 deletions

View file

@ -1,10 +1,11 @@
GIT
remote: https://github.com/biosistemika/canaid
revision: f2000c19b75e66ea929a44cb0575262b7f5fc13e
revision: 943ae9b9801819fd2513f6ab9e1143ad8de523ce
branch: master
specs:
canaid (1.0.1)
canaid (1.0.2)
devise (>= 3.4.1)
docile (>= 1.1.0)
rails (>= 4)
GIT

View file

@ -12,6 +12,7 @@
//= require jquery-ui/widgets/draggable
//= require jquery-ui/widgets/droppable
//= require jquery.ui.touch-punch.min
//= require jquery-ui/effects/effect-slide
//= require jquery.caret.min
//= require jquery.atwho.min
//= require hammer

View file

@ -452,12 +452,12 @@
.find('.form-submit-link')
.css({
'pointer-events': 'auto',
'color': '<%= Constants::COLOR_NERO %>'});
'color': '<%= Constants::COLOR_BLACK %>'});
$(el)
.find("[data-action='edit']")
.css({
'pointer-events': 'auto',
'color': '<%= Constants::COLOR_NERO %>'});
'color': '<%= Constants::COLOR_BLACK %>'});
});
}

View file

@ -43,7 +43,7 @@
var task_button = $("[data-action='complete-task']");
task_button.attr('data-action', 'uncomplete-task');
task_button.find('.btn')
.removeClass('btn-primary').addClass('btn-greyed');
.removeClass('btn-primary').addClass('btn-default');
$('.task-due-date').html(data.module_header_due_date_label);
$('.task-state-label').html(data.module_state_label);
task_button

View file

@ -7,77 +7,7 @@
location.reload();
}
function initImportRecordsModal() {
$('#importRecordsButton').off().on('click', function() {
$('#modal-import-records').modal('show');
_initParseRecordsModal();
});
}
function _initParseRecordsModal() {
$('#form-records-file').on('ajax:success', function(ev, data) {
$('#modal-import-records').modal('hide');
$(data.html).appendTo('body').promise().done(function() {
$('#parse-records-modal')
.modal('show')
.on('hidden.bs.modal', function() {
animateSpinner();
location.reload();
});
repositoryRecordsImporter();
});
}).on('ajax:error', function(ev, data) {
$(this).find('.form-group').addClass('has-error');
$(this).find('.form-group').find('.help-block').remove();
$(this).find('.form-group').append("<span class='help-block'>" +
data.responseJSON.message + '</span>');
});
}
function loadRepositoryTab() {
var param;
$('#repository-tabs a').on("click", function(e) {
e.preventDefault();
var pane = $(this);
$.ajax({
url: $(this).attr("data-url"),
type: "GET",
dataType: "json",
success: function (data) {
var tabBody = $(pane.context.hash).find(".tab-content-body");
tabBody.html(data.html);
pane.tab('show').promise().done(function(el) {
initImportRecordsModal();
RepositoryDatatable.destroy()
RepositoryDatatable.init(el.attr('data-repo-table'));
});
},
error: function (error) {
// TODO
}
});
});
// on page load
if( param = getParam('repository') ){
// load selected tab
$('a[href="#custom_repo_'+param+'"]').click();
}
else {
// load first tab content
$('#repository-tabs a:first').click();
}
// clean tab content
$('a[data-toggle="tab"]').on('hide.bs.tab', function (e) {
$(".tab-content-body").html("");
})
}
$('.create-repository').initializeModal('#create-repo-modal');
$(document).ready(function() {
loadRepositoryTab();
initImportRecordsModal();
$('#create-new-repository').initializeModal('#create-repo-modal');
});
})(window);

View file

@ -47,7 +47,7 @@ var RepositoryDatatable = (function(global) {
originalHeader = $(TABLE_ID + ' thead').children().clone();
viewAssigned = 'assigned';
TABLE = $(TABLE_ID).DataTable({
order: [[2, 'desc']],
order: [[3, 'desc']],
dom: "R<'row'<'col-sm-9-custom toolbar'l><'col-sm-3-custom'f>>tpi",
stateSave: true,
processing: true,
@ -85,6 +85,11 @@ var RepositoryDatatable = (function(global) {
sWidth: '1%'
}, {
targets: 2,
searchable: true,
orderable: true,
sWidth: '1%'
}, {
targets: 3,
render: function(data, type, row) {
return "<a href='" + row.recordInfoUrl + "'" +
"class='record-info-link'>" + data + '</a>';
@ -255,15 +260,18 @@ var RepositoryDatatable = (function(global) {
case 'assigned':
val = -2;
break;
case 'row-name':
case 'row-id':
val = -3;
break;
case 'added-by':
break
case 'row-name':
val = -4;
break;
case 'added-on':
case 'added-by':
val = -5;
break;
case 'added-on':
val = -6;
break;
default:
val = th.attr('id');
}

View file

@ -0,0 +1,38 @@
(function() {
'use strict';
function initImportRecordsModal() {
$('#importRecordsButton').off().on('click', function() {
$('#modal-import-records').modal('show');
_initParseRecordsModal();
});
}
function _initParseRecordsModal() {
$('#form-records-file').on('ajax:success', function(ev, data) {
$('#modal-import-records').modal('hide');
$(data.html).appendTo('body').promise().done(function() {
$('#parse-records-modal')
.modal('show')
.on('hidden.bs.modal', function() {
animateSpinner();
location.reload();
});
repositoryRecordsImporter();
});
}).on('ajax:error', function(ev, data) {
$(this).find('.form-group').addClass('has-error');
$(this).find('.form-group').find('.help-block').remove();
$(this).find('.form-group').append("<span class='help-block'>" +
data.responseJSON.message + '</span>');
});
}
function initialzerRepositoryTable() {
initImportRecordsModal();
RepositoryDatatable.destroy();
RepositoryDatatable.init('#' + $('.repository-table table').attr('id'));
}
$(document).ready(initialzerRepositoryTable);
})()

View file

@ -0,0 +1,35 @@
(function(global) {
'use strict';
global.SideBarToggle = (function() {
function show() {
$('#sideBarLeft').show();
$('#sideBarRight').hide();
$('#sidebar-wrapper').show(
'slide', { direction: 'right', easing: 'linear' }, 400
);
$('#wrapper').css('paddingLeft', '280px');
$('.navbar-secondary').css(
{ 'margin-left': '-280px', 'padding-left': '280px' }
);
}
function hide() {
$('#sideBarLeft').hide();
$('#sideBarRight').show();
$('#sidebar-wrapper').hide(
'slide', { direction: 'left', easing: 'linear'}, 400
);
$('#wrapper').css('paddingLeft', '0');
$('.navbar-secondary').css({
'margin-left': '0',
'padding-left': '0'
});
}
return Object.freeze({
show: show,
hide: hide
})
})();
})(window);

View file

@ -9,6 +9,8 @@
*= require introjs
*= stub reports_pdf
*/
@import "constants";
@import "bootstrap-sprockets";
@import "bootstrap";
@import "bootstrap-datetimepicker";

View file

@ -1,54 +1,35 @@
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,400italic&subset=latin,latin-ext);
//==============================================================================
// Colors
//==============================================================================
// Theme colors
$color-theme-primary: #41B0E0;
$color-theme-secondary: #8fd13f;
$color-theme-dark: #6d6e71;
// Grayscale colors
$color-border: #DDDDDD;
$color-list-separator: #BDC3C7;
$color-white: #fff;
$color-alabaster: #fcfcfc;
$color-snow: #f9f9f9;
$color-wild-sand: #f5f5f5;
$color-concrete: #f2f2f2;
$color-gallery: #eee;
$color-gainsboro: #e3e3e3;
$color-alto: #d2d2d2;
$color-silver: #c5c5c5;
$color-dark-gray: #adadad;
$color-silver-chalice: #a0a0a0;
$color-gray: #909088;
$color-dove-gray: #666;
$color-emperor: #555;
$color-mine-shaft: #333;
$color-nero: #262626;
$color-black: #000;
$color-cloud: rgba(0, 0, 0, .1);
$color-gray-light-yadcf: #ccc;
$color-gray-dark-yadcf: #a9a9a9;
// Miscelaneous colors
$color-mystic: #eaeff2;
$color-candlelight: #ffda23;
$color-orange: #ff900b;
$color-saturated-green: #008600;
$color-confirmation-green: #25AE88;
$color-blue-yadcf: #337ab7;
// Theme colors
$brand-default: $color-white;
$brand-primary: #41b0e0;
$brand-success: #5cb85c;
$brand-info: #5bc0de;
$brand-warning: #f0ad4e;
$brand-danger: #d9534f;
$brand-other: #9b59b6;
$brand-extra: #34495e;
$brand-primary-light: #dcedf6;
$brand-success-light: #e2eed8;
$brand-warning-light: #fcf7e4;
$brand-danger-light: #efdfdf;
// Red colors
$color-mojo: #cf4b48;
$color-apple-blossom: #a94442;
$color-milano-red: #a70b05;
// Colors for specific intents
$color-visited-link: #23527c;
// Overlay shade for drag'n dropdown
$color-drag-overlay: rgba(0, 0, 0, .4);
//==============================================================================
// Other
@ -56,3 +37,456 @@ $color-drag-overlay: rgba(0, 0, 0, .4);
// Some big value which is still supported by all browsers
$infinity: 9999999;
//==============================================================================
// Bootstrap
//==============================================================================
// Grayscale Colors in bootstrap
$gray-darker: $color-black;
$gray-dark: $color-emperor;
$gray: $color-emperor;
$gray-light: $color-dove-gray;
$gray-lighter: $color-concrete;
// Scaffolding
$body-bg: $color-concrete;
$text-color: $color-emperor;
$link-color: $brand-primary;
$link-hover-color: darken($link-color, 15%);
$link-hover-decoration: underline;
// Typography
$font-family-sans-serif: "Open Sans", Arial, Helvetica, sans-serif;
$font-family-serif: Georgia, "Times New Roman", Times, serif;
$font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
$font-family-base: $font-family-sans-serif;
$font-size-base: 14px;
$font-size-large: ceil(($font-size-base * 1.1)); //16px
$font-size-small: ceil(($font-size-base * .9)); //13px
$font-size-h1: floor(($font-size-base * 2.6)); //36px
$font-size-h2: floor(($font-size-base * 2.15)); //30px
$font-size-h3: ceil(($font-size-base * 1.7)); //24px
$font-size-h4: ceil(($font-size-base * 1.25)); //18px
$font-size-h5: $font-size-base; //14px
$font-size-h6: ceil(($font-size-base * .85)); //12px
$line-height-base: 1.428571429;
$line-height-computed: floor(($font-size-base * $line-height-base));
$headings-font-family: inherit;
$headings-font-weight: 500;
$headings-line-height: 1.1;
$headings-color: inherit;
// // Iconography
// $icon-font-path: "../fonts/";
// $icon-font-name: "glyphicons-halflings-regular";
// $icon-font-svg-id: "glyphicons_halflingsregular";
// Components
$padding-base-vertical: 6px;
$padding-base-horizontal: 12px;
$padding-large-vertical: 10px;
$padding-large-horizontal: 16px;
$padding-small-vertical: 5px;
$padding-small-horizontal: 10px;
$padding-xs-vertical: 1px;
$padding-xs-horizontal: 5px;
$line-height-large: 1.3333333;
$line-height-small: 1.5;
$border-radius-base: 4px;
$border-radius-large: 6px;
$border-radius-small: 3px;
$component-active-color: $color-white;
$component-active-bg: $brand-primary;
$caret-width-base: 4px;
$caret-width-large: 5px;
// // Tables
// $table-cell-padding: 8px;
// $table-condensed-cell-padding: 5px;
// $table-bg: transparent;
// $table-bg-accent: #f9f9f9;
// $table-bg-hover: #f5f5f5;
// $table-bg-active: $table-bg-hover;
// $table-border-color: #ddd;
// Buttons
$btn-font-weight: normal;
$btn-default-color: $gray-dark;
$btn-default-bg: $brand-default;
$btn-default-border: $color-silver;
$btn-primary-color: $color-white;
$btn-primary-bg: $brand-primary;
$btn-primary-border: darken($btn-primary-bg, 5%);
$btn-success-color: $color-white;
$btn-success-bg: $brand-success;
$btn-success-border: darken($btn-success-bg, 5%);
$btn-info-color: $color-white;
$btn-info-bg: $brand-info;
$btn-info-border: darken($btn-info-bg, 5%);
$btn-warning-color: $color-white;
$btn-warning-bg: $brand-warning;
$btn-warning-border: darken($btn-warning-bg, 5%);
$btn-danger-color: $color-white;
$btn-danger-bg: $brand-danger;
$btn-danger-border: darken($btn-danger-bg, 5%);
$btn-link-disabled-color: $gray-light;
$btn-border-radius-base: $border-radius-base;
$btn-border-radius-large: $border-radius-large;
$btn-border-radius-small: $border-radius-small;
// // Forms
// $input-bg: #fff;
// $input-bg-disabled: $gray-lighter;
// $input-color: $gray;
// $input-border: #ccc;
// $input-border-radius: $border-radius-base;
// $input-border-radius-large: $border-radius-large;
// $input-border-radius-small: $border-radius-small;
// $input-border-focus: #66afe9;
// $input-color-placeholder: #999;
// $input-height-base: ($line-height-computed + ($padding-base-vertical * 2) + 2);
// $input-height-large: (ceil($font-size-large * $line-height-large) + ($padding-large-vertical * 2) + 2);
// $input-height-small: (floor($font-size-small * $line-height-small) + ($padding-small-vertical * 2) + 2);
// $form-group-margin-bottom: 15px;
// $legend-color: $gray-dark;
// $legend-border-color: #e5e5e5;
// $input-group-addon-bg: $gray-lighter;
// $input-group-addon-border-color: $input-border;
// $cursor-disabled: not-allowed;
//
// // Dropdowns
// $dropdown-bg: #fff;
// $dropdown-border: rgba(0,0,0,.15);
// $dropdown-fallback-border: #ccc;
// $dropdown-divider-bg: #e5e5e5;
// $dropdown-link-color: $gray-dark;
// $dropdown-link-hover-color: darken($gray-dark, 5%);
// $dropdown-link-hover-bg: #f5f5f5;
// $dropdown-link-active-color: $component-active-color;
// $dropdown-link-active-bg: $component-active-bg;
// $dropdown-link-disabled-color: $gray-light;
// $dropdown-header-color: $gray-light;
// $dropdown-caret-color: #000;
//
// // Media queries breakpoints
// $screen-xs: 480px;
// $screen-xs-min: $screen-xs;
// $screen-phone: $screen-xs-min;
// $screen-sm: 768px;
// $screen-sm-min: $screen-sm;
// $screen-tablet: $screen-sm-min;
// $screen-md: 992px;
// $screen-md-min: $screen-md;
// $screen-desktop: $screen-md-min;
// $screen-lg: 1200px;
// $screen-lg-min: $screen-lg;
// $screen-lg-desktop: $screen-lg-min;
// $screen-xs-max: ($screen-sm-min - 1);
// $screen-sm-max: ($screen-md-min - 1);
// $screen-md-max: ($screen-lg-min - 1);
//
// // Grid system
// $grid-columns: 12;
// $grid-gutter-width: 30px;
// $grid-float-breakpoint: $screen-sm-min;
// $grid-float-breakpoint-max: ($grid-float-breakpoint - 1);
//
// // Container sizes
// $container-tablet: (720px + $grid-gutter-width);
// $container-sm: $container-tablet;
// $container-desktop: (940px + $grid-gutter-width);
// $container-md: $container-desktop;
// $container-large-desktop: (1140px + $grid-gutter-width);
// $container-lg: $container-large-desktop;
//
// // Navbar
// $navbar-height: 50px;
// $navbar-margin-bottom: $line-height-computed;
// $navbar-border-radius: $border-radius-base;
// $navbar-padding-horizontal: floor(($grid-gutter-width / 2));
// $navbar-padding-vertical: (($navbar-height - $line-height-computed) / 2);
// $navbar-collapse-max-height: 340px;
// $navbar-default-color: #777;
// $navbar-default-bg: #f8f8f8;
// $navbar-default-border: darken($navbar-default-bg, 6.5%);
// $navbar-default-link-color: #777;
// $navbar-default-link-hover-color: #333;
// $navbar-default-link-hover-bg: transparent;
// $navbar-default-link-active-color: #555;
// $navbar-default-link-active-bg: darken($navbar-default-bg, 6.5%);
// $navbar-default-link-disabled-color: #ccc;
// $navbar-default-link-disabled-bg: transparent;
// $navbar-default-brand-color: $navbar-default-link-color;
// $navbar-default-brand-hover-color: darken($navbar-default-brand-color, 10%);
// $navbar-default-brand-hover-bg: transparent;
// $navbar-default-toggle-hover-bg: #ddd;
// $navbar-default-toggle-icon-bar-bg: #888;
// $navbar-default-toggle-border-color: #ddd;
//
// // Inverted navbar
// $navbar-inverse-color: lighten($gray-light, 15%);
// $navbar-inverse-bg: #222;
// $navbar-inverse-border: darken($navbar-inverse-bg, 10%);
// $navbar-inverse-link-color: lighten($gray-light, 15%);
// $navbar-inverse-link-hover-color: #fff;
// $navbar-inverse-link-hover-bg: transparent;
// $navbar-inverse-link-active-color: $navbar-inverse-link-hover-color;
// $navbar-inverse-link-active-bg: darken($navbar-inverse-bg, 10%);
// $navbar-inverse-link-disabled-color: #444;
// $navbar-inverse-link-disabled-bg: transparent;
// $navbar-inverse-brand-color: $navbar-inverse-link-color;
// $navbar-inverse-brand-hover-color: #fff;
// $navbar-inverse-brand-hover-bg: transparent;
// $navbar-inverse-toggle-hover-bg: #333;
// $navbar-inverse-toggle-icon-bar-bg: #fff;
// $navbar-inverse-toggle-border-color: #333;
//
// // Navs
// $nav-link-padding: 10px 15px;
// $nav-link-hover-bg: $gray-lighter;
// $nav-disabled-link-color: $gray-light;
// $nav-disabled-link-hover-color: $gray-light;
//
// // Tabs
// $nav-tabs-border-color: #ddd;
// $nav-tabs-link-hover-border-color: $gray-lighter;
// $nav-tabs-active-link-hover-bg: $body-bg;
// $nav-tabs-active-link-hover-color: $gray;
// $nav-tabs-active-link-hover-border-color: #ddd;
// $nav-tabs-justified-link-border-color: #ddd;
// $nav-tabs-justified-active-link-border-color: $body-bg;
//
// // Pills
// $nav-pills-border-radius: $border-radius-base;
// $nav-pills-active-link-hover-bg: $component-active-bg;
// $nav-pills-active-link-hover-color: $component-active-color;
//
// // Pagination
// $pagination-color: $link-color;
// $pagination-bg: #fff;
// $pagination-border: #ddd;
// $pagination-hover-color: $link-hover-color;
// $pagination-hover-bg: $gray-lighter;
// $pagination-hover-border: #ddd;
// $pagination-active-color: #fff;
// $pagination-active-bg: $brand-primary;
// $pagination-active-border: $brand-primary;
// $pagination-disabled-color: $gray-light;
// $pagination-disabled-bg: #fff;
// $pagination-disabled-border: #ddd;
//
// // Pager
// $pager-bg: $pagination-bg;
// $pager-border: $pagination-border;
// $pager-border-radius: 15px;
// $pager-hover-bg: $pagination-hover-bg;
// $pager-active-bg: $pagination-active-bg;
// $pager-active-color: $pagination-active-color;
// $pager-disabled-color: $pagination-disabled-color;
//
// // Jumbotron
// $jumbotron-padding: 30px;
// $jumbotron-color: inherit;
// $jumbotron-bg: $gray-lighter;
// $jumbotron-heading-color: inherit;
// $jumbotron-font-size: ceil(($font-size-base * 1.5));
// $jumbotron-heading-font-size: ceil(($font-size-base * 4.5));
//
// // Form states and alerts
// $state-success-text: #3c763d;
// $state-success-bg: #dff0d8;
// $state-success-border: adjust-hue(darken($state-success-bg, 5%), -10);
// $state-info-text: #31708f;
// $state-info-bg: #d9edf7;
// $state-info-border: adjust-hue(darken($state-info-bg, 7%), -10);
// $state-warning-text: #8a6d3b;
// $state-warning-bg: #fcf8e3;
// $state-warning-border: adjust-hue(darken($state-warning-bg, 5%), -10);
// $state-danger-text: #a94442;
// $state-danger-bg: #f2dede;
// $state-danger-border: adjust-hue(darken($state-danger-bg, 5%), -10);
//
// // Tooltips
// $tooltip-max-width: 200px;
// $tooltip-color: #fff;
// $tooltip-bg: #000;
// $tooltip-opacity: .9;
// $tooltip-arrow-width: 5px;
// $tooltip-arrow-color: $tooltip-bg;
//
// // Popovers
// $popover-bg: #fff;
// $popover-max-width: 276px;
// $popover-border-color: rgba(0,0,0,.2);
// $popover-fallback-border-color: #ccc;
// $popover-title-bg: darken($popover-bg, 3%);
// $popover-arrow-width: 10px;
// $popover-arrow-color: $popover-bg;
// $popover-arrow-outer-width: ($popover-arrow-width + 1);
// $popover-arrow-outer-color: fadein($popover-border-color, 5%);
// $popover-arrow-outer-fallback-color: darken($popover-fallback-border-color, 20%);
//
// // Labels
// $label-default-bg: $gray-light;
// $label-primary-bg: $brand-primary;
// $label-success-bg: $brand-success;
// $label-info-bg: $brand-info;
// $label-warning-bg: $brand-warning;
// $label-danger-bg: $brand-danger;
// $label-color: #fff;
// $label-link-hover-color: #fff;
//
// // Modals
// $modal-inner-padding: 15px;
// $modal-title-padding: 15px;
// $modal-title-line-height: $line-height-base;
// $modal-content-bg: #fff;
// $modal-content-border-color: rgba(0,0,0,.2);
// $modal-content-fallback-border-color: #999;
// $modal-backdrop-bg: #000;
// $modal-backdrop-opacity: .5;
// $modal-header-border-color: #e5e5e5;
// $modal-footer-border-color: $modal-header-border-color;
// $modal-lg: 900px;
// $modal-md: 600px;
// $modal-sm: 300px;
//
// // Alerts
// $alert-padding: 15px;
// $alert-border-radius: $border-radius-base;
// $alert-link-font-weight: bold;
// $alert-success-bg: $state-success-bg;
// $alert-success-text: $state-success-text;
// $alert-success-border: $state-success-border;
// $alert-info-bg: $state-info-bg;
// $alert-info-text: $state-info-text;
// $alert-info-border: $state-info-border;
// $alert-warning-bg: $state-warning-bg;
// $alert-warning-text: $state-warning-text;
// $alert-warning-border: $state-warning-border;
// $alert-danger-bg: $state-danger-bg;
// $alert-danger-text: $state-danger-text;
// $alert-danger-border: $state-danger-border;
//
// // Progress bars
// $progress-bg: #f5f5f5;
// $progress-bar-color: #fff;
// $progress-border-radius: $border-radius-base;
// $progress-bar-bg: $brand-primary;
// $progress-bar-success-bg: $brand-success;
// $progress-bar-warning-bg: $brand-warning;
// $progress-bar-danger-bg: $brand-danger;
// $progress-bar-info-bg: $brand-info;
//
// // List group
// $list-group-bg: #fff;
// $list-group-border: #ddd;
// $list-group-border-radius: $border-radius-base;
// $list-group-hover-bg: #f5f5f5;
// $list-group-active-color: $component-active-color;
// $list-group-active-bg: $component-active-bg;
// $list-group-active-border: $list-group-active-bg;
// $list-group-active-text-color: lighten($list-group-active-bg, 40%);
// $list-group-disabled-color: $gray-light;
// $list-group-disabled-bg: $gray-lighter;
// $list-group-disabled-text-color: $list-group-disabled-color;
// $list-group-link-color: #555;
// $list-group-link-hover-color: $list-group-link-color;
// $list-group-link-heading-color: #333;
//
// // Panels
// $panel-bg: #fff;
// $panel-body-padding: 15px;
// $panel-heading-padding: 10px 15px;
// $panel-footer-padding: $panel-heading-padding;
// $panel-border-radius: $border-radius-base;
// $panel-inner-border: #ddd;
// $panel-footer-bg: #f5f5f5;
// $panel-default-text: $gray-dark;
// $panel-default-border: #ddd;
// $panel-default-heading-bg: #f5f5f5;
// $panel-primary-text: #fff;
// $panel-primary-border: $brand-primary;
// $panel-primary-heading-bg: $brand-primary;
// $panel-success-text: $state-success-text;
// $panel-success-border: $state-success-border;
// $panel-success-heading-bg: $state-success-bg;
// $panel-info-text: $state-info-text;
// $panel-info-border: $state-info-border;
// $panel-info-heading-bg: $state-info-bg;
// $panel-warning-text: $state-warning-text;
// $panel-warning-border: $state-warning-border;
// $panel-warning-heading-bg: $state-warning-bg;
// $panel-danger-text: $state-danger-text;
// $panel-danger-border: $state-danger-border;
// $panel-danger-heading-bg: $state-danger-bg;
//
// // Thumbnails
// $thumbnail-padding: 4px;
// $thumbnail-bg: $body-bg;
// $thumbnail-border: #ddd;
// $thumbnail-border-radius: $border-radius-base;
// $thumbnail-caption-color: $text-color;
// $thumbnail-caption-padding: 9px;
//
// // Wells
// $well-bg: #f5f5f5;
// $well-border: darken($well-bg, 7%);
//
// // Badges
// $badge-color: #fff;
// $badge-link-hover-color: #fff;
// $badge-bg: $gray-light;
// $badge-active-color: $link-color;
// $badge-active-bg: #fff;
// $badge-font-weight: bold;
// $badge-line-height: 1;
// $badge-border-radius: 10px;
//
// // Breadcrumbs
// $breadcrumb-padding-vertical: 8px;
// $breadcrumb-padding-horizontal: 15px;
// $breadcrumb-bg: #f5f5f5;
// $breadcrumb-color: #ccc;
// $breadcrumb-active-color: $gray-light;
// $breadcrumb-separator: "/";
//
// // Carousel
// $carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
// $carousel-control-color: #fff;
// $carousel-control-width: 15%;
// $carousel-control-opacity: .5;
// $carousel-control-font-size: 20px;
// $carousel-indicator-active-bg: #fff;
// $carousel-indicator-border-color: #fff;
// $carousel-caption-color: #fff;
//
// // Close
// $close-font-weight: bold;
// $close-color: #000;
// $close-text-shadow: 0 1px 0 #fff;
//
// // Code
// $code-color: #c7254e;
// $code-bg: #f9f2f4;
// $kbd-color: #fff;
// $kbd-bg: #333;
// $pre-bg: #f5f5f5;
// $pre-color: $gray-dark;
// $pre-border-color: #ccc;
// $pre-scrollable-max-height: 340px;
//
// // Type
// $component-offset-horizontal: 180px;
// $text-muted: $gray-light;
// $abbr-border-color: $gray-light;
// $headings-small-color: $gray-light;
// $blockquote-small-color: $gray-light;
// $blockquote-font-size: ($font-size-base * 1.25);
// $blockquote-border-color: $gray-lighter;
// $page-header-border-color: $gray-lighter;
// $dl-horizontal-offset: $component-offset-horizontal;
// $dl-horizontal-breakpoint: $grid-float-breakpoint;
// $hr-border: $gray-lighter;

View file

@ -14,7 +14,7 @@
// Active tab with error should retain error color if clicked on again
.nav-tabs > li.active.has-error > a {
color: $color-apple-blossom;
color: $brand-danger;
}
@media (max-width: 886px) {

View file

@ -8,15 +8,15 @@
.task-due-date,
.task-state-label {
.alert-green {
color: $color-saturated-green;
color: $brand-success;
}
.alert-yellow {
color: $color-candlelight;
color: $brand-warning;
}
.alert-red {
color: $color-milano-red;
color: $brand-danger;
}
}

View file

@ -31,7 +31,7 @@
padding-top: 10px;
&:hover {
background-color: $color-mystic;
background-color: $brand-primary-light;
}
&.no-notifications {
@ -40,7 +40,7 @@
}
.unseen {
border-left: 4px solid $color-theme-primary;
border-left: 4px solid $brand-primary;
}
.text-center {
@ -49,54 +49,39 @@
}
.assignment {
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: inline-block;
font-size: 13px;
font-size: $font-size-small;
height: 30px;
padding-top: 5px;
width: 30px;
}
.system-message {
background-color: $color-theme-secondary;
background-color: $brand-default;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: inline-block;
font-size: 13px;
font-size: $font-size-small;
height: 30px;
padding-top: 5px;
width: 30px;
}
.deliver {
background-color: $color-orange;
background-color: $brand-warning;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: inline-block;
font-size: 13px;
font-size: $font-size-small;
height: 30px;
padding-top: 5px;
width: 30px;
}
}
.notifications-footer {
background-color: $color-mystic;
.btn-more-notifications {
border-bottom: 1px solid $color-alto;
border-left: 1px solid $color-alto;
border-right: 1px solid $color-alto;
margin: 0;
padding: 8px;
text-align: center;
&:hover {
background-color: $color-mystic;
}
}
margin-top: 15px;
}

View file

@ -38,8 +38,8 @@ $toggle-btn-size: 50px;
.sidebar-header {
height: $toggle-btn-size;
background: $color-theme-primary;
border-bottom: 2px solid darken($color-theme-primary, 10%);
background: $brand-primary;
border-bottom: 2px solid darken($brand-primary, 10%);
.sidebar-header-title {
width: inherit;
@ -63,10 +63,10 @@ $toggle-btn-size: 50px;
width: $toggle-btn-size;
margin-left: ($wrapper-width - $toggle-btn-size);
margin-top: -$toggle-btn-size;
font-size: 20pt;
background: $color-theme-primary;
border-left: 2px solid darken($color-theme-primary, 10%);
border-bottom: 2px solid darken($color-theme-primary, 10%);
font-size: $font-size-h3;
background: $brand-primary;
border-left: 2px solid darken($brand-primary, 10%);
border-bottom: 2px solid darken($brand-primary, 10%);
// Animations
@include transition(margin-left 0.5s ease);
@ -118,7 +118,7 @@ $toggle-btn-size: 50px;
@include transition(margin-left 0.5s ease);
span {
color: darken($color-theme-primary, 10%);
color: darken($brand-primary, 10%);
@include rotate-animation(0.5s, 0deg);
@include transition(color 0.5s ease);

View file

@ -18,7 +18,7 @@
}
.first-indent {
background-color: $color-wild-sand;
background-color: $color-concrete;
padding-left: 30px;
}
@ -49,7 +49,7 @@
}
&.active > span {
background-color: $color-theme-primary;
background-color: $brand-primary;
color: $color-white;
font-weight: bold;
@ -74,7 +74,7 @@
color: $color-emperor;
&:hover {
color: $color-theme-primary;
color: $brand-primary;
}
}

View file

@ -2,8 +2,8 @@
@import "mixins";
// Some color definitions
$color-group-hover: $color-theme-primary;
$color-module-hover: $color-theme-secondary;
$color-group-hover: $brand-primary;
$color-module-hover: $brand-default;
/* Canvas index page */
@ -112,7 +112,7 @@ $color-module-hover: $color-theme-secondary;
cursor: pointer;
&:hover {
color: $color-theme-primary;
color: $brand-primary;
padding: 2px 9px 4px 9px;
}
}
@ -122,7 +122,7 @@ $color-module-hover: $color-theme-secondary;
border: 2px solid green;
}
.jsplumb-drag .title {
background-color: $color-theme-primary !important;
background-color: $brand-primary !important;
color: $color-white !important;
}
path, ._jsPlumb_endpoint {
@ -132,7 +132,7 @@ path, ._jsPlumb_endpoint {
fill: $color-white;
}
.ep-hover svg * {
fill: $color-theme-primary;
fill: $brand-primary;
}
/* EDIT MODE MODULE */
@ -140,16 +140,16 @@ path, ._jsPlumb_endpoint {
opacity: 0.7;
}
.module.dragged > .panel-heading {
background-color: $color-theme-primary;
background-color: $brand-primary;
color: $color-white;
}
.module.collided {
.overlay {
display: block;
z-index: 21;
background-color: $color-milano-red;
border: 1px solid $color-milano-red;
@include box-shadow(0 0 0 1pt $color-milano-red);
background-color: $brand-danger;
border: 1px solid $brand-danger;
@include box-shadow(0 0 0 1pt $brand-danger);
border-radius: 4px;
position: absolute;
top: 0;
@ -223,28 +223,28 @@ path, ._jsPlumb_endpoint {
}
&.alert-green .panel-body {
color: $color-saturated-green;
color: $brand-success;
font-weight: bold;
.due-date-link {
color: $color-saturated-green;
color: $brand-success;
}
}
&.alert-yellow .panel-body {
color: $color-candlelight;
color: $brand-warning;
font-weight: bold;
.due-date-link {
color: $color-candlelight;
color: $brand-warning;
}
}
&.alert-red .panel-body {
color: $color-milano-red;
color: $brand-danger;
font-weight: bold;
.due-date-link {
color: $color-milano-red;
color: $brand-danger;
}
}
}
@ -265,18 +265,18 @@ path, ._jsPlumb_endpoint {
}
&.alert-green {
border-color: $color-saturated-green;
border-color: $brand-success;
border-radius: 8px;
border-width: 4px;
}
&.alert-yellow {
border-color: $color-candlelight;
border-color: $brand-warning;
border-width: 4px;
border-radius: 8px;
}
&.alert-red {
border-color: $color-milano-red;
border-color: $brand-danger;
border-width: 4px;
border-radius: 8px;
}
@ -326,13 +326,13 @@ path, ._jsPlumb_endpoint {
span {
font-weight: bold;
font-size: 16px;
font-size: $font-size-large;
text-transform: uppercase;
display: block;
margin-top: 20%;
a {
color: $color-mine-shaft;
color: $color-emperor;
}
}
@ -344,14 +344,14 @@ path, ._jsPlumb_endpoint {
}
&.alert-green {
border-color: $color-saturated-green;
border-color: $brand-success;
}
&.alert-yellow {
border-color: $color-candlelight;
border-color: $brand-warning;
}
&.alert-red {
border-color: $color-milano-red;
border-color: $brand-danger;
}
}
@ -362,7 +362,7 @@ li.group-hover {
}
li.module-hover {
a {
color: $color-theme-primary;
color: $brand-primary;
text-decoration: underline;
}
}
@ -400,7 +400,7 @@ li.module-hover {
margin-top: 5px;
font-family: 'Glyphicons Halflings';
color: $color-white;
font-size: 12pt;
font-size: $font-size-large;
&:before {
content: "\e221";
@ -412,7 +412,7 @@ li.module-hover {
.glyphicon {
color: $color-white;
font-size: 12pt;
font-size: $font-size-h6;
}
a.btn-link {
@ -463,7 +463,7 @@ li.module-hover {
.experiment-no-description {
color: $color-alto;
display: block;
font-size: 18px;
font-size: $font-size-h4;
font-weight: bold;
text-align: center;
@ -508,7 +508,7 @@ li.module-hover {
}
.big-plus {
color: $color-mystic;
color: $brand-primary-light;
display: block;
font-size: 250px;
margin: 20px 0;

View file

@ -0,0 +1,20 @@
.btn-open-file {
position: relative;
overflow: hidden;
& > input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;
}
}

View file

@ -148,7 +148,7 @@ label {
opacity: 0.7;
padding: 15px;
border-radius: 5px;
border: 4px $color-theme-primary solid;
border: 4px $brand-primary solid;
.plus-icon {
bottom: 16px !important;
@ -166,7 +166,7 @@ label {
.filler {
display: block;
height: 4px;
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 1px;
margin-top: 8px;
margin-bottom: 8px;
@ -183,7 +183,7 @@ label {
}
.plus-icon {
color: $color-theme-primary;
color: $brand-primary;
display: block;
text-align: center;
width: 40px;
@ -201,7 +201,7 @@ label {
opacity: 1.0;
.filler {
background-color: $color-theme-primary;
background-color: $brand-primary;
.plus-icon span {
font-weight: bold;
@ -223,7 +223,7 @@ label {
}
.controls {
margin-right: 15px;
font-size: 12pt;
font-size: $font-size-h6;
opacity: 0.05;
}
}
@ -240,8 +240,8 @@ label {
}
&:hover {
background-color: $color-mystic;
@include box-shadow(0 0 2px 15px $color-mystic);
background-color: $brand-primary-light;
@include box-shadow(0 0 2px 15px $brand-primary-light);
& > .report-element-header {
@ -266,7 +266,7 @@ label {
}
&:hover > .report-element-body .project-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -297,7 +297,7 @@ label {
}
&:hover > .report-element-body .module-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -329,7 +329,7 @@ label {
}
&:hover > .report-element-header {
color: $color-theme-primary;
color: $brand-primary;
}
.report-element-body {
@ -368,7 +368,7 @@ label {
/** Step element style */
.report-step-element {
&:hover > .report-element-body .step-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -388,7 +388,7 @@ label {
&:hover > .report-element-header {
.attachment-icon {
color: $color-theme-primary;
color: $brand-primary;
}
}
}
@ -403,7 +403,7 @@ label {
&:hover > .report-element-header {
.table-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
}
@ -417,7 +417,7 @@ label {
}
&:hover > .report-element-header .file-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -438,7 +438,7 @@ label {
}
&:hover > .report-element-header .checklist-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -475,7 +475,7 @@ label {
&:hover > .report-element-header {
.comments-icon,.comments-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
}
@ -504,7 +504,7 @@ label {
&:hover > .report-element-header {
.samples-icon,.samples-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
}
@ -524,7 +524,7 @@ label {
&:hover > .report-element-header {
.repository-icon,
.repository-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
}
@ -559,7 +559,7 @@ label {
&:hover > .report-element-header {
.activity-icon,.activity-name {
color: $color-theme-primary;
color: $brand-primary;
}
}
}

View file

@ -1,3 +1,5 @@
@import "constants";
.repositories-dropdown-menu {
height: auto;
max-height: 400px;
@ -24,3 +26,8 @@
float: right;
text-align: inherit;
}
.breadcrumb.breadcrumb-repository {
background-color: $color-concrete;
margin-bottom: 15px;
}

View file

@ -45,7 +45,7 @@
}
.glyphicon-ok {
color: $color-theme-secondary;
color: $brand-default;
}
.glyphicon {

View file

@ -9,5 +9,5 @@
padding-top: 20px;
}
.search-asset-text-data{
font-size: 14px;
font-size: $font-size-base;
}

View file

@ -0,0 +1,3 @@
#reset-tutorial-btn {
margin-top: 5px;
}

View file

@ -1,114 +0,0 @@
@import 'constants';
@import "mixins";
#reset-tutorial-btn {
margin-top: 15px;
}
.btn-primary {
background-color: $color-theme-secondary;
border-color: darken($color-theme-secondary, 5%);
&.active,
&.focus,
&.active.focus {
background-color: darken($color-theme-secondary, 20%);
border-color: darken($color-theme-secondary, 25%);
&:hover {
background-color: darken($color-theme-secondary, 25%);
border-color: darken($color-theme-secondary, 30%);
}
}
&:active,
&:focus,
&:active:focus,
&:active:hover,
&:focus:hover,
&:active:focus:hover {
background-color: darken($color-theme-secondary, 20%);
border-color: darken($color-theme-secondary, 25%);
}
&:hover {
background-color: darken($color-theme-secondary, 5%);
border-color: darken($color-theme-secondary, 10%);
}
}
.btn-link-alt {
border-radius: 4px;
cursor: pointer;
margin-right: 5px;
padding: 3px;
}
.btn-invis-file {
display: none;
opacity: 0;
position: absolute;
z-index: -1;
}
.btn-open-file {
position: relative;
overflow: hidden;
& > input[type=file] {
position: absolute;
top: 0;
right: 0;
min-width: 100%;
min-height: 100%;
font-size: 100px;
text-align: right;
filter: alpha(opacity=0);
opacity: 0;
outline: none;
background: white;
cursor: inherit;
display: block;
}
}
/** Add users modal */
.btn-group-existing-users {
width: 100%;
label.btn {
text-align: center;
&.btn-title {
color: $color-white;
cursor: inherit;
background-color: $color-theme-primary;
&:focus, &:active, &:hover {
box-shadow: none;
background-color: $color-theme-primary;
border-color: $color-dark-gray;
}
}
}
}
.btn-greyed {
background-color: $color-silver-chalice;
border-color: $color-silver-chalice;
color: $color-white;
&:hover,
&:focus {
background-color: darken($color-silver-chalice, 15%);
border-color: darken($color-silver-chalice, 15%);
color: $color-white;
}
}
/* Sample group color picker */
.btn-group-sample-group-color {
.btn-group > .btn {
border-radius: 0 !important;
}
}

View file

@ -7,14 +7,14 @@
#notifications-dropdown {
.fa-bell {
font-size: 15px;
font-size: $font-size-large;
position: absolute;
}
#count-notifications {
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 5px;
color: $color-wild-sand;
color: $color-concrete;
display: none;
font-size: 11px;
font-weight: bold;
@ -69,7 +69,7 @@
}
.unseen {
border-left: 4px solid $color-theme-primary;
border-left: 4px solid $brand-primary;
}
.text-center {
@ -84,41 +84,41 @@
}
.assignment {
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: block;
font-size: 23px;
font-size: $font-size-h3;
height: 45px;
padding-top: 5px;
width: 45px;
}
.deliver {
background-color: $color-orange;
background-color: $brand-warning;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: block;
font-size: 23px;
font-size: $font-size-h3;
height: 45px;
padding-top: 5px;
width: 45px;
}
.system-message {
background-color: $color-theme-secondary;
background-color: $brand-default;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: block;
font-size: 23px;
font-size: $font-size-h3;
height: 45px;
padding-top: 8px;
width: 45px;
}
.notifications-dropdown-header {
background-color: $color-theme-primary;
color: $color-wild-sand;
background-color: $brand-primary;
color: $color-concrete;
font-weight: bold;
padding: 8px;
@ -128,7 +128,7 @@
}
.notifications-dropdown-footer {
background-color: $color-mystic;
background-color: $brand-primary-light;
padding: 8px;
text-align: center;
}
@ -157,21 +157,6 @@
padding-left: 45px;
}
#search-bar {
border-color: $color-border;
.btn-default {
background-color: $color-theme-primary;
border-color: $color-theme-primary;
color: $color-white;
}
input {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
width: 300px;
}
}
/** Search */
.nav-search {
li.disabled {
@ -188,7 +173,7 @@
padding: 10px 15px;
&.active {
color: $color-theme-primary;
color: $brand-primary;
}
}
@ -233,11 +218,11 @@
}
.assignment {
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: block !important;
font-size: 15px;
font-size: $font-size-base;
height: 30px;
margin-right: 15px;
padding: 7px;
@ -247,11 +232,11 @@
}
.system-message {
background-color: $color-theme-secondary;
background-color: $brand-default;
border-radius: 50%;
color: $color-wild-sand;
color: $color-concrete;
display: block !important;
font-size: 15px;
font-size: $font-size-base;
height: 30px;
margin-right: 15px;
padding: 8px;
@ -274,34 +259,26 @@
}
.glyphicon-ok-sign {
color: $color-confirmation-green;
color: $brand-success;
margin-left: -10px;
margin-right: 10px;
}
.team-name-item {
border-bottom: 1px solid $color-list-separator;
border-bottom: 1px solid $color-silver-chalice;
padding-bottom: 8px;
padding-top: 5px;
}
.btn-default {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
text-align: right;
width: 300px;
}
.btn-group {
border-color: $color-border;
margin-top: 8px;
}
.btn-primary {
background-color: $color-theme-primary;
border-color: $color-theme-primary;
}
.dropdown-menu {
width: 100%;
}
@ -340,7 +317,7 @@
}
.custom-nav-dropdown {
border: 1px solid $color-border;
border: 1px solid $color-alto;
padding: 10px 0 10px 30px;
}

View file

@ -16,9 +16,9 @@
padding-right: 4px;
& > a {
color: $color-gray;
color: $color-silver-chalice;
display: grid;
font-size: 12px;
font-size: $font-size-h6;
margin-left: auto;
margin-right: auto;
padding: 10px;
@ -33,7 +33,7 @@
background-color: $color-gainsboro;
margin-right: 4px;
padding-right: 0;
@include box-shadow(4px 0 0 $color-theme-primary);
@include box-shadow(4px 0 0 $brand-primary);
& > a {
color: $color-emperor;

View file

@ -28,3 +28,12 @@
}
}
}
#repository-columns-dropdown {
float: right;
}
.new-repository-button {
float: left;
margin-right: 5px;
}

View file

@ -1,9 +1,7 @@
@import "constants";
@import "mixins";
@import "main_navigation";
@import "buttons";
@import "repositories";
/** Layout **/
body,
@ -75,7 +73,7 @@ table {
}
.blockquote-search {
font-size: 14px;
font-size: $font-size-base;
margin-bottom: 10px;
}
@ -91,18 +89,8 @@ table {
/** Skin **/
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400,600,700,400italic&subset=latin,latin-ext);
body {
background-color: $color-concrete;
color: $color-emperor;
font-family: "Open Sans",Arial,Helvetica,sans-serif;
font-size: 13px;
}
a {
color: $color-theme-primary;
font-size: $font-size-small;
}
.jumbotron {
@ -110,7 +98,7 @@ a {
}
.badge {
background-color: $color-theme-primary;
background-color: $brand-primary;
font-size: 11px;
border-radius: 5px;
}
@ -129,7 +117,7 @@ a {
}
.bg-primary {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
/* this rule is strict because the order of css files is not correct */
@ -138,7 +126,7 @@ a {
}
mark,.mark {
background-color: $color-candlelight;
background-color: $brand-warning;
}
.label-default {
@ -146,12 +134,12 @@ mark,.mark {
}
.label-primary {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
.circle {
@extend .badge;
background-color: $color-theme-primary;
background-color: $brand-primary;
border-radius: 1em;
&.disabled {
@ -174,10 +162,10 @@ a[data-toggle="tooltip"] {
& > li.has-error {
& > a {
color: $color-apple-blossom;
color: $brand-danger;
&:hover {
color: $color-mojo;
color: $brand-danger;
}
}
}
@ -186,7 +174,7 @@ a[data-toggle="tooltip"] {
.has-error {
.ql-container.ql-snow,
.ql-toolbar.ql-snow {
border: 1px solid $color-apple-blossom;
border: 1px solid $brand-danger;
}
}
@ -197,7 +185,7 @@ a[data-toggle="tooltip"] {
.nav-pills {
& > li {
a {
color: $color-theme-primary;
color: $brand-primary;
}
&:not(.active):hover a {
@ -206,7 +194,7 @@ a[data-toggle="tooltip"] {
&.active a {
color: $color-white;
background-color: $color-theme-primary;
background-color: $brand-primary;
}
}
}
@ -221,7 +209,7 @@ a[data-toggle="tooltip"] {
.nav-tabs-less > li.active > a {
&,&:hover,&:focus {
color: $color-theme-secondary;
color: $brand-default;
background-color: transparent;
border-color: transparent;
}
@ -229,7 +217,7 @@ a[data-toggle="tooltip"] {
.tag.label.label-info {
font-size: 100%;
background-color: $color-theme-primary;
background-color: $brand-primary;
}
#secondary-navigation {
@ -274,14 +262,14 @@ a[data-toggle="tooltip"] {
text-transform: uppercase;
& > a {
color: $color-gray;
color: $color-silver-chalice;
span {
//width: 14px;
}
}
&.active {
@include box-shadow(0 4px 0 $color-theme-primary);
@include box-shadow(0 4px 0 $brand-primary);
&> a {
font-weight: bold;
@ -345,7 +333,7 @@ a[data-toggle="tooltip"] {
padding: 13px;
.glyphicon.glyphicon-info-sign {
font-size: 16px;
font-size: $font-size-large;
margin-top: 4px;
}
}
@ -539,16 +527,16 @@ ul.double-line > li {
.pagination > .active > span,
.pagination > .active > span:hover,
.pagination > .active > span:focus {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
.pagination > li > a,
.pagination > li > span {
color: $color-theme-primary;
color: $brand-primary;
}
.panel-default > .panel-heading {
background-color: $color-mystic;
background-color: $brand-primary-light;
&>.panel-title {
overflow: hidden;
@ -559,15 +547,15 @@ ul.double-line > li {
.panel-project {
.panel-heading {
background-color: $color-theme-primary;
background-color: $brand-primary;
color: $color-white;
}
}
.panel-archive {
.panel-heading {
background-color: darken($color-mystic, 5%);
color: lighten($color-mine-shaft, 15%);
background-color: darken($brand-primary-light, 5%);
color: lighten($color-emperor, 15%);
}
}
@ -638,11 +626,11 @@ ul.double-line > li {
li.notification.alert-red > .date-time {
font-weight: bold;
color: $color-milano-red;
color: $brand-danger;
}
li.notification.alert-yellow > .date-time {
font-weight: bold;
color: $color-candlelight;
color: $brand-warning;
}
}
}
@ -654,7 +642,7 @@ ul.double-line > li {
margin-bottom: 0;
&> .panel-heading {
background-color: $color-mystic;
background-color: $brand-primary-light;
border-bottom: 1px solid $color-alto;
.panel-title > a {
@ -713,14 +701,6 @@ ul.content-activities {
text-align: justify;
}
}
li.activity-date-item {
font-size: 1.4em;
& > span {
padding-left: 2em;
padding-right: 2em;
}
}
}
ul.content-module-activities {
@ -730,8 +710,8 @@ ul.content-module-activities {
.activity-item-date {
font-size: 1.2em;
background-color: $color-theme-primary;
border-color: $color-theme-primary;
background-color: $brand-primary;
border-color: $brand-primary;
color: $color-white;
padding-top: 5px;
padding-bottom: 5px;
@ -899,16 +879,17 @@ ul.content-module-activities {
.dnd-error,
.dnd-total-error {
color: $color-milano-red;
color: $brand-danger;
}
.is-dragover {
background: $color-drag-overlay;
background: $color-black;
bottom: 0;
display: none;
height: 100%;
left: 0;
min-height: 100%;
opacity: .4;
pointer-events: none;
position: fixed;
right: 0;
@ -996,7 +977,7 @@ table.dataTable {
word-break: initial;
thead {
background-color: $color-gray;
background-color: $color-silver-chalice;
}
thead > tr > th {
@ -1021,13 +1002,13 @@ table.dataTable {
color: $color-emperor !important;
a {
color: $color-theme-primary !important;
color: $brand-primary !important;
}
}
.sorting_desc,
.sorting_asc {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
}
@ -1068,12 +1049,12 @@ table.dataTable {
top: 50%;
margin-top: -19px;
border-top: 19px solid transparent;
border-left: 13px solid $color-theme-primary;
border-left: 13px solid $brand-primary;
border-bottom: 19px solid transparent;
}
.nav-stacked-arrow > li.active > a:hover:after {
border-left: 13px solid darken($color-theme-primary, 15%);
border-left: 13px solid darken($brand-primary, 15%);
}
/* Overlay to disable interaction while loading ajax */
@ -1095,7 +1076,7 @@ table.dataTable {
}
.turbolinks-progress-bar::before {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
/* Loading animation for ajax events, inspired by Codrops */
@ -1106,7 +1087,7 @@ table.dataTable {
z-index: -1;
width: 100%;
height: 3px;
background: $color-theme-primary;
background: $brand-primary;
-webkit-transform: translate3d(-100%, 0, 0);
transform: translate3d(-100%, 0, 0);
pointer-events: none;
@ -1137,7 +1118,7 @@ table.dataTable {
.custom .introjs-skipbutton {
border-radius: 0;
color: $color-theme-primary;
color: $brand-primary;
background-color: $color-white;
background-image: none;
border: none;
@ -1163,7 +1144,7 @@ table.dataTable {
.modal-tooltiptext {
background-color: $color-alto;
border-radius: 6px;
color: $color-mine-shaft;
color: $color-emperor;
display: block;
margin-left: 100px;
padding: 5px;
@ -1205,7 +1186,7 @@ table.dataTable {
top: auto;
li:not(.dropdown-header):hover {
background-color: $color-wild-sand;
background-color: $color-concrete;
}
}
@ -1241,9 +1222,19 @@ table.dataTable {
position: absolute;
z-index: 10;
.btn-greyed {
.btn-grey {
background-color: $color-silver-chalice;
border-color: $color-silver-chalice;
border-radius: 0;
color: $color-white;
width: 100px;
&:hover,
&:focus {
background-color: darken($color-silver-chalice, 15%);
border-color: darken($color-silver-chalice, 15%);
color: $color-white;
}
}
}
@ -1281,7 +1272,7 @@ table.dataTable {
// Image preview modal
.modal-image-preview {
background: transparent;
font-size: 16px;
font-size: $font-size-large;
padding-right: 0 !important;
z-index: 1060;
@ -1386,15 +1377,6 @@ textarea.textarea-sm {
-webkit-padding-before: 0;
-webkit-padding-after: 0;
}
.btn.btn-default-link {
border: 0;
height: 100%;
min-height: 34px;
padding: 0;
-webkit-padding-after: 0;
-webkit-padding-before: 0;
}
}
}
@ -1480,7 +1462,7 @@ textarea.textarea-sm {
}
.ok {
color: $color-theme-secondary;
color: $brand-default;
margin-right: 5px;
}
@ -1534,7 +1516,7 @@ th.custom-field .modal-tooltiptext {
color: $color-black;
border: 1px solid $color-emperor;
border-radius: 3px;
box-shadow: 0 0 5px $color-cloud;
box-shadow: 0 0 5px $color-gainsboro;
min-width: 520px;
max-height: 200px;
overflow: auto;
@ -1547,11 +1529,11 @@ th.custom-field .modal-tooltiptext {
}
strong {
color: $color-theme-primary;
color: $brand-primary;
}
.cur {
background: $color-theme-primary;
background: $brand-primary;
color: $color-white;
small {
@ -1583,7 +1565,7 @@ th.custom-field .modal-tooltiptext {
padding-top: 3px;
padding-bottom: 7px;
height: 34px;
background-color: $color-gallery;
background-color: $color-concrete;
border-bottom: 1px solid $color-emperor;
clear: both;
@ -1596,12 +1578,10 @@ th.custom-field .modal-tooltiptext {
margin-left: 15px;
.btn {
border-radius: 4px;
margin-right: 5px;
padding: 3px;
}
.btn:last-child {
margin-right: 20px;
}

View file

@ -11,21 +11,16 @@ class RepositoriesController < ApplicationController
before_action :check_create_permissions, only:
%i(create_new_modal create copy_modal copy)
layout 'fluid'
def index
render('repositories/index')
unless @repositories.length.zero? && current_team
redirect_to repository_path(@repositories.first) and return
end
render 'repositories/index'
end
def show_tab
respond_to do |format|
format.json do
render json: {
html: render_to_string(
partial: 'repositories/repository.html.erb',
locals: { repository: @repository }
)
}
end
end
def show
end
def create_modal
@ -53,7 +48,7 @@ class RepositoriesController < ApplicationController
if @repository.save
flash[:success] = t('repositories.index.modal_create.success_flash',
name: @repository.name)
render json: { url: team_repositories_path(repository: @repository) },
render json: { url: repository_path(@repository) },
status: :ok
else
render json: @repository.errors,
@ -287,7 +282,7 @@ class RepositoriesController < ApplicationController
end
def load_parent_vars
@team = Team.find_by_id(params[:team_id])
@team = current_team
render_404 unless @team
@repositories = @team.repositories.order(created_at: :asc)
end

View file

@ -4,6 +4,8 @@ class SearchController < ApplicationController
def index
redirect_to new_search_path unless @search_query
@search_id = params[:search_id] ? params[:search_id] : generate_search_id
count_search_results
search_projects if @search_category == :projects
@ -86,6 +88,10 @@ class SearchController < ApplicationController
protected
def generate_search_id
SecureRandom.urlsafe_base64(32)
end
def search_by_name(model)
model.search(current_user,
true,
@ -109,7 +115,10 @@ class SearchController < ApplicationController
end
def count_by_repository
count_total = 0
@repository_search_count =
Rails.cache.fetch("#{@search_id}/repository_search_count",
expires_in: 5.minutes) do
search_count = {}
search_results = Repository.search(current_user,
@search_query,
Constants::SEARCH_NO_LIMIT,
@ -117,7 +126,7 @@ class SearchController < ApplicationController
match_case: @search_case,
whole_word: @search_whole_word,
whole_phrase: @search_whole_phrase)
@repository_search_count = {}
current_user.teams.includes(:repositories).each do |team|
team_results = {}
team_results[:count] = 0
@ -128,33 +137,39 @@ class SearchController < ApplicationController
repository_results[:count] = 0
search_results.each do |result|
if repository.id == result.id
count_total += result.counter
repository_results[:count] += result.counter
end
end
team_results[:repositories][repository.name] = repository_results
team_results[:count] += repository_results[:count]
end
@repository_search_count[team.name] = team_results
search_count[team.name] = team_results
end
search_count
end
count_total = 0
@repository_search_count.each_value do |team_results|
count_total += team_results[:count]
end
count_total
end
def count_search_results
@project_search_count = count_by_name Project
@experiment_search_count = count_by_name Experiment
@module_search_count = count_by_name MyModule
@result_search_count = count_by_name Result
@tag_search_count = count_by_name Tag
@report_search_count = count_by_name Report
@protocol_search_count = count_by_name Protocol
@step_search_count = count_by_name Step
@checklist_search_count = count_by_name Checklist
@sample_search_count = count_by_name Sample
@project_search_count = fetch_cached_count Project
@experiment_search_count = fetch_cached_count Experiment
@module_search_count = fetch_cached_count MyModule
@result_search_count = fetch_cached_count Result
@tag_search_count = fetch_cached_count Tag
@report_search_count = fetch_cached_count Report
@protocol_search_count = fetch_cached_count Protocol
@step_search_count = fetch_cached_count Step
@checklist_search_count = fetch_cached_count Checklist
@sample_search_count = fetch_cached_count Sample
@repository_search_count_total = count_by_repository
@asset_search_count = count_by_name Asset
@table_search_count = count_by_name Table
@comment_search_count = count_by_name Comment
@asset_search_count = fetch_cached_count Asset
@table_search_count = fetch_cached_count Table
@comment_search_count = fetch_cached_count Comment
@search_results_count = @project_search_count
@search_results_count += @experiment_search_count
@ -172,6 +187,15 @@ class SearchController < ApplicationController
@search_results_count += @comment_search_count
end
def fetch_cached_count(type)
exp = 5.minutes
Rails.cache.fetch(
"#{@search_id}/#{type.name.underscore}_search_count", expires_in: exp
) do
count_by_name type
end
end
def search_projects
@project_results = []
@project_results = search_by_name(Project) if @project_search_count > 0

View file

@ -117,68 +117,7 @@ module ApplicationHelper
# Check if text have smart annotations of resources
# and outputs a link to resource
def smart_annotation_filter_resources(text)
sa_reg = /\[\#(.*?)~(prj|exp|tsk|sam)~([0-9a-zA-Z]+)\]/
new_text = text.gsub(sa_reg) do |el|
match = el.match(sa_reg)
case match[2]
when 'prj'
project = Project.find_by_id(match[3].base62_decode)
next unless project
if project.archived?
"<span class='sa-type'>" \
"#{sanitize_input(match[2])}</span>" \
"#{link_to project.name,
projects_archive_path} #{I18n.t('atwho.res.archived')}"
else
"<span class='sa-type'>" \
"#{sanitize_input(match[2])}</span>" \
"#{link_to project.name,
project_path(project)}"
end
when 'exp'
experiment = Experiment.find_by_id(match[3].base62_decode)
next unless experiment
if experiment.archived?
"<span class='sa-type'>" \
"#{sanitize_input(match[2])}</span>" \
"#{link_to experiment.name,
experiment_archive_project_path(experiment.project)} " \
"#{I18n.t('atwho.res.archived')}"
else
"<span class='sa-type'>"\
"#{sanitize_input(match[2])}</span>" \
"#{link_to experiment.name,
canvas_experiment_path(experiment)}"
end
when 'tsk'
my_module = MyModule.find_by_id(match[3].base62_decode)
next unless my_module
if my_module.archived?
"<span class='sa-type'>" \
"#{sanitize_input(match[2])}</span>" \
"#{link_to my_module.name,
module_archive_experiment_path(my_module.experiment)} " \
"#{I18n.t('atwho.res.archived')}"
else
"<span class='sa-type'>" \
"#{sanitize_input(match[2])}</span>" \
"#{link_to my_module.name,
protocols_my_module_path(my_module)}"
end
when 'sam'
sample = Sample.find_by_id(match[3].base62_decode)
if sample
"<span class='glyphicon glyphicon-tint'></span>" \
"#{link_to(sample.name,
sample_path(sample.id),
class: 'sample-info-link')}"
else
"<span class='glyphicon glyphicon-tint'></span>" \
"#{match[1]} #{I18n.t('atwho.res.deleted')}"
end
end
end
new_text
SmartAnnotations::TagToHtml.new(current_user, text).html
end
# Check if text have smart annotations of users

View file

@ -10,9 +10,10 @@ module RepositoryDatatableHelper
row = {
'DT_RowId': record.id,
'1': assigned_row(record, assigned_rows),
'2': escape_input(record.name),
'3': I18n.l(record.created_at, format: :full),
'4': escape_input(record.created_by.full_name),
'2': record.id,
'3': escape_input(record.name),
'4': I18n.l(record.created_at, format: :full),
'5': escape_input(record.created_by.full_name),
'recordEditUrl': Rails.application.routes.url_helpers
.edit_repository_repository_row_path(
repository,

View file

@ -14,8 +14,8 @@ import ActivityDateElement from "./ActivityDateElement";
import {
WHITE_COLOR,
COLOR_CONCRETE,
COLOR_MINE_SHAFT,
COLOR_GRAY_LIGHT_YADCF
COLOR_EMPEROR,
COLOR_ALTO
} from "../../../config/constants/colors";
const StyledBottom = styled(Button)`
@ -37,14 +37,14 @@ const StyledBottom = styled(Button)`
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
color: ${COLOR_MINE_SHAFT};
color: ${COLOR_EMPEROR};
background-color: ${WHITE_COLOR};
border-color: ${COLOR_GRAY_LIGHT_YADCF};
border-color: ${COLOR_ALTO};
`;
const StyledModalBody = styled(Modal.Body)`
background-color: ${COLOR_CONCRETE};
color: ${COLOR_MINE_SHAFT};
color: ${COLOR_EMPEROR};
`;
type Props = {

View file

@ -4,7 +4,7 @@ import ReactDataGrid from 'react-data-grid';
import styled from "styled-components";
import {
WHITE_COLOR,
COLOR_GRAY
COLOR_SILVER_CHALICE
} from "../../config/constants/colors";
const StyledReactDataGrid = styled(ReactDataGrid)`
@ -16,7 +16,7 @@ const StyledReactDataGrid = styled(ReactDataGrid)`
.react-grid-Header {
.react-grid-HeaderCell {
background-color: ${COLOR_GRAY};
background-color: ${COLOR_SILVER_CHALICE};
color: ${WHITE_COLOR};
font-weight: normal;

View file

@ -5,14 +5,14 @@ import styled from "styled-components";
import { FormattedMessage } from "react-intl";
import {
WHITE_COLOR,
COLOR_GRAY,
COLOR_SILVER_CHALICE,
COLOR_ALTO,
COLOR_ALABASTER
} from "../../config/constants/colors";
const StyledBootstrapTable = styled(BootstrapTable)`
thead {
background-color: ${COLOR_GRAY};
background-color: ${COLOR_SILVER_CHALICE};
> tr > th,
> tr > td {

View file

@ -7,16 +7,14 @@ export const BORDER_LIGHT_COLOR = "#e3e3e3";
export const WILD_SAND_COLOR = "#f5f5f5";
export const MYSTIC_COLOR = "#eaeff2";
export const COLOR_CONCRETE = "#f2f2f2";
export const COLOR_MINE_SHAFT = "#333";
export const COLOR_EMPEROR = "#333";
export const COLOR_BLACK = "#000";
export const COLOR_GRAY_LIGHT_YADCF = "#ccc";
export const COLOR_ALTO = "#ccc";
export const ICON_GREEN_COLOR = "#8fd13f";
export const NOTIFICATION_YES = "#5a8921";
export const NOTIFICATION_YES_BORDER = "#4d751c";
export const SIDEBAR_HOVER_GRAY_COLOR = "#D2D2D2";
export const COLOR_ALTO = "#dddddd";
export const COLOR_GRAY = "#909088";
export const COLOR_SILVER_CHALICE = "#909088";
export const COLOR_ALABASTER = "#fcfcfc";
export const COLOR_APPLE_BLOSSOM = "#a94442";
export const COLOR_ORANGE = "#ff900b";

View file

@ -3,50 +3,24 @@
//==============================================================================
// Theme colors
$color-theme-primary: #37a0d9;
$color-theme-secondary: #8fd13f;
$color-theme-dark: #6d6e71;
$brand-primary: #37a0d9;
$brand-default: #8fd13f;
// Grayscale colors
$color-white: #fff;
$color-alabaster: #fcfcfc;
$color-snow: #f9f9f9;
$color-wild-sand: #f5f5f5;
$color-concrete: #f2f2f2;
$color-gallery: #eee;
$color-gainsboro: #e3e3e3;
$color-alto: #d2d2d2;
$color-silver: #c5c5c5;
$color-dark-gray: #adadad;
$color-silver-chalice: #a0a0a0;
$color-gray: #909088;
$color-dove-gray: #666;
$color-emperor: #555;
$color-mine-shaft: #333;
$color-nero: #262626;
$color-black: #000;
$color-cloud: rgba(0, 0, 0, .1);
$color-gray-light-yadcf: #ccc;
$color-gray-dark-yadcf: #a9a9a9;
// Miscelaneous colors
$color-mystic: #eaeff2;
$color-candlelight: #ffda23;
$color-orange: #ff900b;
$color-saturated-green: #008600;
$color-blue-yadcf: #337ab7;
$primary-hover-color: #75b22b;
// Red colors
$color-mojo: #cf4b48;
$color-apple-blossom: #a94442;
$color-milano-red: #a70b05;
// Colors for specific intents
$color-visited-link: #23527c;
// Overlay shade for drag'n dropdown
$color-drag-overlay: rgba(0, 0, 0, .4);
//==============================================================================
// Other

View file

@ -9,7 +9,7 @@ body {
}
.label-primary {
background-color: $color-theme-primary;
background-color: $brand-primary;
}
.btn {
@ -17,18 +17,18 @@ body {
}
.btn-primary {
background-color: $color-theme-secondary;
border-color: darken($color-theme-secondary, 5%);
background-color: $brand-default;
border-color: darken($brand-default, 5%);
&.active,
&.focus,
&.active.focus {
background-color: darken($color-theme-secondary, 20%);
border-color: darken($color-theme-secondary, 25%);
background-color: darken($brand-default, 20%);
border-color: darken($brand-default, 25%);
&:hover {
background-color: darken($color-theme-secondary, 25%);
border-color: darken($color-theme-secondary, 30%);
background-color: darken($brand-default, 25%);
border-color: darken($brand-default, 30%);
}
}
@ -38,19 +38,19 @@ body {
&:active:hover,
&:focus:hover,
&:active:focus:hover {
background-color: darken($color-theme-secondary, 20%);
border-color: darken($color-theme-secondary, 25%);
background-color: darken($brand-default, 20%);
border-color: darken($brand-default, 25%);
}
&:hover {
background-color: darken($color-theme-secondary, 5%);
border-color: darken($color-theme-secondary, 10%);
background-color: darken($brand-default, 5%);
border-color: darken($brand-default, 10%);
}
}
// tags input
.react-tagsinput--focused {
border-color: $color-theme-primary;
border-color: $brand-primary;
}
.react-tagsinput-input {
@ -58,7 +58,7 @@ body {
}
.react-tagsinput-tag {
background-color: $color-theme-primary;
background-color: $brand-primary;
border: 0;
color: $color-white;
font-weight: bold;

View file

@ -91,37 +91,19 @@ class Asset < ApplicationRecord
def self.search(
user,
include_archived,
_include_archived,
query = nil,
page = 1,
_current_team = nil,
options = {}
)
step_ids =
Step
.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT)
.joins(:step_assets)
.distinct
.pluck('step_assets.id')
result_ids =
Result
.search(user, include_archived, nil, Constants::SEARCH_NO_LIMIT)
.joins(:result_asset)
.distinct
.pluck('result_assets.id')
ids =
new_query =
Asset
.select(:id)
.distinct
.joins('LEFT OUTER JOIN step_assets ON step_assets.asset_id = assets.id')
.joins('LEFT OUTER JOIN result_assets ON ' \
'result_assets.asset_id = assets.id')
.joins('LEFT JOIN asset_text_data ON ' \
'assets.id = asset_text_data.asset_id')
.where('(step_assets.id IN (?) OR result_assets.id IN (?))',
step_ids, result_ids)
.select('assets.*')
.left_outer_joins(:asset_text_datum)
.where(team: user.teams)
a_query = s_query = ''
@ -144,7 +126,7 @@ class Asset < ApplicationRecord
a_query = '\\y(' + a_query + ')\\y'
s_query = s_query.tr('\'', '"')
ids = ids.where(
new_query = new_query.where(
"(trim_html_tags(assets.file_file_name) #{like} ? " \
"OR asset_text_data.data_vector @@ to_tsquery(?))",
a_query,
@ -165,7 +147,7 @@ class Asset < ApplicationRecord
.map { |t| t + ':*' }
.join('|')
.tr('\'', '"')
ids = ids.where(
new_query = new_query.where(
"(trim_html_tags(assets.file_file_name) #{like} ANY (array[?]) " \
"OR asset_text_data.data_vector @@ to_tsquery(?))",
a_query,
@ -175,19 +157,14 @@ class Asset < ApplicationRecord
# Show all results if needed
if page != Constants::SEARCH_NO_LIMIT
ids = ids
.limit(Constants::SEARCH_LIMIT)
.offset((page - 1) * Constants::SEARCH_LIMIT)
end
Asset
.joins('LEFT JOIN asset_text_data ON ' \
' assets.id = asset_text_data.asset_id')
.select('assets.*')
.select("ts_headline(data, to_tsquery('" +
new_query.select("ts_headline(data, to_tsquery('" +
sanitize_sql_for_conditions(s_query) +
"'), 'StartSel=<mark>, StopSel=</mark>') headline")
.where('assets.id IN (?)', ids)
.limit(Constants::SEARCH_LIMIT)
.offset((page - 1) * Constants::SEARCH_LIMIT)
else
new_query
end
end
def is_image?

View file

@ -68,15 +68,26 @@ module SearchableModel
end
else
unless attrs.empty?
# quick fix to enable searching by repositoy_row id
id_index = { present: false }
where_str =
(attrs.map.with_index do |a, i|
if a == 'repository_rows.id'
id_index = { present: true, val: i }
"(#{a}) = :t#{i} OR "
else
"(trim_html_tags(#{a})) #{like} :t#{i} OR "
end
end
).join[0..-5]
vals = (
attrs.map.with_index do |_, i|
if id_index[:present] && id_index[:val] == i
["t#{i}".to_sym, sanitize_sql_like(query).to_i]
else
["t#{i}".to_sym, "%#{sanitize_sql_like(query.to_s)}%"]
end
end
).to_h
return where(where_str, vals)

View file

@ -343,6 +343,7 @@ class MyModule < ApplicationRecord
.where(repository_id: repository_id)
.order(created_at: order).find_each do |row|
row_json = []
row_json << row.id
row_json << row.name
row_json << I18n.l(row.created_at, format: :full)
row_json << row.created_by.full_name
@ -351,6 +352,7 @@ class MyModule < ApplicationRecord
# Prepare column headers
headers = [
I18n.t('repositories.table.id'),
I18n.t('repositories.table.row_name'),
I18n.t('repositories.table.added_on'),
I18n.t('repositories.table.added_by')

View file

@ -16,7 +16,6 @@ Canaid::Permissions.register_for(Project) do
# project: read, read activities, read comments, read users, read archive,
# read notifications
# reports: read
# samples: read
can :read_project do |user, project|
user.is_member_of_project?(project) ||
user.is_admin_of_team?(project.team) ||

View file

@ -55,7 +55,9 @@ class RepositoryDatatableService
def search(value)
includes_json = { repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES }
searchable_attributes = ['repository_rows.name', 'users.full_name'] +
searchable_attributes = ['repository_rows.name',
'users.full_name',
'repository_rows.id'] +
Extends::REPOSITORY_EXTRA_SEARCH_ATTR
RepositoryRow.left_outer_joins(:created_by)
@ -76,6 +78,7 @@ class RepositoryDatatableService
def sortable_columns
array = [
'assigned',
'repository_rows.id',
'repository_rows.name',
'repository_rows.created_at',
'users.full_name'

View file

@ -24,10 +24,12 @@ module RepositoryZipExport
when -1, -2
next
when -3
I18n.t('repositories.table.row_name')
I18n.t('repositories.table.id')
when -4
I18n.t('repositories.table.added_by')
I18n.t('repositories.table.row_name')
when -5
I18n.t('repositories.table.added_by')
when -6
I18n.t('repositories.table.added_on')
else
column = RepositoryColumn.find_by_id(c_id)
@ -44,10 +46,12 @@ module RepositoryZipExport
when -1, -2
next
when -3
row.name
row.id
when -4
row.created_by.full_name
row.name
when -5
row.created_by.full_name
when -6
I18n.l(row.created_at, format: :full)
else
cell = row.repository_cells

View file

@ -0,0 +1,31 @@
# frozen_string_literal: true
module SmartAnnotations
class PermissionEval
class << self
include Canaid::Helpers::PermissionsHelper
def check(user, type, object)
send("validate_#{type}_permissions", user, object)
end
private
def validate_prj_permissions(user, object)
can_read_project?(user, object)
end
def validate_exp_permissions(user, object)
can_read_experiment?(user, object)
end
def validate_tsk_permissions(user, object)
can_read_experiment?(user, object.experiment)
end
def validate_rep_item_permissions(user, object)
can_read_team?(user, object.repository.team)
end
end
end
end

View file

@ -0,0 +1,63 @@
# frozen_string_literal: true
module SmartAnnotations
class Preview
class << self
def html(name, type, object)
send("generate_#{type}_snippet", name, object)
end
private
ROUTES = Rails.application.routes.url_helpers
def generate_prj_snippet(_, object)
if object.archived?
return "<span class='sa-type'>PRJ</span><a href='" \
"#{ROUTES.projects_archive_path}'>#{object.name}</a>" \
"#{I18n.t('atwho.res.archived')}"
end
"<span class='sa-type'>PRJ</span>" \
"<a href='#{ROUTES.project_path(object)}'>#{object.name}</a>"
end
def generate_exp_snippet(_, object)
if object.archived?
return "<span class='sa-type'>EXP</span><a href='" \
"#{ROUTES.experiment_archive_project_path(object.project)}'>" \
"#{object.name}</a> #{I18n.t('atwho.res.archived')}"
end
"<span class='sa-type'>EXP</span>" \
"<a href='#{ROUTES.canvas_experiment_path(object)}'>#{object.name}</a>"
end
def generate_tsk_snippet(_, object)
if object.archived?
return "<span class='sa-type'>TSK</span><a href='" \
"#{ROUTES.module_archive_experiment_path(
object.experiment
)}'>#{object.name}</a> #{I18n.t('atwho.res.archived')}"
end
"<span class='sa-type'>TSK</span>" \
"<a href='#{ROUTES.protocols_my_module_path(object)}'>" \
"#{object.name}</a>"
end
def generate_rep_item_snippet(name, object)
if object
repository_name = object.repository.name
return "<span class='sa-type'>" \
"#{trim_repository_name(repository_name)}</span>" \
"<a href='#{ROUTES.repository_row_path(object)}' " \
"class='record-info-link'>#{object.name}</a>"
end
"<span class='sa-type'>REP</span>" \
"#{name} #{I18n.t('atwho.res.deleted')}"
end
def trim_repository_name(name)
name.strip.slice(0..2).upcase
end
end
end
end

View file

@ -0,0 +1,66 @@
# frozen_string_literal: true
require 'smart_annotations/permision_eval'
require 'smart_annotations/preview'
module SmartAnnotations
class TagToHtml
attr_reader :html
def initialize(user, text)
parse(user, text)
end
private
REGEX = /\[\#(.*?)~(prj|exp|tsk|rep_item)~([0-9a-zA-Z]+)\]/
OBJECT_MAPPINGS = { prj: Project,
exp: Experiment,
tsk: MyModule,
rep_item: RepositoryRow }.freeze
def parse(user, text)
@html = text.gsub(REGEX) do |el|
value = extract_values(el)
type = value[:object_type]
begin
object = fetch_object(type, value[:object_id])
# handle repository_items edge case
if type == 'rep_item'
repository_item(value[:name], user, type, object)
else
next unless object && SmartAnnotations::PermissionEval.check(user,
type,
object)
SmartAnnotations::Preview.html(nil, type, object)
end
rescue ActiveRecord::RecordNotFound
next
end
end
end
def repository_item(name, user, type, object)
if object && SmartAnnotations::PermissionEval.check(user, type, object)
return SmartAnnotations::Preview.html(nil, type, object)
end
SmartAnnotations::Preview.html(name, type, object)
end
def extract_values(element)
match = element.match(REGEX)
{
name: match[1],
object_type: match[2],
object_id: match[3].base62_decode
}
end
def fetch_object(type, id)
klass = OBJECT_MAPPINGS.fetch(type.to_sym) do
raise ActiveRecord::RecordNotFound.new("#{type} does not exist")
end
klass.find_by_id(id)
end
end
end

View file

@ -1,4 +1,4 @@
<button class="btn btn-greyed">
<button class="btn btn-default">
<span class="glyphicon glyphicon-remove"></span>
<%= t("my_modules.buttons.uncomplete") %>
</button>

View file

@ -5,10 +5,10 @@
<div id="results-toolbar">
<div class="pull-right">
<button class="btn btn-greyed" id="results-collapse-btn">
<button class="btn btn-default" id="results-collapse-btn">
<span class="glyphicon glyphicon-collapse-up"></span>
<span class="hidden-xs-custom"><%= t'my_modules.results.collapse_label' %></button></span>
<button class="btn btn-greyed" id="results-expand-btn">
<button class="btn btn-default" id="results-expand-btn">
<span class="glyphicon glyphicon-collapse-down"></span>
<span class="hidden-xs-custom"><%= t'my_modules.results.expand_label' %></button></span>
</div>

View file

@ -10,10 +10,10 @@
<span class="hidden-xs"><%=t "protocols.steps.new_step" %></span>
</a>
<% end %>
<a class="btn btn-greyed" data-action="collapse-steps">
<a class="btn btn-default" data-action="collapse-steps">
<span class="glyphicon glyphicon-collapse-up"></span>
<span class="hidden-xs"><%= t("protocols.steps.collapse_label") %></a></span>
<a class="btn btn-greyed" data-action="expand-steps">
<a class="btn btn-default" data-action="expand-steps">
<span class="glyphicon glyphicon-collapse-down"></span>
<span class="hidden-xs"><%= t("protocols.steps.expand_label") %></a></span>
</div>

View file

@ -12,7 +12,9 @@
<h4 class="modal-title"><%=t 'zip_export.modal_label' %></h4>
</div>
<div class="modal-body">
<%=t('zip_export.repository_html', repository: repository.name) %>
<div><%=t('zip_export.repository_header_html', repository: repository.name) %></div>
<div class="alert alert-info" role="alert"><%=t 'zip_export.files_alert' %></div>
<div><%=t 'zip_export.repository_footer_html' %></div>
</div>
<div class="modal-footer">
<button type='button' class='btn btn-primary' data-dismiss='modal' id='export-repositories'> <%=t 'my_modules.repository.export' %> </button>

View file

@ -13,7 +13,7 @@
remote: true) do |f|%>
<%= f.hidden_field :team_id, value: current_team.id %>
<div class="modal-body">
<h4><%= t("teams.parse_sheet.help_text") %></h4>
<p><%= t("teams.parse_sheet.help_text") %></p>
<div style="overflow-x: scroll">
<table class="table parse-records-table" style="display: block">
<thead>
@ -62,6 +62,12 @@
<div id="import-errors-container">
</div>
<div class="alert alert-info" role="alert">
<ul>
<li><%= t('repositories.modal_parse.warning_1') %></li>
<li><%= t('repositories.modal_parse.warning_2') %></li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" onClick="pageReload()"><%= t('general.cancel')%></button>

View file

@ -7,14 +7,23 @@
</div>
<div class="modal-body">
<ol class="breadcrumb breadcrumb-repository">
<span class="fa fa-cubes" aria-hidden="true"></span>
<%= t('repositories.repository', name: @repository_row.repository.name) %>
</ol>
<p>
<span>
<%= t "repository_row.modal_info.added_on" %>
<%=t 'repository_row.modal_info.ID' %>
<%= @repository_row.id %>
</span>
<br>
<span>
<%= t "repository_row.modal_info.added_on" %>:
<%= l @repository_row.created_at, format: :full %>
</span>
<br>
<span>
<%= t "repository_row.modal_info.added_by" %>
<%= t "repository_row.modal_info.added_by" %>:
<%= @repository_row.created_by.full_name %>
</span>
<% @repository_row.repository_cells.each do |repository_cell| %>

View file

@ -3,7 +3,7 @@
data-current-uri="<%= request.original_url %>"
data-repository-id="<%= repository.id %>"
data-source="<%= repository_index_link %>"
data-num-columns="<%= 5 + repository.repository_columns.count %>"
data-num-columns="<%= 6 + repository.repository_columns.count %>"
data-create-record="<%= repository_repository_rows_path(repository) %>"
data-delete-record="<%= repository_delete_records_path(repository) %>"
data-max-dropdown-length="<%= Constants::NAME_TRUNCATION_LENGTH_DROPDOWN %>"
@ -16,6 +16,7 @@
<tr>
<th id="checkbox"><input name="select_all" value="1" type="checkbox"></th>
<th id="assigned"><%= t("repositories.table.assigned") %></th>
<th id="row-id"><%= t("repositories.table.id") %></th>
<th id="row-name"><%= t("repositories.table.row_name") %></th>
<th id="added-on"><%= t("repositories.table.added_on") %></th>
<th id="added-by"><%= t("repositories.table.added_by") %></th>

View file

@ -0,0 +1,34 @@
<%= content_for :sidebar do %>
<div id="slide-panel" class="visible">
<div class="tree">
<ul>
<li>
<span class="tree-link line-wrap no-indent">
<strong title="<%= t('libraries.sidebar.title') %>"><%= t('libraries.sidebar.title') %></strong>
</span>
</li>
<% repositories.each do |repository| %>
<% cache repository do %>
<li class="<%= 'active parent_li' if current_page?(repository_path(repository)) %>" >
<span class="tree-link line-wrap no-indent">
<% if current_page?(repository_path(repository)) %>
<span title="<%= repository.name %>"><%= repository.name %></span>
<% else %>
<%= link_to repository.name,
repository_path(repository),
data: { 'no-turbolink' => 'true' } %>
<% end %>
</span>
</li>
<% end %>
<% end %>
</ul>
</div>
</div>
<% end %>
<script>
$(document).ready(function() {
$('#wrapper').show();
})
</script>

View file

@ -1,51 +1,21 @@
<% provide(:head_title, t("repositories.index.head_title")) %>
<% provide(:head_title, t("libraries.index.head_title")) %>
<% if current_team %>
<%= render partial: "repositories/breadcrumbs.html.erb",
locals: { teams: @teams, current_team: current_team, type: @type } %>
<!-- Nav tabs -->
<ul class="nav nav-tabs nav-settings" role="tablist" id="repository-tabs">
<% @repositories.each do |repo| %>
<li role="presentation">
<a href="#custom_repo_<%= repo.id %>"
data-toggle="tab"
data-repo-table="#repository-table-<%= repo.id %>"
aria-controls="custom_repo_<%= repo.id %>"
data-url="<%=team_repository_show_tab_path(current_team, repo)%>"
title="<%=repo.name%>"><%= truncate(repo.name, length: Constants::NAME_TRUNCATION_LENGTH) %></a>
</li>
<% end %>
<!-- Add new repository tab -->
<li role="presentation"
<% unless can_create_repositories?(current_team) || current_team.repositories.count < Constants::REPOSITORIES_LIMIT %>
class="disabled"
<% end %>>
<a
<% if can_create_repositories?(current_team) && current_team.repositories.count < Constants::REPOSITORIES_LIMIT %>
href="<%= create_modal_team_repositories_path %>"
class='create-repository'
data-remote='true'
<% end %>>
<span class="glyphicon glyphicon-plus"></span>
<span class="hidden-xs">&nbsp;<%= t('repositories.index.add_new_repository_tab') %></span>
</a>
</li>
</ul>
<!-- Tab panes -->
<div class="tab-content">
<% @repositories.each do |repo| %>
<div class="tab-pane tab-pane-settings" id="custom_repo_<%= repo.id %>">
<!-- Tab Content -->
<div class="container-fluid">
<div class="tab-content-body"></div>
<%= render partial: "sidebar", locals: { repositories: @repositories } %>
<%
# show only if no repositories present. If the team will have them we will
# handle this in left side navigation bar
%>
<div class="jumbotron text-center" style="margin-top:25%">
<strong><%=t 'libraries.index.no_libraries.text' %></strong>
<h2><strong><%=t 'libraries.index.no_libraries.title' %><strong></h2>
<br />
<%= link_to t('libraries.index.no_libraries.create_new_button'),
create_modal_team_repositories_path(current_team),
class: "btn btn-primary btn-lg",
id: "create-new-repository",
remote: true %>
</div>
</div>
<% end %>
</div>
<% else %>
<!-- If member of no teams -->
<div class="jumbotron">
@ -54,6 +24,4 @@
</div>
<% end %>
<%= stylesheet_link_tag 'datatables' %>
<%= javascript_include_tag 'repositories/repository_datatable' %>
<%= javascript_include_tag "repositories/index", "data-turbolinks-track" => true %>

View file

@ -1,13 +1,12 @@
<%= render partial: "repositories/delete_record_modal.html.erb" %>
<%= render partial: "repositories/delete_column_modal.html.erb" %>
<%= render partial: 'repositories/export_repository_modal.html.erb',
locals: { repository: repository } %>
<% provide(:head_title, t("libraries.show.head_title", library: @repository.name)) %>
<%= stylesheet_link_tag 'datatables' %>
<%= render partial: "sidebar", locals: { repositories: @repositories } %>
<div id="alert-container"></div>
<div id="repository-toolbar">
<% if can_create_repository_rows?(repository.team) %>
<% if can_create_repository_rows?(@repository.team) %>
<button type="button" class="btn btn-default editAdd" id="addRepositoryRecord" onclick="onClickAddRecord()">
<span class="glyphicon glyphicon-plus"></span>
<span class="hidden-xs"><%= t("repositories.add_new_record") %></span>
@ -18,7 +17,7 @@
</button>
<% end %>
<% if can_read_team?(repository.team) %>
<% if can_read_team?(@repository.team) %>
<a href="#" class="btn btn-default" id="exportRepositoriesButton" data-turbolinks="false">
<span class="glyphicon glyphicon-cloud-download"></span>
<span class="hidden-xs"><%= t("my_modules.repository.export") %></span>
@ -32,19 +31,19 @@
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="true"
<%= "disabled='disabled'" unless can_manage_repository?(repository) || can_create_repositories?(repository.team) %>>
<%= "disabled" unless can_manage_repository?(@repository) || can_create_repositories?(@repository.team) %>>
<span class="glyphicon glyphicon-cog"></span>
<span class="caret"></span>
</div>
<% if can_manage_repository?(repository) || can_create_repositories?(repository.team) %>
<% if can_manage_repository?(@repository) || can_create_repositories?(@repository.team) %>
<ul class="dropdown-menu pull-right">
<li class="dropdown-header">
<%= t("repositories.index.options_dropdown.header") %>
</li>
<% if can_manage_repository?(repository) %>
<% if can_manage_repository?(@repository) %>
<li>
<%= link_to t('repositories.index.options_dropdown.rename'),
team_repository_rename_modal_path(repository_id: repository),
team_repository_rename_modal_path(current_team, repository_id: @repository),
class: "rename-repo-option",
remote: true %>
</li>
@ -53,19 +52,19 @@
repository_repository_columns_path(repository) %>
</li>
<% end %>
<% if can_create_repositories?(repository.team) %>
<% if can_create_repositories?(@repository.team) %>
<li>
<%= link_to t('repositories.index.options_dropdown.copy'),
team_repository_copy_modal_path(repository_id: repository),
team_repository_copy_modal_path(current_team, repository_id: @repository),
class: "copy-repo-option",
remote: true %>
</li>
<% end %>
<% if can_manage_repository?(repository) %>
<% if can_manage_repository?(@repository) %>
<li role="separator" class="divider"></li>
<li>
<%= link_to t('repositories.index.modal_delete.delete'),
team_repository_destroy_modal_path(repository_id: repository),
team_repository_destroy_modal_path(current_team, repository_id: @repository),
class: "delete-repo-option",
remote: true %>
</li>
@ -75,8 +74,40 @@
</div>
</div>
<div id="datatables-buttons" style="display: inline;">
<%= render partial: "columns_reorder_dropdown", formats: :html %>
<div class="new-repository-button">
<% if can_create_repositories?(@repository.team) %>
<%= link_to t('libraries.index.no_libraries.create_new_button'),
create_modal_team_repositories_path(@repository.team),
class: "btn btn-default",
id: "create-new-repository",
remote: true %>
<% end %>
</div>
<div id="repository-columns-dropdown" class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown">
<%= t('repositories.columns') %>
<span class="caret"></span>
</button>
<ul class="dropdown-menu dropdown-menu-right smart-dropdown" id="repository-columns-list">
<% if can_create_repository_columns?(@repository.team) %>
<li class="add-new-column-form">
<div id="new-column-form" class="form-group" data-action="<%= repository_repository_columns_path(@repository) %>">
<div class="input-group">
<input class="form-control" id="new-column-name" placeholder="<%= t("repositories.column_new_text") %>">
<span class="input-group-btn">
<a id="add-new-column-button" class="btn btn-primary">
<%= t("repositories.column_create") %>
</a>
</span>
</div>
</div>
</li>
<% end %>
</ul>
</div>
</div>
</div>
@ -98,7 +129,7 @@
<span class="hidden-xs-custom"><%= t("repositories.edit_record") %></span>
</button>
<% if can_manage_repository_rows?(repository.team) %>
<% if can_manage_repository_rows?(@repository.team) %>
<button type="button" class="btn btn-default"
id="deleteRepositoryRecordsButton" data-target="#deleteRepositoryRecord" data-toggle="modal" disabled>
<span class="glyphicon glyphicon-trash"></span>
@ -111,10 +142,19 @@
<%= render partial: "repositories/repository_table.html.erb",
locals: {
repository: repository,
repository_index_link: repository_table_index_path(repository)
repository: @repository,
repository_index_link: repository_table_index_path(@repository)
}
%>
<%= render partial: 'repositories/import_repository_records_modal.html.erb',
locals: { repository: repository } %>
locals: { repository: @repository } %>
<%= render partial: "repositories/delete_record_modal.html.erb" %>
<%= render partial: "repositories/delete_column_modal.html.erb" %>
<%= render partial: 'repositories/export_repository_modal.html.erb',
locals: { repository: @repository } %>
<%= javascript_include_tag 'repositories/edit', 'data-turbolinks-track' => true %>
<%= javascript_include_tag 'repositories/repository_datatable' %>
<%= javascript_include_tag "repositories/show", "data-turbolinks-track" => true %>
<%= javascript_include_tag "repositories/index", "data-turbolinks-track" => true %>

View file

@ -51,7 +51,8 @@
>
<a href="?<%= {category: 'projects', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @project_search_count %></span>
<span class="glyphicon glyphicon-blackboard"></span>
<%= t'Projects' %>
@ -64,7 +65,8 @@
>
<a href="?<%= {category: 'experiments', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @experiment_search_count %></span>
<%= fa_icon 'flask' %>
<%= t'Experiments' %>
@ -77,7 +79,8 @@
>
<a href="?<%= {category: 'modules', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @module_search_count %></span>
<span class="glyphicon glyphicon-credit-card"></span>
<%= t'Modules' %>
@ -90,7 +93,8 @@
>
<a href="?<%= {category: 'results', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @result_search_count %></span>
<span class="glyphicon glyphicon-modal-window"></span>
<%= t'Results' %>
@ -103,7 +107,8 @@
>
<a href="?<%= {category: 'tags', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @tag_search_count %></span>
<span class="glyphicon glyphicon-tags"></span>
<%= t'Tags' %>
@ -116,7 +121,8 @@
>
<a href="?<%= {category: 'reports', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @report_search_count %></span>
<span class="glyphicon glyphicon-align-left"></span>
<%= t'Reports' %>
@ -129,7 +135,8 @@
>
<a href="?<%= {category: 'protocols', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @protocol_search_count %></span>
<span class="glyphicon glyphicon-list-alt"></span>
<%= t'Protocols' %>
@ -142,7 +149,8 @@
>
<a href="?<%= {category: 'steps', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @step_search_count %></span>
<span class="glyphicon glyphicon-circle-arrow-right"></span>
<%= t'Steps' %>
@ -155,7 +163,8 @@
>
<a href="?<%= {category: 'checklists', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @checklist_search_count %></span>
<span class="glyphicon glyphicon-list"></span>
<%= t'Checklists' %>
@ -168,7 +177,8 @@
>
<a href="?<%= {category: 'samples', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @sample_search_count %></span>
<span class="glyphicon glyphicon-tint"></span>
<%= t'Samples' %>
@ -182,7 +192,8 @@
>
<a href="?<%= {category: 'assets', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @asset_search_count %></span>
<span class="glyphicon glyphicon-file"></span>
<%= t'Assets' %>
@ -195,7 +206,8 @@
>
<a href="?<%= {category: 'tables', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @table_search_count %></span>
<span class="glyphicon glyphicon-th"></span>
<%= t'Tables' %>
@ -208,7 +220,8 @@
>
<a href="?<%= {category: 'comments', q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= @comment_search_count %></span>
<span class="glyphicon glyphicon-comment"></span>
<%= t'Comments' %>
@ -229,7 +242,8 @@
<a href="?<%= {category: 'repositories',
repository: values[:id], q: @search_query,
whole_word: @search_whole_word, whole_phrase: @search_whole_phrase,
match_case: @search_case, utf8: '✓'}.to_query %>">
match_case: @search_case, utf8: '✓',
search_id: @search_id}.to_query %>">
<span class="badge pull-right"><%= values[:count] %></span>
<%= repository %>
</a>

View file

@ -12,13 +12,6 @@
<%= render partial: "search/results/partials/asset_text.html.erb", locals: { asset: asset, query: search_query } %>
</h5>
<!-- Display asset contents if it exists -->
<% if asset.headline.present? && !asset.headline.empty? && asset.headline.include?("<mark>") %>
<blockquote class="blockquote-search">
<p><%= highlight(sanitize_input(asset.headline), search_query.strip.split(/\s+/)) %></p>
</blockquote>
<% end %>
<p>
<span>
<%=t "search.index.created_at" %>
@ -93,6 +86,24 @@
<%= render partial: "search/results/partials/team_text.html.erb",
locals: { team: asset.result.my_module.experiment.project.team } %>
</span>
<% elsif asset.repository_asset_value %>
<span>
<%=t "search.index.repository_row" %>
<%= render partial: "search/results/partials/repository_row_text.html.erb",
locals: { repository_row: asset.repository_asset_value.repository_cell.repository_row } %>
</span>
<br>
<span>
<%=t "search.index.repository" %>
<%= render partial: "search/results/partials/repository_text.html.erb",
locals: { repository: asset.repository_asset_value.repository_cell.repository_row.repository } %>
</span>
<br>
<span>
<%=t "search.index.team" %>
<%= render partial: "search/results/partials/team_text.html.erb",
locals: { team: asset.team } %>
</span>
<% end %>
</p>

View file

@ -6,13 +6,11 @@
</h5>
<p>
<% repository_row.repository_cells.each do |cell| %>
<span>
<%=t "search.index.repositories.custom_column", column: cell.repository_column.name %>
<%= highlight cell.value.data, search_query.strip.split(/\s+/) %>
<%=t 'repository_row.modal_info.ID' %>
<%= repository_row.id %>
</span>
<br>
<% end %>
<br />
<span>
<%=t "search.index.repositories.added_on" %>
<%=l repository_row.created_at, format: :full %>
@ -22,6 +20,13 @@
<%=t "search.index.repositories.added_by" %>
<%= highlight repository_row.created_by.full_name, search_query.strip.split(/\s+/) %>
</span>
<% repository_row.repository_cells.each do |cell| %>
<span>
<%=t "search.index.repositories.custom_column", column: cell.repository_column.name %>
<%= highlight cell.value.data, search_query.strip.split(/\s+/) %>
</span>
<br>
<% end %>
</p>
<p>

View file

@ -1,15 +1,43 @@
<% query ||= nil %>
<% asset_read_allowed = false %>
<% text = query.present? ? highlight(asset.file_file_name, query.strip.split(/\s+/)) : asset.file_file_name %>
<% if asset.step %>
<% protocol = asset.step.protocol %>
<% if can_read_protocol_in_module?(protocol) ||
can_read_protocol_in_repository?(protocol) ||
(asset.result && can_read_experiment?(protocol.my_module.experiment)) %>
can_read_protocol_in_repository?(protocol) %>
<% asset_read_allowed = true %>
<a href="<%= download_asset_path asset %>" target="_blank">
<%= text %>
</a>
<% else %>
<%= text %>
<% end %>
<% elsif asset.result %>
<% if can_read_experiment?(asset.result.my_module.experiment) %>
<% asset_read_allowed = true %>
<a href="<%= download_asset_path asset %>" target="_blank">
<%= text %>
</a>
<% else %>
<%= text %>
<% end %>
<% elsif asset.repository_asset_value %>
<% if can_read_team?(asset.repository_asset_value.repository_cell.repository_row.repository.team) %>
<% asset_read_allowed = true %>
<a href="<%= download_asset_path asset %>" target="_blank">
<%= text %>
</a>
<% else %>
<%= text %>
<% end %>
<% else %>
<%= text %>
<% end %>
<!-- Display asset contents if it exists -->
<% if asset_read_allowed && asset.headline.present? && asset.headline.include?("<mark>") %>
<blockquote class="blockquote-search">
<p><%= highlight(sanitize_input(asset.headline), query.strip.split(/\s+/)) %></p>
</blockquote>
<% end %>

View file

@ -0,0 +1,7 @@
<% if can_read_team?(repository_row.repository.team) %>
<%= route_to_other_team repository_path(id: repository_row.repository.id),
repository_row.repository.team,
repository_row.name %>
<% else %>
<%= repository_row.name %>
<% end %>

View file

@ -0,0 +1,7 @@
<% if can_read_team?(repository.team) %>
<%= route_to_other_team repository_path(id: repository.id),
repository.team,
repository.name %>
<% else %>
<%= repository.name %>
<% end %>

View file

@ -1,13 +1,26 @@
<div id="left-menu-bar" class="menu-bar">
<ul class="nav">
<li class="text-center">
<span id="sideBarLeft"
class="glyphicon glyphicon-chevron-left"
aria-hidden="true"
onclick="SideBarToggle.hide()"
></span>
<span id="sideBarRight"
class="glyphicon glyphicon-chevron-right"
aria-hidden="true"
onclick="SideBarToggle.show()"
style="display:none;"
></span>
</li>
<li class="<%= "active" if projects_are_selected? %>">
<%= link_to projects_path, id: "projects-link", class: "toggle-sidebar-link", title: t('left_menu_bar.projects') do %>
<%= link_to projects_path, id: "projects-link", title: t('left_menu_bar.projects') do %>
<span class="glyphicon glyphicon-home"></span>
<span><%= t('left_menu_bar.projects') %></span>
<% end %>
</li>
<li class="<%= "active" if repositories_are_selected? %>">
<%= link_to team_repositories_path(current_team), id: "repositories-link", title: t('left_menu_bar.repositories') do %>
<%= link_to repositories_path, id: "repositories-link", title: t('left_menu_bar.repositories') do %>
<span class="fa fa-cubes" aria-hidden="true"></span>
<span><%= t('left_menu_bar.repositories') %></span>
<% end %>
@ -65,3 +78,5 @@
</li>
</ul>
</div>
<%= javascript_include_tag("sidebar_toggle") %>

View file

@ -1,6 +1,5 @@
<%= content_for :sidebar do %>
<div id="slide-panel" class="visible">
<div class="tree">
<ul>
<% if project_page? && action_name == 'index' ||

View file

@ -14,13 +14,13 @@
<% end %>
</ul>
</div>
<div class="notifications-footer">
<% if @overflown %>
<a class="btn-more-notifications col-xs-12" href="<%= @more_notifications_url %>" data-remote="true">
<div class="text-center">
<a class="btn btn-default btn-more-notifications" href="<%= @more_notifications_url %>" data-remote="true">
<span><%= t('notifications.show_more') %></span>
</a>
<% end %>
</div>
<% end %>
</div>
<%= javascript_include_tag("notifications") %>

View file

@ -33,7 +33,7 @@
<%= image_tag @user_avatar_url %>
</div>
<div class="avatar-edit">
<div class="btn btn-greyed btn-sm">
<div class="btn btn-grey btn-sm">
<span class="glyphicon glyphicon-pencil"></span>
<%=t "users.registrations.edit.avatar_btn" %>
</div>

View file

@ -84,6 +84,8 @@ Rails.application.config.assets.precompile +=
%w(repositories/my_module_repository.js)
Rails.application.config.assets.precompile += %w(activities/index.js)
Rails.application.config.assets.precompile += %w(repository_columns/index.js)
Rails.application.config.assets.precompile += %w(repositories/show.js)
Rails.application.config.assets.precompile += %w(sidebar_toggle.js)
# Libraries needed for Handsontable formulas
Rails.application.config.assets.precompile += %w(lodash.js)

View file

@ -144,40 +144,21 @@ class Constants
].freeze
# Theme colors
COLOR_THEME_PRIMARY = '#37a0d9'.freeze # $color-theme-primary
COLOR_THEME_SECONDARY = '#8fd13f'.freeze # $color-theme-secondary
COLOR_THEME_DARK = '#6d6e71'.freeze # $color-theme-dark
BRAND_PRIMARY = '#37a0d9'.freeze # $brand-primary
BRAND_DEFAULT = '#8fd13f'.freeze # $brand-default
# Grayscale colors
COLOR_WHITE = '#ffffff'.freeze # $color-white
COLOR_ALABASTER = '#fcfcfc'.freeze # $color-alabaster
COLOR_SNOW = '#f9f9f9'.freeze # $color-snow
COLOR_WILD_SAND = '#f5f5f5'.freeze # $color-wild-sand
COLOR_CONCRETE = '#f2f2f2'.freeze # $color-concrete
COLOR_GALLERY = '#eeeeee'.freeze # $color-gallery
COLOR_GAINSBORO = '#e3e3e3'.freeze # $color-gainsboro
COLOR_ALTO = '#d2d2d2'.freeze # $color-alto
COLOR_SILVER = '#c5c5c5'.freeze # $color-silver
COLOR_DARK_GRAY = '#adadad'.freeze # $color-dark-gray
COLOR_SILVER_CHALICE = '#a0a0a0'.freeze # $color-silver-chalice
COLOR_GRAY = '#909088'.freeze # $color-gray
COLOR_DOVE_GRAY = '#666666'.freeze # $color-dove-gray
COLOR_EMPEROR = '#555555'.freeze # $color-emperor
COLOR_MINE_SHAFT = '#333333'.freeze # $color-mine-shaft
COLOR_NERO = '#262626'.freeze # $color-nero
COLOR_BLACK = '#000000'.freeze # $color-black
COLOR_GRAY_LIGHT_YADCF = '#cccccc'.freeze # $color-gray-light-yadcf
COLOR_GRAY_DARK_YADCF = '#a9a9a9'.freeze # $color-gray-dark-yadcf
# Miscelaneous colors
COLOR_MYSTIC = '#eaeff2'.freeze # $color-mystic
COLOR_CANDLELIGHT = '#ffda23'.freeze # $color-candlelight
COLOR_BLUE_YADCF = '#337ab7'.freeze # $color-blue-yadcf
# Red colors
COLOR_MOJO = '#cf4b48'.freeze # $color-mojo
COLOR_APPLE_BLOSSOM = '#a94442'.freeze # $color-apple-blossom
COLOR_MILANO_RED = '#a70b05'.freeze # $color-milano-red
#=============================================================================
# External URLs
@ -861,17 +842,17 @@ class Constants
REPOSITORY_TABLE_DEFAULT_STATE = {
'time' => 0,
'start' => 0,
'length' => 5,
'order' => [[2, 'desc']],
'length' => 6,
'order' => [[3, 'desc']],
'search' => { 'search' => '',
'smart' => true,
'regex' => false,
'caseInsensitive' => true },
'columns' => [],
'assigned' => 'assigned',
'ColReorder' => [*0..4]
'ColReorder' => [*0..5]
}
5.times do
6.times do
REPOSITORY_TABLE_DEFAULT_STATE['columns'] << {
'visible' => true,
'search' => { 'search' => '',

View file

@ -52,11 +52,13 @@ class Extends
# Extra attributes used for search in repositories, text columns
# are only supported
REPOSITORY_EXTRA_SEARCH_ATTR = ['repository_text_values.data',
'repository_list_items.data']
'repository_list_items.data',
'assets.file_file_name']
# Array of includes used in search query for repository rows
REPOSITORY_SEARCH_INCLUDES = [:repository_text_value,
repository_list_value: :repository_list_item]
repository_list_value: :repository_list_item,
repository_asset_value: :asset]
# List of implemented core API versions
API_VERSIONS = ['20170715']

View file

@ -152,6 +152,8 @@ en:
description: "Description: "
no_description: "No description"
team: "Team: "
repository: "Repository: "
repository_row: "Repository item: "
project: "Project: "
experiment: "Experiment: "
protocol: "Protocol: "
@ -211,7 +213,6 @@ en:
one: "1 day"
other: "%{count} days"
module_one_day_due_html: "Task <em>%{module}</em> is due in less than 1 day."
new_comment: "New comment"
user_role: "Role: "
user_full_name: "User: "
edit_user: "Edit role"
@ -873,6 +874,7 @@ en:
success_flash: "Table result successfully deleted."
repositories:
repository: "Repository: %{name}"
index:
head_title: "Repositories"
title: "Repositories"
@ -917,6 +919,7 @@ en:
breadcrumbs:
repositories: "Repositories"
table:
id: 'ID'
assigned: "Assigned"
row_name: "Name"
added_on: "Added on"
@ -963,6 +966,8 @@ en:
delete: "Delete column"
modal_parse:
title: 'Import items'
warning_1: 'Be careful when importing into Dropdown column/s! Each new unique cell value from the file will create a new Dropdown option. This could result in large amounts of Dropdown options.'
warning_2: 'Importing into file columns is not supported.'
modal_import:
title: 'Import items'
notice: 'You may upload .csv file (comma separated) or tab separated file (.txt or .tsv) or Excel file (.xlsx). First row should include header names, followed by rows with sample data.'
@ -1015,8 +1020,19 @@ en:
no_column: "No columns"
edit_column: "Edit"
back_to_repository_html: "<span class='glyphicon glyphicon-chevron-left'></span> Back to %{repository}"
sidebar:
title: "Inventories"
index:
head_title: "Inventories"
no_libraries:
text: "You don't have any inventories."
title: "Please create your first Inventory"
create_new_button: "Create New Inventory"
show:
head_title: "Inventories | %{library}"
repository_row:
modal_info:
ID: 'ID:'
head_title: "Information for item '%{repository_row}'"
added_on: "Added on"
added_by: "Added by"
@ -1870,7 +1886,9 @@ en:
expired_description: 'Please export the data again in order to receive a new link.'
modal_label: 'Export request received'
modal_html: "<p>Your export request is being processed.</p><p>When completed we will <strong>send an email to %{email}</strong> inbox with a link to your exported samples. Note that the link will expire in 7 days.</p>"
repository_html: '<p>You are about to export selected items in repository %{repository}</p> <br> Repository will be exported in a .csv file format. You will receive <strong>email with a link</strong> where you can download it.'
repository_header_html: 'You are about to export selected items in inventory %{repository}.'
files_alert: 'Files uploaded to inventory items will not be exported. Only filenames will be exported.'
repository_footer_html: 'Inventory will be exported in a .csv file format. You will receive <strong>email with a link</strong> where you can download it.'
export_error: "Error when creating zip export."
# This section contains general words that can be used in any parts of

View file

@ -153,8 +153,6 @@ Rails.application.routes.draw do
get 'create_modal', to: 'repositories#create_modal',
defaults: { format: 'json' }
end
get 'show_tab', to: 'repositories#show_tab',
defaults: { format: 'json' }
get 'destroy_modal', to: 'repositories#destroy_modal',
defaults: { format: 'json' }
get 'rename_modal', to: 'repositories#rename_modal',

View file

@ -62,7 +62,7 @@ describe RepositoryRowsController, type: :controller do
describe 'json object' do
it 'returns a valid object' do
params = { order: { 0 => { column: '3', dir: 'asc' } },
params = { order: { 0 => { column: '4', dir: 'asc' } },
drow: '0',
search: { value: '' },
length: '10',
@ -77,7 +77,7 @@ describe RepositoryRowsController, type: :controller do
describe 'pagination' do
it 'returns first 10 records' do
params = { order: { 0 => { column: '3', dir: 'asc' } },
params = { order: { 0 => { column: '4', dir: 'asc' } },
drow: '0',
search: { value: '' },
length: '10',
@ -86,11 +86,11 @@ describe RepositoryRowsController, type: :controller do
get :index, params: params, format: :json
response_body = JSON.parse(response.body)
expect(response_body['data'].length).to eq 10
expect(response_body['data'].first['2']).to eq 'row (0)'
expect(response_body['data'].first['3']).to eq 'row (0)'
end
it 'returns next 10 records' do
params = { order: { 0 => { column: '3', dir: 'asc' } },
params = { order: { 0 => { column: '4', dir: 'asc' } },
drow: '0',
search: { value: '' },
length: '10',
@ -99,11 +99,11 @@ describe RepositoryRowsController, type: :controller do
get :index, params: params, format: :json
response_body = JSON.parse(response.body)
expect(response_body['data'].length).to eq 10
expect(response_body['data'].first['2']).to eq 'row (10)'
expect(response_body['data'].first['3']).to eq 'row (10)'
end
it 'returns first 25 records' do
params = { order: { 0 => { column: '2', dir: 'desc' } },
params = { order: { 0 => { column: '4', dir: 'desc' } },
drow: '0',
search: { value: '' },
length: '25',

View file

@ -52,7 +52,7 @@ describe RepositoryDatatableService do
context 'object' do
let(:params) do
{ order: { 0 => { column: '2', dir: 'asc' } },
{ order: { 0 => { column: '3', dir: 'asc' } },
search: { value: 'row' } }
end
@ -65,7 +65,7 @@ describe RepositoryDatatableService do
contitions = subject.send(:build_conditions, params)
expect(contitions[:search_value]).to eq 'row'
expect(contitions[:order_by_column]).to eq(
{ column: 2, dir: 'asc' }
{ column: 3, dir: 'asc' }
)
end
end
@ -73,7 +73,7 @@ describe RepositoryDatatableService do
describe '#sortable_columns' do
it 'returns an array of all columns that are sortable' do
columns = subject.send(:sortable_columns)
expect(columns.length).to eq 5
expect(columns.length).to eq 6
end
end
@ -92,7 +92,7 @@ describe RepositoryDatatableService do
describe 'ordering' do
it 'is ordered by row name asc' do
params = { order: { 0 => { column: '2', dir: 'asc' } },
params = { order: { 0 => { column: '3', dir: 'asc' } },
search: { value: '' } }
subject = RepositoryDatatableService.new(repository,
params,
@ -102,7 +102,7 @@ describe RepositoryDatatableService do
end
it 'is ordered by row name desc' do
params = { order: { 0 => { column: '2', dir: 'desc' } },
params = { order: { 0 => { column: '3', dir: 'desc' } },
search: { value: '' } }
subject = RepositoryDatatableService.new(repository,
params,
@ -121,7 +121,7 @@ describe RepositoryDatatableService do
end
it 'returns only the searched entity' do
params = { order: { 0 => { column: '2', dir: 'desc' } },
params = { order: { 0 => { column: '4', dir: 'desc' } },
search: { value: 'test' } }
subject = RepositoryDatatableService.new(repository,
params,

View file

@ -0,0 +1,47 @@
require 'rails_helper'
require 'smart_annotations/permision_eval'
describe SmartAnnotations::PermissionEval do
let(:subject) { described_class }
let(:user) { create :user }
let(:team) { create :team }
let(:user_team) { create :user_team, user: user, team: team, role: 2 }
let(:project) { create :project, name: 'my project' }
let(:experiment) do
create :experiment, name: 'my experiment',
project: project,
created_by: user,
last_modified_by: user
end
let(:task) { create :my_module, name: 'task', experiment: experiment }
let(:repository) { create :repository, team: team, created_by: user }
let(:repository_item) { create :repository_row, repository: repository }
describe '#validate_prj_permissions/2' do
it 'returns a boolean' do
value = subject.send(:validate_prj_permissions, user, project)
expect(value).to be_in([true, false])
end
end
describe '#validate_exp_permissions/2' do
it 'returns a boolean' do
value = subject.send(:validate_exp_permissions, user, experiment)
expect(value).to be_in([true, false])
end
end
describe '#validate_tsk_permissions/2' do
it 'returns a boolean' do
value = subject.send(:validate_tsk_permissions, user, task)
expect(value).to be_in([true, false])
end
end
describe '#validate_rep_item_permissions/2' do
it 'returns a boolean' do
value = subject.send(:validate_rep_item_permissions, user, repository_item)
expect(value).to be_in([true, false])
end
end
end

View file

@ -0,0 +1,63 @@
require 'rails_helper'
require 'smart_annotations/preview'
describe SmartAnnotations::Preview do
let(:subject) { described_class }
let(:user) { create :user }
let(:project) { create :project, name: 'my project' }
let(:experiment) do
create :experiment, name: 'my experiment',
project: project,
created_by: user,
last_modified_by: user
end
let(:task) { create :my_module, name: 'task', experiment: experiment }
describe 'Project annotations with type prj' do
it 'returns a html snippet' do
snippet = subject.html(nil, 'prj', project)
expect(snippet).to eq(
"<span class='sa-type'>PRJ</span>" \
"<a href='/projects/#{project.id}'>my project</a>"
)
end
end
context 'Experiment annotations with type exp' do
it 'returns a html snippet' do
snippet = subject.html(nil, 'exp', experiment)
expect(snippet).to eq(
"<span class='sa-type'>EXP</span>" \
"<a href='/experiments/#{experiment.id}/canvas'>my experiment</a>"
)
end
end
context 'MyModule annotations with type tsk' do
it 'returns a html snippet' do
snippet = subject.html(nil, 'tsk', task)
expect(snippet).to eq(
"<span class='sa-type'>TSK</span>" \
"<a href='/modules/#{task.id}/protocols'>task</a>"
)
end
end
context 'Repository item annotations with type rep_item' do
it 'returns a html snippet' do
snippet = subject.html('my item', 'rep_item', nil)
expect(snippet).to eq(
'<span class=\'sa-type\'>REP</span>my item (deleted)'
)
end
end
describe '#trim_repository_name/1' do
it 'is returns a 3 letter upcase string' do
trimmed_repository_name = subject.__send__(
:trim_repository_name, 'banana'
)
expect(trimmed_repository_name).to eq('BAN')
end
end
end

View file

@ -0,0 +1,44 @@
require 'rails_helper'
describe SmartAnnotations::TagToHtml do
let!(:user) { create :user }
let!(:team) { create :team }
let!(:user_team) { create :user_team, user: user, team: team, role: 2 }
let!(:project) { create :project, name: 'my project', team: team }
let!(:user_project) do
create :user_project, project: project, user: user, role: 0
end
let(:text) do
"My annotation of [#my project~prj~#{project.id.base62_encode}]"
end
let(:subject) { described_class.new(user, text) }
describe 'Parsed text' do
it 'returns a existing string with smart annotation' do
expect(subject.html).to eq(
"My annotation of <span class='sa-type'>PRJ</span>"\
"<a href='/projects/#{project.id}'>my project</a>"
)
end
end
describe '#extract_values/1' do
it 'returns a parsed hash of smart annotation' do
values = subject.send(:extract_values, '[#my project~prj~1]')
expect(values[:name]).to eq 'my project'
expect(values[:object_id]).to eq 1
expect(values[:object_type]).to eq 'prj'
end
end
describe '#fetch_object/2' do
it 'rises an error if type is not valid' do
expect {
subject.send(:fetch_object, 'banana', project.id)
}.to raise_error(ActiveRecord::RecordNotFound)
end
it 'returns the required object' do
expect(subject.send(:fetch_object, 'prj', project.id)).to eq project
end
end
end

View file

@ -8,13 +8,14 @@
"data": {
"type": "array",
"items":{
"required": ["DT_RowId", "1", "2", "3", "4", "recordEditUrl", "recordUpdateUrl", "recordInfoUrl"],
"required": ["DT_RowId", "1", "2", "3", "4", "5", "recordEditUrl", "recordUpdateUrl", "recordInfoUrl"],
"properties": {
"DT_RowId": { "type": "integer" },
"1": { "type": "string" },
"2": { "type": "string" },
"2": { "type": "integer" },
"3": { "type": "string" },
"4": { "type": "string" },
"5": { "type": "string" },
"recordEditUrl": { "type": "string" },
"recordUpdateUrl": { "type": "string" },
"recordInfoUrl": { "type": "string" }