1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-19 13:54:25 +01:00

[bug] the event themes are not kept when editing the event again

This commit is contained in:
Sylvain 2021-05-12 14:54:56 +02:00
parent 910567e156
commit 2a7a7fd614
16 changed files with 367 additions and 38 deletions

View File

@ -4,6 +4,7 @@
- Updated i18next to 19.9.3
- Prevent the worker from crashing if OpenLab is not reachable in dev
- Fix a bug: the notification sent to the project author when a collaborator has confirmed his participation is not sent
- Fix a bug: the event themes are not kept when editing the event again
- Fix a security issue: updated underscore to 1.12.1 to fix [CVE-2021-23358](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-23358)
- Fix a security issue: updated lodash to 4.17.21 to fix [CVE-2021-23337](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-23337)
- Fix a security issue: updated url-parse to 1.5.1 to fix [CVE-2021-27515](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-27515)

View File

@ -0,0 +1,11 @@
import apiClient from './api-client';
import { AxiosResponse } from 'axios';
import { EventTheme } from '../models/event-theme';
export default class EventThemeAPI {
async index (): Promise<Array<EventTheme>> {
const res: AxiosResponse<Array<EventTheme>> = await apiClient.get(`/api/event_themes`);
return res?.data;
}
}

View File

@ -0,0 +1,11 @@
import apiClient from './api-client';
import { AxiosResponse } from 'axios';
import { Theme } from '../models/theme';
export default class ThemeAPI {
async index (): Promise<Array<Theme>> {
const res: AxiosResponse<Array<Theme>> = await apiClient.get(`/api/themes`);
return res?.data;
}
}

View File

@ -0,0 +1,103 @@
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import Select from 'react-select';
import { react2angular } from 'react2angular';
import { Loader } from './loader';
import { Event } from '../models/event';
import { EventTheme } from '../models/event-theme';
import { IApplication } from '../models/application';
import EventThemeAPI from '../api/event-theme';
declare var Application: IApplication;
interface EventThemesProps {
event: Event,
onChange: (themes: Array<EventTheme>) => void
}
/**
* Option format, expected by react-select
* @see https://github.com/JedWatson/react-select
*/
type selectOption = { value: number, label: string };
/**
* This component shows a select input to edit the themes associated with the event
*/
const EventThemes: React.FC<EventThemesProps> = ({ event, onChange }) => {
const { t } = useTranslation('shared');
const [themes, setThemes] = useState<Array<EventTheme>>([]);
useEffect(() => {
new EventThemeAPI().index().then(data => setThemes(data));
}, []);
/**
* Check if there's any EventTheme in DB, otherwise we won't display the selector
*/
const hasThemes = (): boolean => {
return themes.length > 0;
};
/**
* Return the current theme(s) for the given event, formatted to match the react-select format
*/
const defaultValues = (): Array<selectOption> => {
const res = [];
themes.forEach(t => {
if (event.event_theme_ids.indexOf(t.id) > -1) {
res.push({ value: t.id, label: t.name });
}
});
return res;
}
/**
* Callback triggered when the selection has changed.
* Convert the react-select specific format to an array of EventTheme, and call the provided callback.
*/
const handleChange = (selectedOptions: Array<selectOption>): void => {
const res = [];
selectedOptions.forEach(opt => {
res.push(themes.find(t => t.id === opt.value));
})
onChange(res);
// compile
}
/**
* Convert all themes to the react-select format
*/
const buildOptions = (): Array<selectOption> => {
return themes.map(t => {
return { value: t.id, label: t.name }
});
}
return (
<div className="event-themes">
{hasThemes() && <div className="event-themes--panel">
<h3>{ t('app.shared.event.event_themes') }</h3>
<div className="content">
<Select defaultValue={defaultValues()}
placeholder={t('app.shared.event.select_theme')}
onChange={handleChange}
options={buildOptions()}
isMulti />
</div>
</div>}
</div>
);
}
const EventThemesWrapper: React.FC<EventThemesProps> = ({ event, onChange }) => {
return (
<Loader>
<EventThemes event={event} onChange={onChange}/>
</Loader>
);
}
Application.Components.component('eventThemes', react2angular(EventThemesWrapper, ['event', 'onChange']));

View File

@ -21,6 +21,7 @@
*
* Provides :
* - $scope.datePicker = {}
* - $scope.event_themes = []
* - $scope.submited(content)
* - $scope.cancel()
* - $scope.addFile()
@ -31,9 +32,11 @@
* - $scope.toggleRecurrenceEnd(e)
* - $scope.addPrice()
* - $scope.removePrice(price, $event)
* - $scope.handleEventChange(?)
*
* Requires :
* - $scope.event.event_files_attributes = []
* - $scope.event.
* - $state (Ui-Router) [ 'app.public.events_list' ]
*/
class EventsController {
@ -49,6 +52,9 @@ class EventsController {
}
};
// themes of the current event
$scope.event_themes = $scope.event.event_theme_ids;
/**
* For use with ngUpload (https://github.com/twilson63/ngUpload).
* Intended to be the callback when an upload is done: any raised error will be stacked in the
@ -147,6 +153,14 @@ class EventsController {
$scope.event.prices.splice(index, 1);
}
};
/**
* When the theme selection has changes, extract the IDs to populate the form
* @param themes {Array<EventTheme>}
*/
$scope.handleEventChange = function (themes) {
$scope.event_themes = themes.map(t => t.id);
};
}
}
@ -284,7 +298,8 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
resolve: {
category () { return {}; }
},
controller: 'PriceCategoryController' }).result['finally'](null).then(function (p_cat) {
controller: 'PriceCategoryController'
}).result.finally(null).then(function (p_cat) {
// save the price category to the API
PriceCategory.save(p_cat, function (cat) {
$scope.priceCategories.push(cat);
@ -312,7 +327,8 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
resolve: {
category () { return $scope.priceCategories[index]; }
},
controller: 'PriceCategoryController' }).result['finally'](null).then(function (p_cat) {
controller: 'PriceCategoryController'
}).result.finally(null).then(function (p_cat) {
// update the price category to the API
PriceCategory.update({ id }, { price_category: p_cat }, function (cat) {
$scope.priceCategories[index] = cat;
@ -374,7 +390,6 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
return $scope.page = 1;
};
/**
* Setup the feature-tour for the admin/events page.
* This is intended as a contextual help (when pressing F1)
@ -468,7 +483,7 @@ Application.Controllers.controller('AdminEventsController', ['$scope', '$state',
if (settingsPromise.feature_tour_display !== 'manual' && $scope.currentUser.profile.tours.indexOf('events') < 0) {
uitour.start();
}
}
};
/* PRIVATE SCOPE */
@ -532,9 +547,9 @@ Application.Controllers.controller('ShowEventReservationsController', ['$scope',
* @param reservation {Reservation}
* @returns {boolean}
*/
$scope.isCancelled = function(reservation) {
$scope.isCancelled = function (reservation) {
return !!(reservation.slots[0].canceled_at);
}
};
}]);
/**
@ -585,7 +600,7 @@ Application.Controllers.controller('NewEventController', ['$scope', '$state', 'C
];
// triggered when the new event form was submitted to the API and have received an answer
$scope.onSubmited = function(content) {
$scope.onSubmited = function (content) {
if ((content.id == null)) {
$scope.alerts = [];
angular.forEach(content, function (v, k) {
@ -655,7 +670,7 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
}
});
// submit form event by edit-mode
modalInstance.result.then(function(res) {
modalInstance.result.then(function (res) {
$scope.isShowEditModeModal = false;
$scope.editMode = res.editMode;
e.target.click();
@ -664,12 +679,12 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
};
// triggered when the edit event form was submitted to the API and have received an answer
$scope.onSubmited = function(data) {
$scope.onSubmited = function (data) {
if (data.total === data.updated) {
if (data.updated > 1) {
growl.success(_t(
'app.admin.events_edit.events_updated',
{COUNT: data.updated - 1}
{ COUNT: data.updated - 1 }
));
} else {
growl.success(_t(
@ -680,7 +695,7 @@ Application.Controllers.controller('EditEventController', ['$scope', '$state', '
if (data.total > 1) {
growl.warning(_t(
'app.admin.events_edit.events_not_updated',
{TOTAL: data.total, COUNT: data.total - data.updated}
{ TOTAL: data.total, COUNT: data.total - data.updated }
));
if (_.find(data.details, { error: 'EventPriceCategory' })) {
growl.error(_t(
@ -750,20 +765,20 @@ Application.Controllers.controller('EditRecurrentEventController', ['$scope', '$
$uibModalInstance.close({
editMode: $scope.editMode
});
}
};
/**
* Test if any of the dates of the event has changed
*/
$scope.hasDateChanged = function() {
$scope.hasDateChanged = function () {
return (!moment(initialDates.start).isSame(currentEvent.start_date, 'day') || !moment(initialDates.end).isSame(currentEvent.end_date, 'day'));
}
};
/**
* Cancellation callback
*/
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
}
};
}
]);

View File

@ -0,0 +1,5 @@
export interface EventTheme {
id: number,
name: string,
related_to: number
}

View File

@ -0,0 +1,50 @@
export interface Event {
id: number,
title: string,
description: string,
event_image: string,
event_files_attributes: Array<{
id: number,
attachment: string,
attachment_url: string
}>,
category_id: number,
category: {
id: number,
name: string,
slug: string
},
event_theme_ids: Array<number>,
event_themes: Array<{
name: string
}>,
age_range_id: number,
age_range: {
name: string
},
start_date: Date,
start_time: Date,
end_date: Date,
end_time: Date,
month: string;
month_id: number,
year: number,
all_day: boolean,
availability: {
id: number,
start_at: Date,
end_at: Date
},
availability_id: number,
amount: number,
prices: Array<{
id: number,
amount: number,
category: {
id: number,
name: string
}
}>,
nb_total_places: number,
nb_free_places: number
}

View File

@ -0,0 +1,4 @@
export interface Theme {
id: number,
name: string
}

View File

@ -33,5 +33,6 @@
@import "modules/stripe-confirm";
@import "modules/payment-schedule-dashboard";
@import "modules/plan-card";
@import "modules/event-themes";
@import "app.responsive";

View File

@ -0,0 +1,20 @@
.event-themes {
&--panel {
border: 1px solid #dddddd;
border-radius: 6px;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
margin: 30px 15px;
h3 {
padding: 15px 15px;
border-bottom: 1px solid #dddddd;
margin: 0;
font-size: 1.4rem;
}
.content {
font-size: 1.4rem;
padding: 15px;
}
}
}

View File

@ -109,23 +109,8 @@
</div>
</div>
<div class="widget panel b-a m m-t-lg" ng-show="themes.length > 0">
<div class="panel-heading b-b small">
<h3 translate>{{ 'app.shared.event.event_theme' }}</h3>
</div>
<div class="widget-content no-bg wrapper">
<input type="hidden" name="event[event_theme_ids][]" value="" />
<ui-select ng-model="event.event_theme_ids" name="event[event_theme_ids][]">
<ui-select-match>
<span ng-bind="$select.selected.name"></span>
<input type="hidden" name="event[event_theme_ids][]" value="{{$select.selected.id}}" />
</ui-select-match>
<ui-select-choices repeat="t.id as t in (themes | filter: $select.search)">
<span ng-bind-html="t.name | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
</div>
</div>
<event-themes event="event" on-change="handleEventChange"></event-themes>
<input type="hidden" name="event[event_theme_ids][]" ng-repeat="id in event_themes" value="{{id}}" />
<div class="widget panel b-a m m-t-lg" ng-show="ageRanges.length > 0">
<div class="panel-heading b-b small">

View File

@ -1,6 +1,6 @@
# frozen_string_literal: true
json.extract! event, :id, :title, :description, :age_range_id
json.extract! event, :id, :title, :description
json.event_image event.event_image.attachment_url if event.event_image
json.event_files_attributes event.event_files do |f|
json.id f.id

View File

@ -157,7 +157,8 @@ en:
standard_rate: "Standard rate"
0_equal_free: "0 = free"
tickets_available: "Tickets available"
event_theme: "Event theme"
event_themes: "Event themes"
select_theme: "Pick up a theme..."
age_range: "Age range"
#subscription plan edition form
plan:

View File

@ -157,7 +157,8 @@ fr:
standard_rate: "Tarif standard"
0_equal_free: "0 = gratuit"
tickets_available: "Places disponibles"
event_theme: "Thème de l'événement"
event_themes: "Thèmes de l'événement"
select_theme: "Choisissez un thème ..."
age_range: "Tranche d'âge"
#subscription plan edition form
plan:

View File

@ -102,6 +102,7 @@
"react-dom": "^17.0.0",
"react-i18next": "^11.7.3",
"react-modal": "^3.11.2",
"react-select": "^4.3.1",
"react-switch": "^5.0.1",
"react2angular": "^4.0.6",
"summernote": "0.8.18",

126
yarn.lock
View File

@ -970,7 +970,7 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.6":
"@babel/runtime@^7.12.0", "@babel/runtime@^7.13.10", "@babel/runtime@^7.13.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.14.0"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.14.0.tgz#46794bc20b612c5f75e62dd071e24dfd95f1cbe6"
integrity sha512-JELkvo/DlpNdJ7dlyw/eY7E0suy5i5GQH+Vlxaq1nsNJ+H7f4Vtv3jMeCEgRhZZQFXTjldYfQgv2qmM6M1v5wA==
@ -1043,6 +1043,71 @@
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
"@emotion/cache@^11.4.0":
version "11.4.0"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.4.0.tgz#293fc9d9a7a38b9aad8e9337e5014366c3b09ac0"
integrity sha512-Zx70bjE7LErRO9OaZrhf22Qye1y4F7iDl+ITjet0J+i+B88PrAOBkKvaAWhxsZf72tDLajwCgfCjJ2dvH77C3g==
dependencies:
"@emotion/memoize" "^0.7.4"
"@emotion/sheet" "^1.0.0"
"@emotion/utils" "^1.0.0"
"@emotion/weak-memoize" "^0.2.5"
stylis "^4.0.3"
"@emotion/hash@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413"
integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==
"@emotion/memoize@^0.7.4":
version "0.7.5"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.5.tgz#2c40f81449a4e554e9fc6396910ed4843ec2be50"
integrity sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==
"@emotion/react@^11.1.1":
version "11.4.0"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.4.0.tgz#2465ad7b073a691409b88dfd96dc17097ddad9b7"
integrity sha512-4XklWsl9BdtatLoJpSjusXhpKv9YVteYKh9hPKP1Sxl+mswEFoUe0WtmtWjxEjkA51DQ2QRMCNOvKcSlCQ7ivg==
dependencies:
"@babel/runtime" "^7.13.10"
"@emotion/cache" "^11.4.0"
"@emotion/serialize" "^1.0.2"
"@emotion/sheet" "^1.0.1"
"@emotion/utils" "^1.0.0"
"@emotion/weak-memoize" "^0.2.5"
hoist-non-react-statics "^3.3.1"
"@emotion/serialize@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.0.2.tgz#77cb21a0571c9f68eb66087754a65fa97bfcd965"
integrity sha512-95MgNJ9+/ajxU7QIAruiOAdYNjxZX7G2mhgrtDWswA21VviYIRP1R5QilZ/bDY42xiKsaktP4egJb3QdYQZi1A==
dependencies:
"@emotion/hash" "^0.8.0"
"@emotion/memoize" "^0.7.4"
"@emotion/unitless" "^0.7.5"
"@emotion/utils" "^1.0.0"
csstype "^3.0.2"
"@emotion/sheet@^1.0.0", "@emotion/sheet@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.0.1.tgz#245f54abb02dfd82326e28689f34c27aa9b2a698"
integrity sha512-GbIvVMe4U+Zc+929N1V7nW6YYJtidj31lidSmdYcWozwoBIObXBnaJkKNDjZrLm9Nc0BR+ZyHNaRZxqNZbof5g==
"@emotion/unitless@^0.7.5":
version "0.7.5"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.7.5.tgz#77211291c1900a700b8a78cfafda3160d76949ed"
integrity sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==
"@emotion/utils@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.0.0.tgz#abe06a83160b10570816c913990245813a2fd6af"
integrity sha512-mQC2b3XLDs6QCW+pDQDiyO/EdGZYOygE8s5N5rrzjSI4M3IejPE/JPndCBwRT9z982aqQNi6beWs1UeayrQxxA==
"@emotion/weak-memoize@^0.2.5":
version "0.2.5"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
"@fortawesome/fontawesome-free@5.14.0":
version "5.14.0"
resolved "https://registry.yarnpkg.com/@fortawesome/fontawesome-free/-/fontawesome-free-5.14.0.tgz#a371e91029ebf265015e64f81bfbf7d228c9681f"
@ -3301,6 +3366,14 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dom-serializer@0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
@ -4569,6 +4642,13 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
dependencies:
react-is "^16.7.0"
holderjs@2.6:
version "2.6.0"
resolved "https://registry.yarnpkg.com/holderjs/-/holderjs-2.6.0.tgz#e2ab6e02d4177684c0fe1414ecea013bc4b1505e"
@ -5764,6 +5844,11 @@ medium-editor@4.4.0:
resolved "https://registry.yarnpkg.com/medium-editor/-/medium-editor-4.4.0.tgz#ef188cc9cc5cba87177da8cb657a885dfbbe5760"
integrity sha1-7xiMycxcuocXfajLZXqIXfu+V2A=
memoize-one@^5.0.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
memory-fs@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552"
@ -7548,7 +7633,7 @@ promise-inflight@^1.0.1:
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
prop-types@^15.5.10, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -7725,7 +7810,14 @@ react-i18next@^11.7.3:
"@babel/runtime" "^7.13.6"
html-parse-stringify "^3.0.1"
react-is@^16.8.1:
react-input-autosize@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-3.0.0.tgz#6b5898c790d4478d69420b55441fcc31d5c50a85"
integrity sha512-nL9uS7jEs/zu8sqwFE5MAPx6pPkNAriACQ2rGLlqmKr2sPGtN7TXTyDdQt4lbNXVx7Uzadb40x8qotIuru6Rhg==
dependencies:
prop-types "^15.5.8"
react-is@^16.7.0, react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
@ -7750,6 +7842,19 @@ react-refresh@^0.9.0:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.9.0.tgz#71863337adc3e5c2f8a6bfddd12ae3bfe32aafbf"
integrity sha512-Gvzk7OZpiqKSkxsQvO/mbTN1poglhmAV7gR/DdIrRrSMXraRQQlfikRJOr3Nb9GTMPC5kof948Zy6jJZIFtDvQ==
react-select@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/react-select/-/react-select-4.3.1.tgz#389fc07c9bc7cf7d3c377b7a05ea18cd7399cb81"
integrity sha512-HBBd0dYwkF5aZk1zP81Wx5UsLIIT2lSvAY2JiJo199LjoLHoivjn9//KsmvQMEFGNhe58xyuOITjfxKCcGc62Q==
dependencies:
"@babel/runtime" "^7.12.0"
"@emotion/cache" "^11.4.0"
"@emotion/react" "^11.1.1"
memoize-one "^5.0.0"
prop-types "^15.6.0"
react-input-autosize "^3.0.0"
react-transition-group "^4.3.0"
react-switch@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/react-switch/-/react-switch-5.0.1.tgz#449277f4c3aed5286fffd0f50d5cbc2a23330406"
@ -7757,6 +7862,16 @@ react-switch@^5.0.1:
dependencies:
prop-types "^15.6.2"
react-transition-group@^4.3.0:
version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react2angular@^4.0.6:
version "4.0.6"
resolved "https://registry.yarnpkg.com/react2angular/-/react2angular-4.0.6.tgz#ec49ef834d101c9a320e25229fc5afa5b29edc4f"
@ -8879,6 +8994,11 @@ stylehacks@^4.0.0:
postcss "^7.0.0"
postcss-selector-parser "^3.0.0"
stylis@^4.0.3:
version "4.0.10"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.0.10.tgz#446512d1097197ab3f02fb3c258358c3f7a14240"
integrity sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==
summernote@0.8.18:
version "0.8.18"
resolved "https://registry.yarnpkg.com/summernote/-/summernote-0.8.18.tgz#be5c368b1c92de8a05039a9976157bdea7aae386"