1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2024-11-28 09:24:24 +01:00

filter projects list by member

This commit is contained in:
Nicolas Florentin 2023-06-29 14:32:06 +02:00
parent 11a079b3e2
commit 97c652f785
20 changed files with 114 additions and 6 deletions

View File

@ -269,6 +269,8 @@ GEM
net-smtp (0.3.3)
net-protocol
nio4r (2.5.8)
nokogiri (1.14.3-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.14.3-x86_64-linux)
racc (~> 1.4)
oauth2 (1.4.4)
@ -524,6 +526,7 @@ GEM
zeitwerk (2.6.7)
PLATFORMS
x86_64-darwin-21
x86_64-linux
DEPENDENCIES

View File

@ -281,8 +281,8 @@ class ProjectsController {
/**
* Controller used on projects listing page
*/
Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout', 'settingsPromise', 'openLabActive',
function ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout, settingsPromise, openLabActive) {
Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'Project', 'machinesPromise', 'themesPromise', 'componentsPromise', 'paginationService', 'OpenlabProject', '$window', 'growl', '_t', '$location', '$timeout', 'settingsPromise', 'openLabActive', 'Member', 'Diacritics',
function ($scope, $state, Project, machinesPromise, themesPromise, componentsPromise, paginationService, OpenlabProject, $window, growl, _t, $location, $timeout, settingsPromise, openLabActive, Member, Diacritics) {
/* PRIVATE STATIC CONSTANTS */
// Number of projects added to the page when the user clicks on 'load more projects'
@ -294,12 +294,18 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
// Fab-manager's instance ID in the openLab network
$scope.openlabAppId = settingsPromise.openlab_app_id;
$scope.memberFilterPresence = settingsPromise.projects_list_member_filter_presence !== 'false';
// Is openLab enabled on the instance?
$scope.openlab = {
projectsActive: openLabActive.isPresent,
searchOverWholeNetwork: settingsPromise.openlab_default === 'true'
};
if (!$scope.memberFilterPresence) {
$location.$$search.member_id = '';
}
// default search parameters
$scope.search = {
q: ($location.$$search.q || ''),
@ -307,7 +313,24 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
machine_id: (parseInt($location.$$search.machine_id) || undefined),
component_id: (parseInt($location.$$search.component_id) || undefined),
theme_id: (parseInt($location.$$search.theme_id) || undefined),
status_id: (parseInt($location.$$search.status_id) || undefined)
status_id: (parseInt($location.$$search.status_id) || undefined),
member_id: (parseInt($location.$$search.member_id) || undefined)
};
$scope.autoCompleteMemberName = function (nameLookup) {
if (!nameLookup) {
return;
}
$scope.isLoadingMembers = true;
const asciiName = Diacritics.remove(nameLookup);
const q = { query: asciiName };
Member.search(q, function (users) {
$scope.matchingMembers = users;
$scope.isLoadingMembers = false;
}
, function (error) { console.error(error); });
};
// list of projects to display
@ -361,6 +384,7 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
$scope.search.component_id = undefined;
$scope.search.theme_id = undefined;
$scope.search.status_id = undefined;
$scope.search.member_id = undefined;
$scope.$apply();
$scope.setUrlQueryParams($scope.search);
$scope.triggerSearch();
@ -420,6 +444,16 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
updateUrlParam('component_id', search.component_id);
updateUrlParam('machine_id', search.machine_id);
updateUrlParam('status_id', search.status_id);
updateUrlParam('member_id', search.member_id);
return true;
};
$scope.setSearchMemberId = function (searchMember) {
if (searchMember) {
$scope.search.member_id = searchMember.id;
} else {
$scope.search.member_id = undefined;
}
return true;
};
@ -450,6 +484,11 @@ Application.Controllers.controller('ProjectsController', ['$scope', '$state', 'P
} else {
$scope.openlab.searchOverWholeNetwork = $scope.openlab.projectsActive;
}
if ($location.$$search.member_id && $scope.memberFilterPresence) {
Member.get({ id: $location.$$search.member_id }, function (member) {
$scope.searchMember = member;
});
}
return $scope.triggerSearch();
};

View File

@ -198,7 +198,8 @@ export const fabHubSettings = [
export const projectsSettings = [
'allowed_cad_extensions',
'allowed_cad_mime_types',
'disqus_shortname'
'disqus_shortname',
'projects_list_member_filter_presence'
] as const;
export const prepaidPacksSettings = [

View File

@ -301,7 +301,7 @@ angular.module('application.router', ['ui.router'])
themesPromise: ['Theme', function (Theme) { return Theme.query().$promise; }],
componentsPromise: ['Component', function (Component) { return Component.query().$promise; }],
machinesPromise: ['Machine', function (Machine) { return Machine.query().$promise; }],
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['openlab_app_id', 'openlab_default']" }).$promise; }],
settingsPromise: ['Setting', function (Setting) { return Setting.query({ names: "['openlab_app_id', 'openlab_default', 'projects_list_member_filter_presence']" }).$promise; }],
openLabActive: ['Setting', function (Setting) { return Setting.isPresent({ name: 'openlab_app_secret' }).$promise; }]
}
})

View File

@ -95,3 +95,18 @@
</div>
</div>
</div>
<div class="panel panel-default m-t-lg">
<div class="panel-heading">
<span class="font-sbold" translate>{{ 'app.admin.projects.settings.filters' }}</span>
</div>
<div class="panel-body">
<div class="row">
<boolean-setting name="'projects_list_member_filter_presence'"
label="'app.admin.settings.projects_list_member_filter_presence' | translate"
on-success="onSuccess"
on-error="onError"
class-name="'m-l'"></boolean-setting>
</div>
</div>
</div>

View File

@ -65,6 +65,15 @@
<option value="" translate>{{ 'app.public.projects_list.all_materials' }}</option>
</select>
<ui-select ng-if="currentUser && memberFilterPresence" ng-model="searchMember" on-select="setSearchMemberId(searchMember) && setUrlQueryParams(search) && triggerSearch()">
<ui-select-match allow-clear="true" placeholder="{{ 'app.public.projects_list.filter_by_member' | translate }}">
<span ng-bind="$select.selected.name"></span>
</ui-select-match>
<ui-select-choices repeat="m in matchingMembers" refresh="autoCompleteMemberName($select.search)" refresh-delay="300">
<span ng-bind-html="m.name | highlight: $select.search"></span>
</ui-select-choices>
</ui-select>
<status-filter on-filter-change="onStatusChange" current-status-index="search.status_id"/>
</div>
</div>

View File

@ -196,6 +196,7 @@ module SettingsHelper
events_banner_cta_active
events_banner_cta_label
events_banner_cta_url
projects_list_member_filter_presence
].freeze
end
# rubocop:enable Metrics/ModuleLength

View File

@ -46,7 +46,7 @@ class SettingPolicy < ApplicationPolicy
external_id machines_banner_active machines_banner_text machines_banner_cta_active machines_banner_cta_label
machines_banner_cta_url trainings_banner_active trainings_banner_text trainings_banner_cta_active trainings_banner_cta_label
trainings_banner_cta_url events_banner_active events_banner_text events_banner_cta_active events_banner_cta_label
events_banner_cta_url]
events_banner_cta_url projects_list_member_filter_presence]
end
##

View File

@ -23,6 +23,14 @@ class ProjectService
records = records.with_theme(query_params['theme_id']) if query_params['theme_id'].present?
records = records.with_space(query_params['space_id']) if query_params['space_id'].present?
records = records.with_status(query_params['status_id']) if query_params['status_id'].present?
if query_params['member_id'].present?
member = User.find(query_params['member_id'])
if member
records = records.where(id: Project.user_projects(member.statistic_profile.id)).or(Project.where(id: Project.collaborations(member.id)))
end
end
records = if query_params['q'].present?
records.search(query_params['q'])
else

View File

@ -61,6 +61,9 @@
buttons: <%= I18n.t('app.shared.buttons').to_json.html_safe %>,
messages: <%= I18n.t('app.shared.messages').to_json.html_safe %>
}
},
date: {
month_names: <%= I18n.t('date.month_names').to_json.html_safe %>
}
};
Fablab.weekStartingDay = <%= Date.parse(Rails.application.secrets.week_starting_day).strftime('%w') %>;

View File

@ -445,6 +445,7 @@ en:
open_lab_app_secret: "Secret"
openlab_default_info_html: "In the projects gallery, visitors can switch between two views: all shared projects from the whole OpenLab network, or only the projects documented in your Fab Lab.<br/>Here, you can choose which view is shown by default."
default_to_openlab: "Display OpenLab by default"
filters: Projects list filters
projects_setting:
add: "Add"
actions_controls: "Actions"
@ -1773,6 +1774,7 @@ en:
extended_prices_in_same_day: "Extended prices in the same day"
public_registrations: "Public registrations"
show_username_in_admin_list: "Show the username in the list"
projects_list_member_filter_presence: "Presence of member filter on projects list"
overlapping_options:
training_reservations: "Trainings"
machine_reservations: "Machines"

View File

@ -445,6 +445,7 @@ fr:
open_lab_app_secret: "Secret"
openlab_default_info_html: "Dans la galerie de projets, les visiteurs peuvent choisir entre deux vues : tous les projets de l'ensemble du réseau OpenLab, ou uniquement les projets documentés dans votre Fab Lab.<br/>Ici, vous pouvez choisir quelle vue est affichée par défaut."
default_to_openlab: "Afficher OpenLab par défaut"
filters: Filtres de la vue liste
projects_setting:
add: "Ajouter"
actions_controls: "Actions"
@ -1773,6 +1774,7 @@ fr:
extended_prices_in_same_day: "Prix étendus le même jour"
public_registrations: "Inscriptions publiques"
show_username_in_admin_list: "Afficher le nom d'utilisateur dans la liste"
projects_list_member_filter_presence: "Présence du filtre par membre dans la vue liste des projets"
overlapping_options:
training_reservations: "Formations"
machine_reservations: "Machines"

View File

@ -183,6 +183,7 @@ en:
all_materials: "All materials"
load_next_projects: "Load next projects"
rough_draft: "Rough draft"
filter_by_member: "Filter by member"
status_filter:
all_statuses: "All statuses"
select_status: "Select a status"

View File

@ -183,6 +183,7 @@ fr:
all_materials: "Tous les matériaux"
load_next_projects: "Charger les projets suivants"
rough_draft: "Brouillon"
filter_by_member: "Filter par membre"
status_filter:
all_statuses: "Tous les statuts"
select_status: "Sélectionnez un statut"

View File

@ -697,6 +697,7 @@ en:
trainings_authorization_validity_duration: "Trainings validity period duration"
trainings_invalidation_rule: "Trainings automatic invalidation"
trainings_invalidation_rule_period: "Grace period before invalidating a training"
projects_list_member_filter_presence: "Presence of member filter on projects list"
#statuses of projects
statuses:
new: "New"

View File

@ -697,6 +697,7 @@ fr:
trainings_authorization_validity_duration: "Durée de la période de validité des formations"
trainings_invalidation_rule: "Invalidation automatique des formations"
trainings_invalidation_rule_period: "Période de grâce avant d'invalider une formation"
projects_list_member_filter_presence: "Présence du filtre par membre dans la vue liste des projets"
#statuses of projects
statuses:
new: "Nouveau"

View File

@ -728,3 +728,5 @@ Setting.set('accounting_Error_code', 'ERROR') unless Setting.find_by(name: 'acco
Setting.set('accounting_Error_label', 'Erroneous invoices to refund') unless Setting.find_by(name: 'accounting_Error_label').try(:value)
Setting.set('external_id', false) unless Setting.find_by(name: 'external_id').try(:value)
Setting.set('projects_list_member_filter_presence', false) unless Setting.find_by(name: 'projects_list_member_filter_presence')

View File

@ -852,3 +852,10 @@ history_value_100:
updated_at: 2023-04-05 09:16:08.000511500 Z
invoicing_profile_id: 1
history_value_103:
id: 103
setting_id: 102
value: 'false'
created_at: 2023-04-05 09:16:08.000511500 Z
updated_at: 2023-04-05 09:16:08.000511500 Z
invoicing_profile_id: 1

View File

@ -586,3 +586,9 @@ setting_99:
name: home_css
created_at: 2023-04-05 09:16:08.000511500 Z
updated_at: 2023-04-05 09:16:08.000511500 Z
setting_102:
id: 102
name: projects_list_member_filter_presence
created_at: 2023-04-05 09:16:08.000511500 Z
updated_at: 2023-04-05 09:16:08.000511500 Z

View File

@ -825,6 +825,12 @@ export const settings: Array<Setting> = [
value: 'https://www.sleede.com/',
last_update: '2022-12-23T14:39:12+0100',
localized: 'Url'
},
{
name: 'projects_list_member_filter_presence',
value: 'false',
last_update: '2022-12-23T14:39:12+0100',
localized: 'Projects list member filter presence'
}
];