1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-17 06:52:27 +01:00

Merge branch 'projects-openfablab' into dev

This commit is contained in:
cyril 2016-05-02 16:56:31 +02:00
commit c271d50991
25 changed files with 445 additions and 119 deletions

View File

@ -137,3 +137,5 @@ gem 'chroma'
gem 'protected_attributes'
gem 'message_format'
gem 'openlab_ruby'

View File

@ -174,6 +174,9 @@ GEM
http-cookie (1.0.2)
domain_name (~> 0.5)
http_parser.rb (0.6.0)
httparty (0.13.7)
json (~> 1.8)
multi_xml (>= 0.5.2)
i18n (0.7.0)
ice_nine (0.11.1)
jbuilder (2.2.12)
@ -242,6 +245,8 @@ GEM
omniauth-oauth2 (1.3.1)
oauth2 (~> 1.0)
omniauth (~> 1.2)
openlab_ruby (0.0.3)
httparty (~> 0.13)
orm_adapter (0.5.0)
pdf-core (0.5.1)
pg (0.18.1)
@ -458,6 +463,7 @@ DEPENDENCIES
oj
omniauth
omniauth-oauth2
openlab_ruby
pg
prawn
prawn-table

View File

@ -144,16 +144,18 @@ class ProjectsController
##
# Controller used on projects listing page
##
Application.Controllers.controller "ProjectsController", ["$scope", "$state", 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise'
, ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise) ->
Application.Controllers.controller "ProjectsController", ["$scope", "$state", 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout'
, ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout) ->
### PRIVATE STATIC CONSTANTS ###
# Number of notifications added to the page when the user clicks on 'load next notifications'
PROJECTS_PER_PAGE = 12
# Number of projects added to the page when the user clicks on 'load more projects'
PROJECTS_PER_PAGE = 16
$scope.openlabAppId = Fablab.openlabAppId
### PUBLIC SCOPE ###
$scope.search = { q: "", from: undefined, machine_id: undefined, component_id: undefined, theme_id: undefined }
$scope.search = { q: ($location.$$search.q || ""), from: ($location.$$search.from || undefined), machine_id: (parseInt($location.$$search.machine_id) || undefined), component_id: (parseInt($location.$$search.component_id) || undefined), theme_id: (parseInt($location.$$search.theme_id) || undefined) }
## list of projects to display
$scope.projects = []
@ -167,47 +169,101 @@ Application.Controllers.controller "ProjectsController", ["$scope", "$state", 'P
## list of components / used for filtering
$scope.components = componentsPromise
## By default, the pagination mode is activated to limit the page size
$scope.paginateActive = true
$scope.openlab = {}
$scope.openlab.projectsActive = Fablab.openlabProjectsActive
## The currently displayed page number
$scope.page = 1
if $location.$$search.whole_network is 'f'
$scope.openlab.searchOverWholeNetwork = false
else
$scope.openlab.searchOverWholeNetwork = $scope.openlab.projectsActive || false
$scope.resetFilters = ->
normalizeProjectsAttrs = (projects)->
projects.map((project)->
project.project_image = project.image_url
return project
)
$scope.searchOverWholeNetworkChanged = ->
setTimeout ->
$scope.resetFiltersAndTriggerSearch()
, 150
loadMoreCallback = (projectsPromise)->
$scope.projects = $scope.projects.concat(projectsPromise.projects)
updateUrlParam('page', $scope.projectsPagination.currentPage)
loadMoreOpenlabCallback = (projectsPromise)->
$scope.projects = $scope.projects.concat(normalizeProjectsAttrs(projectsPromise.projects))
updateUrlParam('page', $scope.projectsPagination.currentPage)
$scope.loadMore = ->
if $scope.openlab.searchOverWholeNetwork is true
$scope.projectsPagination.loadMore(q: $scope.search.q)
else
$scope.projectsPagination.loadMore(search: $scope.search)
$scope.resetFiltersAndTriggerSearch = ->
$scope.search.q = ""
$scope.search.from = undefined
$scope.search.machine_id = undefined
$scope.search.component_id = undefined
$scope.search.theme_id = undefined
$scope.setUrlQueryParams($scope.search)
$scope.triggerSearch()
$scope.triggerSearch = ->
Project.search { search: $scope.search, page: 1 }, (projects)->
$scope.projects = projects
if projects.length < PROJECTS_PER_PAGE
$scope.paginateActive = false
else
$scope.paginateActive = true
$scope.page = 2
$scope.loadMoreProjects = ->
# Project.query {page: $scope.page}, (projects) ->
# $scope.projects = $scope.projects.concat projects
# $scope.paginateActive = false if projects.length < PROJECTS_PER_PAGE
Project.search { search: $scope.search, page: $scope.page }, (projects)->
$scope.projects = $scope.projects.concat projects
$scope.paginateActive = false if projects.length < PROJECTS_PER_PAGE
$scope.page += 1
currentPage = parseInt($location.$$search.page) || 1
if $scope.openlab.searchOverWholeNetwork is true
updateUrlParam('whole_network', 't')
$scope.projectsPagination = new paginationService.Instance(OpenlabProject, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreOpenlabCallback)
OpenlabProject.query { q: $scope.search.q, page: currentPage, per_page: PROJECTS_PER_PAGE }, (projectsPromise)->
if projectsPromise.errors?
growl.error(_t('openlab_search_not_available_at_the_moment'))
$scope.openlab.searchOverWholeNetwork = false
$scope.triggerSearch()
else
$scope.projectsPagination.totalCount = projectsPromise.meta.total
$scope.projects = normalizeProjectsAttrs(projectsPromise.projects)
else
updateUrlParam('whole_network', 'f')
$scope.projectsPagination = new paginationService.Instance(Project, currentPage, PROJECTS_PER_PAGE, null, { }, loadMoreCallback, 'search')
Project.search { search: $scope.search, page: currentPage, per_page: PROJECTS_PER_PAGE }, (projectsPromise)->
$scope.projectsPagination.totalCount = projectsPromise.meta.total
$scope.projects = projectsPromise.projects
##
# Callback to switch the user's view to the detailled project page
# @param project {{slug:string}} The project to display
##
$scope.showProject = (project) ->
$state.go('app.public.projects_show', {id: project.slug})
if ($scope.openlab.searchOverWholeNetwork is true) and (project.app_id isnt Fablab.openlabAppId)
$window.open(project.project_url, '_blank')
return true
else
$state.go('app.public.projects_show', {id: project.slug})
##
# function to set all url query search parameters from search object
##
$scope.setUrlQueryParams = (search)->
updateUrlParam('page', 1)
updateUrlParam('q', search.q)
updateUrlParam('from', search.from)
updateUrlParam('theme_id', search.theme_id)
updateUrlParam('component_id', search.component_id)
updateUrlParam('machine_id', search.machine_id)
##
# function to update url query param, little hack to turn off reloadOnSearch and re-enable it after setting the params
# params example: 'q' , 'presse-purée'
##
updateUrlParam = (name, value) ->
$state.current.reloadOnSearch = false
$location.search(name, value)
$timeout ->
$state.current.reloadOnSearch = undefined
## initialization
$scope.triggerSearch()

View File

@ -219,7 +219,7 @@ angular.module('application.router', ['ui.router']).
# projects
.state 'app.public.projects_list',
url: '/projects'
url: '/projects?q&page&theme_id&component_id&machine_id&from&whole_network'
views:
'main@':
templateUrl: '<%= asset_path "projects/index.html" %>'

View File

@ -0,0 +1,9 @@
'use strict'
Application.Services.factory 'OpenlabProject', ["$resource", ($resource)->
$resource "/api/openlab_projects/:id",
{id: "@id"},
query:
method: 'GET'
isArray: false
]

View File

@ -0,0 +1,50 @@
'use strict'
Application.Services.factory("paginationService", [->
helpers = {}
helpers.pageCount = (totalCount, perPage)->
Math.ceil(totalCount/perPage)
helpers.hasNextPage = (currentPage, totalCount, perPage)->
_pageCount = helpers.pageCount(totalCount, perPage)
(_pageCount != currentPage) and (_pageCount != 0)
Instance = (resourceService, currentPage, perPage, totalCount, defaultQueryParams, callback, functionName)->
@resourceService = resourceService
@currentPage = currentPage
@perPage = perPage
@totalCount = totalCount
@defaultQueryParams = defaultQueryParams
@callback = callback
@functionName = functionName || 'query'
@loading = false
@pageCount = ->
helpers.pageCount(@totalCount, @perPage)
@hasNextPage = ->
helpers.hasNextPage(@currentPage, @totalCount, @perPage)
@loadMore = (queryParams)->
@currentPage += 1
@loading = true
_queryParams = { page: @currentPage, per_page: @perPage }
if queryParams
for k,v of queryParams
_queryParams[k] = v
for k,v of @defaultQueryParams
_queryParams[k] = v
@resourceService[@functionName](_queryParams, (dataPromise)=>
@callback(dataPromise)
@loading = false
)
return
return { Instance: Instance }
])

View File

@ -10,5 +10,5 @@ Application.Services.factory 'Project', ["$resource", ($resource)->
search:
method: 'GET'
url: '/api/projects/search'
isArray: true
isArray: false
]

View File

@ -65,49 +65,73 @@
height: 100%;
}
.box-thumb {
opacity: 0.9;
&:hover { opacity: 1;}
&:hover .box-footer { opacity: 1; }
// component card
.card {
position: relative;
background-size: cover;
background-repeat: no-repeat;
border-radius: 8px;
margin-bottom: 30px;
cursor: pointer;
// todo
display: block;
margin-bottom: .75rem;
background-color: #fff;
border: 1px solid #e5e5e5;
border-radius: .25rem;
height: 325px;
overflow: hidden;
height: 280px;
img {
opacity: 0.9;
margin-bottom: 3rem;
cursor: pointer;
}
.project-caption {
text-shadow: rgba(29, 29, 29, 0.5) 0 -1px, rgba(29, 29, 29, 0.5) -1px 0,
rgba(29, 29, 29, 0.5) 1px 0, rgba(29, 29, 29, 0.5) 0 1px;
}
.box-content {
.card-overlay {
margin: 1.25rem;
position: absolute;
top: 45px;
cursor: pointer;
z-index: 2;
top: 0;
left: 0;
right: 0;
h1 {
padding: 0 20px;
color: white;
text-transform: uppercase;
font-size: rem-calc(24);
font-weight: 900;
line-height: rem-calc(30);
text-align: center;
background-color: rgba(43,46,56,0.8);
text-align: center;
opacity: 0;
-webkit-transition: all 0.1s ease-out;
transition: all 0.1s ease-out;
height: 180px;
cursor: pointer;
.btn-group { margin-top: 70px;}
.btn {
background: rgba(255,255,255,0.1);
border: 1px solid #fff;
color: #fff;
}
}
.box-footer {
opacity: 0;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
text-align: center;
&:hover {
.card-overlay {
opacity: 1;
}
}
.card-header {
width: 100%;
display: block;
padding: 1.25rem;
.card-header-bg {
background-size: cover;
background-repeat: no-repeat;
background-position: center;
height: 180px;
}
}
.card-block {
padding: 0 1.25rem 1.25rem 1.25rem;
.card-title {
font-size: 1.5rem;
line-height: 2rem;
margin: 0;
text-align: center;
margin-top: 5px;
}
.card-meta {
font-size: 1.2rem;
margin: 0;
text-align: center
}
}
}

View File

@ -22,77 +22,100 @@
<section class="m-lg">
<div class="row m-b-md">
<div class="col-md-12"><h3 class="m-t-xs">{{ 'filter_projects' | translate }}
<a href="" class="text-sm pull-right" name="button" ng-click="resetFilters()"><i class="fa fa-refresh"></i> {{ 'reset_all_filters' | translate }}</a></h3>
</div>
<div class="col-md-12 m-b">
<form class="form-inline">
<a href="javascript:void(0);" class="text-sm pull-right" name="button" ng-click="resetFiltersAndTriggerSearch()" ng-show="!openlab.searchOverWholeNetwork"><i class="fa fa-refresh"></i> {{ 'reset_all_filters' | translate }}</a>
<span ng-if="openlab.projectsActive" uib-tooltip="{{ 'tooltip_openlab_projects_switch' | translate }}" tooltip-trigger="mouseenter">
<label for="searchOverWholeNetwork" class="control-label m-r text-sm" translate>{{ 'search_over_the_whole_network' }}</label>
<input bs-switch
ng-model="openlab.searchOverWholeNetwork"
type="checkbox"
class="form-control"
switch-on-text="{{ 'yes' | translate }}"
switch-off-text="{{ 'no' | translate }}"
switch-animate="true"
ng-change="searchOverWholeNetworkChanged()"
/>
{{ searchOverWholeNetwork }}
</span>
<form class="form-inline m-t text-center" role="form" ng-submit="setUrlQueryParams(search) && triggerSearch()">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-search"></i></div>
<input type="search" class="form-control" placeholder="Mots-clés" ng-model="search.q"/>
<div class="input-group-btn">
<button ng-click="triggerSearch()" type="button" class="btn btn-warning" translate>{{ 'search' }}</button>
<button type="submit" class="btn btn-warning" translate>{{ 'search' }}</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-md-3 m-b" ng-show="isAuthenticated()">
<select ng-model="search.from" ng-change="triggerSearch()" class="form-control">
<option value="" translate>{{ 'all_projects' }}</option>
<option value="mine" translate>{{ 'my_projects' }}</option>
<option value="collaboration" translate>{{ 'projects_to_whom_i_take_part_in' }}</option>
</select>
</div>
<span ng-if="!openlab.searchOverWholeNetwork">
<div class="col-md-3 m-b" ng-show="isAuthenticated()">
<select ng-model="search.from" ng-change="setUrlQueryParams(search) && triggerSearch()" class="form-control">
<option value="" translate>{{ 'all_projects' }}</option>
<option value="mine" translate>{{ 'my_projects' }}</option>
<option value="collaboration" translate>{{ 'projects_to_whom_i_take_part_in' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.machine_id" ng-change="triggerSearch()" class="form-control" ng-options="m.id as m.name for m in machines">
<option value="" translate>{{ 'all_machines' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.machine_id" ng-change="setUrlQueryParams(search) && triggerSearch()" class="form-control" ng-options="m.id as m.name for m in machines">
<option value="" translate>{{ 'all_machines' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.theme_id" ng-change="triggerSearch()" class="form-control" ng-options="t.id as t.name for t in themes">
<option value="" translate>{{ 'all_themes' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.theme_id" ng-change="setUrlQueryParams(search) && triggerSearch()" class="form-control" ng-options="t.id as t.name for t in themes">
<option value="" translate>{{ 'all_themes' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.component_id" ng-change="triggerSearch()" class="form-control" ng-options="t.id as t.name for t in components">
<option value="" translate>{{ 'all_materials' }}</option>
</select>
</div>
<div class="col-md-3 m-b">
<select ng-model="search.component_id" ng-change="setUrlQueryParams(search) && triggerSearch()" class="form-control" ng-options="t.id as t.name for t in components">
<option value="" translate>{{ 'all_materials' }}</option>
</select>
</div>
</span>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-4" ng-repeat="project in projects" ng-click="showProject(project)">
<div class="box-thumb box-thumb-project" style="background-image: url({{project.project_image}});">
<span class="col-md-12" ng-show="projects && (projects.length == 0)"> {{ 'project_search_result_is_empty' | translate }} </span>
<div class="col-xs-12 col-sm-6 col-md-3" ng-repeat="project in projects" ng-click="showProject(project)">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:FontAwesome/icon" bs-holder ng-if="!project.project_image">
<div class="card card-project">
<div class="box-content project-caption">
<h1>{{project.name}}</h1>
<div class="card-header">
<div class="card-header-bg" style="background-image: url({{project.project_image}});">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:FontAwesome/icon" bs-holder ng-if="!project.project_image">
</div>
</div>
<div class="box-footer">
<div class="card-block">
<h3 class="card-meta" ng-if="openlab.searchOverWholeNetwork && project.app_id != openlabAppId"><i class="fa fa-tag"></i> {{ project.app_name }}</h3>
<h1 class="card-title">{{project.name}}</h1>
</div>
<div class="card-overlay">
<div class="btn-group">
<div class="btn btn-default" ui-sref="app.logged.projects_edit({id:project.id})" ng-if="projectEditableBy(currentUser) || isAuthorized('admin')">
<i class="fa fa-edit"></i> {{ 'edit' | translate }}
</div>
<div class="btn btn-default" ng-click="showProject(project)">
<i class="fa fa-eye"></i> {{ 'consult' | translate }}
<i ng-class="{'fa fa-external-link' : (openlab.searchOverWholeNetwork && project.app_id != openlabAppId) }"></i> {{ 'consult' | translate }}
</div>
<div class="btn btn-default" ui-sref="app.logged.projects_edit({id:project.id})" ng-if="isAuthorized('admin') && !openlab.searchOverWholeNetwork">
<i class="fa fa-edit"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 text-center">
<a class="btn btn-warning" ng-click="loadMoreProjects()" ng-if="paginateActive" translate>{{ 'load_next_projects' }}</a>
<a class="btn btn-warning" ng-click="loadMore()" ng-if="projectsPagination.hasNextPage()" translate>{{ 'load_next_projects' }}</a>
</div>
</div>
</section>

View File

@ -0,0 +1,11 @@
class API::OpenlabProjectsController < API::ApiController
PROJECTS = Openlab::Projects.new
def index
begin
render json: PROJECTS.search(params[:q], page: params[:page], per_page: params[:per_page]).response.body
rescue StandardError
render json: { errors: ['service unavailable'] }
end
end
end

View File

@ -51,7 +51,9 @@ class API::ProjectsController < API::ApiController
def search
query_params = JSON.parse(params[:search])
@projects = Project.search(query_params, current_user).page(params[:page]).records
records = Project.search(query_params, current_user).page(params[:page]).records
@total = records.total
@projects = records.includes(:users, :project_image)
render :index
end

View File

@ -1,6 +1,7 @@
class Project < ActiveRecord::Base
include AASM
include NotifyWith::NotificationAttachedObject
include OpenlabSync
# elastic initialisations
include Elasticsearch::Model
@ -32,6 +33,9 @@ class Project < ActiveRecord::Base
has_many :project_steps, dependent: :destroy
accepts_nested_attributes_for :project_steps, allow_destroy: true
# validations
validates :author, :name, presence: true
after_save :after_save_and_publish
aasm :column => 'state' do
@ -104,7 +108,7 @@ class Project < ActiveRecord::Base
}
}
if params['q'].empty? # we sort by created_at if there isn't a query
if params['q'].blank? # we sort by created_at if there isn't a query
search[:sort] = { created_at: { order: :desc } }
else # otherwise we search for the word (q) in various fields
search[:query][:filtered][:query] = {

View File

@ -0,0 +1,65 @@
module Project::OpenlabSync
extend ActiveSupport::Concern
included do
include ActionView::Helpers::SanitizeHelper
after_create :openlab_create, if: :openlab_sync_active?
after_update :openlab_update, if: :openlab_sync_active?
after_destroy :openlab_destroy, if: :openlab_sync_active?
def openlab_create
OpenlabWorker.delay_for(2.seconds).perform_async(:create, self.id) if self.published?
end
def openlab_update
if self.published?
if self.state_was == 'draft'
OpenlabWorker.perform_async(:create, self.id)
else
OpenlabWorker.perform_async(:update, self.id)
end
end
end
def openlab_destroy
OpenlabWorker.perform_async(:destroy, self.id)
end
def openlab_attributes
{
id: id, slug: slug, name: name, description: description, tags: tags,
machines: machines.map(&:name),
components: components.map(&:name),
themes: themes.map(&:name),
author: author&.profile&.full_name,
collaborators: users.map { |u| u.profile.full_name },
steps_body: steps_body,
image_path: project_image&.attachment&.medium&.url,
project_path: "/#!/projects/#{slug}",
updated_at: updated_at.to_s(:iso8601),
created_at: created_at.to_s(:iso8601),
published_at: published_at.to_s(:iso8601)
}
end
def steps_body
concatenated_steps = project_steps.map { |s| "#{s.title} #{s.description}" }
.join(' ').gsub('</p>', ' </p>')
.gsub("\r\n", ' ').gsub("\n\r", ' ')
.gsub("\n", ' ').gsub("\r", ' ').gsub("\t", ' ')
strip_tags(concatenated_steps).strip
end
def openlab_sync_active?
self.class.openlab_sync_active?
end
end
class_methods do
def openlab_sync_active?
Rails.application.secrets.openlab_app_secret.present?
end
end
end

View File

@ -1,10 +1,11 @@
json.array!(@projects) do |project|
json.projects @projects do |project|
json.extract! project, :id, :name, :description, :author_id, :licence_id, :slug
json.url project_url(project, format: :json)
json.project_image project.project_image.attachment.medium.url if project.project_image
json.machine_ids project.machine_ids
json.author_id project.author_id
json.user_ids project.user_ids
json.theme_ids project.theme_ids
json.component_ids project.component_ids
end
json.meta do
json.total @total if @total
end

View File

@ -45,6 +45,12 @@
Fablab.weekStartingDay = <%= Date.parse(Rails.application.secrets.week_starting_day).strftime('%w') %>;
Fablab.d3DateFormat = "<%= Rails.application.secrets.d3_date_format %>";
Fablab.uibDateFormat = "<%= Rails.application.secrets.uib_date_format %>";
Fablab.openlabProjectsActive = <%= Rails.application.secrets.openlab_app_secret.present? %>;
<% if Rails.application.secrets.openlab_app_id.present? %>
Fablab.openlabAppId = "<%= Rails.application.secrets.openlab_app_id %>";
<% else %>
Fablab.openlabAppId = null;
<% end %>
</script>
<%= stylesheet_link_tag 'application', media: 'all' %>

View File

@ -0,0 +1,24 @@
class OpenlabWorker
include Sidekiq::Worker
sidekiq_options queue: 'default', retry: true
Logger = Sidekiq.logger.level == Logger::DEBUG ? Sidekiq.logger : nil
OPENLAB_CLIENT = Openlab::Projects.new
def perform(action, project_id)
logger.debug ["Openlab sync", action, "project ID: #{project_id}"]
case action.to_s
when /create/
project = Project.find(project_id)
response = OPENLAB_CLIENT.create(project.openlab_attributes)
when /update/
project = Project.find(project_id)
response = OPENLAB_CLIENT.update(project_id, project.openlab_attributes)
when /destroy/
response = OPENLAB_CLIENT.destroy(project_id)
end
logger.debug ["Openlab sync", "RESPONSE ERROR", response.inspect] unless response.success?
end
end

View File

@ -47,3 +47,7 @@ TIME_ZONE: 'Paris'
WEEK_STARTING_DAY: 'monday'
D3_DATE_FORMAT: '%d/%m/%y'
UIB_DATE_FORMAT: 'dd/MM/yyyy'
OPENLAB_APP_SECRET:
OPENLAB_APP_ID:
OPENLAB_BASE_URI: 'https://openprojects.fab-manager.com'

View File

@ -0,0 +1,4 @@
Openlab.configure do |config|
config.app_secret = Rails.application.secrets.openlab_app_secret
config.base_uri = Rails.application.secrets.openlab_base_uri
end

View File

@ -118,8 +118,11 @@ en:
projects_list:
# projects gallery
the_fablab_projects: "The Fab Lab projects"
search_over_the_whole_network: "Search over the whole Fab Manager network"
tooltip_openlab_projects_switch: "The search over the whole network lets you search over the projects of every Fab-manager using this feature !"
openlab_search_not_available_at_the_moment: "Search over the whole network is not available at the moment. You still can search over the projects of this platform."
project_search_result_is_empty: "Sorry, we found no results matching your search criteria."
add_a_project: "Add a project"
filter_projects: "Filter projects:"
reset_all_filters: "Reset all filters"
search: "Search"
all_projects: "All projects"
@ -128,7 +131,7 @@ en:
all_machines: "All machines"
all_themes: "All themes"
all_materials: "All materials"
load_next_projects: "Load next projects..."
load_next_projects: "Load next projects"
projects_show:
# details of a projet
@ -212,4 +215,4 @@ en:
you_booked_(DATE): "You booked ({{DATE}}):" # angular interpolation
book: "Book"
change_the_reservation: "Change the reservation"
you_can_shift_this_reservation_on_the_following_slots: "You can shift this reservation on the following slots:"
you_can_shift_this_reservation_on_the_following_slots: "You can shift this reservation on the following slots:"

View File

@ -118,8 +118,11 @@ fr:
projects_list:
# galerie des projets
the_fablab_projects: "Les projets du FabLab"
search_over_the_whole_network: "Chercher sur tout le réseau Fab Manager"
tooltip_openlab_projects_switch: "La recherche sur tout le réseau vous permet de rechercher parmis les projets de tous les Fab-managers utilisant cette fonctionnalité !"
openlab_search_not_available_at_the_moment: "La recherche sur tout le réseau n'est pas disponible pour le moment. Vous ne pouvez cependant effectuer une recherche parmis les projets de cette plateforme."
project_search_result_is_empty: "Il n'y a pas de projets correspondant à vos critères de recherche."
add_a_project: "Ajouter un projet"
filter_projects: "Filtrer les projets :"
reset_all_filters: "Réinitialiser tous les filtres"
search: "Rechercher"
all_projects: "Tous les projets"
@ -128,7 +131,7 @@ fr:
all_machines: "Toutes les machines"
all_themes: "Toutes les thématiques"
all_materials: "Tous les matériaux"
load_next_projects: "Charger les projets suivants ..."
load_next_projects: "Charger les projets suivants"
projects_show:
# détails d'un projet
@ -212,4 +215,4 @@ fr:
you_booked_(DATE): "Vous avez réservé ({{DATE}}) :" # angular interpolation
book: "Réserver"
change_the_reservation: "Modifier la réservation"
you_can_shift_this_reservation_on_the_following_slots: "Vous pouvez déplacer cette réservation sur les créneaux suivants :"
you_can_shift_this_reservation_on_the_following_slots: "Vous pouvez déplacer cette réservation sur les créneaux suivants :"

View File

@ -27,6 +27,7 @@ Rails.application.routes.draw do
get :search
end
end
resources :openlab_projects, only: :index
resources :machines
resources :components
resources :themes

View File

@ -28,6 +28,9 @@ development:
messageformat_locale: <%= ENV["MESSAGEFORMAT_LOCALE"] %>
fullcalendar_locale: <%= ENV["FULLCALENDAR_LOCALE"] %>
elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %>
openlab_app_secret: <%= ENV["OPENLAB_APP_SECRET"] %>
openlab_app_id: <%= ENV["OPENLAB_APP_ID"] %>
openlab_base_uri: <%= ENV["OPENLAB_BASE_URI"] %>
test:
secret_key_base: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30
@ -47,7 +50,9 @@ test:
messageformat_locale: en
fullcalendar_locale: en
elasticsearch_language_analyzer: french
openlab_app_secret:
openlab_app_id:
openlab_base_uri:
staging:
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
@ -74,6 +79,9 @@ staging:
messageformat_locale: <%= ENV["MESSAGEFORMAT_LOCALE"] %>
fullcalendar_locale: <%= ENV["FULLCALENDAR_LOCALE"] %>
elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %>
openlab_app_secret: <%= ENV["OPENLAB_APP_SECRET"] %>
openlab_app_id: <%= ENV["OPENLAB_APP_ID"] %>
openlab_base_uri: <%= ENV["OPENLAB_BASE_URI"] %>
# Do not keep production secrets in the repository,
# instead read values from the environment.
@ -102,3 +110,6 @@ production:
messageformat_locale: <%= ENV["MESSAGEFORMAT_LOCALE"] %>
fullcalendar_locale: <%= ENV["FULLCALENDAR_LOCALE"] %>
elasticsearch_language_analyzer: <%= ENV["ELASTICSEARCH_LANGUAGE_ANALYZER"] %>
openlab_app_secret: <%= ENV["OPENLAB_APP_SECRET"] %>
openlab_app_id: <%= ENV["OPENLAB_APP_ID"] %>
openlab_base_uri: <%= ENV["OPENLAB_BASE_URI"] %>

View File

@ -43,4 +43,7 @@ ELASTICSEARCH_LANGUAGE_ANALYZER=french
TIME_ZONE=Paris
WEEK_STARTING_DAY=monday
D3_DATE_FORMAT=%d/%m/%y
UIB_DATE_FORMAT=dd/MM/yyyy
UIB_DATE_FORMAT=dd/MM/yyyy
OPENLAB_APP_SECRET: 'fSF9jZEWxjHyqjAzzg34jd92'
OPENLAB_APP_ID: 'xLn9CmryyURNNHZiDRYVRXbv'

View File

@ -76,9 +76,10 @@ namespace :fablab do
desc "sync all/one project in elastic search index"
task :es_build_projects_index, [:id] => :environment do |task, args|
unless Project.__elasticsearch__.client.indices.exists? index: 'fablab'
Project.__elasticsearch__.client.indices.create index: Project.index_name, body: { settings: Project.settings.to_hash, mappings: Project.mappings.to_hash }
if Project.__elasticsearch__.client.indices.exists? index: 'fablab'
Project.__elasticsearch__.client.indices.delete index: 'fablab'
end
Project.__elasticsearch__.client.indices.create index: Project.index_name, body: { settings: Project.settings.to_hash, mappings: Project.mappings.to_hash }
if args.id
IndexerWorker.perform_async(:index, id)
else

View File

@ -0,0 +1,13 @@
namespace :fablab do
namespace :openlab do
task bulk_export: :environment do
if Rails.application.secrets.openlab_app_secret.present?
Project.find_each do |project|
project.openlab_create
end
else
warn "Rails.application.secrets.openlab_app_secret not present. Export can't be done."
end
end
end
end