mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2024-11-28 09:24:24 +01:00
Merge branch 'dev' for release 4.7.9
This commit is contained in:
commit
c7527d06dd
29
CHANGELOG.md
29
CHANGELOG.md
@ -1,5 +1,34 @@
|
||||
# Changelog Fab-manager
|
||||
|
||||
## v4.7.9 2021 May 17
|
||||
|
||||
- Updated dependency to OpenLab
|
||||
- Updated i18next to 19.9.3
|
||||
- Prevent the worker from crashing if OpenLab is not reachable in dev
|
||||
- Allow setting multiple themes for a single event
|
||||
- Increased the width of the input field for the prices of the events
|
||||
- Script to run a rails command with ease in production (`run.fab.mn`)
|
||||
- Fix a bug: invalid currency in notifications for locales with region (eg. fr-CM)
|
||||
- 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 bug: the count of successfully updated events was not correct
|
||||
- Fix a bug: german watermark was missing
|
||||
- Fix a bug: invoices are not generated in test/development for locale with region (eg. fr-CA)
|
||||
- Fix a bug: cannot access to "about" page on small devices
|
||||
- Fix a bug: "about" page shows a non-functional menu icon
|
||||
- Fix a bug: responsiveness of the "about" page title
|
||||
− Fix a bug: unable to change the slots durations for a new availability
|
||||
- Fix a bug: some invoices does not have the name of the user
|
||||
- Fix a bug: unable to sort invoices by date
|
||||
- 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)
|
||||
- Fix a security issue: updated hosted-git-info to 2.8.9 to fix [CVE-2021-23362](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-23362)
|
||||
- Fix a security issue: updated codemirror to 5.58.2 to fix [CVE-2020-7760](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7760)
|
||||
- Fix a security issue: updated rails to 5.2.6 to fix [CVE-2021-22904](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-22904)
|
||||
- Fix a security issue: updated react-i18next to 11.8.15 to fix [CVE-2021-23346](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-23346)
|
||||
- [TODO DEPLOY] `rails fablab:fix:invoices_without_names`
|
||||
|
||||
## v4.7.8 2021 April 02
|
||||
- Updated mimemagic to 0.3.10 to fix [a build issue](https://github.com/mimemagicrb/mimemagic/issues/139)
|
||||
|
||||
|
97
Gemfile.lock
97
Gemfile.lock
@ -4,46 +4,46 @@ GEM
|
||||
Ascii85 (1.0.3)
|
||||
aasm (5.0.8)
|
||||
concurrent-ruby (~> 1.0)
|
||||
actioncable (5.2.4.5)
|
||||
actionpack (= 5.2.4.5)
|
||||
actioncable (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailer (5.2.4.5)
|
||||
actionpack (= 5.2.4.5)
|
||||
actionview (= 5.2.4.5)
|
||||
activejob (= 5.2.4.5)
|
||||
actionmailer (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (5.2.4.5)
|
||||
actionview (= 5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
actionpack (5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
||||
actionpack-page_caching (1.2.2)
|
||||
actionpack (>= 5.0.0)
|
||||
actionview (5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
actionview (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
||||
active_record_query_trace (1.7)
|
||||
activejob (5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
activejob (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
activerecord (5.2.4.5)
|
||||
activemodel (= 5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
activemodel (5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
activerecord (5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
arel (>= 9.0)
|
||||
activestorage (5.2.4.5)
|
||||
actionpack (= 5.2.4.5)
|
||||
activerecord (= 5.2.4.5)
|
||||
marcel (~> 0.3.1)
|
||||
activesupport (5.2.4.5)
|
||||
activestorage (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
marcel (~> 1.0.0)
|
||||
activesupport (5.2.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
@ -154,10 +154,10 @@ GEM
|
||||
hashery (2.1.2)
|
||||
hashie (4.1.0)
|
||||
htmlentities (4.3.4)
|
||||
httparty (0.18.0)
|
||||
httparty (0.18.1)
|
||||
mime-types (~> 3.0)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (1.8.9)
|
||||
i18n (1.8.10)
|
||||
concurrent-ruby (~> 1.0)
|
||||
icalendar (2.5.3)
|
||||
ice_cube (~> 0.16)
|
||||
@ -188,25 +188,24 @@ GEM
|
||||
listen (3.0.8)
|
||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
||||
rb-inotify (~> 0.9, >= 0.9.7)
|
||||
loofah (2.9.0)
|
||||
loofah (2.9.1)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (0.3.3)
|
||||
mimemagic (~> 0.3.2)
|
||||
marcel (1.0.1)
|
||||
message_format (0.0.6)
|
||||
twitter_cldr (~> 5.0)
|
||||
method_source (1.0.0)
|
||||
mime-types (3.3.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2020.0512)
|
||||
mimemagic (0.3.10)
|
||||
mime-types-data (3.2021.0225)
|
||||
mimemagic (0.4.3)
|
||||
nokogiri (~> 1)
|
||||
rake
|
||||
mini_magick (4.10.1)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.5.0)
|
||||
mini_mime (1.1.0)
|
||||
mini_portile2 (2.5.1)
|
||||
minitest (5.14.4)
|
||||
minitest-reporters (1.4.2)
|
||||
ansi
|
||||
@ -217,8 +216,8 @@ GEM
|
||||
multi_json (1.14.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
nio4r (2.5.5)
|
||||
nokogiri (1.11.1)
|
||||
nio4r (2.5.7)
|
||||
nokogiri (1.11.3)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
notify_with (0.0.2)
|
||||
@ -241,7 +240,7 @@ GEM
|
||||
omniauth-rails_csrf_protection (0.1.2)
|
||||
actionpack (>= 4.2)
|
||||
omniauth (>= 1.3.1)
|
||||
openlab_ruby (0.0.4)
|
||||
openlab_ruby (0.0.5)
|
||||
httparty (~> 0.13)
|
||||
orm_adapter (0.5.0)
|
||||
parallel (1.19.1)
|
||||
@ -278,18 +277,18 @@ GEM
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
railroady (1.5.3)
|
||||
rails (5.2.4.5)
|
||||
actioncable (= 5.2.4.5)
|
||||
actionmailer (= 5.2.4.5)
|
||||
actionpack (= 5.2.4.5)
|
||||
actionview (= 5.2.4.5)
|
||||
activejob (= 5.2.4.5)
|
||||
activemodel (= 5.2.4.5)
|
||||
activerecord (= 5.2.4.5)
|
||||
activestorage (= 5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
rails (5.2.6)
|
||||
actioncable (= 5.2.6)
|
||||
actionmailer (= 5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
actionview (= 5.2.6)
|
||||
activejob (= 5.2.6)
|
||||
activemodel (= 5.2.6)
|
||||
activerecord (= 5.2.6)
|
||||
activestorage (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 5.2.4.5)
|
||||
railties (= 5.2.6)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
@ -303,9 +302,9 @@ GEM
|
||||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (5.2.4.5)
|
||||
actionpack (= 5.2.4.5)
|
||||
activesupport (= 5.2.4.5)
|
||||
railties (5.2.6)
|
||||
actionpack (= 5.2.6)
|
||||
activesupport (= 5.2.6)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.19.0, < 2.0)
|
||||
|
@ -64,7 +64,9 @@ class API::EventsController < API::ApiController
|
||||
def update
|
||||
authorize Event
|
||||
res = EventService.update(@event, event_params.permit!, params[:edit_mode])
|
||||
render json: { action: 'update', total: res.length, updated: res.select { |r| r[:status] }.length, details: res }, status: :ok, location: @event
|
||||
render json: { action: 'update', total: res[:events].length, updated: res[:events].select { |r| r[:status] }.length, details: res },
|
||||
status: :ok,
|
||||
location: @event
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -4,7 +4,6 @@
|
||||
class API::TranslationsController < API::ApiController
|
||||
before_action :set_locale
|
||||
|
||||
|
||||
def show
|
||||
translations = I18n.t params[:state]
|
||||
if translations.class.name == String.name && translations.start_with?('translation missing')
|
||||
@ -16,6 +15,8 @@ class API::TranslationsController < API::ApiController
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_locale
|
||||
I18n.locale = params[:locale] || I18n.default_locale
|
||||
end
|
||||
|
@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base
|
||||
respond_to :html, :json
|
||||
|
||||
before_action :configure_permitted_parameters, if: :devise_controller?
|
||||
around_action :switch_locale
|
||||
|
||||
# Globally rescue Authorization Errors in controller.
|
||||
# Returning 403 Forbidden if permission is denied
|
||||
@ -61,6 +62,13 @@ class ApplicationController < ActionController::Base
|
||||
head 403
|
||||
end
|
||||
|
||||
# Set the configured locale for each action (API call)
|
||||
# @see https://guides.rubyonrails.org/i18n.html
|
||||
def switch_locale(&action)
|
||||
locale = params[:locale] || Rails.application.secrets.rails_locale
|
||||
I18n.with_locale(locale, &action)
|
||||
end
|
||||
|
||||
# @return [User]
|
||||
# This is a placeholder for Devise's current_user.
|
||||
# As Devise generate the method at runtime, IDEs autocomplete features will complain about 'method not found'
|
||||
|
11
app/frontend/src/javascript/api/event-theme.ts
Normal file
11
app/frontend/src/javascript/api/event-theme.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
|
11
app/frontend/src/javascript/api/theme.ts
Normal file
11
app/frontend/src/javascript/api/theme.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
|
102
app/frontend/src/javascript/components/event-themes.tsx
Normal file
102
app/frontend/src/javascript/components/event-themes.tsx
Normal file
@ -0,0 +1,102 @@
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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']));
|
@ -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');
|
||||
}
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
11
app/frontend/src/javascript/controllers/header.js
Normal file
11
app/frontend/src/javascript/controllers/header.js
Normal file
@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('HeaderController', ['$scope', '$rootScope', '$state',
|
||||
function ($scope, $rootScope, $state) {
|
||||
$scope.aboutPage = ($state.current.name === 'app.public.about');
|
||||
|
||||
$rootScope.$on('$stateChangeStart', function (event, toState) {
|
||||
$scope.aboutPage = (toState.name === 'app.public.about');
|
||||
});
|
||||
}
|
||||
]);
|
5
app/frontend/src/javascript/models/event-theme.ts
Normal file
5
app/frontend/src/javascript/models/event-theme.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export interface EventTheme {
|
||||
id: number,
|
||||
name: string,
|
||||
related_to: number
|
||||
}
|
50
app/frontend/src/javascript/models/event.ts
Normal file
50
app/frontend/src/javascript/models/event.ts
Normal 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
|
||||
}
|
4
app/frontend/src/javascript/models/theme.ts
Normal file
4
app/frontend/src/javascript/models/theme.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface Theme {
|
||||
id: number,
|
||||
name: string
|
||||
}
|
@ -21,7 +21,8 @@ angular.module('application.router', ['ui.router'])
|
||||
abstract: true,
|
||||
views: {
|
||||
header: {
|
||||
templateUrl: '/shared/header.html.erb'
|
||||
templateUrl: '/shared/header.html.erb',
|
||||
controller: 'HeaderController'
|
||||
},
|
||||
leftnav: {
|
||||
templateUrl: '/shared/leftnav.html',
|
||||
|
@ -445,11 +445,12 @@
|
||||
font-size: rem-calc(18);
|
||||
}
|
||||
|
||||
p {
|
||||
.about-title,
|
||||
.about-title p
|
||||
{
|
||||
font-size: rem-calc(18);
|
||||
line-height: rem-calc(30);
|
||||
color: $black-light;
|
||||
text-align: justify;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&.ng-hide {
|
||||
|
@ -10,7 +10,8 @@
|
||||
}
|
||||
|
||||
.about-fablab {
|
||||
.about-title {
|
||||
.about-title,
|
||||
.about-title p {
|
||||
font-size: rem-calc(30);
|
||||
line-height: rem-calc(28);
|
||||
text-align: center;
|
||||
|
@ -458,6 +458,10 @@ p, .widget p {
|
||||
.p-l {
|
||||
padding: 16px;
|
||||
}
|
||||
.p-h-0 {
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.p-h-xs {
|
||||
padding-left: 5px;
|
||||
|
@ -33,5 +33,6 @@
|
||||
@import "modules/stripe-confirm";
|
||||
@import "modules/payment-schedule-dashboard";
|
||||
@import "modules/plan-card";
|
||||
@import "modules/event-themes";
|
||||
|
||||
@import "app.responsive";
|
||||
|
20
app/frontend/src/stylesheets/modules/event-themes.scss
Normal file
20
app/frontend/src/stylesheets/modules/event-themes.scss
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
@ -89,7 +89,7 @@
|
||||
</p>
|
||||
<div class="col-md-5">
|
||||
<div class="input-group">
|
||||
<input type="number" class="form-control" ng-model="availability.slot_duration" step="5" min="1" required="true" />
|
||||
<input type="number" class="form-control" ng-model="availability.slot_duration" min="1" required="true" />
|
||||
<span class="input-group-addon" translate>{{ 'app.admin.calendar.minutes' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -109,23 +109,9 @@
|
||||
</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}}" />
|
||||
<input type="hidden" name="event[event_theme_ids][]" value="" ng-if="event_themes.length === 0" />
|
||||
|
||||
<div class="widget panel b-a m m-t-lg" ng-show="ageRanges.length > 0">
|
||||
<div class="panel-heading b-b small">
|
||||
@ -243,7 +229,7 @@
|
||||
<div class="widget-content no-bg wrapper">
|
||||
<div class="form-group">
|
||||
<label for="event_amount" class="col-sm-5 control-label" translate>{{ 'app.shared.event.standard_rate' }}</label>
|
||||
<div class="col-sm-5">
|
||||
<div class="col-sm-6 p-h-0">
|
||||
<div class="input-group">
|
||||
<input ng-model="event.amount" type="number" name="event[amount]" class="form-control" id="event_amount" required>
|
||||
<div class="input-group-addon">{{currencySymbol}}</div>
|
||||
@ -260,7 +246,7 @@
|
||||
ng-options="cat as cat.name for cat in priceCategories track by cat.id">
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-sm-5">
|
||||
<div class="col-sm-6 p-h-0">
|
||||
<div class="input-group">
|
||||
<input ng-model="price.amount"
|
||||
type="number"
|
||||
@ -271,17 +257,17 @@
|
||||
</div>
|
||||
<div class="col-sm-1">
|
||||
<input type="hidden" name="event[event_price_categories_attributes][][_destroy]" ng-value="price._destroy">
|
||||
<a class="btn" ng-click="removePrice(price, $event)" href="#"><i class="fa fa-times text-danger"></i></a>
|
||||
<a class="btn p-h-0" ng-click="removePrice(price, $event)" href="#"><i class="fa fa-times text-danger"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="link-icon m-b" ng-hide="event.prices.length == priceCategories.length">
|
||||
<div class="col-sm-offset-5">
|
||||
<i class="fa fa-plus"></i> <span ng-click="addPrice()">Ajouter un tarif</span>
|
||||
<i class="fa fa-plus"></i> <span ng-click="addPrice()" translate>{{ 'app.shared.event.add_price' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="event_nb_total_places" class="col-sm-5 control-label" translate>{{ 'app.shared.event.tickets_available' }}</label>
|
||||
<div class="col-sm-6">
|
||||
<div class="col-sm-6 p-h-0">
|
||||
<div class="input-group">
|
||||
<input ng-model="event.nb_total_places" type="number" name="event[nb_total_places]" class="form-control" id="event_nb_total_places">
|
||||
<div class="input-group-addon"><i class="fa fa-ticket"></i> </div>
|
||||
|
@ -59,7 +59,9 @@
|
||||
<h6 class="m-n" ng-if="event.amount">{{ 'app.public.events_list.full_price_' | translate }} {{event.amount | currency}} <span ng-repeat="price in event.prices">/ {{ price.category.name }} {{price.amount | currency}}</span></h6>
|
||||
|
||||
<div>
|
||||
<span class="text-black-light text-xs" ng-if="event.event_themes[0]"><i class="fa fa-tags" aria-hidden="true"></i> {{event.event_themes[0].name}}</span>
|
||||
<span class="text-black-light text-xs m-r-xs" ng-repeat="theme in event.event_themes">
|
||||
<i class="fa fa-tags" aria-hidden="true"></i> {{theme.name}}
|
||||
</span>
|
||||
<span class="text-black-light text-xs" ng-if="event.age_range"><i class="fa fa-users" aria-hidden="true"></i> {{event.age_range.name}}</span>
|
||||
</div>
|
||||
|
||||
|
@ -75,7 +75,9 @@
|
||||
|
||||
<h5>{{event.category.name}}</h5>
|
||||
<dl class="text-sm">
|
||||
<dt ng-if="event.event_themes.length > 0"><i class="fa fa-tags" aria-hidden="true"></i> {{event.event_themes[0].name}}</dt>
|
||||
<dt ng-repeat="theme in event.event_themes">
|
||||
<i class="fa fa-tags" aria-hidden="true"></i> {{theme.name}}
|
||||
</dt>
|
||||
<dt ng-if="event.age_range"><i class="fa fa-users" aria-hidden="true"></i> {{event.age_range.name}}</dt>
|
||||
</dl>
|
||||
<dl class="text-sm">
|
||||
|
@ -1,7 +1,12 @@
|
||||
|
||||
<div class="navbar-header">
|
||||
<a ng-click="toggleNavSize($event)" class="btn btn-link visible-xs" data-toggle="class:nav-off-screen" data-target="#nav"><i class="fa fa-bars"></i></a>
|
||||
<a ui-sref="app.public.home" class="navbar-brand" ng-click="goabout = false">
|
||||
<a ng-click="toggleNavSize($event)" class="btn btn-link visible-xs" data-toggle="class:nav-off-screen" data-target="#nav" ng-hide="aboutPage">
|
||||
<i class="fa fa-bars"></i>
|
||||
</a>
|
||||
<a ui-sref="app.public.home" class="btn btn-link visible-xs" ng-show="aboutPage">
|
||||
<i class="fa fa-caret-up"></i>
|
||||
</a>
|
||||
<a ui-sref="app.public.home" class="navbar-brand">
|
||||
<img ng-src="{{logo.custom_asset_file_attributes.attachment_url}}" alt="{{logo.custom_asset_file_attributes.attachment}}" class="m-r-sm"/>
|
||||
<%= "<label class='label-staging label label-warning text-sm hidden-sm hidden-xs'>Staging</label>".html_safe if Rails.env.staging? %>
|
||||
</a>
|
||||
@ -9,12 +14,12 @@
|
||||
|
||||
<ul class="nav navbar-nav hidden-xs">
|
||||
<li class="about-page-link">
|
||||
<a href class="about-link font-sbold text-sm" ng-click="goabout = !goabout" ui-sref="app.public.about" ng-show="!goabout">
|
||||
<a href class="about-link font-sbold text-sm" ui-sref="app.public.about" ng-show="!aboutPage">
|
||||
<span class="label label-theme rounded text-lg text-white m-r-sm font-ebold">?</span>
|
||||
{{ linkName }}
|
||||
</a>
|
||||
<a href class="about-link font-sbold text-sm" ng-click="goabout = !goabout" ui-sref="app.public.home" ng-show="goabout">
|
||||
<span class="label label-theme label-icon rounded text-lg text-white m-r-sm font-ebold"><i class="fa fa-caret-up" ng-show="goabout"></i></span>
|
||||
<a href class="about-link font-sbold text-sm" ui-sref="app.public.home" ng-show="aboutPage">
|
||||
<span class="label label-theme label-icon rounded text-lg text-white m-r-sm font-ebold"><i class="fa fa-caret-up" ng-show="aboutPage"></i></span>
|
||||
{{ 'app.public.common.return' | translate }}
|
||||
</a>
|
||||
</li>
|
||||
|
@ -62,6 +62,11 @@
|
||||
</a>
|
||||
</li>
|
||||
<!-- Common menu entries -->
|
||||
<li class="hidden-sm hidden-md hidden-lg">
|
||||
<a class="auto pointer" ui-sref="app.public.about">
|
||||
<i class="fa fa-question-circle-o"></i> <span>{{ linkName }}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="{{navLink.class}}" ng-repeat="navLink in navLinks">
|
||||
<a ng-click="toggleNavSize($event)" ui-sref="{{navLink.state}}" ui-sref-active="active" class="auto" data-toggle="class:nav-off-screen" data-target="#nav" ng-if="navLink.state">
|
||||
<i class="fa fa-{{navLink.linkIcon}} fa-lg"></i>
|
||||
|
@ -135,7 +135,8 @@ class Invoice < PaymentDocument
|
||||
def prevent_refund?
|
||||
return true if user.nil?
|
||||
|
||||
if invoiced_type == 'Reservation' && invoiced.reservable_type == 'Training'
|
||||
# workaround for reservation saved after invoice
|
||||
if invoiced_type == 'Reservation' && invoiced&.reservable_type == 'Training'
|
||||
user.trainings.include?(invoiced.reservable_id)
|
||||
else
|
||||
false
|
||||
|
@ -12,7 +12,7 @@ class Profile < ApplicationRecord
|
||||
validates :last_name, presence: true, length: { maximum: 30 }
|
||||
validates_numericality_of :phone, only_integer: true, allow_blank: false, if: -> { Setting.get('phone_required') }
|
||||
|
||||
after_commit :update_invoicing_profile, if: :invoicing_data_was_modified?, on: [:update]
|
||||
after_commit :update_invoicing_profile, if: :invoicing_data_was_modified?
|
||||
|
||||
def full_name
|
||||
# if first_name or last_name is nil, the empty string will be used as a temporary replacement
|
||||
|
@ -29,7 +29,7 @@ class ProjectUser < ApplicationRecord
|
||||
|
||||
def notify_project_author_when_collaborator_valid
|
||||
NotificationCenter.call type: 'notify_project_author_when_collaborator_valid',
|
||||
receiver: project.author,
|
||||
receiver: project.author.user,
|
||||
attached_object: self
|
||||
end
|
||||
end
|
||||
|
@ -438,7 +438,9 @@ class User < ApplicationRecord
|
||||
raise NoProfileError if invoicing_profile.nil?
|
||||
|
||||
invoicing_profile.update_attributes(
|
||||
email: email
|
||||
email: email,
|
||||
first_name: first_name,
|
||||
last_name: last_name
|
||||
)
|
||||
end
|
||||
end
|
||||
|
BIN
app/pdfs/data/watermark-de.png
Normal file
BIN
app/pdfs/data/watermark-de.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.4 KiB |
@ -353,7 +353,7 @@ class PDF::Invoice < Prawn::Document
|
||||
|
||||
transparent(0.1) do
|
||||
rotate(45, origin: [0, 0]) do
|
||||
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.locale}.png", at: [90, 150]
|
||||
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.default_locale}.png", at: [90, 150]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -126,7 +126,7 @@ class PDF::PaymentSchedule < Prawn::Document
|
||||
|
||||
transparent(0.1) do
|
||||
rotate(45, origin: [0, 0]) do
|
||||
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.locale}.png", at: [90, 150]
|
||||
image "#{Rails.root}/app/pdfs/data/watermark-#{I18n.default_locale}.png", at: [90, 150]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -102,7 +102,10 @@ class EventService
|
||||
private
|
||||
|
||||
def update_events(event, events, event_params)
|
||||
results = []
|
||||
results = {
|
||||
events: [],
|
||||
slots: []
|
||||
}
|
||||
events.each do |e|
|
||||
next unless e.id != event.id
|
||||
|
||||
@ -164,18 +167,18 @@ class EventService
|
||||
event_files_attributes: ef_attributes
|
||||
)
|
||||
begin
|
||||
results.push status: !!e.update(e_params.permit!), event: e # rubocop:disable Style/DoubleNegation
|
||||
results[:events].push status: !!e.update(e_params.permit!), event: e # rubocop:disable Style/DoubleNegation
|
||||
rescue StandardError => err
|
||||
results.push status: false, event: e, error: err.try(:record).try(:class).try(:name), message: err.message
|
||||
results[:events].push status: false, event: e, error: err.try(:record).try(:class).try(:name), message: err.message
|
||||
end
|
||||
results.concat(update_slots(e.availability_id))
|
||||
results[:slots].concat(update_slots(e.availability_id))
|
||||
end
|
||||
begin
|
||||
results.push status: !!event.update(event_params), event: event # rubocop:disable Style/DoubleNegation
|
||||
results[:events].push status: !!event.update(event_params), event: event # rubocop:disable Style/DoubleNegation
|
||||
rescue StandardError => err
|
||||
results.push status: false, event: event, error: err.try(:record).try(:class).try(:name), message: err.message
|
||||
results[:events].push status: false, event: event, error: err.try(:record).try(:class).try(:name), message: err.message
|
||||
end
|
||||
results.concat(update_slots(event.availability_id))
|
||||
results[:slots].concat(update_slots(event.availability_id))
|
||||
results
|
||||
end
|
||||
|
||||
|
@ -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
|
||||
|
@ -1,7 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
json.title notification.notification_type
|
||||
amount = notification.attached_object.amount
|
||||
json.description t('.wallet_is_credited',
|
||||
AMOUNT: number_to_currency(amount),
|
||||
USER: notification.attached_object.wallet.user&.profile&.full_name || t('api.notifications.deleted_user'),
|
||||
ADMIN: notification.attached_object.user&.profile&.full_name || t('api.notifications.deleted_user'))
|
||||
AMOUNT: number_to_currency(amount),
|
||||
USER: notification.attached_object.wallet.user&.profile&.full_name || t('api.notifications.deleted_user'),
|
||||
ADMIN: notification.attached_object.user&.profile&.full_name || t('api.notifications.deleted_user'))
|
||||
|
||||
|
@ -28,5 +28,7 @@ class OpenlabWorker
|
||||
end
|
||||
|
||||
logger.debug ['Openlab sync', 'RESPONSE ERROR', response.inspect] unless response.success?
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
logger.warn "Unable to connect to OpenProject, maybe the dev instance is not running: #{e}" if Rails.env.development?
|
||||
end
|
||||
end
|
||||
|
@ -40,9 +40,6 @@ module Fablab
|
||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||
config.time_zone = Rails.application.secrets.time_zone
|
||||
|
||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
|
||||
config.to_prepare do
|
||||
Devise::Mailer.layout 'notifications_mailer'
|
||||
end
|
||||
@ -66,6 +63,10 @@ module Fablab
|
||||
# enable the app to find locales in plugins locales directory
|
||||
config.i18n.load_path += Dir["#{Rails.root}/plugins/*/config/locales/*.yml"]
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# enable the app to find views in plugins views directory
|
||||
Dir["#{Rails.root}/plugins/*/views"].each do |path|
|
||||
Rails.application.config.paths['app/views'] << path
|
||||
|
@ -86,10 +86,6 @@ Rails.application.configure do
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
|
@ -57,10 +57,6 @@ Rails.application.configure do
|
||||
# Set this to true and configure the email server for immediate delivery to raise delivery errors.
|
||||
# config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
|
||||
# the I18n.default_locale when a translation cannot be found).
|
||||
config.i18n.fallbacks = true
|
||||
|
||||
# Send deprecation notices to registered listeners.
|
||||
config.active_support.deprecation = :notify
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# List of all allowed values for RAILS_LOCALE
|
||||
I18n.config.available_locales += %i[de de-AT de-CH de-DE
|
||||
en en-AU-CA en-GB en-IE en-IN en-NZ en-US en-ZA
|
||||
en en-AU en-CA en-GB en-IE en-IN en-NZ en-US en-ZA
|
||||
fr fa-CA fr-CH fr-CM fr-FR
|
||||
es es-419 es-AR es-CL es-CO es-CR es-DO es-EC es-ES es-MX es-PA es-PE es-US es-VE
|
||||
pt pt-BR
|
||||
@ -14,5 +14,5 @@ I18n.config.available_locales += %i[de de-AT de-CH de-DE
|
||||
#
|
||||
# /!\ ALL locales SHOULD be configured accordingly with the default_locale. /!\
|
||||
#
|
||||
I18n.config.default_locale = Rails.application.secrets.rails_locale
|
||||
I18n.config.default_locale = Rails.application.secrets.rails_locale.to_s.split('-')[0]
|
||||
I18n.config.locale = Rails.application.secrets.rails_locale
|
||||
|
@ -157,8 +157,10 @@ de:
|
||||
standard_rate: "Standardpreis"
|
||||
0_equal_free: "0 = kostenlos"
|
||||
tickets_available: "Tickets verfügbar"
|
||||
event_theme: "Veranstaltungsthema"
|
||||
event_themes: "Veranstaltungsthemen"
|
||||
select_theme: "Pick up a theme..."
|
||||
age_range: "Altersklasse"
|
||||
add_price: "Add a price"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "Allgemeine Informationen"
|
||||
|
@ -157,8 +157,10 @@ 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"
|
||||
add_price: "Add a price"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "General information"
|
||||
|
@ -157,8 +157,10 @@ es:
|
||||
standard_rate: "Puntuación estándar"
|
||||
0_equal_free: "0 = Gratis"
|
||||
tickets_available: "Entradas disponibles"
|
||||
event_theme: "Tema del evento"
|
||||
event_themes: "Temas del evento"
|
||||
select_theme: "Pick up a theme..."
|
||||
age_range: "Rango de edades"
|
||||
add_price: "Add a price"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "Información general"
|
||||
|
@ -157,8 +157,10 @@ 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"
|
||||
add_price: "Ajouter un tarif"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "Informations générales"
|
||||
|
@ -157,8 +157,10 @@ pt:
|
||||
standard_rate: "Taxa padrão"
|
||||
0_equal_free: "0 = grátis"
|
||||
tickets_available: "Tickets disponíveis"
|
||||
event_theme: "Tema do evento"
|
||||
event_themes: "Temas do evento"
|
||||
select_theme: "Pick up a theme..."
|
||||
age_range: "Faixa etária"
|
||||
add_price: "Add a price"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "Informação geral"
|
||||
|
@ -157,8 +157,10 @@ zu:
|
||||
standard_rate: "crwdns9627:0crwdne9627:0"
|
||||
0_equal_free: "crwdns9629:0crwdne9629:0"
|
||||
tickets_available: "crwdns9631:0crwdne9631:0"
|
||||
event_theme: "crwdns9633:0crwdne9633:0"
|
||||
event_themes: "crwdns21464:0crwdne21464:0"
|
||||
select_theme: "crwdns21466:0crwdne21466:0"
|
||||
age_range: "crwdns9635:0crwdne9635:0"
|
||||
add_price: "crwdns21468:0crwdne21468:0"
|
||||
#subscription plan edition form
|
||||
plan:
|
||||
general_information: "crwdns9637:0crwdne9637:0"
|
||||
|
5
config/locales/base.de.yml
Normal file
5
config/locales/base.de.yml
Normal file
@ -0,0 +1,5 @@
|
||||
de:
|
||||
time:
|
||||
formats:
|
||||
# See http://apidock.com/ruby/DateTime/strftime for a list of available directives
|
||||
hour_minute: "%I:%M %p"
|
@ -77,6 +77,9 @@ You will also need to translate the invoice watermark, located in `app/pdfs/data
|
||||
You'll find there the [GIMP source of the image](app/pdfs/data/watermark.xcf), which is using [Rubik Mono One](https://fonts.google.com/specimen/Rubik+Mono+One) as font.
|
||||
Use it to generate a similar localised PNG image which keep the default image size, as PDF are not responsive.
|
||||
|
||||
Also, please create a [base.LOCALE.yml](../config/locales/base.en.yml) and fill it with the time-only format in use in your locale.
|
||||
|
||||
Finally, add your new locale and its derivatives to the `available_locales` array in [initializers/locale.rb](../config/initializers/locale.rb) to make it available in Fab-manager.
|
||||
|
||||
<a name="configuration"></a>
|
||||
## Configuration
|
||||
|
@ -187,5 +187,13 @@ namespace :fablab do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
desc '[release 4.7.9] fix invoicing profiles without names'
|
||||
task invoices_without_names: :environment do
|
||||
InvoicingProfile.where('(first_name IS NULL OR last_name IS NULL) AND user_id IS NOT NULL').each do |ip|
|
||||
ip.update_attribute('first_name', ip.user.profile.first_name)
|
||||
ip.update_attribute('last_name', ip.user.profile.last_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "fab-manager",
|
||||
"version": "4.7.8",
|
||||
"version": "4.7.9",
|
||||
"description": "Fab-manager is the FabLab management solution. It provides a comprehensive, web-based, open-source tool to simplify your administrative tasks and your marker's projects.",
|
||||
"keywords": [
|
||||
"fablab",
|
||||
@ -79,7 +79,7 @@
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||
"bootstrap-sass": "3.4.1",
|
||||
"checklist-model": "0.2",
|
||||
"codemirror": "^4.8.0",
|
||||
"codemirror": "^5.58.2",
|
||||
"d3": "3.5",
|
||||
"elasticsearch-browser": "3.1",
|
||||
"fullcalendar": "3.10.2",
|
||||
@ -102,13 +102,14 @@
|
||||
"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",
|
||||
"twitter-fetcher": "^18.0.2",
|
||||
"typescript": "^4.0.5",
|
||||
"ui-select": "0.19",
|
||||
"underscore": "1.7"
|
||||
"underscore": "1.12"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0",
|
||||
|
17
scripts/run.sh
Executable file
17
scripts/run.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
yq() {
|
||||
docker run --rm -i -v "${PWD}:/workdir" mikefarah/yq:4 "$@"
|
||||
}
|
||||
|
||||
config() {
|
||||
SERVICE="$(yq eval '.services.*.image | select(. == "sleede/fab-manager*") | path | .[-2]' docker-compose.yml)"
|
||||
}
|
||||
|
||||
run()
|
||||
{
|
||||
config
|
||||
docker-compose exec "$SERVICE" bundle exec rails "${@:-c}"
|
||||
}
|
||||
|
||||
run "$@"
|
206
yarn.lock
206
yarn.lock
@ -970,10 +970,10 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime@^7.12.0", "@babel/runtime@^7.3.1":
|
||||
version "7.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz#b4116a6b6711d010b2dad3b7b6e43bf1b9954740"
|
||||
integrity sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==
|
||||
"@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==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
@ -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"
|
||||
@ -2553,10 +2618,10 @@ code-point-at@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||
|
||||
codemirror@^4.8.0:
|
||||
version "4.13.0"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-4.13.0.tgz#209772d38a7bb99647c37b500db121110dd9af6f"
|
||||
integrity sha1-IJdy04p7uZZHw3tQDbEhEQ3Zr28=
|
||||
codemirror@^5.58.2:
|
||||
version "5.58.2"
|
||||
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.58.2.tgz#ed54a1796de1498688bea1cdd4e9eeb187565d1b"
|
||||
integrity sha512-K/hOh24cCwRutd1Mk3uLtjWzNISOkm4fvXiMO7LucCrqbh6aJDdtqUziim3MZUI6wOY0rvY1SlL1Ork01uMy6w==
|
||||
|
||||
collection-visit@^1.0.0:
|
||||
version "1.0.0"
|
||||
@ -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"
|
||||
@ -4587,9 +4667,9 @@ hone@1.1.0:
|
||||
integrity sha512-OT6AXfa+pMwM0jJbpyZk6/pgQ4m9vMkiUSKMfRbYv+Tnca/IRLsfBbmJy/FcsrqujW54Yvn6g+ApBwUnD8MQZg==
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
||||
version "2.8.9"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
|
||||
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
|
||||
|
||||
hpack.js@^2.1.6:
|
||||
version "2.1.6"
|
||||
@ -4654,12 +4734,12 @@ html-minifier-terser@^5.1.1:
|
||||
relateurl "^0.2.7"
|
||||
terser "^4.6.3"
|
||||
|
||||
html-parse-stringify2@2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/html-parse-stringify2/-/html-parse-stringify2-2.0.1.tgz#dc5670b7292ca158b7bc916c9a6735ac8872834a"
|
||||
integrity sha1-3FZwtyksoVi3vJFsmmc1rIhyg0o=
|
||||
html-parse-stringify@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz#dfc1017347ce9f77c8141a507f233040c59c55d2"
|
||||
integrity sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==
|
||||
dependencies:
|
||||
void-elements "^2.0.1"
|
||||
void-elements "3.1.0"
|
||||
|
||||
htmlparser2@^4.1.0:
|
||||
version "4.1.0"
|
||||
@ -4761,9 +4841,9 @@ i18next-icu@^1.4.2:
|
||||
intl-messageformat "2.2.0"
|
||||
|
||||
i18next@^19.8.3:
|
||||
version "19.8.3"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.8.3.tgz#10df7222db8c23389b13bceb9ba67a5e20a0241e"
|
||||
integrity sha512-eVrqAw2gGGYYJaJMYw4VM1FNFawLD4b84IsoTZMVXeWHaxAM2gyTa34j2Sip15UkBz/LrSxdFJj0Jhlrz7EvHA==
|
||||
version "19.9.2"
|
||||
resolved "https://registry.yarnpkg.com/i18next/-/i18next-19.9.2.tgz#ea5a124416e3c5ab85fddca2c8e3c3669a8da397"
|
||||
integrity sha512-0i6cuo6ER6usEOtKajUUDj92zlG+KArFia0857xxiEHAQcUwh/RtOQocui1LPJwunSYT574Pk64aNva1kwtxZg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.0"
|
||||
|
||||
@ -5642,21 +5722,11 @@ lodash.uniq@^4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
|
||||
|
||||
lodash@^4.0.0, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.5, lodash@~4.17.10:
|
||||
lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.10, lodash@~4.17.20:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
lodash@^4.17.11, lodash@^4.17.4, lodash@~4.17.20:
|
||||
version "4.17.20"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
|
||||
integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
|
||||
|
||||
lodash@^4.17.14:
|
||||
version "4.17.19"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
|
||||
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
|
||||
|
||||
loglevel@^1.6.8:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.7.0.tgz#728166855a740d59d38db01cf46f042caa041bb0"
|
||||
@ -5774,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"
|
||||
@ -7558,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==
|
||||
@ -7728,14 +7803,21 @@ react-dom@^17.0.0:
|
||||
scheduler "^0.20.0"
|
||||
|
||||
react-i18next@^11.7.3:
|
||||
version "11.7.3"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.7.3.tgz#256461c46baf5b3208c3c6860ca4e569fc7ed053"
|
||||
integrity sha512-7sYZqVZgdaS9Z0ZH6nuJFErCD0zz5wK3jR4/xCrWjZcxHHF3GRu7BXdicbSPprZV4ZYz7LJzxxMHO7dg5Qb70A==
|
||||
version "11.8.15"
|
||||
resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.15.tgz#89450d585298f18d4a8eb1628b0868863f3a4767"
|
||||
integrity sha512-ZbKcbYYKukgDL0MiUWKJTEsEftjSTNVZv67/V+SjPqTRwuF/aL4NbUtuEcb4WjHk0HyZ1M+2wGd07Fp0RUNHKA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.3.1"
|
||||
html-parse-stringify2 "2.0.1"
|
||||
"@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==
|
||||
@ -7760,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"
|
||||
@ -7767,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"
|
||||
@ -8889,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"
|
||||
@ -9241,10 +9351,10 @@ unbox-primitive@^1.0.0:
|
||||
has-symbols "^1.0.2"
|
||||
which-boxed-primitive "^1.0.2"
|
||||
|
||||
underscore@1.7:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.7.0.tgz#6bbaf0877500d36be34ecaa584e0db9fef035209"
|
||||
integrity sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=
|
||||
underscore@1.12:
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
|
||||
integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^1.0.4:
|
||||
version "1.0.4"
|
||||
@ -9339,9 +9449,9 @@ urix@^0.1.0:
|
||||
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
|
||||
|
||||
url-parse@^1.4.3:
|
||||
version "1.4.7"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278"
|
||||
integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.1.tgz#d5fa9890af8a5e1f274a2c98376510f6425f6e3b"
|
||||
integrity sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==
|
||||
dependencies:
|
||||
querystringify "^2.1.1"
|
||||
requires-port "^1.0.0"
|
||||
@ -9445,10 +9555,10 @@ vm-browserify@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0"
|
||||
integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==
|
||||
|
||||
void-elements@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec"
|
||||
integrity sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=
|
||||
void-elements@3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09"
|
||||
integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk=
|
||||
|
||||
warning@^4.0.3:
|
||||
version "4.0.3"
|
||||
|
Loading…
Reference in New Issue
Block a user