mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-20 14:54:15 +01:00
Merge branch 'custom_home' into dev
This commit is contained in:
commit
d0c4dd0caf
@ -56,6 +56,7 @@
|
||||
//= require angular-base64-upload/dist/angular-base64-upload.min
|
||||
//= require summernote/dist/summernote
|
||||
//= require angular-summernote/dist/angular-summernote
|
||||
//= require summernote-ext-nugget
|
||||
//= require jquery-minicolors/jquery.minicolors.js
|
||||
//= require angular-minicolors/angular-minicolors.js
|
||||
//= require angular-translate/dist/angular-translate
|
||||
|
@ -12,8 +12,8 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('SettingsController', ['$scope', '$filter', '$uibModal', 'Setting', 'growl', 'settingsPromise', 'privacyDraftsPromise', 'cgvFile', 'cguFile', 'logoFile', 'logoBlackFile', 'faviconFile', 'profileImageFile', 'CSRF', '_t',
|
||||
function ($scope, $filter, $uibModal, Setting, growl, settingsPromise, privacyDraftsPromise, cgvFile, cguFile, logoFile, logoBlackFile, faviconFile, profileImageFile, CSRF, _t) {
|
||||
Application.Controllers.controller('SettingsController', ['$scope', '$rootScope', '$filter', '$uibModal', 'dialogs', 'Setting', 'growl', 'settingsPromise', 'privacyDraftsPromise', 'cgvFile', 'cguFile', 'logoFile', 'logoBlackFile', 'faviconFile', 'profileImageFile', 'CSRF', '_t',
|
||||
function ($scope, $rootScope, $filter, $uibModal, dialogs, Setting, growl, settingsPromise, privacyDraftsPromise, cgvFile, cguFile, logoFile, logoBlackFile, faviconFile, profileImageFile, CSRF, _t) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// timepickers steps configuration
|
||||
@ -59,6 +59,7 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
$scope.privacyDpoSetting = { name: 'privacy_dpo', value: settingsPromise.privacy_dpo };
|
||||
$scope.aboutContactsSetting = { name: 'about_contacts', value: settingsPromise.about_contacts };
|
||||
$scope.homeBlogpostSetting = { name: 'home_blogpost', value: settingsPromise.home_blogpost };
|
||||
$scope.homeContent = { name: 'home_content', value: settingsPromise.home_content };
|
||||
$scope.machineExplicationsAlert = { name: 'machine_explications_alert', value: settingsPromise.machine_explications_alert };
|
||||
$scope.trainingExplicationsAlert = { name: 'training_explications_alert', value: settingsPromise.training_explications_alert };
|
||||
$scope.trainingInformationMessage = { name: 'training_information_message', value: settingsPromise.training_information_message };
|
||||
@ -135,6 +136,21 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
bodyTemp: settingsPromise.privacy_body
|
||||
};
|
||||
|
||||
// Extend the options for summernote editor, with special tools for home page
|
||||
$scope.summernoteOptsHomePage = Object.assign({}, $rootScope.summernoteOpts);
|
||||
$scope.summernoteOptsHomePage.toolbar[5][1].push('nugget'); // toolbar -> insert -> nugget
|
||||
$scope.summernoteOptsHomePage.nugget = {
|
||||
label: '\uF12E',
|
||||
tooltip: _t('app.admin.settings.home_items'),
|
||||
list: [
|
||||
`<div id="news">${_t('app.admin.settings.item_news')}</div>`,
|
||||
`<div id="projects">${_t('app.admin.settings.item_projects')}</div>`,
|
||||
`<div id="twitter">${_t('app.admin.settings.item_twitter')}</div>`,
|
||||
`<div id="members">${_t('app.admin.settings.item_members')}</div>`,
|
||||
`<div id="events">${_t('app.admin.settings.item_events')}</div>`
|
||||
]
|
||||
}
|
||||
|
||||
/**
|
||||
* For use with 'ng-class', returns the CSS class name for the uploads previews.
|
||||
* The preview may show a placeholder or the content of the file depending on the upload state.
|
||||
@ -293,6 +309,29 @@ Application.Controllers.controller('SettingsController', ['$scope', '$filter', '
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the home page to its initial state (factory value)
|
||||
*/
|
||||
$scope.resetHomePage = function () {
|
||||
dialogs.confirm({
|
||||
resolve: {
|
||||
object () {
|
||||
return {
|
||||
title: _t('app.admin.settings.confirmation_required'),
|
||||
msg: _t('app.admin.settings.confirm_reset_home_page')
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
, function () { // confirmed
|
||||
Setting.reset({ name: 'home_content' }, function (data) {
|
||||
$scope.homeContent.value = data.value;
|
||||
growl.success(_t('app.admin.settings.home_content_reset'));
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
/**
|
||||
|
@ -1,40 +1,11 @@
|
||||
/* eslint-disable
|
||||
no-undef,
|
||||
*/
|
||||
// TODO: This file was created by bulk-decaffeinate.
|
||||
// Fix any style issues and re-enable lint.
|
||||
/*
|
||||
* decaffeinate suggestions:
|
||||
* DS102: Remove unnecessary code created because of implicit returns
|
||||
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', 'lastMembersPromise', 'lastProjectsPromise', 'upcomingEventsPromise', 'homeBlogpostPromise', 'twitterNamePromise',
|
||||
function ($scope, $stateParams, lastMembersPromise, lastProjectsPromise, upcomingEventsPromise, homeBlogpostPromise, twitterNamePromise) {
|
||||
Application.Controllers.controller('HomeController', ['$scope', '$stateParams', 'homeContentPromise',
|
||||
function ($scope, $stateParams, homeContentPromise) {
|
||||
/* PUBLIC SCOPE */
|
||||
|
||||
// The last registered members who confirmed their addresses
|
||||
$scope.lastMembers = lastMembersPromise;
|
||||
|
||||
// The last projects published/documented on the plateform
|
||||
$scope.lastProjects = lastProjectsPromise;
|
||||
|
||||
// The closest upcoming events
|
||||
$scope.upcomingEvents = upcomingEventsPromise;
|
||||
|
||||
// The admin blogpost
|
||||
$scope.homeBlogpost = homeBlogpostPromise.setting.value;
|
||||
|
||||
// Twitter username
|
||||
$scope.twitterName = twitterNamePromise.setting.value;
|
||||
|
||||
/**
|
||||
* Test if the provided event run on a single day or not
|
||||
* @param event {Object} single event from the $scope.upcomingEvents array
|
||||
* @returns {boolean} false if the event runs on more that 1 day
|
||||
*/
|
||||
$scope.isOneDayEvent = event => moment(event.start_date).isSame(event.end_date, 'day');
|
||||
// Home page HTML content
|
||||
$scope.homeContent = null;
|
||||
|
||||
/* PRIVATE SCOPE */
|
||||
|
||||
@ -47,6 +18,46 @@ Application.Controllers.controller('HomeController', ['$scope', '$stateParams',
|
||||
if ($stateParams.reset_password_token) {
|
||||
return $scope.$parent.editPassword($stateParams.reset_password_token);
|
||||
}
|
||||
|
||||
// We set the home page content, with the directives replacing the placeholders
|
||||
$scope.homeContent = insertDirectives(homeContentPromise.setting.value);
|
||||
};
|
||||
|
||||
const insertDirectives = function (html) {
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = html.trim();
|
||||
|
||||
const newsNode = node.querySelector('div#news');
|
||||
if (newsNode) {
|
||||
const news = document.createElement('news');
|
||||
newsNode.parentNode.replaceChild(news, newsNode);
|
||||
}
|
||||
|
||||
const projectsNode = node.querySelector('div#projects');
|
||||
if (projectsNode) {
|
||||
const projects = document.createElement('projects');
|
||||
projectsNode.parentNode.replaceChild(projects, projectsNode);
|
||||
}
|
||||
|
||||
const twitterNode = node.querySelector('div#twitter');
|
||||
if (twitterNode) {
|
||||
const twitter = document.createElement('twitter');
|
||||
twitterNode.parentNode.replaceChild(twitter, twitterNode);
|
||||
}
|
||||
|
||||
const membersNode = node.querySelector('div#members');
|
||||
if (membersNode) {
|
||||
const members = document.createElement('members');
|
||||
membersNode.parentNode.replaceChild(members, membersNode);
|
||||
}
|
||||
|
||||
const eventsNode = node.querySelector('div#events');
|
||||
if (eventsNode) {
|
||||
const events = document.createElement('events');
|
||||
eventsNode.parentNode.replaceChild(events, eventsNode);
|
||||
}
|
||||
|
||||
return node.outerHTML;
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the controller
|
||||
|
21
app/assets/javascripts/directives/compile.js
Normal file
21
app/assets/javascripts/directives/compile.js
Normal file
@ -0,0 +1,21 @@
|
||||
Application.Directives.directive('compile', ['$compile', function ($compile) {
|
||||
return function (scope, element, attrs) {
|
||||
scope.$watch(
|
||||
function (scope) {
|
||||
// watch the 'compile' expression for changes
|
||||
return scope.$eval(attrs.compile);
|
||||
},
|
||||
function (value) {
|
||||
// when the 'compile' expression changes
|
||||
// assign it into the current DOM
|
||||
element.html(value);
|
||||
|
||||
// compile the new DOM and link it to the current
|
||||
// scope.
|
||||
// NOTE: we only compile .childNodes so that
|
||||
// we don't get into infinite loop compiling ourselves
|
||||
$compile(element.contents())(scope);
|
||||
}
|
||||
);
|
||||
};
|
||||
}]);
|
31
app/assets/javascripts/directives/events.js.erb
Normal file
31
app/assets/javascripts/directives/events.js.erb
Normal file
@ -0,0 +1,31 @@
|
||||
Application.Directives.directive('events', [ 'Event',
|
||||
function (Event) {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/events.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// The closest upcoming events
|
||||
$scope.upcomingEvents = null;
|
||||
|
||||
/**
|
||||
* Test if the provided event run on a single day or not
|
||||
* @param event {Object} single event from the $scope.upcomingEvents array
|
||||
* @returns {boolean} false if the event runs on more that 1 day
|
||||
*/
|
||||
$scope.isOneDayEvent = function(event) {
|
||||
return moment(event.start_date).isSame(event.end_date, 'day');
|
||||
}
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Event.upcoming({ limit: 3 }, function (data) {
|
||||
$scope.upcomingEvents = data;
|
||||
})
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize();
|
||||
}
|
||||
});
|
||||
}
|
||||
]);
|
22
app/assets/javascripts/directives/members.js.erb
Normal file
22
app/assets/javascripts/directives/members.js.erb
Normal file
@ -0,0 +1,22 @@
|
||||
Application.Directives.directive('members', [ 'Member',
|
||||
function (Member) {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/members.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// The last registered members who confirmed their addresses
|
||||
$scope.lastMembers = null;
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Member.lastSubscribed({ limit: 4 }, function (data) {
|
||||
$scope.lastMembers = data;
|
||||
})
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize();
|
||||
}
|
||||
});
|
||||
}
|
||||
]);
|
22
app/assets/javascripts/directives/news.js.erb
Normal file
22
app/assets/javascripts/directives/news.js.erb
Normal file
@ -0,0 +1,22 @@
|
||||
Application.Directives.directive('news', [ 'Setting',
|
||||
function (Setting) {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/news.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// The admin blogpost
|
||||
$scope.homeBlogpost = null;
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Setting.get({ name: 'home_blogpost' }, function (data) {
|
||||
$scope.homeBlogpost = data.setting.value;
|
||||
})
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize();
|
||||
}
|
||||
});
|
||||
}
|
||||
]);
|
22
app/assets/javascripts/directives/projects.js.erb
Normal file
22
app/assets/javascripts/directives/projects.js.erb
Normal file
@ -0,0 +1,22 @@
|
||||
Application.Directives.directive('projects', [ 'Project',
|
||||
function (Project) {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/projects.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// The last projects published/documented on the plateform
|
||||
$scope.lastProjects = null;
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Project.lastPublished(function (data) {
|
||||
$scope.lastProjects = data;
|
||||
})
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize();
|
||||
}
|
||||
});
|
||||
}
|
||||
]);
|
@ -1,32 +1,43 @@
|
||||
/* global twitterFetcher */
|
||||
|
||||
/**
|
||||
* This directive will allow show latest tweet.
|
||||
* Usage: <twitter profile="{{twitterName}}"/>
|
||||
* This directive will show the last tweet.
|
||||
* Usage: <twitter />
|
||||
*/
|
||||
Application.Directives.directive('twitter', [ function () {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
scope: {
|
||||
profile: '@'
|
||||
},
|
||||
templateUrl: '<%= asset_path "shared/_twitter.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
var configProfile = {
|
||||
'profile': { 'screenName': $scope.profile },
|
||||
'domId': 'twitter',
|
||||
'maxTweets': 1,
|
||||
'enableLinks': true,
|
||||
'showUser': false,
|
||||
'showTime': true,
|
||||
'showImages': false,
|
||||
'showRetweet': true,
|
||||
'showInteraction': false,
|
||||
'lang': Fablab.locale
|
||||
};
|
||||
if ($scope.profile) {
|
||||
twitterFetcher.fetch(configProfile);
|
||||
Application.Directives.directive('twitter', ['Setting',
|
||||
function (Setting) {
|
||||
return ({
|
||||
restrict: 'E',
|
||||
templateUrl: '<%= asset_path "home/twitter.html" %>',
|
||||
link ($scope, element, attributes) {
|
||||
// Twitter username
|
||||
$scope.twitterName = null;
|
||||
|
||||
// constructor
|
||||
const initialize = function () {
|
||||
Setting.get({ name: 'twitter_name' }, function (data) {
|
||||
$scope.twitterName = data.setting.value;
|
||||
if ($scope.twitterName) {
|
||||
const configProfile = {
|
||||
'profile': { 'screenName': $scope.twitterName },
|
||||
'domId': 'twitter',
|
||||
'maxTweets': 1,
|
||||
'enableLinks': true,
|
||||
'showUser': false,
|
||||
'showTime': true,
|
||||
'showImages': false,
|
||||
'showRetweet': true,
|
||||
'showInteraction': false,
|
||||
'lang': Fablab.locale
|
||||
};
|
||||
twitterFetcher.fetch(configProfile);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// !!! MUST BE CALLED AT THE END of the directive
|
||||
return initialize();
|
||||
}
|
||||
}
|
||||
});
|
||||
}]);
|
||||
});
|
||||
}
|
||||
]);
|
||||
|
@ -98,11 +98,7 @@ angular.module('application.router', ['ui.router'])
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
lastMembersPromise: ['Member', function (Member) { return Member.lastSubscribed({ limit: 4 }).$promise; }],
|
||||
lastProjectsPromise: ['Project', function (Project) { return Project.lastPublished().$promise; }],
|
||||
upcomingEventsPromise: ['Event', function (Event) { return Event.upcoming({ limit: 3 }).$promise; }],
|
||||
homeBlogpostPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_blogpost' }).$promise; }],
|
||||
twitterNamePromise: ['Setting', function (Setting) { return Setting.get({ name: 'twitter_name' }).$promise; }],
|
||||
homeContentPromise: ['Setting', function (Setting) { return Setting.get({ name: 'home_content' }).$promise; }]
|
||||
}
|
||||
})
|
||||
.state('app.public.privacy', {
|
||||
@ -1006,7 +1002,7 @@ angular.module('application.router', ['ui.router'])
|
||||
'fablab_name', 'name_genre', 'reminder_enable', \
|
||||
'reminder_delay', 'visibility_yearly', 'visibility_others', \
|
||||
'display_name_enable', 'machines_sort_by', 'fab_analytics', \
|
||||
'link_name']` }).$promise;
|
||||
'link_name', 'home_content']` }).$promise;
|
||||
}],
|
||||
privacyDraftsPromise: ['Setting', function (Setting) { return Setting.get({ name: 'privacy_draft', history: true }).$promise; }],
|
||||
cguFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'cgu-file' }).$promise; }],
|
||||
|
@ -15,6 +15,11 @@ Application.Services.factory('Setting', ['$resource', function ($resource) {
|
||||
},
|
||||
query: {
|
||||
isArray: false
|
||||
},
|
||||
reset: {
|
||||
url: '/api/settings/reset/:name',
|
||||
params: { name: '@name' },
|
||||
method: 'PUT'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -636,3 +636,8 @@ body.container{
|
||||
left: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.home-page {
|
||||
@extend .wrapper;
|
||||
}
|
||||
|
44
app/assets/stylesheets/modules/settings.scss
Normal file
44
app/assets/stylesheets/modules/settings.scss
Normal file
@ -0,0 +1,44 @@
|
||||
.admin-settings {
|
||||
.home-page-settings {
|
||||
.home-page-content {
|
||||
.note-editor {
|
||||
.note-toolbar .note-btn-group .note-btn .nugget {
|
||||
font-family: "FontAwesome";
|
||||
}
|
||||
.note-editing-area .note-editable {
|
||||
#news {
|
||||
width: 100%;
|
||||
background-color: #b1b1b1;
|
||||
color: white;
|
||||
border: 1px dashed #8f9091;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 10rem;
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
#projects {
|
||||
@extend #news;
|
||||
line-height: 523px;
|
||||
}
|
||||
|
||||
#twitter {
|
||||
@extend #news;
|
||||
line-height: 162px;
|
||||
}
|
||||
|
||||
#members {
|
||||
@extend #news;
|
||||
line-height: 320px;
|
||||
}
|
||||
|
||||
#events {
|
||||
@extend #news;
|
||||
line-height: 621px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,17 @@
|
||||
<div class="panel panel-default m-t-md">
|
||||
<div class="panel panel-default m-t-md home-page-settings">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-md-12 home-page-content">
|
||||
<h4 translate>{{ 'app.admin.settings.customize_home_page' }}</h4>
|
||||
<button class="btn btn-default pull-right m-t-n-xl" ng-click="resetHomePage()" title="{{ 'app.admin.settings.reset_home_page' | translate }}"><i class="fa fa-undo"></i></button>
|
||||
<summernote ng-model="homeContent.value"
|
||||
id="home_content"
|
||||
config="summernoteOptsHomePage">
|
||||
</summernote>
|
||||
<button name="button" class="btn btn-warning" ng-click="save(homeContent)" translate>{{ 'app.shared.buttons.save' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row m-t-lg">
|
||||
<div class="col-md-6">
|
||||
<h4 translate>{{ 'app.admin.settings.news_of_the_home_page' }}</h4>
|
||||
<div ng-model="homeBlogpostSetting.value" class="well" medium-editor options='{"placeholder": "{{ "app.admin.settings.type_your_news_here" | translate }}",
|
||||
|
@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="m-lg">
|
||||
<section class="m-lg admin-settings">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
@ -1,129 +1,2 @@
|
||||
|
||||
<div class="alert alert-warning m-sm text-center" ng-if="(homeBlogpost != null) && (homeBlogpost != '') && (homeBlogpost != undefined)">
|
||||
<span ng-bind-html="homeBlogpost"></span>
|
||||
</div>
|
||||
|
||||
<div class="row wrapper">
|
||||
<div class="col-lg-8">
|
||||
<h4 class="text-sm m-t-sm" translate>{{ 'app.public.home.latest_documented_projects' }}</h4>
|
||||
|
||||
<uib-carousel interval="5000" disable-animation="true">
|
||||
<uib-slide class="h480 cover r" ng-repeat="p in lastProjects" active="p.active" style="background-image:url({{p.project_image}});">
|
||||
<!-- <img ng-src="{{p.project_image}}" style="margin:auto;"> -->
|
||||
<div class="carousel-caption">
|
||||
<h1 class="title"><a ui-sref="app.public.projects_show({id:p.slug})">{{p.name}}</a></h1>
|
||||
<!-- <p class="description hidden-xs">{{p.description | humanize : 120}}</p> -->
|
||||
</div>
|
||||
</uib-slide>
|
||||
</uib-carousel>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-lg-4 m-t-lg">
|
||||
<twitter profile="{{twitterName}}" ng-show="twitterName"/>
|
||||
|
||||
<section class="widget panel b-a" >
|
||||
<div class="panel-heading small b-b">
|
||||
<!-- <span class="badge inverse pull-right">110</span> -->
|
||||
<h2 translate>{{ 'app.public.home.latest_registered_members' }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="row m-n">
|
||||
<div class="col-md-6 b-b b-r block-link" ng-repeat="member in lastMembers" ui-sref="app.logged.members_show({id:member.slug})">
|
||||
|
||||
|
||||
<div class="padder-v">
|
||||
<span class="avatar avatar-block text-center">
|
||||
<fab-user-avatar ng-model="member.profile.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
|
||||
<!-- <i class="on b-white bottom"></i> -->
|
||||
<a ><span class="user-name m-l-sm text-black m-t-xs">{{member.name}}</span></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- TODO EVEN <div class="col-md-6 b-b"> -->
|
||||
|
||||
</div>
|
||||
<div class="m-t-sm m-b-sm text-center" ng-if="!isAuthenticated()">
|
||||
<button href="#" ng-click="signup($event)" class="btn btn-warning-full width-70 font-sbold rounded text-sm" translate>{{ 'app.public.home.create_an_account' }}</button>
|
||||
</div>
|
||||
|
||||
<div class="m-t-sm m-b-sm text-center" ng-if="isAuthenticated()">
|
||||
<button href="#" ui-sref="app.logged.members" class="btn btn-warning-full width-70 font-sbold rounded text-sm" translate>{{ 'app.public.home.discover_members' }}</button>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<section class="home-events col-lg-12 wrapper">
|
||||
<h4 class="text-sm m-t-sm">{{ 'app.public.home.fablab_s_next_events' | translate }} <a ui-sref="app.public.events_list" class="pull-right"><i class="fa fa-tags"></i> {{ 'app.public.home.every_events' | translate }}</a></h4>
|
||||
|
||||
<div class="row" ng-repeat="event in (upcomingEvents.length/3 | array)">
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-4" ng-repeat="event in upcomingEvents.slice(3*$index, 3*$index + 3)">
|
||||
|
||||
|
||||
<div class="widget panel panel-default" ui-sref="app.public.events_show({id: event.id})">
|
||||
<div class="panel-heading picture" style="background-image: url({{event.event_image_medium}});" >
|
||||
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!event.event_image" class="img-responsive">
|
||||
</div>
|
||||
<div class="panel-body" style="heigth:170px;">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<h1 class="m-b">{{event.title}}</h1>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<span class="v-middle badge text-xs" ng-class="'bg-{{event.category.slug}}'">{{event.category.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="event-description" ng-bind-html="event.description | simpleText | humanize : 500 | breakFilter"></p>
|
||||
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-calendar red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9 " ng-hide="isOneDayEvent(event)">{{ 'app.public.home.from_date_to_date' | translate:{START:(event.start_date | amDateFormat:'L'), END:(event.end_date | amDateFormat:'L')} }}</h6>
|
||||
<h6 class="m-n col-xs-9 " ng-show="isOneDayEvent(event)">{{ 'app.public.home.on_the_date' | translate:{DATE:(event.start_date | amDateFormat:'L')} }}</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-clock-o red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9">
|
||||
<span ng-if="event.all_day == 'true'" translate>{{ 'app.public.home.all_day' }}</span>
|
||||
<span ng-if="event.all_day == 'false'">{{ 'app.public.home.from_time_to_time' | translate:{START:(event.start_date | amDateFormat:'LT'), END:(event.end_date | amDateFormat:'LT')} }}</span>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-user red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9 ">
|
||||
<span ng-if="event.nb_free_places > 0">{{ 'app.public.home.still_available' | translate }} {{event.nb_free_places}}</span>
|
||||
<span ng-if="!event.nb_total_places" translate>{{ 'app.public.home.free_entry' }}</span>
|
||||
<span ng-if="event.nb_total_places > 0 && event.nb_free_places <= 0" translate>{{ 'app.public.home.event_full' }}</span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-bookmark red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9">
|
||||
<span ng-if="event.amount == 0" translate>{{ 'app.public.home.free_admission' }}</span>
|
||||
<span ng-if="event.amount > 0">{{ 'app.public.home.full_price' | translate }} {{event.amount | currency}}</span>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center clearfix ">
|
||||
<div class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm m-b-sm upper text-sm width-70" ui-sref="app.public.events_show({id: event.id})" ><span translate>{{ 'app.shared.buttons.consult' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="home-page" compile="homeContent">
|
||||
</div>
|
||||
|
65
app/assets/templates/home/events.html
Normal file
65
app/assets/templates/home/events.html
Normal file
@ -0,0 +1,65 @@
|
||||
<section class="home-events">
|
||||
<h4 class="text-sm m-t-sm">{{ 'app.public.home.fablab_s_next_events' | translate }} <a ui-sref="app.public.events_list" class="pull-right"><i class="fa fa-tags"></i> {{ 'app.public.home.every_events' | translate }}</a></h4>
|
||||
|
||||
<div class="row" ng-repeat="event in (upcomingEvents.length/3 | array)">
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-6 col-lg-4" ng-repeat="event in upcomingEvents.slice(3*$index, 3*$index + 3)">
|
||||
|
||||
|
||||
<div class="widget panel panel-default" ui-sref="app.public.events_show({id: event.id})">
|
||||
<div class="panel-heading picture" style="background-image: url({{event.event_image_medium}});" >
|
||||
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:/font:FontAwesome/icon" bs-holder ng-if="!event.event_image" class="img-responsive">
|
||||
</div>
|
||||
<div class="panel-body" style="heigth:170px;">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<h1 class="m-b">{{event.title}}</h1>
|
||||
</div>
|
||||
<div class="col-xs-3">
|
||||
<span class="v-middle badge text-xs" ng-class="'bg-{{event.category.slug}}'">{{event.category.name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<p class="event-description" ng-bind-html="event.description | simpleText | humanize : 500 | breakFilter"></p>
|
||||
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-calendar red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9 " ng-hide="isOneDayEvent(event)">{{ 'app.public.home.from_date_to_date' | translate:{START:(event.start_date | amDateFormat:'L'), END:(event.end_date | amDateFormat:'L')} }}</h6>
|
||||
<h6 class="m-n col-xs-9 " ng-show="isOneDayEvent(event)">{{ 'app.public.home.on_the_date' | translate:{DATE:(event.start_date | amDateFormat:'L')} }}</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-clock-o red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9">
|
||||
<span ng-if="event.all_day == 'true'" translate>{{ 'app.public.home.all_day' }}</span>
|
||||
<span ng-if="event.all_day == 'false'">{{ 'app.public.home.from_time_to_time' | translate:{START:(event.start_date | amDateFormat:'LT'), END:(event.end_date | amDateFormat:'LT')} }}</span>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-user red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9 ">
|
||||
<span ng-if="event.nb_free_places > 0">{{ 'app.public.home.still_available' | translate }} {{event.nb_free_places}}</span>
|
||||
<span ng-if="!event.nb_total_places" translate>{{ 'app.public.home.free_entry' }}</span>
|
||||
<span ng-if="event.nb_total_places > 0 && event.nb_free_places <= 0" translate>{{ 'app.public.home.event_full' }}</span>
|
||||
</h6>
|
||||
</div>
|
||||
<div class="col-sm-6 row m-b-sm">
|
||||
<i class="fa fa-bookmark red col-xs-3 padder-icon"></i>
|
||||
<h6 class="m-n col-xs-9">
|
||||
<span ng-if="event.amount == 0" translate>{{ 'app.public.home.free_admission' }}</span>
|
||||
<span ng-if="event.amount > 0">{{ 'app.public.home.full_price' | translate }} {{event.amount | currency}}</span>
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="text-center clearfix ">
|
||||
<div class="btn btn-lg btn-warning bg-white b-2x rounded m-t-sm m-b-sm upper text-sm width-70" ui-sref="app.public.events_show({id: event.id})" ><span translate>{{ 'app.shared.buttons.consult' }}</span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
27
app/assets/templates/home/members.html
Normal file
27
app/assets/templates/home/members.html
Normal file
@ -0,0 +1,27 @@
|
||||
<section class="widget panel b-a" >
|
||||
<div class="panel-heading small b-b">
|
||||
<h2 translate>{{ 'app.public.home.latest_registered_members' }}</h2>
|
||||
</div>
|
||||
|
||||
<div class="row m-n">
|
||||
<div class="col-md-6 b-b b-r block-link" ng-repeat="member in lastMembers" ui-sref="app.logged.members_show({id:member.slug})">
|
||||
|
||||
<div class="padder-v">
|
||||
<span class="avatar avatar-block text-center">
|
||||
<fab-user-avatar ng-model="member.profile.user_avatar" avatar-class="thumb-50"></fab-user-avatar>
|
||||
<!-- <i class="on b-white bottom"></i> -->
|
||||
<a ><span class="user-name m-l-sm text-black m-t-xs">{{member.name}}</span></a>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="m-t-sm m-b-sm text-center" ng-if="!isAuthenticated()">
|
||||
<button href="#" ng-click="signup($event)" class="btn btn-warning-full width-70 font-sbold rounded text-sm" translate>{{ 'app.public.home.create_an_account' }}</button>
|
||||
</div>
|
||||
|
||||
<div class="m-t-sm m-b-sm text-center" ng-if="isAuthenticated()">
|
||||
<button href="#" ui-sref="app.logged.members" class="btn btn-warning-full width-70 font-sbold rounded text-sm" translate>{{ 'app.public.home.discover_members' }}</button>
|
||||
</div>
|
||||
</section>
|
3
app/assets/templates/home/news.html
Normal file
3
app/assets/templates/home/news.html
Normal file
@ -0,0 +1,3 @@
|
||||
<div class="alert alert-warning text-center" ng-if="(homeBlogpost != null) && (homeBlogpost != '') && (homeBlogpost != undefined)">
|
||||
<span ng-bind-html="homeBlogpost"></span>
|
||||
</div>
|
11
app/assets/templates/home/projects.html
Normal file
11
app/assets/templates/home/projects.html
Normal file
@ -0,0 +1,11 @@
|
||||
<div>
|
||||
<h4 class="text-sm m-t-sm" translate>{{ 'app.public.home.latest_documented_projects' }}</h4>
|
||||
|
||||
<uib-carousel interval="5000" disable-animation="true">
|
||||
<uib-slide class="h480 cover r" ng-repeat="p in lastProjects" active="p.active" style="background-image:url({{p.project_image}});">
|
||||
<div class="carousel-caption">
|
||||
<h1 class="title"><a ui-sref="app.public.projects_show({id:p.slug})">{{p.name}}</a></h1>
|
||||
</div>
|
||||
</uib-slide>
|
||||
</uib-carousel>
|
||||
</div>
|
@ -1,7 +1,7 @@
|
||||
<section class="widget panel b-a m-t-sm">
|
||||
<section class="widget panel b-a m-t-sm" ng-show="twitterName">
|
||||
<div class="panel-heading b-b small">
|
||||
<div class="pull-right text-xs align">
|
||||
<a href="https://twitter.com/{{ profile }}" target="_blank">{{ 'app.public.home.follow_us' | translate }}
|
||||
<a href="https://twitter.com/{{ twitterName }}" target="_blank">{{ 'app.public.home.follow_us' | translate }}
|
||||
<span class="fa-stack fa-lg">
|
||||
<i class="fa fa-circle fa-stack-2x text-yellow"></i>
|
||||
<i class="fa fa-twitter fa-stack-1x fa-inverse text-white"></i>
|
@ -2,7 +2,7 @@
|
||||
|
||||
# API Controller for resources of type Setting
|
||||
class API::SettingsController < API::ApiController
|
||||
before_action :authenticate_user!, only: :update
|
||||
before_action :authenticate_user!, only: %i[update bulk_update reset]
|
||||
|
||||
def index
|
||||
@settings = Setting.where(name: names_as_string_to_array)
|
||||
@ -36,6 +36,19 @@ class API::SettingsController < API::ApiController
|
||||
@show_history = params[:history] == 'true' && current_user.admin?
|
||||
end
|
||||
|
||||
def reset
|
||||
authorize Setting
|
||||
|
||||
setting = Setting.find_or_create_by(name: params[:name])
|
||||
first_val = setting.history_values.order(created_at: :asc).limit(1).first
|
||||
new_val = HistoryValue.create!(
|
||||
setting_id: setting.id,
|
||||
value: first_val.value,
|
||||
invoicing_profile_id: current_user.invoicing_profile.id
|
||||
)
|
||||
render json: new_val, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def setting_params
|
||||
|
@ -1,3 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Setting is a configuration element of the platform. Only administrators are allowed to modify Settings
|
||||
# For some settings, changing them will involve some callback actions (like rebuilding the stylesheets if the theme color Setting is changed).
|
||||
# A full history of the previous values is kept in database with the date and the author of the change
|
||||
class Setting < ActiveRecord::Base
|
||||
has_many :history_values
|
||||
validates :name, inclusion:
|
||||
@ -65,7 +70,8 @@ class Setting < ActiveRecord::Base
|
||||
hub_last_version
|
||||
hub_public_key
|
||||
fab_analytics
|
||||
link_name] }
|
||||
link_name
|
||||
home_content] }
|
||||
|
||||
after_update :update_stylesheet, :notify_privacy_policy_changed if :value_changed?
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Check the access policies for API::SettingsController
|
||||
class SettingPolicy < ApplicationPolicy
|
||||
%w[update bulk_update].each do |action|
|
||||
%w[update bulk_update reset].each do |action|
|
||||
define_method "#{action}?" do
|
||||
user.admin?
|
||||
end
|
||||
|
@ -928,6 +928,18 @@ fr:
|
||||
space_explications_alert: "l'explication sur la page de réservation d'un espace"
|
||||
main_color: "la couleur principale"
|
||||
secondary_color: "la couleur secondaire"
|
||||
customize_home_page: "Personnaliser la page d'accueil"
|
||||
reset_home_page: "Remettre la page d'accueil dans son état initial"
|
||||
confirmation_required: "Confirmation requise"
|
||||
confirm_reset_home_page: "Voulez-vous vraiment remettre la page d'accueil à sa valeur d'usine ?"
|
||||
home_items: "Éléments de la page d'accueil"
|
||||
item_news: "Brève"
|
||||
item_projects: "Derniers projets"
|
||||
item_twitter: "Dernier tweet"
|
||||
item_members: "Derniers membres"
|
||||
item_events: "Prochains événements"
|
||||
home_content: "la page d'accueil"
|
||||
home_content_reset: "La page d'accueil a bien été restaurée dans sa configuration initiale."
|
||||
home_blogpost: "la brève de la page d'accueil"
|
||||
twitter_name: "nom du flux Twitter"
|
||||
link_name: "l'intitulé du lien vers la page \"À propos\""
|
||||
|
@ -47,6 +47,7 @@ Rails.application.routes.draw do
|
||||
resources :admins, only: %i[index create destroy]
|
||||
resources :settings, only: %i[show update index], param: :name do
|
||||
patch '/bulk_update', action: 'bulk_update', on: :collection
|
||||
put '/reset/:name', action: 'reset', on: :collection
|
||||
end
|
||||
resources :users, only: %i[index create]
|
||||
resources :members, only: %i[index show create update destroy] do
|
||||
|
311
db/seeds.rb
311
db/seeds.rb
@ -214,7 +214,7 @@ if Machine.count.zero?
|
||||
"\r\nVitesse d'analyse (scannage): 4-15 mm/sec\r\n \r\n \r\nLogiciel utilisé pour le fraisage: Roland Modela player" \
|
||||
" 4 \r\nLogiciel utilisé pour l'usinage de circuits imprimés: Cad.py (linux)\r\nFormats acceptés: STL,PNG 3D\r\n" \
|
||||
"Format d'exportation des données scannées: DXF, VRML, STL, 3DMF, IGES, Grayscale, Point Group et BMP\r\n",
|
||||
slug: 'petite-fraiseuse' },
|
||||
slug: 'petite-fraiseuse' }
|
||||
])
|
||||
|
||||
Price.all.each do |p|
|
||||
@ -294,13 +294,18 @@ end
|
||||
|
||||
unless Setting.find_by(name: 'subscription_explications_alert').try(:value)
|
||||
setting = Setting.find_or_initialize_by(name: 'subscription_explications_alert')
|
||||
setting.value = '<p><b>Règle sur la date de début des abonnements</b><br></p><ul><li>' \
|
||||
' <span style=\"font-size: 1.6rem; line-height: 2.4rem;\">Si vous êtes un nouvel utilisateur - i.e aucune ' \
|
||||
" formation d'enregistrée sur le site - votre abonnement débutera à la date de réservation de votre première " \
|
||||
' formation.</span><br></li><li><span style=\"font-size: 1.6rem; line-height: 2.4rem;\">Si vous avez déjà une ' \
|
||||
" formation ou plus de validée, votre abonnement débutera à la date de votre achat d'abonnement.</span></li>" \
|
||||
" </ul><p>Merci de bien prendre ses informations en compte, et merci de votre compréhension. L'équipe du Fab Lab.<br>" \
|
||||
' </p><p></p>'
|
||||
setting.value = <<~HTML
|
||||
<p><b>Règle sur la date de début des abonnements</b></p>
|
||||
<ul>
|
||||
<li><span style=\"font-size: 1.6rem; line-height: 2.4rem;\">Si vous êtes un nouvel utilisateur - i.e aucune
|
||||
formation d'enregistrée sur le site - votre abonnement débutera à la date de réservation de votre première
|
||||
formation.</span></li>
|
||||
<li><span style="font-size: 1.6rem; line-height: 2.4rem;">Si vous avez déjà une formation ou plus de validée,
|
||||
votre abonnement débutera à la date de votre achat d'abonnement.</span></li>
|
||||
</ul>
|
||||
<p>Merci de bien prendre ses informations en compte, et merci de votre compréhension. L'équipe du Fab Lab.<br>
|
||||
</p>
|
||||
HTML
|
||||
setting.save
|
||||
end
|
||||
|
||||
@ -495,138 +500,140 @@ end
|
||||
|
||||
unless Setting.find_by(name: 'privacy_draft').try(:value)
|
||||
setting = Setting.find_or_initialize_by(name: 'privacy_draft')
|
||||
setting.value = "<p>La présente politique de confidentialité définit et vous informe de la manière dont _________ utilise et protège les
|
||||
informations que vous nous transmettez, le cas échéant, lorsque vous utilisez le présent site accessible à partir de l’URL suivante :
|
||||
_________ (ci-après le « Site »).</p><p>Veuillez noter que cette politique de confidentialité est susceptible d’être modifiée ou
|
||||
complétée à tout moment par _________, notamment en vue de se conformer à toute évolution législative, réglementaire, jurisprudentielle
|
||||
ou technologique. Dans un tel cas, la date de sa mise à jour sera clairement identifiée en tête de la présente politique et l'Utilisateur
|
||||
sera informé par courriel. Ces modifications engagent l’Utilisateur dès leur mise en ligne. Il convient par conséquent que l’Utilisateur
|
||||
consulte régulièrement la présente politique de confidentialité et d’utilisation des cookies afin de prendre connaissance de ses
|
||||
éventuelles modifications.</p><h3>I. DONNÉES PERSONNELLES</h3><p>D’une manière générale, il vous est possible de visiter le site de
|
||||
_________ sans communiquer aucune information personnelle vous concernant. En toute hypothèse, vous n’êtes en aucune manière obligé de
|
||||
transmettre ces informations à _________.</p><p>Néanmoins, en cas de refus, il se peut que vous ne puissiez pas bénéficier de
|
||||
certaines informations ou services que vous avez demandé. A ce titre en effet, _________ peut être amené dans certains cas à vous
|
||||
demander de renseigner vos nom, prénom, pseudonyme, sexe, adresse mail, numéro de téléphone, entreprise et date de naissance (ci-après
|
||||
vos « Informations Personnelles »). En fournissant ces informations, vous acceptez expressément qu’elles soient traitées par
|
||||
_________, aux fins indiquées au point 2 ci-dessous.</p><p>Conformément au Règlement Général sur la Protection des Données (General
|
||||
Data Protection Regulation) adopté par le Parlement européen le 14 avril 2016, et à la Loi Informatique et Libertés du 6 janvier 1978
|
||||
modifiée, _________ vous informe des points suivants :</p><h4>1. Identité du responsable du traitement</h4><p>Le responsable du
|
||||
traitement est (la société/l'association) _________ – (adresse) _________, (code postal) _________ (ville) _________ – (Pays)
|
||||
_________ .</p><h4>2. Finalités du traitement</h4><p>_________ est susceptible de traiter vos Informations Personnelles :</p><p>(a)
|
||||
aux fins de vous fournir les informations ou les services que vous avez demandés (notamment : l'envoi de notifications relatives à
|
||||
vos activités sur le Site, l’envoi de la Newsletter, la correspondance par email, l’envoi d’informations commerciales, livres
|
||||
blancs ou encore l’évaluation de votre niveau de satisfaction quant aux services proposés) ;</p><p>(b) aux fins de recueillir des
|
||||
informations nous permettant d’améliorer notre Site, nos produits et services (notamment par le biais de cookies) ;</p><p>(c)
|
||||
aux fins de pouvoir vous contacter à propos de différents événements relatifs à _________, incluant notamment la mise à jour des
|
||||
produits et le support client.</p><h4>3. Destinataires</h4><p>Seul _________ est destinataire de vos Informations Personnelles.
|
||||
Celles-ci, que ce soit sous forme individuelle ou agrégée, ne sont jamais transmises à un tiers, nonobstant les sous-traitants
|
||||
auxquels _________ fait appel (vous trouverez de plus amples informations à leur sujet au point 7 ci-dessous). Ni _________,
|
||||
ni l’un quelconque de ses sous-traitants, ne procèdent à la commercialisation des données personnelles des visiteurs et Utilisateurs de
|
||||
son Site.</p><h4>4. Durée de conservation</h4><p>Vos Informations Personnelles sont conservées par _________ uniquement pour le temps
|
||||
correspondant à la finalité de la collecte tel qu’indiqué en 2 ci-dessus qui ne saurait en tout état de cause excéder 36 mois.</p><h4>5.
|
||||
Droits Informatique et Libertés</h4><p>Vous disposez des droits suivants concernant vos Informations Personnelles, que vous pouvez exercer
|
||||
en nous écrivant à l’adresse postale mentionnée au point 1 ou en contactant le délégué à la protection des données, dont l'adresse est
|
||||
mentionnée ci-contre.</p><p><b>o Droit d’accès et de communication des données</b></p><p>Vous avez la faculté d’accéder aux Informations
|
||||
Personnelles qui vous concernent.</p><p>Cependant, en raison de l’obligation de sécurité et de confidentialité dans le traitement des
|
||||
données à caractère personnel qui incombe à _________, vous êtes informé que votre demande sera traitée sous réserve que vous apportiez la
|
||||
preuve de votre identité, notamment par la production d’un scan de votre titre d’identité valide (en cas de demande par voie électronique)
|
||||
ou d’une photocopie signée de votre titre d’identité valide (en cas de demande adressée par écrit).</p><p>_________ vous informe qu’il
|
||||
sera en droit, le cas échéant, de s’opposer aux demandes manifestement abusives (de par leur nombre, leur caractère répétitif ou
|
||||
systématique).</p><p>Pour vous aider dans votre démarche, notamment si vous désirez exercer votre droit d’accès par le biais d’une
|
||||
demande écrite à l’adresse postale mentionnée au point 1, vous trouverez en cliquant sur le <a
|
||||
href=\"https://www.cnil.fr/fr/modele/courrier/exercer-son-droit-dacces\">lien</a> suivant un modèle de courrier élaboré par la Commission
|
||||
Nationale de l’Informatique et des Libertés (la « CNIL »).</p><p><b>o Droit de rectification des données</b></p><p>Au titre de ce droit,
|
||||
la législation vous habilite à demander la rectification, la mise à jour, le verrouillage ou encore l’effacement des données vous
|
||||
concernant qui peuvent s’avérer le cas échéant inexactes, erronées, incomplètes ou obsolètes.</p><p>Egalement, vous pouvez définir des
|
||||
directives générales et particulières relatives au sort des données à caractère personnel après votre décès. Le cas échéant, les héritiers
|
||||
d’une personne décédée peuvent exiger de prendre en considération le décès de leur proche et/ou de procéder aux mises à jour nécessaires.
|
||||
</p><p>Pour vous aider dans votre démarche, notamment si vous désirez exercer, pour votre propre compte ou pour le compte de l’un de vos
|
||||
proches défunt, votre droit de rectification par le biais d’une demande écrite à l’adresse postale mentionnée au point 1, vous trouverez
|
||||
en cliquant sur le <a href=\"https://www.cnil.fr/fr/modele/courrier/rectifier-des-donnees-inexactes-obsoletes-ou-perimees\">lien</a>
|
||||
suivant un modèle de courrier élaboré par la CNIL.</p><p><b>o Droit d’opposition</b></p><p>L’exercice de ce droit n’est possible que dans
|
||||
l’une des deux situations suivantes :</p><p>Lorsque l’exercice de ce droit est fondé sur des motifs légitimes ; ou</p><p>Lorsque
|
||||
l’exercice de ce droit vise à faire obstacle à ce que les données recueillies soient utilisées à des fins de prospection commerciale.</p>
|
||||
<p>Pour vous aider dans votre démarche, notamment si vous désirez exercer votre droit d’opposition par le biais d’une demande écrite
|
||||
adressée à l’adresse postale indiquée au point 1, vous trouverez en cliquant sur le <a
|
||||
href=\"https://www.cnil.fr/fr/modele/courrier/supprimer-des-informations-vous-concernant-dun-site-internet\">lien</a> suivant un modèle de
|
||||
courrier élaboré par la CNIL.</p><h4>6. Délais de réponse</h4><p> _________ s’engage à répondre à votre demande d’accès, de rectification
|
||||
ou d’opposition ou toute autre demande complémentaire d’informations dans un délai raisonnable qui ne saurait dépasser 1 mois à compter
|
||||
de la réception de votre demande.</p><h4>7. Prestataires habilités et transfert vers un pays tiers de l’Union Européenne</h4><p>_________
|
||||
vous informe qu’il a recours à ses prestataires habilités pour faciliter le recueil et le traitement des données que vous nous avez
|
||||
communiqué. Ces prestataires peuvent être situés en dehors de l’Union Européenne et ont communication des données recueillies par le
|
||||
biais des divers formulaires présents sur le Site.</p><p>_________ s’est préalablement assuré de la mise en œuvre par ses prestataires de
|
||||
garanties adéquates et du respect de conditions strictes en matière de confidentialité, d’usage et de protection des données. Tout
|
||||
particulièrement, la vigilance s’est portée sur l’existence d’un fondement légal pour effectuer un quelconque transfert de données vers un
|
||||
pays tiers. A ce titre, l’un de nos prestataires est soumis à (nom de la règle) _________ approuvées par la (nom de l'autorité) _________
|
||||
en (année d'approbation) _________.</p><h4>8. Plainte auprès de l’autorité compétente</h4><p>Si vous considérez que _________ ne
|
||||
respecte pas ses obligations au regard de vos Informations Personnelles, vous pouvez adresser une plainte ou une demande auprès de
|
||||
l’autorité compétente. En France, l’autorité compétente est la CNIL à laquelle vous pouvez adresser une demande par voie électronique en
|
||||
cliquant sur le lien suivant : <a href=\"https://www.cnil.fr/fr/plaintes/internet\">https://www.cnil.fr/fr/plaintes/internet</a>.</p>
|
||||
<h3>II. POLITIQUE RELATIVE AUX COOKIES</h3><p>Lors de votre première connexion sur le site web de _________, vous êtes avertis par un
|
||||
bandeau en bas de votre écran que des informations relatives à votre navigation sont susceptibles d’être enregistrées dans des fichiers
|
||||
dénommés « cookies ». Notre politique d’utilisation des cookies vous permet de mieux comprendre les dispositions que nous mettons en œuvre
|
||||
en matière de navigation sur notre site web. Elle vous informe notamment sur l’ensemble des cookies présents sur notre site web, leur
|
||||
finalité (partie I.) et vous donne la marche à suivre pour les paramétrer (partie II.)</p><h4>1. Informations générales sur les cookies
|
||||
présents sur le site de _________</h4><p>_________, en tant qu’éditeur du présent site web, pourra procéder à l’implantation d’un cookie
|
||||
sur le disque dur de votre terminal (ordinateur, tablette, mobile etc.) afin de vous garantir une navigation fluide et optimale sur notre
|
||||
site Internet.</p><p>Les « cookies » (ou témoins de connexion) sont des petits fichiers texte de taille limitée qui nous permettent de
|
||||
reconnaître votre ordinateur, votre tablette ou votre mobile aux fins de personnaliser les services que nous vous proposons.</p><p>Les
|
||||
informations recueillies par le biais des cookies ne permettent en aucune manière de vous identifier nominativement. Elles sont utilisées
|
||||
exclusivement pour nos besoins propres afin d’améliorer l’interactivité et la performance de notre site web et de vous adresser des
|
||||
contenus adaptés à vos centres d’intérêts. Aucune de ces informations ne fait l’objet d’une communication auprès de tiers sauf lorsque
|
||||
_________ a obtenu au préalable votre consentement ou bien lorsque la divulgation de ces informations est requise par la loi, sur ordre
|
||||
d’un tribunal ou toute autorité administrative ou judiciaire habilitée à en connaître.</p><p>Pour mieux vous éclairer sur les informations
|
||||
que les cookies identifient, vous trouverez ci-dessous un tableau listant les différents types de cookies susceptibles d’être utilisés sur
|
||||
le site web de _________, leur nom, leur finalité ainsi que leur durée de conservation.</p><h4>2. Configuration de vos préférences sur les
|
||||
cookies</h4><p>Vous pouvez accepter ou refuser le dépôt de cookies à tout moment.</p><p>Lors de votre première connexion sur le site web
|
||||
de _________, une bannière présentant brièvement des informations relatives au dépôt de cookies et de technologies similaires apparaît en
|
||||
bas de votre écran. Cette bannière vous demande de choisir explicitement d'acceptez ou non le dépôt de cookies sur votre terminal.
|
||||
</p><p>Après avoir fait votre choix, vous pouvez le modifier ultérieurement en vous connectant à votre compte utilisateur puis en
|
||||
naviguant dans la section intitulée « mes paramètres », accessible via un clic sur votre nom, en haut à droite de l'écran.</p>
|
||||
<p>Selon le type de cookie en cause, le recueil de votre consentement au dépôt et à la lecture de cookies sur votre terminal peut être
|
||||
impératif.</p><h4>a. Les cookies exemptés de consentement</h4><p>Conformément aux recommandations de la Commission Nationale de
|
||||
l’Informatique et des Libertés (CNIL), certains cookies sont dispensés du recueil préalable de votre consentement dans la mesure où ils
|
||||
sont strictement nécessaires au fonctionnement du site internet ou ont pour finalité exclusive de permettre ou faciliter la communication
|
||||
par voie électronique. Il s’agit des cookies suivants :</p><p><b>o Identifiant de session</b> et <b>authentification</b> sur l'API.
|
||||
Ces cookies sont intégralement soumis à la présente politique dans la mesure où ils sont émis et gérés par _________.</p><p>
|
||||
<b>o Stripe</b>, permettant de gérer les paiements par carte bancaire et dont la politique de confidentialité est accessible sur ce
|
||||
<a href=\"https://stripe.com/fr/privacy\">lien</a>.</p><p><b>o Disqus</b>, permettant de poster des commentaires sur les fiches projet et
|
||||
dont la politique de confidentialité est accessible sur ce <a href=\"https://help.disqus.com/articles/1717103-disqus-privacy-policy\">lien
|
||||
</a>.</p><h4>b. Les cookies nécessitant le recueil préalable de votre consentement</h4><p>Cette
|
||||
exigence concerne les cookies émis par des tiers et qui sont qualifiés de « persistants » dans la mesure où ils demeurent dans votre
|
||||
terminal jusqu’à leur effacement ou leur date d’expiration.</p><p>De tels cookies étant émis par des tiers, leur utilisation et leur dépôt
|
||||
sont soumis à leurs propres politiques de confidentialité dont vous trouverez un lien ci-dessous. Cette famille de cookie comprend les
|
||||
cookies de mesure d’audience (Google Analytics).</p><p>Les cookies de mesure d’audience établissent des statistiques concernant la
|
||||
fréquentation et l’utilisation de divers éléments du site web (comme les contenus/pages que vous avez visité).
|
||||
Ces données participent à l’amélioration de l’ergonomie du site web de _________. Un outil de mesure d’audience est utilisé sur le
|
||||
présent site internet :</p><p><b>o Google Analytics</b> pour gérer les statistiques de visites dont la politique de
|
||||
confidentialité est disponible (uniquement en anglais) à partir du <a href=\"https://policies.google.com/privacy?hl=fr&gl=ZZ\">lien
|
||||
</a> suivant. </p><h4>c. Vous disposez de divers outils de paramétrage des cookies</h4><p>La plupart
|
||||
des navigateurs Internet sont configurés par défaut de façon à ce que le dépôt de cookies soit autorisé. Votre navigateur vous offre
|
||||
l’opportunité de modifier ces paramètres standards de manière à ce que l’ensemble des cookies soit rejeté systématiquement ou bien à ce
|
||||
qu’une partie seulement des cookies soit acceptée ou refusée en fonction de leur émetteur.</p><p><b>ATTENTION</b> : Nous attirons votre
|
||||
attention sur le fait que le refus du dépôt de cookies sur votre terminal est néanmoins susceptible d’altérer votre expérience
|
||||
d’utilisateur ainsi que votre accès à certains services ou fonctionnalités du présent site web. Le cas échéant, _________ décline toute
|
||||
responsabilité concernant les conséquences liées à la dégradation de vos conditions de navigation qui interviennent en raison de votre
|
||||
choix de refuser, supprimer ou bloquer les cookies nécessaires au fonctionnement du site.
|
||||
Ces conséquences ne sauraient constituer un dommage et vous ne pourrez prétendre à aucune indemnité de ce fait.</p>
|
||||
<p>Votre navigateur vous permet également de supprimer les cookies existants sur votre
|
||||
terminal ou encore de vous signaler lorsque de nouveaux cookies sont susceptibles d’être déposés sur votre terminal. Ces paramètres n’ont
|
||||
pas d’incidence sur votre navigation mais vous font perdre tout le bénéfice apporté par le cookie.</p><p>Veuillez ci-dessous prendre
|
||||
connaissance des multiples outils mis à votre disposition afin que vous puissiez paramétrer les cookies déposés sur votre terminal.</p>
|
||||
<h4>d. Le paramétrage de votre navigateur Internet</h4><p>Chaque navigateur Internet propose ses propres paramètres de gestion des
|
||||
cookies. Pour savoir de quelle manière modifier vos préférences en matière de cookies, vous trouverez ci-dessous les liens vers l’aide
|
||||
nécessaire pour accéder au menu de votre navigateur prévu à cet effet :</p>
|
||||
<ul>
|
||||
<li><a href=\"https://support.google.com/chrome/answer/95647?hl=fr\">Chrome</a></li>
|
||||
<li><a href=\"https://support.mozilla.org/fr/kb/activer-desactiver-cookies\">Firefox</a></li>
|
||||
<li><a href=\"https://support.microsoft.com/fr-fr/help/17442/windows-internet-explorer-delete-manage-cookies#ie=ie-11\">Internet
|
||||
Explorer</a></li>
|
||||
<li><a href=\"http://help.opera.com/Windows/10.20/fr/cookies.html\">Opera</a></li>
|
||||
<li><a href=\"https://support.apple.com/kb/PH21411?viewlocale=fr_FR&locale=fr_FR\">Safari</a></li>
|
||||
</ul>
|
||||
<p>Pour de plus amples informations concernant les outils de maîtrise des cookies, vous pouvez consulter le
|
||||
<a href=\"https://www.cnil.fr/fr/cookies-les-outils-pour-les-maitriser\">site internet</a> de la CNIL.</p>"
|
||||
setting.value = <<~HTML
|
||||
<p>La présente politique de confidentialité définit et vous informe de la manière dont _________ utilise et protège les
|
||||
informations que vous nous transmettez, le cas échéant, lorsque vous utilisez le présent site accessible à partir de l’URL suivante :
|
||||
_________ (ci-après le « Site »).</p><p>Veuillez noter que cette politique de confidentialité est susceptible d’être modifiée ou
|
||||
complétée à tout moment par _________, notamment en vue de se conformer à toute évolution législative, réglementaire, jurisprudentielle
|
||||
ou technologique. Dans un tel cas, la date de sa mise à jour sera clairement identifiée en tête de la présente politique et l'Utilisateur
|
||||
sera informé par courriel. Ces modifications engagent l’Utilisateur dès leur mise en ligne. Il convient par conséquent que l’Utilisateur
|
||||
consulte régulièrement la présente politique de confidentialité et d’utilisation des cookies afin de prendre connaissance de ses
|
||||
éventuelles modifications.</p><h3>I. DONNÉES PERSONNELLES</h3><p>D’une manière générale, il vous est possible de visiter le site de
|
||||
_________ sans communiquer aucune information personnelle vous concernant. En toute hypothèse, vous n’êtes en aucune manière obligé de
|
||||
transmettre ces informations à _________.</p><p>Néanmoins, en cas de refus, il se peut que vous ne puissiez pas bénéficier de
|
||||
certaines informations ou services que vous avez demandé. A ce titre en effet, _________ peut être amené dans certains cas à vous
|
||||
demander de renseigner vos nom, prénom, pseudonyme, sexe, adresse mail, numéro de téléphone, entreprise et date de naissance (ci-après
|
||||
vos « Informations Personnelles »). En fournissant ces informations, vous acceptez expressément qu’elles soient traitées par
|
||||
_________, aux fins indiquées au point 2 ci-dessous.</p><p>Conformément au Règlement Général sur la Protection des Données (General
|
||||
Data Protection Regulation) adopté par le Parlement européen le 14 avril 2016, et à la Loi Informatique et Libertés du 6 janvier 1978
|
||||
modifiée, _________ vous informe des points suivants :</p><h4>1. Identité du responsable du traitement</h4><p>Le responsable du
|
||||
traitement est (la société/l'association) _________ – (adresse) _________, (code postal) _________ (ville) _________ – (Pays)
|
||||
_________ .</p><h4>2. Finalités du traitement</h4><p>_________ est susceptible de traiter vos Informations Personnelles :</p><p>(a)
|
||||
aux fins de vous fournir les informations ou les services que vous avez demandés (notamment : l'envoi de notifications relatives à
|
||||
vos activités sur le Site, l’envoi de la Newsletter, la correspondance par email, l’envoi d’informations commerciales, livres
|
||||
blancs ou encore l’évaluation de votre niveau de satisfaction quant aux services proposés) ;</p><p>(b) aux fins de recueillir des
|
||||
informations nous permettant d’améliorer notre Site, nos produits et services (notamment par le biais de cookies) ;</p><p>(c)
|
||||
aux fins de pouvoir vous contacter à propos de différents événements relatifs à _________, incluant notamment la mise à jour des
|
||||
produits et le support client.</p><h4>3. Destinataires</h4><p>Seul _________ est destinataire de vos Informations Personnelles.
|
||||
Celles-ci, que ce soit sous forme individuelle ou agrégée, ne sont jamais transmises à un tiers, nonobstant les sous-traitants
|
||||
auxquels _________ fait appel (vous trouverez de plus amples informations à leur sujet au point 7 ci-dessous). Ni _________,
|
||||
ni l’un quelconque de ses sous-traitants, ne procèdent à la commercialisation des données personnelles des visiteurs et Utilisateurs de
|
||||
son Site.</p><h4>4. Durée de conservation</h4><p>Vos Informations Personnelles sont conservées par _________ uniquement pour le temps
|
||||
correspondant à la finalité de la collecte tel qu’indiqué en 2 ci-dessus qui ne saurait en tout état de cause excéder 36 mois.</p><h4>5.
|
||||
Droits Informatique et Libertés</h4><p>Vous disposez des droits suivants concernant vos Informations Personnelles, que vous pouvez exercer
|
||||
en nous écrivant à l’adresse postale mentionnée au point 1 ou en contactant le délégué à la protection des données, dont l'adresse est
|
||||
mentionnée ci-contre.</p><p><b>o Droit d’accès et de communication des données</b></p><p>Vous avez la faculté d’accéder aux Informations
|
||||
Personnelles qui vous concernent.</p><p>Cependant, en raison de l’obligation de sécurité et de confidentialité dans le traitement des
|
||||
données à caractère personnel qui incombe à _________, vous êtes informé que votre demande sera traitée sous réserve que vous apportiez la
|
||||
preuve de votre identité, notamment par la production d’un scan de votre titre d’identité valide (en cas de demande par voie électronique)
|
||||
ou d’une photocopie signée de votre titre d’identité valide (en cas de demande adressée par écrit).</p><p>_________ vous informe qu’il
|
||||
sera en droit, le cas échéant, de s’opposer aux demandes manifestement abusives (de par leur nombre, leur caractère répétitif ou
|
||||
systématique).</p><p>Pour vous aider dans votre démarche, notamment si vous désirez exercer votre droit d’accès par le biais d’une
|
||||
demande écrite à l’adresse postale mentionnée au point 1, vous trouverez en cliquant sur le <a
|
||||
href="https://www.cnil.fr/fr/modele/courrier/exercer-son-droit-dacces">lien</a> suivant un modèle de courrier élaboré par la Commission
|
||||
Nationale de l’Informatique et des Libertés (la « CNIL »).</p><p><b>o Droit de rectification des données</b></p><p>Au titre de ce droit,
|
||||
la législation vous habilite à demander la rectification, la mise à jour, le verrouillage ou encore l’effacement des données vous
|
||||
concernant qui peuvent s’avérer le cas échéant inexactes, erronées, incomplètes ou obsolètes.</p><p>Egalement, vous pouvez définir des
|
||||
directives générales et particulières relatives au sort des données à caractère personnel après votre décès. Le cas échéant, les héritiers
|
||||
d’une personne décédée peuvent exiger de prendre en considération le décès de leur proche et/ou de procéder aux mises à jour nécessaires.
|
||||
</p><p>Pour vous aider dans votre démarche, notamment si vous désirez exercer, pour votre propre compte ou pour le compte de l’un de vos
|
||||
proches défunt, votre droit de rectification par le biais d’une demande écrite à l’adresse postale mentionnée au point 1, vous trouverez
|
||||
en cliquant sur le <a href="https://www.cnil.fr/fr/modele/courrier/rectifier-des-donnees-inexactes-obsoletes-ou-perimees">lien</a>
|
||||
suivant un modèle de courrier élaboré par la CNIL.</p><p><b>o Droit d’opposition</b></p><p>L’exercice de ce droit n’est possible que dans
|
||||
l’une des deux situations suivantes :</p><p>Lorsque l’exercice de ce droit est fondé sur des motifs légitimes ; ou</p><p>Lorsque
|
||||
l’exercice de ce droit vise à faire obstacle à ce que les données recueillies soient utilisées à des fins de prospection commerciale.</p>
|
||||
<p>Pour vous aider dans votre démarche, notamment si vous désirez exercer votre droit d’opposition par le biais d’une demande écrite
|
||||
adressée à l’adresse postale indiquée au point 1, vous trouverez en cliquant sur le <a
|
||||
href="https://www.cnil.fr/fr/modele/courrier/supprimer-des-informations-vous-concernant-dun-site-internet">lien</a> suivant un modèle de
|
||||
courrier élaboré par la CNIL.</p><h4>6. Délais de réponse</h4><p> _________ s’engage à répondre à votre demande d’accès, de rectification
|
||||
ou d’opposition ou toute autre demande complémentaire d’informations dans un délai raisonnable qui ne saurait dépasser 1 mois à compter
|
||||
de la réception de votre demande.</p><h4>7. Prestataires habilités et transfert vers un pays tiers de l’Union Européenne</h4><p>_________
|
||||
vous informe qu’il a recours à ses prestataires habilités pour faciliter le recueil et le traitement des données que vous nous avez
|
||||
communiqué. Ces prestataires peuvent être situés en dehors de l’Union Européenne et ont communication des données recueillies par le
|
||||
biais des divers formulaires présents sur le Site.</p><p>_________ s’est préalablement assuré de la mise en œuvre par ses prestataires de
|
||||
garanties adéquates et du respect de conditions strictes en matière de confidentialité, d’usage et de protection des données. Tout
|
||||
particulièrement, la vigilance s’est portée sur l’existence d’un fondement légal pour effectuer un quelconque transfert de données vers un
|
||||
pays tiers. A ce titre, l’un de nos prestataires est soumis à (nom de la règle) _________ approuvées par la (nom de l'autorité) _________
|
||||
en (année d'approbation) _________.</p><h4>8. Plainte auprès de l’autorité compétente</h4><p>Si vous considérez que _________ ne
|
||||
respecte pas ses obligations au regard de vos Informations Personnelles, vous pouvez adresser une plainte ou une demande auprès de
|
||||
l’autorité compétente. En France, l’autorité compétente est la CNIL à laquelle vous pouvez adresser une demande par voie électronique en
|
||||
cliquant sur le lien suivant : <a href="https://www.cnil.fr/fr/plaintes/internet">https://www.cnil.fr/fr/plaintes/internet</a>.</p>
|
||||
<h3>II. POLITIQUE RELATIVE AUX COOKIES</h3><p>Lors de votre première connexion sur le site web de _________, vous êtes avertis par un
|
||||
bandeau en bas de votre écran que des informations relatives à votre navigation sont susceptibles d’être enregistrées dans des fichiers
|
||||
dénommés « cookies ». Notre politique d’utilisation des cookies vous permet de mieux comprendre les dispositions que nous mettons en œuvre
|
||||
en matière de navigation sur notre site web. Elle vous informe notamment sur l’ensemble des cookies présents sur notre site web, leur
|
||||
finalité (partie I.) et vous donne la marche à suivre pour les paramétrer (partie II.)</p><h4>1. Informations générales sur les cookies
|
||||
présents sur le site de _________</h4><p>_________, en tant qu’éditeur du présent site web, pourra procéder à l’implantation d’un cookie
|
||||
sur le disque dur de votre terminal (ordinateur, tablette, mobile etc.) afin de vous garantir une navigation fluide et optimale sur notre
|
||||
site Internet.</p><p>Les « cookies » (ou témoins de connexion) sont des petits fichiers texte de taille limitée qui nous permettent de
|
||||
reconnaître votre ordinateur, votre tablette ou votre mobile aux fins de personnaliser les services que nous vous proposons.</p><p>Les
|
||||
informations recueillies par le biais des cookies ne permettent en aucune manière de vous identifier nominativement. Elles sont utilisées
|
||||
exclusivement pour nos besoins propres afin d’améliorer l’interactivité et la performance de notre site web et de vous adresser des
|
||||
contenus adaptés à vos centres d’intérêts. Aucune de ces informations ne fait l’objet d’une communication auprès de tiers sauf lorsque
|
||||
_________ a obtenu au préalable votre consentement ou bien lorsque la divulgation de ces informations est requise par la loi, sur ordre
|
||||
d’un tribunal ou toute autorité administrative ou judiciaire habilitée à en connaître.</p><p>Pour mieux vous éclairer sur les informations
|
||||
que les cookies identifient, vous trouverez ci-dessous un tableau listant les différents types de cookies susceptibles d’être utilisés sur
|
||||
le site web de _________, leur nom, leur finalité ainsi que leur durée de conservation.</p><h4>2. Configuration de vos préférences sur les
|
||||
cookies</h4><p>Vous pouvez accepter ou refuser le dépôt de cookies à tout moment.</p><p>Lors de votre première connexion sur le site web
|
||||
de _________, une bannière présentant brièvement des informations relatives au dépôt de cookies et de technologies similaires apparaît en
|
||||
bas de votre écran. Cette bannière vous demande de choisir explicitement d'acceptez ou non le dépôt de cookies sur votre terminal.
|
||||
</p><p>Après avoir fait votre choix, vous pouvez le modifier ultérieurement en vous connectant à votre compte utilisateur puis en
|
||||
naviguant dans la section intitulée « mes paramètres », accessible via un clic sur votre nom, en haut à droite de l'écran.</p>
|
||||
<p>Selon le type de cookie en cause, le recueil de votre consentement au dépôt et à la lecture de cookies sur votre terminal peut être
|
||||
impératif.</p><h4>a. Les cookies exemptés de consentement</h4><p>Conformément aux recommandations de la Commission Nationale de
|
||||
l’Informatique et des Libertés (CNIL), certains cookies sont dispensés du recueil préalable de votre consentement dans la mesure où ils
|
||||
sont strictement nécessaires au fonctionnement du site internet ou ont pour finalité exclusive de permettre ou faciliter la communication
|
||||
par voie électronique. Il s’agit des cookies suivants :</p><p><b>o Identifiant de session</b> et <b>authentification</b> sur l'API.
|
||||
Ces cookies sont intégralement soumis à la présente politique dans la mesure où ils sont émis et gérés par _________.</p><p>
|
||||
<b>o Stripe</b>, permettant de gérer les paiements par carte bancaire et dont la politique de confidentialité est accessible sur ce
|
||||
<a href="https://stripe.com/fr/privacy">lien</a>.</p><p><b>o Disqus</b>, permettant de poster des commentaires sur les fiches projet et
|
||||
dont la politique de confidentialité est accessible sur ce <a href="https://help.disqus.com/articles/1717103-disqus-privacy-policy">lien
|
||||
</a>.</p><h4>b. Les cookies nécessitant le recueil préalable de votre consentement</h4><p>Cette
|
||||
exigence concerne les cookies émis par des tiers et qui sont qualifiés de « persistants » dans la mesure où ils demeurent dans votre
|
||||
terminal jusqu’à leur effacement ou leur date d’expiration.</p><p>De tels cookies étant émis par des tiers, leur utilisation et leur dépôt
|
||||
sont soumis à leurs propres politiques de confidentialité dont vous trouverez un lien ci-dessous. Cette famille de cookie comprend les
|
||||
cookies de mesure d’audience (Google Analytics).</p><p>Les cookies de mesure d’audience établissent des statistiques concernant la
|
||||
fréquentation et l’utilisation de divers éléments du site web (comme les contenus/pages que vous avez visité).
|
||||
Ces données participent à l’amélioration de l’ergonomie du site web de _________. Un outil de mesure d’audience est utilisé sur le
|
||||
présent site internet :</p><p><b>o Google Analytics</b> pour gérer les statistiques de visites dont la politique de
|
||||
confidentialité est disponible (uniquement en anglais) à partir du <a href="https://policies.google.com/privacy?hl=fr&gl=ZZ">lien
|
||||
</a> suivant. </p><h4>c. Vous disposez de divers outils de paramétrage des cookies</h4><p>La plupart
|
||||
des navigateurs Internet sont configurés par défaut de façon à ce que le dépôt de cookies soit autorisé. Votre navigateur vous offre
|
||||
l’opportunité de modifier ces paramètres standards de manière à ce que l’ensemble des cookies soit rejeté systématiquement ou bien à ce
|
||||
qu’une partie seulement des cookies soit acceptée ou refusée en fonction de leur émetteur.</p><p><b>ATTENTION</b> : Nous attirons votre
|
||||
attention sur le fait que le refus du dépôt de cookies sur votre terminal est néanmoins susceptible d’altérer votre expérience
|
||||
d’utilisateur ainsi que votre accès à certains services ou fonctionnalités du présent site web. Le cas échéant, _________ décline toute
|
||||
responsabilité concernant les conséquences liées à la dégradation de vos conditions de navigation qui interviennent en raison de votre
|
||||
choix de refuser, supprimer ou bloquer les cookies nécessaires au fonctionnement du site.
|
||||
Ces conséquences ne sauraient constituer un dommage et vous ne pourrez prétendre à aucune indemnité de ce fait.</p>
|
||||
<p>Votre navigateur vous permet également de supprimer les cookies existants sur votre
|
||||
terminal ou encore de vous signaler lorsque de nouveaux cookies sont susceptibles d’être déposés sur votre terminal. Ces paramètres n’ont
|
||||
pas d’incidence sur votre navigation mais vous font perdre tout le bénéfice apporté par le cookie.</p><p>Veuillez ci-dessous prendre
|
||||
connaissance des multiples outils mis à votre disposition afin que vous puissiez paramétrer les cookies déposés sur votre terminal.</p>
|
||||
<h4>d. Le paramétrage de votre navigateur Internet</h4><p>Chaque navigateur Internet propose ses propres paramètres de gestion des
|
||||
cookies. Pour savoir de quelle manière modifier vos préférences en matière de cookies, vous trouverez ci-dessous les liens vers l’aide
|
||||
nécessaire pour accéder au menu de votre navigateur prévu à cet effet :</p>
|
||||
<ul>
|
||||
<li><a href="https://support.google.com/chrome/answer/95647?hl=fr">Chrome</a></li>
|
||||
<li><a href="https://support.mozilla.org/fr/kb/activer-desactiver-cookies">Firefox</a></li>
|
||||
<li><a href="https://support.microsoft.com/fr-fr/help/17442/windows-internet-explorer-delete-manage-cookies#ie=ie-11">Internet
|
||||
Explorer</a></li>
|
||||
<li><a href="http://help.opera.com/Windows/10.20/fr/cookies.html">Opera</a></li>
|
||||
<li><a href="https://support.apple.com/kb/PH21411?viewlocale=fr_FR&locale=fr_FR">Safari</a></li>
|
||||
</ul>
|
||||
<p>Pour de plus amples informations concernant les outils de maîtrise des cookies, vous pouvez consulter le
|
||||
<a href="https://www.cnil.fr/fr/cookies-les-outils-pour-les-maitriser">site internet</a> de la CNIL.</p>
|
||||
HTML
|
||||
setting.save
|
||||
end
|
||||
|
||||
@ -644,6 +651,30 @@ unless Setting.find_by(name: 'link_name').try(:value)
|
||||
setting.save
|
||||
end
|
||||
|
||||
unless Setting.find_by(name: 'home_content').try(:value)
|
||||
setting = Setting.find_or_initialize_by(name: 'home_content')
|
||||
setting.value = <<~HTML
|
||||
<div class="m-sm">
|
||||
<div id="news">#{I18n.t('app.admin.settings.item_news')}</div>
|
||||
</div>
|
||||
<div class="row wrapper">
|
||||
<div class="col-lg-8">
|
||||
<div id="projects">#{I18n.t('app.admin.settings.item_projects')}</div>
|
||||
</div>
|
||||
<div class="col-lg-4 m-t-lg">
|
||||
<div id="twitter">#{I18n.t('app.admin.settings.item_twitter')}</div>
|
||||
<div id="members">#{I18n.t('app.admin.settings.item_members')}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row wrapper m-t-sm">
|
||||
<div class="col-lg-12">
|
||||
<div id="events">#{I18n.t('app.admin.settings.item_events')}</div>
|
||||
</div>
|
||||
</div>
|
||||
HTML
|
||||
setting.save
|
||||
end
|
||||
|
||||
if StatisticCustomAggregation.count.zero?
|
||||
# available reservations hours for machines
|
||||
machine_hours = StatisticType.find_by(key: 'hour', statistic_index_id: 2)
|
||||
|
125
vendor/assets/javascripts/summernote-ext-nugget.js
vendored
Normal file
125
vendor/assets/javascripts/summernote-ext-nugget.js
vendored
Normal file
@ -0,0 +1,125 @@
|
||||
// Inspired by: https://github.com/pHAlkaline/summernote-plugins/tree/master/plugins/nugget
|
||||
|
||||
(function (factory) {
|
||||
/* global define */
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['jquery'], factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(require('jquery'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory(window.jQuery);
|
||||
}
|
||||
}(function ($) {
|
||||
|
||||
|
||||
$.extend($.summernote.options, {
|
||||
nugget: {
|
||||
list: []
|
||||
}
|
||||
|
||||
});
|
||||
$.extend(true, $.summernote, {
|
||||
// add localization texts
|
||||
lang: {
|
||||
'en-US': {
|
||||
nugget: {
|
||||
Nugget: 'Nugget',
|
||||
Insert_nugget: 'Insert Nugget'
|
||||
|
||||
}
|
||||
},
|
||||
'en-GB': {
|
||||
nugget: {
|
||||
Nugget: 'Nugget',
|
||||
Insert_nugget: 'Insert Nugget'
|
||||
|
||||
}
|
||||
},
|
||||
'pt-PT': {
|
||||
nugget: {
|
||||
Nugget: 'Pepita',
|
||||
Insert_nugget: 'Inserir pepita'
|
||||
|
||||
}
|
||||
},
|
||||
'it-IT': {
|
||||
nugget: {
|
||||
Nugget: 'Pepite',
|
||||
Insert_nugget: 'Pepite Inserto'
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
// Extends plugins for adding nuggets.
|
||||
// - plugin is external module for customizing.
|
||||
$.extend($.summernote.plugins, {
|
||||
/**
|
||||
* @param {Object} context - context object has status of editor.
|
||||
*/
|
||||
'nugget': function (context) {
|
||||
// ui has renders to build ui elements.
|
||||
// - you can create a button with `ui.button`
|
||||
const ui = $.summernote.ui;
|
||||
const options = context.options.nugget;
|
||||
const context_options = context.options;
|
||||
const lang = context_options.langInfo;
|
||||
const defaultOptions = {
|
||||
label: lang.nugget.Nugget,
|
||||
tooltip: lang.nugget.Insert_nugget
|
||||
};
|
||||
|
||||
// Assign default values if not supplied
|
||||
for (const propertyName in defaultOptions) {
|
||||
if (options.hasOwnProperty(propertyName) === false) {
|
||||
options[propertyName] = defaultOptions[propertyName];
|
||||
}
|
||||
}
|
||||
|
||||
// add hello button
|
||||
context.memo('button.nugget', function () {
|
||||
// create button
|
||||
|
||||
const button = ui.buttonGroup([
|
||||
ui.button({
|
||||
className: 'dropdown-toggle',
|
||||
contents: '<span class="nugget">' + options.label + ' </span><span class="note-icon-caret"></span>',
|
||||
tooltip: options.tooltip,
|
||||
data: {
|
||||
toggle: 'dropdown'
|
||||
}
|
||||
}),
|
||||
ui.dropdown({
|
||||
className: 'dropdown-nugget',
|
||||
contents: options.list.map((i) => {
|
||||
const li = document.createElement('li');
|
||||
const a = document.createElement('a');
|
||||
a.innerHTML = i.trim();
|
||||
a.setAttribute('href', '#');
|
||||
li.appendChild(a);
|
||||
return li.outerHTML;
|
||||
}),
|
||||
click: function (event) {
|
||||
event.preventDefault();
|
||||
|
||||
const $button = $(event.target);
|
||||
const value = $button[0].outerHTML;
|
||||
const node = document.createElement('div');
|
||||
node.innerHTML = value.trim();
|
||||
context.invoke('editor.insertNode', node.firstChild);
|
||||
|
||||
}
|
||||
})
|
||||
]);
|
||||
|
||||
// create jQuery object from button instance.
|
||||
return button.render();
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}));
|
Loading…
x
Reference in New Issue
Block a user