mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-12-11 14:45:59 +08:00
Merge branch 'develop' into features/new-task-layout
This commit is contained in:
commit
10fdd0c1c7
43 changed files with 641 additions and 208 deletions
2
VERSION
2
VERSION
|
|
@ -1 +1 @@
|
||||||
1.18.6
|
1.18.7
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,31 @@ var Sidebar = (function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadLastState() {
|
function loadLastState() {
|
||||||
|
var currentProject = $(SIDEBAR_ID).attr('data-current-project');
|
||||||
|
var currentExperiment = $(SIDEBAR_ID).attr('data-current-experiment');
|
||||||
|
var currentTask = $(SIDEBAR_ID).attr('data-current-task');
|
||||||
|
|
||||||
|
if (currentProject) {
|
||||||
|
let projectBranch = $(`.tree-child[data-branch-id="pro${currentProject}"]`).attr('data-active', 'true');
|
||||||
|
projectBranch.prev().addClass('active');
|
||||||
|
if (!currentExperiment) projectBranch.closest('.branch').addClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentExperiment) {
|
||||||
|
let experimentBranch = $(`.tree-child[data-branch-id="exp${currentExperiment}"]`).attr('data-active', 'true');
|
||||||
|
experimentBranch.prev().addClass('active');
|
||||||
|
if (!currentTask) {
|
||||||
|
experimentBranch.closest('.branch')
|
||||||
|
.addClass('show-canvas-handler')
|
||||||
|
.addClass('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTask) {
|
||||||
|
$(`.leaf[data-module-id="${currentTask}"]`).addClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
toggleTree($(SIDEBAR_ID).find('.tree-child[data-active="true"]'));
|
toggleTree($(SIDEBAR_ID).find('.tree-child[data-active="true"]'));
|
||||||
toggleTree($(SIDEBAR_ID).find('.tree-child.hidden').filter(sessionStorage.getItem(STORAGE_TREE_KEY)));
|
toggleTree($(SIDEBAR_ID).find('.tree-child.hidden').filter(sessionStorage.getItem(STORAGE_TREE_KEY)));
|
||||||
PerfectSb().update_all();
|
PerfectSb().update_all();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
// scss-lint:disable SelectorDepth
|
// scss-lint:disable SelectorDepth
|
||||||
// scss-lint:disable NestingDepth
|
// scss-lint:disable NestingDepth
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.dashboard-container .calendar-widget {
|
.dashboard-container .calendar-widget {
|
||||||
|
--calendar-day-size: 32px;
|
||||||
grid-column: 10 / span 3;
|
grid-column: 10 / span 3;
|
||||||
grid-row: 1 / span 6;
|
grid-row: 1 / span 6;
|
||||||
min-height: 320px;
|
min-height: 320px;
|
||||||
|
|
@ -57,12 +60,12 @@
|
||||||
animation-timing-function: $timing-function-sharp;
|
animation-timing-function: $timing-function-sharp;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 32px;
|
height: var(--calendar-day-size);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: .3s;
|
transition: .3s;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
width: 32px;
|
width: var(--calendar-day-size);
|
||||||
|
|
||||||
&.adjacent-month {
|
&.adjacent-month {
|
||||||
color: $color-alto;
|
color: $color-alto;
|
||||||
|
|
@ -75,9 +78,9 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 30px;
|
height: calc(var(--calendar-day-size) - 2px);
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 30px;
|
width: calc(var(--calendar-day-size) - 2px);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $color-concrete;
|
background: $color-concrete;
|
||||||
|
|
@ -91,9 +94,9 @@
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
content: "";
|
content: "";
|
||||||
height: 4px;
|
height: 4px;
|
||||||
left: 14px;
|
left: calc((var(--calendar-day-size) / 2) - 2px);
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 24px;
|
top: calc((var(--calendar-day-size) / 2) + 8px);
|
||||||
width: 4px;
|
width: 4px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -143,3 +146,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.dashboard-container .calendar-widget {
|
||||||
|
--calendar-day-size: 28px;
|
||||||
|
grid-column: 1 / span 12;
|
||||||
|
grid-row: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -335,3 +335,59 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.dashboard-container .current-tasks-widget {
|
||||||
|
--widget-header-size: 72px;
|
||||||
|
grid-row: 1;
|
||||||
|
min-height: 450px;
|
||||||
|
|
||||||
|
.widget-title {
|
||||||
|
flex-basis: 100%;
|
||||||
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions-container {
|
||||||
|
flex-grow: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-tasks-navbar {
|
||||||
|
flex-basis: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-container {
|
||||||
|
margin-right: 5px;
|
||||||
|
|
||||||
|
.task-search-field {
|
||||||
|
width: 150px;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-tasks-list {
|
||||||
|
.current-task-item {
|
||||||
|
.item-row {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.task-due-date {
|
||||||
|
@include font-small;
|
||||||
|
|
||||||
|
.fas {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-progress-container {
|
||||||
|
flex-basis: 100%;
|
||||||
|
max-width: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
|
// scss-lint:disable SelectorDepth
|
||||||
|
// scss-lint:disable NestingDepth
|
||||||
|
|
||||||
.dashboard-container .quick-start-widget {
|
.dashboard-container .quick-start-widget {
|
||||||
grid-column: 1 / span 2;
|
grid-column: 1 / span 2;
|
||||||
grid-row: 7 / span 6;
|
grid-row: 7 / span 6;
|
||||||
|
|
@ -34,3 +37,12 @@
|
||||||
grid-row: 5 / span 4;
|
grid-row: 5 / span 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.dashboard-container .quick-start-widget {
|
||||||
|
--widget-header-size: 36px;
|
||||||
|
grid-column: 1 / span 12;
|
||||||
|
grid-row: 4;
|
||||||
|
min-height: 300px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,3 +83,41 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.dashboard-container .recent-work-widget {
|
||||||
|
--widget-header-size: 72px;
|
||||||
|
grid-row: 3;
|
||||||
|
min-height: 450px;
|
||||||
|
|
||||||
|
.widget-title {
|
||||||
|
flex-basis: 100%;
|
||||||
|
line-height: 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.recent-work-container {
|
||||||
|
.recent-work-item {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 5px 0;
|
||||||
|
|
||||||
|
.object-name {
|
||||||
|
flex-basis: 100%;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-type {
|
||||||
|
flex-basis: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-changed {
|
||||||
|
flex-basis: 0;
|
||||||
|
flex-grow: 1;
|
||||||
|
line-height: 18px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
|
// scss-lint:disable SelectorDepth
|
||||||
|
// scss-lint:disable NestingDepth
|
||||||
|
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
--widget-header-size: 44px;
|
|
||||||
--dashboard-widgets-gap: 30px;
|
--dashboard-widgets-gap: 30px;
|
||||||
|
--widget-header-size: 44px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-column-gap: var(--dashboard-widgets-gap);
|
grid-column-gap: var(--dashboard-widgets-gap);
|
||||||
grid-row-gap: var(--dashboard-widgets-gap);
|
grid-row-gap: var(--dashboard-widgets-gap);
|
||||||
|
|
@ -19,7 +22,6 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border-bottom: $border-tertiary;
|
border-bottom: $border-tertiary;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
height: var(--widget-header-size);
|
height: var(--widget-header-size);
|
||||||
padding-left: 16px;
|
padding-left: 16px;
|
||||||
|
|
||||||
|
|
@ -54,3 +56,18 @@
|
||||||
--dashboard-widgets-gap: 16px;
|
--dashboard-widgets-gap: 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 700px) {
|
||||||
|
.dashboard-container {
|
||||||
|
--widget-header-size: 72px;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
|
||||||
|
.widget-header {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
.sci-secondary-navbar {
|
||||||
|
height: 36px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
33
app/assets/stylesheets/forgot_password.scss
Normal file
33
app/assets/stylesheets/forgot_password.scss
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
// scss-lint:disable SelectorDepth NestingDepth IdSelector
|
||||||
|
|
||||||
|
.forgot-password-layout {
|
||||||
|
#content-wrapper {
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
.container:first-child {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.forgot-password-container {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.forgot-password-form-wrapper {
|
||||||
|
flex-basis: 50%;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.center-block-narrow {
|
||||||
|
margin-top: 72px;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forgot-password-title {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sci-input-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -58,6 +58,7 @@
|
||||||
.canvas-center-on {
|
.canvas-center-on {
|
||||||
animation-timing-function: $timing-function-sharp;
|
animation-timing-function: $timing-function-sharp;
|
||||||
color: $color-volcano;
|
color: $color-volcano;
|
||||||
|
display: none;
|
||||||
flex-basis: 36px;
|
flex-basis: 36px;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
|
|
@ -66,6 +67,12 @@
|
||||||
transition: .2s;
|
transition: .2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
.line-wrap {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.line-wrap {
|
.line-wrap {
|
||||||
background-color: $color-alto;
|
background-color: $color-alto;
|
||||||
|
|
@ -94,6 +101,12 @@
|
||||||
color: $brand-primary;
|
color: $brand-primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.show-canvas-handler {
|
||||||
|
.canvas-center-on {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.leaf {
|
.leaf {
|
||||||
|
|
|
||||||
1
app/assets/stylesheets/shared_styles/constants.scss
Normal file
1
app/assets/stylesheets/shared_styles/constants.scss
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
@import "constants/*";
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
.sci-input-container {
|
.sci-input-container {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
@include font-small;
|
@include font-small;
|
||||||
|
|
@ -14,8 +15,8 @@
|
||||||
.sci-input-field {
|
.sci-input-field {
|
||||||
@include font-button;
|
@include font-button;
|
||||||
animation-timing-function: $timing-function-sharp;
|
animation-timing-function: $timing-function-sharp;
|
||||||
border: $border-default;
|
border: $border-secondary;
|
||||||
border-radius: $border-radius-default;
|
border-radius: $border-radius-default !important;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
.sci-secondary-navbar {
|
.sci-secondary-navbar {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
|
||||||
.navbar-link {
|
.navbar-link {
|
||||||
@include font-small;
|
@include font-small;
|
||||||
|
|
@ -13,6 +14,7 @@
|
||||||
position: relative;
|
position: relative;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-volcano;
|
color: $color-volcano;
|
||||||
|
|
|
||||||
61
app/assets/stylesheets/sign_up.scss
Normal file
61
app/assets/stylesheets/sign_up.scss
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
// scss-lint:disable SelectorDepth NestingDepth IdSelector
|
||||||
|
|
||||||
|
.sign-up-layout {
|
||||||
|
#content-wrapper {
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
.container:first-child {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-up-container {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.sign-up-form-wrapper {
|
||||||
|
flex-basis: 50%;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.center-block-narrow {
|
||||||
|
margin-top: 72px;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-up-title {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sci-input-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.minimum-password-length {
|
||||||
|
@include font-small;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-up-button {
|
||||||
|
padding: 7px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkedin-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.linkedin-link {
|
||||||
|
margin-right: 15px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkedin-signin-button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
73
app/assets/stylesheets/sing_in.scss
Normal file
73
app/assets/stylesheets/sing_in.scss
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
// scss-lint:disable SelectorDepth NestingDepth IdSelector
|
||||||
|
|
||||||
|
.sign-in-layout {
|
||||||
|
#content-wrapper {
|
||||||
|
margin-left: 0;
|
||||||
|
|
||||||
|
.container:first-child {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-in-container {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.sign-in-form-wrapper {
|
||||||
|
flex-basis: 50%;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
.center-block-narrow {
|
||||||
|
margin-top: 72px;
|
||||||
|
padding: 0 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-in-title {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.remember-me {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin-left: 8px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sci-input-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkedin-container {
|
||||||
|
margin-bottom: 24px;
|
||||||
|
|
||||||
|
.linkedin-link {
|
||||||
|
margin-right: 15px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.linkedin-signin-button {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.log-in-button {
|
||||||
|
padding: 7px 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.forgot-password-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -56,9 +56,7 @@ module Api
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_manage_permissions
|
def check_manage_permissions
|
||||||
unless can_manage_repository_column?(@inventory_column)
|
raise PermissionError.new(RepositoryColumn, :manage) unless can_manage_repository_column?(@inventory_column)
|
||||||
raise PermissionError.new(RepositoryColumn, :manage)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_create_permissions
|
def check_create_permissions
|
||||||
|
|
@ -66,12 +64,11 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
def inventory_column_params
|
def inventory_column_params
|
||||||
unless params.require(:data).require(:type) == 'inventory_columns'
|
raise TypeError unless params.require(:data).require(:type) == 'inventory_columns'
|
||||||
raise TypeError
|
|
||||||
end
|
|
||||||
params.require(:data).require(:attributes)
|
params.require(:data).require(:attributes)
|
||||||
new_params = params
|
new_params = params
|
||||||
.permit(data: { attributes: %i(name data_type) })[:data]
|
.permit(data: { attributes: [:name, :data_type, metadata: {}] })[:data]
|
||||||
.merge(created_by: @current_user)
|
.merge(created_by: @current_user)
|
||||||
if new_params[:attributes][:data_type].present?
|
if new_params[:attributes][:data_type].present?
|
||||||
new_params[:attributes][:data_type] =
|
new_params[:attributes][:data_type] =
|
||||||
|
|
@ -82,9 +79,8 @@ module Api
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_inventory_column_params
|
def update_inventory_column_params
|
||||||
unless params.require(:data).require(:id).to_i == params[:id].to_i
|
raise IDMismatchError unless params.require(:data).require(:id).to_i == params[:id].to_i
|
||||||
raise IDMismatchError
|
|
||||||
end
|
|
||||||
if inventory_column_params[:attributes].include?(:data_type)
|
if inventory_column_params[:attributes].include?(:data_type)
|
||||||
raise ActiveRecord::RecordInvalid,
|
raise ActiveRecord::RecordInvalid,
|
||||||
I18n.t('api.core.errors.inventory_column_type.detail')
|
I18n.t('api.core.errors.inventory_column_type.detail')
|
||||||
|
|
|
||||||
|
|
@ -28,25 +28,40 @@ module Users
|
||||||
email = auth.info.email
|
email = auth.info.email
|
||||||
email ||= auth.dig(:extra, :raw_info, :id_token_claims, :emails)&.first
|
email ||= auth.dig(:extra, :raw_info, :id_token_claims, :emails)&.first
|
||||||
user = User.from_omniauth(auth)
|
user = User.from_omniauth(auth)
|
||||||
if user
|
|
||||||
# User found in database so just sign in him
|
|
||||||
sign_in_and_redirect(user)
|
|
||||||
elsif email.present?
|
|
||||||
user = User.find_by(email: email)
|
|
||||||
|
|
||||||
if user.blank?
|
# User found in database so just signing in
|
||||||
# Create new user and identity
|
return sign_in_and_redirect(user) if user.present?
|
||||||
User.create_from_omniauth!(auth)
|
|
||||||
sign_in_and_redirect(user)
|
if email.blank?
|
||||||
elsif provider_conf[:auto_link_on_sign_in]
|
# No email in the token so can not link or create user
|
||||||
# Link to existing local account
|
error_message = I18n.t('devise.azure.errors.no_email')
|
||||||
|
return redirect_to after_omniauth_failure_path_for(resource_name)
|
||||||
|
end
|
||||||
|
|
||||||
|
user = User.find_by(email: email)
|
||||||
|
|
||||||
|
if user.blank?
|
||||||
|
# Create new user and identity
|
||||||
|
full_name = "#{auth.info.first_name} #{auth.info.last_name}"
|
||||||
|
user = User.new(full_name: full_name,
|
||||||
|
initials: generate_initials(full_name),
|
||||||
|
email: email,
|
||||||
|
password: generate_user_password)
|
||||||
|
User.transaction do
|
||||||
|
user.save!
|
||||||
user.user_identities.create!(provider: auth.provider, uid: auth.uid)
|
user.user_identities.create!(provider: auth.provider, uid: auth.uid)
|
||||||
sign_in_and_redirect(user)
|
user.update!(confirmed_at: user.created_at)
|
||||||
else
|
|
||||||
# Cannot do anything with it, so just return an error
|
|
||||||
error_message = I18n.t('devise.azure.errors.no_local_user_map')
|
|
||||||
redirect_to after_omniauth_failure_path_for(resource_name)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
sign_in_and_redirect(user)
|
||||||
|
elsif provider_conf[:auto_link_on_sign_in]
|
||||||
|
# Link to existing local account
|
||||||
|
user.user_identities.create!(provider: auth.provider, uid: auth.uid)
|
||||||
|
sign_in_and_redirect(user)
|
||||||
|
else
|
||||||
|
# Cannot do anything with it, so just return an error
|
||||||
|
error_message = I18n.t('devise.azure.errors.no_local_user_map')
|
||||||
|
redirect_to after_omniauth_failure_path_for(resource_name)
|
||||||
end
|
end
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
Rails.logger.error e.message
|
Rails.logger.error e.message
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
module FormTagHelper
|
module FormTagHelper
|
||||||
def recaptcha_input_tag
|
def recaptcha_input_tag
|
||||||
if Rails.configuration.x.enable_recaptcha
|
if Rails.configuration.x.enable_recaptcha
|
||||||
res = "<div class='form-group "
|
res = "<div class='form-group sci-input-container"
|
||||||
res << 'has-error' if flash[:recaptcha_error]
|
res << 'has-error' if flash[:recaptcha_error]
|
||||||
res << "'>"
|
res << "'>"
|
||||||
|
res << label_tag(:recaptcha_label, I18n.t('users.registrations.new.captcha_description'))
|
||||||
res << recaptcha_tags
|
res << recaptcha_tags
|
||||||
if flash[:recaptcha_error]
|
if flash[:recaptcha_error]
|
||||||
res << "<span class='help-block'>"
|
res << "<span class='help-block'>"
|
||||||
|
|
|
||||||
4
app/models/application_settings.rb
Normal file
4
app/models/application_settings.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ApplicationSettings < Settings
|
||||||
|
end
|
||||||
|
|
@ -293,6 +293,8 @@ class Experiment < ApplicationRecord
|
||||||
my_module.last_modified_by = current_user
|
my_module.last_modified_by = current_user
|
||||||
my_module.save!
|
my_module.save!
|
||||||
|
|
||||||
|
my_module.assign_user(current_user)
|
||||||
|
|
||||||
ids_map[m[:id]] = my_module.id.to_s
|
ids_map[m[:id]] = my_module.id.to_s
|
||||||
end
|
end
|
||||||
my_modules.reload
|
my_modules.reload
|
||||||
|
|
|
||||||
|
|
@ -538,6 +538,21 @@ class MyModule < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def assign_user(user, assigned_by = nil)
|
||||||
|
user_my_modules.create(
|
||||||
|
assigned_by: assigned_by || user,
|
||||||
|
user: user
|
||||||
|
)
|
||||||
|
Activities::CreateActivityService
|
||||||
|
.call(activity_type: :assign_user_to_module,
|
||||||
|
owner: assigned_by || user,
|
||||||
|
team: experiment.project.team,
|
||||||
|
project: experiment.project,
|
||||||
|
subject: self,
|
||||||
|
message_items: { my_module: id,
|
||||||
|
user_target: user.id })
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def create_blank_protocol
|
def create_blank_protocol
|
||||||
|
|
|
||||||
|
|
@ -354,20 +354,6 @@ class User < ApplicationRecord
|
||||||
.take
|
.take
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create_from_omniauth!(auth)
|
|
||||||
full_name = "#{auth.info.first_name} #{auth.info.last_name}"
|
|
||||||
user = User.new(full_name: full_name,
|
|
||||||
initials: generate_initials(full_name),
|
|
||||||
email: email,
|
|
||||||
password: generate_user_password)
|
|
||||||
User.transaction do
|
|
||||||
user.save!
|
|
||||||
user.user_identities.create!(provider: auth.provider, uid: auth.uid)
|
|
||||||
user.update!(confirmed_at: user.created_at)
|
|
||||||
end
|
|
||||||
user
|
|
||||||
end
|
|
||||||
|
|
||||||
# Search all active users for username & email. Can
|
# Search all active users for username & email. Can
|
||||||
# also specify which team to ignore.
|
# also specify which team to ignore.
|
||||||
def self.search(
|
def self.search(
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ module Api
|
||||||
module V1
|
module V1
|
||||||
class InventoryColumnSerializer < ActiveModel::Serializer
|
class InventoryColumnSerializer < ActiveModel::Serializer
|
||||||
type :inventory_columns
|
type :inventory_columns
|
||||||
attributes :name, :data_type
|
attributes :name, :data_type, :metadata
|
||||||
has_many :repository_list_items,
|
has_many :repository_list_items,
|
||||||
key: :inventory_list_items,
|
key: :inventory_list_items,
|
||||||
serializer: InventoryListItemSerializer,
|
serializer: InventoryListItemSerializer,
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,9 @@ class CreateMyModuleService
|
||||||
|
|
||||||
@my_module.save!
|
@my_module.save!
|
||||||
create_my_module_activity
|
create_my_module_activity
|
||||||
|
|
||||||
|
@my_module.assign_user(@user)
|
||||||
|
|
||||||
@params[:experiment].generate_workflow_img
|
@params[:experiment].generate_workflow_img
|
||||||
new_my_module = @my_module
|
new_my_module = @my_module
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,13 @@ class SpreadsheetParser
|
||||||
|
|
||||||
def self.parse_row(row, sheet)
|
def self.parse_row(row, sheet)
|
||||||
if sheet.is_a?(Roo::Excelx)
|
if sheet.is_a?(Roo::Excelx)
|
||||||
row.map { |cell| cell&.formatted_value }
|
row.map do |cell|
|
||||||
|
if cell.is_a?(Roo::Excelx::Cell::Number) && cell.format == 'General'
|
||||||
|
cell&.value&.to_d
|
||||||
|
else
|
||||||
|
cell&.formatted_value
|
||||||
|
end
|
||||||
|
end
|
||||||
else
|
else
|
||||||
row.map(&:to_s)
|
row.map(&:to_s)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@
|
||||||
<label><%= t("dashboard.current_tasks.filter.sort") %></label>
|
<label><%= t("dashboard.current_tasks.filter.sort") %></label>
|
||||||
<select class="sort-filter">
|
<select class="sort-filter">
|
||||||
<option value="date_asc" ><%= t("dashboard.current_tasks.filter.date_asc") %></option>
|
<option value="date_asc" ><%= t("dashboard.current_tasks.filter.date_asc") %></option>
|
||||||
<option value="date_desc" ><%= t("dashboard.current_tasks.filter.date_desc") %></option>
|
|
||||||
<option value="atoz" ><%= t("dashboard.current_tasks.filter.atoz") %></option>
|
<option value="atoz" ><%= t("dashboard.current_tasks.filter.atoz") %></option>
|
||||||
<option value="ztoa" ><%= t("dashboard.current_tasks.filter.ztoa") %></option>
|
<option value="ztoa" ><%= t("dashboard.current_tasks.filter.ztoa") %></option>
|
||||||
</select>
|
</select>
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,7 @@
|
||||||
<div class="tree perfect-scrollbar" data-scroll="<%= params[:scroll] %>">
|
<div class="tree perfect-scrollbar" data-scroll="<%= params[:scroll] %>">
|
||||||
<% cache [action_name, current_user, current_team] do %>
|
<% cache [action_name, current_user, current_team] do %>
|
||||||
<%= render partial: 'shared/sidebar/projects', locals: {
|
<%= render partial: 'shared/sidebar/projects', locals: {
|
||||||
current_project: current_project,
|
} %>
|
||||||
current_experiment: current_experiment,
|
|
||||||
current_task: current_task
|
|
||||||
} %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<% if project.active_experiments.present? %>
|
<% if project.active_experiments.present? %>
|
||||||
<ul class="tree-child hidden" data-active="<%= project.id == current_project&.id %>" data-branch-id="pro<%= project.id %>">
|
<ul class="tree-child hidden" data-branch-id="pro<%= project.id %>">
|
||||||
<% project.active_experiments.each do |experiment| %>
|
<% project.active_experiments.each do |experiment| %>
|
||||||
<% cache [action_name, current_user, experiment] do %>
|
<% cache [action_name, current_user, experiment] do %>
|
||||||
<li data-parent="candidate" class="branch <%= 'active' if experiment_page? && current_experiment == experiment %>">
|
<li data-parent="candidate" class="branch">
|
||||||
<span class="tree-link first-indent" title="<%= experiment.name %>">
|
<span class="tree-link first-indent" title="<%= experiment.name %>">
|
||||||
<% if experiment.active_my_modules.any? %>
|
<% if experiment.active_my_modules.any? %>
|
||||||
<i class="fas fa-caret-right tree-toggle"></i>
|
<i class="fas fa-caret-right tree-toggle"></i>
|
||||||
|
|
@ -10,15 +10,10 @@
|
||||||
<%= link_to experiment.name,
|
<%= link_to experiment.name,
|
||||||
experiment_action_to_link_to(experiment),
|
experiment_action_to_link_to(experiment),
|
||||||
class: 'overview_exp_label line-wrap',
|
class: 'overview_exp_label line-wrap',
|
||||||
style: (current_experiment == experiment ? 'font-weight: bold' : ''),
|
|
||||||
data: { type: 'experiment', id: experiment.id }
|
data: { type: 'experiment', id: experiment.id }
|
||||||
%>
|
%>
|
||||||
</span>
|
</span>
|
||||||
<%= render partial: 'shared/sidebar/my_modules', locals: {
|
<%= render partial: 'shared/sidebar/my_modules', locals: { experiment: experiment } %>
|
||||||
experiment: experiment,
|
|
||||||
current_experiment: current_experiment,
|
|
||||||
current_task: current_task
|
|
||||||
} %>
|
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<% if experiment.active_my_modules.present? %>
|
<% if experiment.active_my_modules.present? %>
|
||||||
<ul class="tree-child hidden" data-active="<%= current_experiment&.id == experiment.id %>" data-branch-id="exp<%= experiment.id %>">
|
<ul class="tree-child hidden" data-branch-id="exp<%= experiment.id %>">
|
||||||
<% experiment.active_my_modules.each do |my_module| %>
|
<% experiment.active_my_modules.each do |my_module| %>
|
||||||
<li class="leaf <%= 'active' if module_page? && current_task == my_module %>" data-module-id="<%= my_module.id %>">
|
<li class="leaf" data-module-id="<%= my_module.id %>">
|
||||||
<span class="tree-link task-tree-link second-indent" title="<%= my_module.name %>">
|
<span class="tree-link task-tree-link second-indent" title="<%= my_module.name %>">
|
||||||
<%= link_to my_module.name,
|
<%= link_to my_module.name,
|
||||||
module_action_to_link_to(my_module),
|
module_action_to_link_to(my_module),
|
||||||
class: 'line-wrap',
|
class: 'line-wrap',
|
||||||
data: { type: 'my_module', id: my_module.id } %>
|
data: { type: 'my_module', id: my_module.id } %>
|
||||||
<% if experiment_page? && current_experiment == experiment && action_name =='canvas' %>
|
<% if action_name =='canvas' %>
|
||||||
<a href="" class="canvas-center-on"><i class="fas fa-map-marker-alt"></i></a>
|
<a href="" class="canvas-center-on"><i class="fas fa-map-marker-alt"></i></a>
|
||||||
<% end %>
|
<% end %>
|
||||||
</span>
|
</span>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<% @projects_tree.each do |project| %>
|
<% @projects_tree.each do |project| %>
|
||||||
<% cache [action_name, current_user, project] do %>
|
<% cache [action_name, current_user, project] do %>
|
||||||
<li data-parent="candidate"
|
<li data-parent="candidate"
|
||||||
class="branch <%= 'active' if project_page? && current_project == project %>" >
|
class="branch" >
|
||||||
<span class="tree-link no-indent" title="<%= project.name %>">
|
<span class="tree-link no-indent" title="<%= project.name %>">
|
||||||
<% if project.active_experiments.any? %>
|
<% if project.active_experiments.any? %>
|
||||||
<i class="fas fa-caret-right tree-toggle"></i>
|
<i class="fas fa-caret-right tree-toggle"></i>
|
||||||
|
|
@ -11,15 +11,9 @@
|
||||||
project_action_to_link_to(project),
|
project_action_to_link_to(project),
|
||||||
title: project.name,
|
title: project.name,
|
||||||
class: 'line-wrap',
|
class: 'line-wrap',
|
||||||
style: (current_project == project ? 'font-weight: bold' : ''),
|
|
||||||
data: { type: 'project', id: project.id } %>
|
data: { type: 'project', id: project.id } %>
|
||||||
</span>
|
</span>
|
||||||
<%= render partial: 'shared/sidebar/experiments', locals: {
|
<%= render partial: 'shared/sidebar/experiments', locals: { project: project } %>
|
||||||
project: project,
|
|
||||||
current_project: current_project,
|
|
||||||
current_experiment: current_experiment,
|
|
||||||
current_task: current_task
|
|
||||||
} %>
|
|
||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,29 @@
|
||||||
<% provide(:head_title, t("devise.passwords.new.head_title")) %>
|
<% provide(:head_title, t("devise.passwords.new.head_title")) %>
|
||||||
|
<% content_for(:body_class, 'forgot-password-layout') %>
|
||||||
|
<div class="forgot-password-container">
|
||||||
|
<div class="forgot-password-form-wrapper">
|
||||||
|
<div class="center-block center-block-narrow">
|
||||||
|
<h1 class="forgot-password-title"><%=t "devise.passwords.new.title" %></h1>
|
||||||
|
|
||||||
<div class="center-block center-block-narrow">
|
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
|
||||||
<h2><%=t "devise.passwords.new.title" %></h2>
|
|
||||||
|
|
||||||
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| %>
|
<% if not resource.errors.empty? %>
|
||||||
|
<div class="alert alert-danger" id="alert-flash">
|
||||||
|
<%= devise_error_messages! %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<% if not resource.errors.empty? %>
|
<div class="form-group sci-input-container">
|
||||||
<div class="alert alert-danger" id="alert-flash">
|
<%= f.label :email %><br /actions>
|
||||||
<%= devise_error_messages! %>
|
<%= f.email_field :email, autofocus: true, class: "form-control sci-input-field" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<%= f.submit t("devise.passwords.new.submit"), class: "btn btn-primary" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= render partial: 'users/shared/links', locals: {linkedin_skip: true} %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<%= f.label :email %><br /actions>
|
|
||||||
<%= f.email_field :email, autofocus: true, class: "form-control" %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<%= f.submit t("devise.passwords.new.submit"), class: "btn btn-primary" %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= render "users/shared/links" %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,64 @@
|
||||||
<% provide(:head_title, t('users.registrations.new.head_title')) %>
|
<% provide(:head_title, t('users.registrations.new.head_title')) %>
|
||||||
|
<% content_for(:body_class, 'sign-up-layout') %>
|
||||||
|
<div class="sign-up-container">
|
||||||
|
<div class="sign-up-form-wrapper">
|
||||||
|
<div class="center-block center-block-narrow">
|
||||||
|
<h1 class="sign-up-title"><%= t 'users.registrations.new.head_title' %></h1>
|
||||||
|
|
||||||
<div class="center-block center-block-narrow">
|
<%- if Rails.configuration.x.enable_user_registration && Rails.configuration.x.linkedin_signin_enabled && @oauth_authorize != true %>
|
||||||
<h1><%= t 'users.registrations.new.head_title' %></h1>
|
<div class="linkedin-container">
|
||||||
<div data-hook="sign-up-form-hook">
|
<%= render partial: "users/shared/linkedin_sign_in_links", locals: { resource_name: resource_name } %>
|
||||||
<%= form_for(:user, as: resource_name, url: registration_path(resource_name), html: { id: "sign-up-form" } ) do |f| %>
|
<span><%= t("devise.sessions.new.or") %></span>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
<div class="form-group">
|
<div data-hook="sign-up-form-hook">
|
||||||
<%= f.label :full_name %>
|
<%= form_for(:user, as: resource_name, url: registration_path(resource_name), html: { id: "sign-up-form" } ) do |f| %>
|
||||||
<%= f.text_field :full_name, autofocus: true, class: 'form-control' %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group sci-input-container">
|
||||||
<%= f.label :email %>
|
<%= f.label :full_name, t('users.registrations.new.full_name_label') %>
|
||||||
<%= f.email_field :email, class: 'form-control' %>
|
<%= f.text_field :full_name, autofocus: true, class: 'form-control sci-input-field' %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group sci-input-container">
|
||||||
<%= f.label :password %>
|
<%= f.label :email, t('users.registrations.new.email_label') %>
|
||||||
<% if @minimum_password_length %>
|
<%= f.email_field :email, class: 'form-control sci-input-field' %>
|
||||||
<em>(<%= @minimum_password_length %> characters minimum)</em>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group sci-input-container">
|
||||||
|
<%= f.label :password, t('users.registrations.new.password_label') %>
|
||||||
|
<% if @minimum_password_length %>
|
||||||
|
<em class="minimum-password-length"><%= t('users.registrations.new.minimum_password_length', password_length: @minimum_password_length) %></em>
|
||||||
|
<% end %>
|
||||||
|
<%= f.password_field :password, autocomplete: 'off', class: 'form-control sci-input-field' %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group sci-input-container" id="password_confirmation_form">
|
||||||
|
<%= f.label :password_confirmation, t('users.registrations.new.password_confirmation_label') %>
|
||||||
|
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'form-control sci-input-field' %>
|
||||||
|
</div>
|
||||||
|
<% if Rails.configuration.x.new_team_on_signup %>
|
||||||
|
<div class="form-group sci-input-container" id="team_name_form">
|
||||||
|
<%= label :team, :name, t('users.registrations.new.team_name_label') %>
|
||||||
|
<% if @team %>
|
||||||
|
<%= text_field :team, :name, class: 'form-control sci-input-field', value: @team.name,
|
||||||
|
placeholder: t('users.registrations.new.team_name_placeholder') %>
|
||||||
|
<% else %>
|
||||||
|
<%= text_field :team, :name, class: 'form-control sci-input-field',
|
||||||
|
placeholder: t('users.registrations.new.team_name_placeholder') %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
<%= recaptcha_input_tag %>
|
||||||
|
|
||||||
|
<div class="form-group" data-hook="sign-up-form-submit">
|
||||||
|
<%= f.submit 'Sign up', class: 'btn btn-primary sign-up-button' %>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<%= f.password_field :password, autocomplete: 'off', class: 'form-control' %>
|
</div>
|
||||||
|
<%= render partial: 'users/shared/links', locals: {linkedin_skip: true} %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group" id="password_confirmation_form">
|
|
||||||
<%= f.label :password_confirmation %>
|
|
||||||
<%= f.password_field :password_confirmation, autocomplete: 'off', class: 'form-control' %>
|
|
||||||
</div>
|
|
||||||
<% if Rails.configuration.x.new_team_on_signup %>
|
|
||||||
<div class="form-group" id="team_name_form">
|
|
||||||
<%= label :team, :name, t('users.registrations.new.team_name_label') %>
|
|
||||||
<% if @team %>
|
|
||||||
<%= text_field :team, :name, class: 'form-control', value: @team.name,
|
|
||||||
placeholder: t('users.registrations.new.team_name_placeholder') %>
|
|
||||||
<% else %>
|
|
||||||
<%= text_field :team, :name, class: 'form-control',
|
|
||||||
placeholder: t('users.registrations.new.team_name_placeholder') %>
|
|
||||||
<% end %>
|
|
||||||
<span><small><%= t 'users.registrations.new.team_name_help' %></small></span>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
<%= recaptcha_input_tag %>
|
|
||||||
|
|
||||||
<div class="form-group" data-hook="sign-up-form-submit">
|
|
||||||
<%= f.submit 'Sign up', class: 'btn btn-primary' %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
</div>
|
||||||
<%= render 'users/shared/links' %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if resource and not resource.errors.empty? %>
|
<% if resource and not resource.errors.empty? %>
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,46 @@
|
||||||
<% provide(:head_title, t("devise.sessions.new.head_title")) %>
|
<% provide(:head_title, t("devise.sessions.new.head_title")) %>
|
||||||
|
<% content_for(:body_class, 'sign-in-layout') %>
|
||||||
|
<div class="sign-in-container">
|
||||||
|
<div class="sign-in-form-wrapper">
|
||||||
|
<div class="center-block center-block-narrow">
|
||||||
|
<h1 class="log-in-title"><%=t "devise.sessions.new.title" %></h1>
|
||||||
|
|
||||||
<div class="center-block center-block-narrow">
|
<%- if Rails.configuration.x.enable_user_registration && Rails.configuration.x.linkedin_signin_enabled && @oauth_authorize != true %>
|
||||||
<h1><%=t "devise.sessions.new.title" %></h1>
|
<div class="linkedin-container">
|
||||||
|
<%= render partial: "users/shared/linkedin_sign_in_links", locals: { resource_name: resource_name } %>
|
||||||
|
<span><%= t("devise.sessions.new.or") %></span>
|
||||||
|
</div>
|
||||||
|
<% end -%>
|
||||||
|
|
||||||
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
|
<%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
|
||||||
<div class="input-group">
|
<div class="input-group sci-input-container">
|
||||||
<span class="input-group-addon" style="text-transform: capitalize;">
|
<%= f.label :email, t("devise.sessions.new.email_field") %>
|
||||||
<%= :email %>
|
<%= f.email_field :email, autofocus: true, class: "form-control sci-input-field", placeholder: t("devise.sessions.new.email_placeholder") %>
|
||||||
</span>
|
</div>
|
||||||
<%= f.email_field :email, autofocus: true, class: "form-control", placeholder: t("devise.sessions.new.email_placeholder") %>
|
|
||||||
|
<div class="input-group sci-input-container">
|
||||||
|
<%= f.label :password, t("devise.sessions.new.password_field") %>
|
||||||
|
<%= f.password_field :password, autocomplete: "off", class: "form-control sci-input-field", placeholder: t("devise.sessions.new.password_placeholder") %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if devise_mapping.rememberable? && !@simple_sign_in %>
|
||||||
|
<div class="field remember-me">
|
||||||
|
<div class="sci-checkbox-container">
|
||||||
|
<%= f.check_box :remember_me, class: "sci-checkbox" %>
|
||||||
|
<span class="sci-checkbox-label"></span>
|
||||||
|
</div>
|
||||||
|
<%= f.label :remember_me, t("devise.sessions.new.remember_me") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= hidden_field_tag(:simple_sign_in, @simple_sign_in) %>
|
||||||
|
|
||||||
|
<div class="actions" style="margin-top: 10px; margin-bottom: 10px;">
|
||||||
|
<%= f.submit t("devise.sessions.new.submit"), class: "btn btn-primary log-in-button" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<%= render partial: "users/shared/links", locals: {linkedin_skip: true} unless @simple_sign_in %>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="input-group" style="margin-top: 10px;">
|
</div>
|
||||||
<span class="input-group-addon" style="text-transform: capitalize;">
|
|
||||||
<%= :password %>
|
|
||||||
</span>
|
|
||||||
<%= f.password_field :password, autocomplete: "off", class: "form-control", placeholder: t("devise.sessions.new.password_placeholder") %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<% if devise_mapping.rememberable? && !@simple_sign_in %>
|
|
||||||
<div class="field" style="margin-top: 10px;">
|
|
||||||
<%= f.check_box :remember_me %>
|
|
||||||
<%= f.label :remember_me %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= hidden_field_tag(:simple_sign_in, @simple_sign_in) %>
|
|
||||||
|
|
||||||
<div class="actions" style="margin-top: 10px; margin-bottom: 10px;">
|
|
||||||
<%= f.submit t("devise.sessions.new.submit"), class: "btn btn-primary" %>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<%= render "users/shared/links" unless @simple_sign_in %>
|
|
||||||
</div>
|
|
||||||
10
app/views/users/shared/_linkedin_sign_in_links.html.erb
Normal file
10
app/views/users/shared/_linkedin_sign_in_links.html.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<%- if devise_mapping.omniauthable? && resource_class.omniauth_providers.any? %>
|
||||||
|
<%= link_to omniauth_authorize_path(resource_name, :linkedin), method: :post, title: "Sign in with LinkedIn", class: 'linkedin-link' do %>
|
||||||
|
<%= image_tag('linkedin/Sign-in-Large---Default.png',
|
||||||
|
class: 'linkedin-signin-button',
|
||||||
|
alt: "Sign in with LinkedIn",
|
||||||
|
onmouseover: "src='#{image_path('linkedin/Sign-in-Large---Hover.png')}'",
|
||||||
|
onmouseout: "src='#{image_path('linkedin/Sign-in-Large---Default.png')}'",
|
||||||
|
onclick: "src='#{image_path('linkedin/Sign-in-Large---Active.png')}'") %>
|
||||||
|
<% end -%>
|
||||||
|
<% end -%>
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
<%= link_to login, new_session_path(resource_name) %><br />
|
<%= link_to login, new_session_path(resource_name) %><br />
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<%- if devise_mapping.registerable? && Rails.configuration.x.enable_user_registration && controller_name != 'registrations' %>
|
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
||||||
<%= link_to t("devise.links.signup"), new_registration_path(resource_name) %><br />
|
<%= link_to t("devise.links.forgot"), new_password_path(resource_name), class: 'forgot-password-link' %><br />
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
<%- if devise_mapping.registerable? && Rails.configuration.x.enable_user_registration && controller_name != 'registrations' %>
|
||||||
<%= link_to t("devise.links.forgot"), new_password_path(resource_name) %><br />
|
<%= link_to t("devise.links.signup"), new_registration_path(resource_name), class: 'signup-link' %><br />
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<%- if Rails.configuration.x.enable_email_confirmations && devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
<%- if Rails.configuration.x.enable_email_confirmations && devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||||
|
|
@ -25,16 +25,9 @@
|
||||||
<div data-hook="omniauth-sign-in-links"></div>
|
<div data-hook="omniauth-sign-in-links"></div>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<%- if Rails.configuration.x.enable_user_registration && Rails.configuration.x.linkedin_signin_enabled && @oauth_authorize != true %>
|
<%- unless defined?(linkedin_skip) %>
|
||||||
<%- if devise_mapping.omniauthable? && resource_class.omniauth_providers.any? && controller_name != 'registrations' %>
|
<%- if Rails.configuration.x.enable_user_registration && Rails.configuration.x.linkedin_signin_enabled && @oauth_authorize != true %>
|
||||||
<%= link_to omniauth_authorize_path(resource_name, :linkedin), method: :post, :title => "Sign in with LinkedIn" do %>
|
<%= render partial: "users/shared/linkedin_sign_in_links", locals: { resource_name: resource_name } %>
|
||||||
<%= image_tag('linkedin/Sign-in-Large---Default.png',
|
|
||||||
class: 'linkedin-signin-button',
|
|
||||||
alt: "Sign in with LinkedIn",
|
|
||||||
onmouseover: "src='#{image_path('linkedin/Sign-in-Large---Hover.png')}'",
|
|
||||||
onmouseout: "src='#{image_path('linkedin/Sign-in-Large---Default.png')}'",
|
|
||||||
onclick: "src='#{image_path('linkedin/Sign-in-Large---Active.png')}'") %>
|
|
||||||
<% end -%>
|
|
||||||
<% end -%>
|
<% end -%>
|
||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,4 +34,39 @@ Rails.application.configure do
|
||||||
config.x.azure_ad_apps[value][:sign_in_policy] = ENV["#{app_name}_AZURE_AD_SIGN_IN_POLICY"]
|
config.x.azure_ad_apps[value][:sign_in_policy] = ENV["#{app_name}_AZURE_AD_SIGN_IN_POLICY"]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Checking additional configurations in ApplicationSettings JSON. Key and values should be strings there.
|
||||||
|
begin
|
||||||
|
if ApplicationSettings.instance.values['azure_ad_apps']&.is_a?(Array)
|
||||||
|
config.x.azure_ad_apps ||= HashWithIndifferentAccess.new
|
||||||
|
settings = ApplicationSettings.instance
|
||||||
|
|
||||||
|
settings.values['azure_ad_apps'].each do |azure_ad_app|
|
||||||
|
app_config = {}
|
||||||
|
app_id = azure_ad_app['app_id']
|
||||||
|
Rails.logger.error('No app_id present for the entry in Azure app settings') && next unless app_id
|
||||||
|
|
||||||
|
app_config[:iss] = azure_ad_app['iss']
|
||||||
|
Rails.logger.error("No iss for #{app_id} Azure app") && next unless app_config[:iss]
|
||||||
|
|
||||||
|
app_config[:conf_url] = azure_ad_app['conf_url']
|
||||||
|
Rails.logger.error("No conf_url for #{app_id} Azure app") && next unless app_config[:conf_url]
|
||||||
|
|
||||||
|
app_config[:provider] = azure_ad_app['provider_name']
|
||||||
|
Rails.logger.error("No provider_name for #{app_id} Azure app") && next unless app_config[:provider]
|
||||||
|
|
||||||
|
app_config[:enable_sign_in] = azure_ad_app['enable_sign_in'] == 'true'
|
||||||
|
|
||||||
|
if app_config[:enable_sign_in]
|
||||||
|
app_config[:sign_in_label] = azure_ad_app['sign_in_label'] || 'Sign in with Azure AD'
|
||||||
|
app_config[:auto_link_on_sign_in] = azure_ad_app['auto_link_on_sign_in'] == 'true'
|
||||||
|
app_config[:sign_in_policy] = azure_ad_app['sign_in_policy'] if azure_ad_app['sign_in_policy']
|
||||||
|
end
|
||||||
|
|
||||||
|
config.x.azure_ad_apps[app_id] = app_config
|
||||||
|
end
|
||||||
|
end
|
||||||
|
rescue ActiveRecord::ActiveRecordError, PG::ConnectionBad
|
||||||
|
Rails.logger.info('Not connected to database, skipping additional Azure AD configuration')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,7 @@ en:
|
||||||
title: "Filters"
|
title: "Filters"
|
||||||
clear: "Clear"
|
clear: "Clear"
|
||||||
sort: "Sort by"
|
sort: "Sort by"
|
||||||
date_asc: "Due Date Ascending"
|
date_asc: "Due Date"
|
||||||
date_desc: "Due Date Descending"
|
|
||||||
atoz: "From A to Z"
|
atoz: "From A to Z"
|
||||||
ztoa: "From Z to A"
|
ztoa: "From Z to A"
|
||||||
display: "Display"
|
display: "Display"
|
||||||
|
|
|
||||||
|
|
@ -19,15 +19,19 @@ en:
|
||||||
new:
|
new:
|
||||||
head_title: "Forgot password"
|
head_title: "Forgot password"
|
||||||
title: "Forgot your password?"
|
title: "Forgot your password?"
|
||||||
submit: "Send me reset password instructions"
|
submit: "Reset password"
|
||||||
registrations:
|
registrations:
|
||||||
password_changed: "Password successfully updated."
|
password_changed: "Password successfully updated."
|
||||||
sessions:
|
sessions:
|
||||||
new:
|
new:
|
||||||
head_title: "Log in"
|
head_title: "Log in"
|
||||||
title: "Log in"
|
title: "Log in"
|
||||||
email_placeholder: "username@email.com"
|
or: "OR"
|
||||||
password_placeholder: "pass****"
|
email_field: "E-mail"
|
||||||
|
email_placeholder: "john.doe@email.com"
|
||||||
|
password_field: "Password"
|
||||||
|
password_placeholder: "Enter password"
|
||||||
|
remember_me: "Remember me"
|
||||||
submit: "Log in"
|
submit: "Log in"
|
||||||
create:
|
create:
|
||||||
team_name: "%{user}'s projects"
|
team_name: "%{user}'s projects"
|
||||||
|
|
@ -56,6 +60,7 @@ en:
|
||||||
errors:
|
errors:
|
||||||
generic: "Failed to sign in user"
|
generic: "Failed to sign in user"
|
||||||
no_local_user_map: "No local user record found"
|
no_local_user_map: "No local user record found"
|
||||||
|
no_email: "Email is missing in auth token"
|
||||||
failed_to_save: "Failed to create new user"
|
failed_to_save: "Failed to create new user"
|
||||||
|
|
||||||
doorkeeper:
|
doorkeeper:
|
||||||
|
|
@ -1573,7 +1578,12 @@ en:
|
||||||
head_title: "Sign up"
|
head_title: "Sign up"
|
||||||
team_name_label: "Team name"
|
team_name_label: "Team name"
|
||||||
team_name_placeholder: "e.g. John's lab"
|
team_name_placeholder: "e.g. John's lab"
|
||||||
team_name_help: "This is the name of your lab or your group. You can invite other members to your team if needed."
|
email_label: "E-mail"
|
||||||
|
full_name_label: "Full name"
|
||||||
|
password_label: "Password"
|
||||||
|
minimum_password_length: "(%{password_length} characters minimum)"
|
||||||
|
password_confirmation_label: "Password confirmation"
|
||||||
|
captcha_description: "Let us know you’re human. Enter the captcha below."
|
||||||
new_with_provider:
|
new_with_provider:
|
||||||
head_title: "Complete the Sign up"
|
head_title: "Complete the Sign up"
|
||||||
statistics:
|
statistics:
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,14 @@ Background:
|
||||||
Scenario: User forgot their password and requests for new password
|
Scenario: User forgot their password and requests for new password
|
||||||
Given I am on reset password page
|
Given I am on reset password page
|
||||||
Then I fill in "nonadmin@myorg.com" in "#user_email" field
|
Then I fill in "nonadmin@myorg.com" in "#user_email" field
|
||||||
And I click "Send me reset password instruction" button
|
And I click "Reset password" button
|
||||||
Then I should see "You will receive an email with instructions on how to reset your password in a few minutes." flash message
|
Then I should see "You will receive an email with instructions on how to reset your password in a few minutes." flash message
|
||||||
|
|
||||||
@javascript
|
@javascript
|
||||||
Scenario: User forgot their password and enters non valid email
|
Scenario: User forgot their password and enters non valid email
|
||||||
Given I am on reset password page
|
Given I am on reset password page
|
||||||
Then I fill in "nonuser@myorg.com" in "#user_email" field
|
Then I fill in "nonuser@myorg.com" in "#user_email" field
|
||||||
And I click "Send me reset password instruction" button
|
And I click "Reset password" button
|
||||||
Then I should see "Email not found"
|
Then I should see "Email not found"
|
||||||
|
|
||||||
@javascript
|
@javascript
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ Feature: Sign up
|
||||||
Scenario: Sign up for an existing user
|
Scenario: Sign up for an existing user
|
||||||
Given I visit the sign up page
|
Given I visit the sign up page
|
||||||
Then I fill the sign up form with
|
Then I fill the sign up form with
|
||||||
| Full name | Email | Password | Password confirmation | Team name |
|
| Full name | E-mail | Password | Password confirmation | Team name |
|
||||||
| Magnus | tusk@gmail.com | asdf1234 | asdf1234 | SpliceGirls |
|
| Magnus | tusk@gmail.com | asdf1234 | asdf1234 | SpliceGirls |
|
||||||
And I click on "Sign up"
|
And I click on "Sign up"
|
||||||
Then I should see "has already been taken"
|
Then I should see "has already been taken"
|
||||||
|
|
@ -23,7 +23,7 @@ Feature: Sign up
|
||||||
Scenario: Sign up for an non-existent user
|
Scenario: Sign up for an non-existent user
|
||||||
Given I visit the sign up page
|
Given I visit the sign up page
|
||||||
Then I fill the sign up form with
|
Then I fill the sign up form with
|
||||||
| Full name | Email | Password | Password confirmation | Team name |
|
| Full name | E-mail | Password | Password confirmation | Team name |
|
||||||
| Magnus | magnus@gmail.com | asdf1234 | asdf1234 | SpliceGirls |
|
| Magnus | magnus@gmail.com | asdf1234 | asdf1234 | SpliceGirls |
|
||||||
And I click on "Sign up"
|
And I click on "Sign up"
|
||||||
Then I should be on homepage
|
Then I should be on homepage
|
||||||
|
|
@ -32,7 +32,7 @@ Feature: Sign up
|
||||||
Scenario: Unsuccessful sign up, password confirmation does not match
|
Scenario: Unsuccessful sign up, password confirmation does not match
|
||||||
Given I visit the sign up page
|
Given I visit the sign up page
|
||||||
Then I fill the sign up form with
|
Then I fill the sign up form with
|
||||||
| Full name | Email | Password | Password confirmation | Team name |
|
| Full name | E-mail | Password | Password confirmation | Team name |
|
||||||
| Magnus | magnus@gmail.com | asdf1234 | asdf1234567 | SpliceGirls |
|
| Magnus | magnus@gmail.com | asdf1234 | asdf1234567 | SpliceGirls |
|
||||||
And I click on "Sign up"
|
And I click on "Sign up"
|
||||||
Then I should see "doesn't match Password"
|
Then I should see "doesn't match Password"
|
||||||
|
|
@ -41,7 +41,7 @@ Feature: Sign up
|
||||||
Scenario: Unsuccessful sign up, team name is missing
|
Scenario: Unsuccessful sign up, team name is missing
|
||||||
Given I visit the sign up page
|
Given I visit the sign up page
|
||||||
Then I fill the sign up form with
|
Then I fill the sign up form with
|
||||||
| Full name | Email | Password | Password confirmation |
|
| Full name | E-mail | Password | Password confirmation |
|
||||||
| Magnus | magnus@gmail.com | asdf1234 | asdf1234 |
|
| Magnus | magnus@gmail.com | asdf1234 | asdf1234 |
|
||||||
And I click on "Sign up"
|
And I click on "Sign up"
|
||||||
Then I should see "is too short (minimum is 2 characters)"
|
Then I should see "is too short (minimum is 2 characters)"
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ end
|
||||||
Given("I click on Reset Password link in the reset password email for user {string}") do |email|
|
Given("I click on Reset Password link in the reset password email for user {string}") do |email|
|
||||||
visit new_user_password_path
|
visit new_user_password_path
|
||||||
fill_in 'user_email', with: email
|
fill_in 'user_email', with: email
|
||||||
click_button 'Send me reset password instruction'
|
click_button 'Reset password'
|
||||||
|
|
||||||
Delayed::Worker.new.work_off
|
Delayed::Worker.new.work_off
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ module OmniAuth
|
||||||
response_mode: response_mode,
|
response_mode: response_mode,
|
||||||
response_type: response_type,
|
response_type: response_type,
|
||||||
nonce: new_nonce,
|
nonce: new_nonce,
|
||||||
scope: 'openid'
|
scope: 'openid profile email'
|
||||||
}
|
}
|
||||||
params[:p] = options[:sign_in_policy] if options[:sign_in_policy].present?
|
params[:p] = options[:sign_in_policy] if options[:sign_in_policy].present?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,9 @@ describe Experiment, type: :model do
|
||||||
expect(Activities::CreateActivityService)
|
expect(Activities::CreateActivityService)
|
||||||
.to(receive(:call)
|
.to(receive(:call)
|
||||||
.with(hash_including(activity_type: :create_module)))
|
.with(hash_including(activity_type: :create_module)))
|
||||||
|
expect(Activities::CreateActivityService)
|
||||||
|
.to(receive(:call)
|
||||||
|
.with(hash_including(activity_type: :assign_user_to_module)))
|
||||||
function_call
|
function_call
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -137,12 +139,15 @@ describe Experiment, type: :model do
|
||||||
.to(receive(:call)
|
.to(receive(:call)
|
||||||
.with(hash_including(activity_type:
|
.with(hash_including(activity_type:
|
||||||
:clone_module))).exactly(3).times
|
:clone_module))).exactly(3).times
|
||||||
|
expect(Activities::CreateActivityService)
|
||||||
|
.to(receive(:call)
|
||||||
|
.with(hash_including(activity_type:
|
||||||
|
:assign_user_to_module))).exactly(3).times
|
||||||
function_call
|
function_call
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'creats 3 new activities in DB' do
|
it 'creats 3 new activities in DB' do
|
||||||
expect { function_call }.to change { Activity.all.count }.by(3)
|
expect { function_call }.to change { Activity.all.count }.by(6)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
10
yarn.lock
10
yarn.lock
|
|
@ -1136,7 +1136,7 @@ adjust-sourcemap-loader@^1.1.0:
|
||||||
object-path "^0.9.2"
|
object-path "^0.9.2"
|
||||||
regex-parser "^2.2.9"
|
regex-parser "^2.2.9"
|
||||||
|
|
||||||
agent-base@4, agent-base@^4.1.0:
|
agent-base@4, agent-base@^4.3.0:
|
||||||
version "4.3.0"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee"
|
||||||
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==
|
||||||
|
|
@ -4659,11 +4659,11 @@ https-browserify@^1.0.0:
|
||||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||||
|
|
||||||
https-proxy-agent@^2.2.0:
|
https-proxy-agent@^2.2.0:
|
||||||
version "2.2.1"
|
version "2.2.4"
|
||||||
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0"
|
resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b"
|
||||||
integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==
|
integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base "^4.1.0"
|
agent-base "^4.3.0"
|
||||||
debug "^3.1.0"
|
debug "^3.1.0"
|
||||||
|
|
||||||
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue