1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-02-20 14:54:15 +01:00

(ui) Update layout

This commit is contained in:
vincent 2023-01-20 18:17:50 +01:00 committed by Sylvain
parent b9d86aecdc
commit 554ed083d0
9 changed files with 193 additions and 101 deletions

View File

@ -30,6 +30,7 @@ import ProductLib from '../../lib/product';
import { UIRouter } from '@uirouter/angularjs';
import SettingAPI from '../../api/setting';
import { SelectOption } from '../../models/select';
import { CaretDoubleUp } from 'phosphor-react';
declare const Application: IApplication;
@ -66,7 +67,6 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser, uiRouter
const [resources, setResources] = useImmer<ProductResourcesFetching>(storeInitialResources);
const [machinesModule, setMachinesModule] = useState<boolean>(false);
const [categoriesTree, setCategoriesTree] = useState<CategoryTree[]>([]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [filtersPanel, setFiltersPanel] = useState<boolean>(false);
const [pageCount, setPageCount] = useState<number>(0);
const [productsCount, setProductsCount] = useState<number>(0);
@ -241,11 +241,14 @@ const Store: React.FC<StoreProps> = ({ onError, onSuccess, currentUser, uiRouter
}
</ul>
<aside className={`store-filters ${filtersPanel ? '' : 'collapsed'}`}>
<header>
<h3>{t('app.public.store.products.filter_categories')}</h3>
<div className="grpBtn">
<CaretDoubleUp className='filters-toggle' size={16} weight="bold" onClick={() => setFiltersPanel(!filtersPanel)} />
</div>
</header>
<div className='grp'>
<div className="categories">
<header>
<h3>{t('app.public.store.products.filter_categories')}</h3>
</header>
<div className="group u-scrollbar">
{categoriesTree.map(c =>
<div key={c.parent.id} className={`parent ${selectedCategory?.id === c.parent.id || selectedCategory?.parent_id === c.parent.id ? 'is-active' : ''}`}>

View File

@ -103,7 +103,9 @@
@import "modules/profile-completion/completion-header-info";
@import "modules/profile-completion/profile-form-option";
@import "modules/profile-custom-fields/profile-custom-fields-list";
@import "modules/projects/project-card";
@import "modules/projects/projects-setting.scss";
@import "modules/projects/projects";
@import "modules/select-gateway-modal";
@import "modules/settings/boolean-setting";
@import "modules/settings/check-list-setting";

View File

@ -1,6 +1,6 @@
.machine-card {
background-color: #fff;
border: 1px solid #ddd;
background-color: var(--gray-soft-lightest);
border: 1px solid var(--gray-soft-dark);
border-radius: var(--border-radius);
position: relative;
overflow: hidden;

View File

@ -0,0 +1,48 @@
.project-card {
display: flex;
flex-direction: column;
background-color: var(--gray-soft-lightest);
border: 1px solid var(--gray-soft-dark);
border-radius: var(--border-radius);
overflow: hidden;
&:hover {
border-color: var(--gray-hard);
cursor: pointer;
}
.project-image {
@include imageRatio(50%);
background-size: cover;
background-position: center;
border-bottom: 1px solid var(--gray-soft-dark);
}
.project-info {
flex: 1;
position: relative;
padding: 1.6rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.4rem;
.badge {
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, -50%);
}
.name {
margin: 0;
font-size: 1.6rem;
text-transform: uppercase;
font-weight: 600;
text-align: center;
}
.openlab {
display: flex;
align-items: center;
gap: 0.8rem;
font-size: 1.2rem;
color: var(--main);
}
}
}

View File

@ -0,0 +1,47 @@
.projects {
max-width: calc(1600px + 6rem);
margin: 0 auto;
padding: 3rem 3rem 6rem;
display: grid;
grid-template-columns: 1fr;
align-items: flex-start;
gap: 2.4rem 3.2rem;
&-filters,
.grp {
display: flex;
flex-direction: column;
gap: 1.6rem;
header {
@include header();
padding-top: 0;
}
.switch {
display: flex;
justify-content: space-between;
}
.keywords {
display: flex;
input {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
button {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
}
&-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
gap: 3.2rem;
& > span { grid-column: 1/-1;}
}
@media (min-width: 1200px) {
grid-template-columns: 1fr 3fr;
&-list { grid-column: 2/-1; }
}
}

View File

@ -9,7 +9,7 @@
}
&.collapsed {
header .grpBtn svg { transform: rotateZ(-180deg); }
header .grpBtn .filters-toggle { transform: rotateZ(-180deg); }
header .grpBtn button { display: flex; }
.grp {
max-height: 100vh;
@ -26,7 +26,7 @@
display: flex;
align-items: center;
button { display: none; }
svg {
.filters-toggle {
cursor: pointer;
transition: transform 250ms ease-in-out;
}

View File

@ -63,6 +63,37 @@
line-height: 1.18;
}
@mixin header($sticky: false) {
padding: 2.4rem 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
@if $sticky {
position: sticky;
top: 0;
margin-top: 1px;
padding: 2.4rem 0 4rem;
background: linear-gradient(180deg, var(--gray-soft-lightest) 80%, transparent);
z-index: 1;
}
h2 {
margin: 0;
@include title-lg;
color: var(--gray-hard-darkest) !important;
}
h3 {
margin: 0;
@include text-lg(600);
color: var(--gray-hard-darkest) !important;
}
.grpBtn {
display: flex;
align-items: center;
gap: 1.6rem;
}
}
// Text Editor
@mixin editor {
*:first-child {

View File

@ -19,108 +19,70 @@
</div>
</section>
<section class="projects">
<div class="projects-filters">
<header>
<h3>Filter</h3>
<a href="javascript:void(0);" class="fab-button is-black" name="button" ng-click="resetFiltersAndTriggerSearch()" ng-show="!openlab.searchOverWholeNetwork">{{ 'app.public.projects_list.reset_all_filters' | translate }}</a>
</header>
<span class="switch" ng-if="openlab.projectsActive" uib-tooltip="{{ 'app.public.projects_list.tooltip_openlab_projects_switch' | translate }}" tooltip-trigger="mouseenter">
<label for="searchOverWholeNetwork" class="control-label text-sm" translate>{{ 'app.public.projects_list.network_search' }}</label>
<input bs-switch
ng-model="openlab.searchOverWholeNetwork"
type="checkbox"
class="form-control"
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
switch-off-text="{{ 'app.shared.buttons.no' | translate }}"
switch-animate="true"
ng-change="searchOverWholeNetworkChanged()"
/>
</span>
<section class="m-lg">
<div class="row m-b-md">
<div class="col-md-12 m-b">
<a href="javascript:void(0);" class="text-sm pull-right reinit-filters" name="button" ng-click="resetFiltersAndTriggerSearch()" ng-show="!openlab.searchOverWholeNetwork"><i class="fa fa-refresh"></i> {{ 'app.public.projects_list.reset_all_filters' | translate }}</a>
<form role="form" ng-submit="setUrlQueryParams(search) && triggerSearch()">
<div class="keywords">
<input type="search" class="form-control" placeholder="{{ 'app.public.projects_list.keywords' | translate }}" ng-model="search.q"/>
<button type="submit" class="fab-button fab-button--icon-only is-secondary"><i class="fas fa-search"></i></button>
<!--<button type="submit" class="btn btn-warning" translate>{{ 'app.public.projects_list.search' }}</button>-->
</div>
</form>
<span ng-if="openlab.projectsActive" uib-tooltip="{{ 'app.public.projects_list.tooltip_openlab_projects_switch' | translate }}" tooltip-trigger="mouseenter">
<label for="searchOverWholeNetwork" class="control-label m-r text-sm" translate>{{ 'app.public.projects_list.search_over_the_whole_network' }}</label>
<input bs-switch
ng-model="openlab.searchOverWholeNetwork"
type="checkbox"
class="form-control"
switch-on-text="{{ 'app.shared.buttons.yes' | translate }}"
switch-off-text="{{ 'app.shared.buttons.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="{{ 'app.public.projects_list.keywords' | translate }}" ng-model="search.q"/>
<div class="input-group-btn">
<button type="submit" class="btn btn-warning" translate>{{ 'app.public.projects_list.search' }}</button>
</div>
</div>
</div>
</form>
</div>
<div class="col-md-12" 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>{{ 'app.public.projects_list.all_projects' }}</option>
<option value="mine" translate>{{ 'app.public.projects_list.my_projects' }}</option>
<option value="collaboration" translate>{{ 'app.public.projects_list.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="setUrlQueryParams(search) && triggerSearch()" class="form-control" ng-options="m.id as m.name for m in machines">
<option value="" translate>{{ 'app.public.projects_list.all_machines' }}</option>
</select>
</div>
<div class="grp" ng-if="!openlab.searchOverWholeNetwork">
<select ng-show="isAuthenticated()" ng-model="search.from" ng-change="setUrlQueryParams(search) && triggerSearch()" class="form-control">
<option value="" translate>{{ 'app.public.projects_list.all_projects' }}</option>
<option value="mine" translate>{{ 'app.public.projects_list.my_projects' }}</option>
<option value="collaboration" translate>{{ 'app.public.projects_list.projects_to_whom_i_take_part_in' }}</option>
</select>
<div class="col-md-2 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>{{ 'app.public.projects_list.all_themes' }}</option>
</select>
</div>
<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>{{ 'app.public.projects_list.all_machines' }}</option>
</select>
<div class="col-md-2 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>{{ 'app.public.projects_list.all_materials' }}</option>
</select>
</div>
<div class="col-md-2 m-b">
<status-filter on-filter-change="onStatusChange" current-status-index="search.status_id"/>
</div>
<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>{{ 'app.public.projects_list.all_themes' }}</option>
</select>
<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>{{ 'app.public.projects_list.all_materials' }}</option>
</select>
<status-filter on-filter-change="onStatusChange" current-status-index="search.status_id"/>
</div>
</div>
<div class="row">
<span class="col-md-12" ng-show="projects && (projects.length == 0)"> {{ 'app.public.projects_list.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)">
<div class="card card-project">
<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:'Font Awesome 5 Free'/icon" bs-holder ng-if="!project.project_image">
</div>
<div class="projects-list">
<span ng-show="projects && (projects.length == 0)"> {{ 'app.public.projects_list.project_search_result_is_empty' | translate }} </span>
<div class="project-card" ng-repeat="project in projects" ng-click="showProject(project)">
<div class="project-image" style="background-image: url({{project.project_image}});">
<img src="data:image/png;base64," data-src="holder.js/100%x100%/text:&#xf03e;/font:'Font Awesome 5 Free'/icon" bs-holder ng-if="!project.project_image">
</div>
<div class="card-block">
<h3 class="card-meta" ng-if="openlab.searchOverWholeNetwork"><i class="fa fa-tag"></i> {{ project.app_name }}</h3>
<h1 class="card-title">{{project.name}}</h1>
</div>
<div class="text-center">
<div class="project-info">
<span class="badge" ng-if="project.state == 'draft'" translate>{{ 'app.public.projects_list.rough_draft' }}</span>
<p class="name">{{project.name}}</p>
<span class="openlab" ng-if="openlab.searchOverWholeNetwork"><i class="fa fa-tag"></i> {{ project.app_name }}</span>
</div>
<div class="card-overlay">
<div class="btn-group">
<div class="btn btn-default" ng-click="showProject(project)">
<i ng-class="{'fa fa-external-link' : (openlab.searchOverWholeNetwork && project.app_id != openlabAppId) }"></i> {{ 'app.shared.buttons.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="loadMore()" ng-if="projectsPagination.hasNextPage()" translate>{{ 'app.public.projects_list.load_next_projects' }}</a>
</div>
<a class="btn btn-warning" ng-click="loadMore()" ng-if="projectsPagination.hasNextPage()" translate>{{ 'app.public.projects_list.load_next_projects' }}</a>
</div>
</section>

View File

@ -169,13 +169,12 @@ en:
projects_list:
the_fablab_projects: "The projects"
add_a_project: "Add a project"
search_over_the_whole_network: "Search over the whole Fab-manager network"
network_search: "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."
reset_all_filters: "Reset all filters"
reset_all_filters: "Clear all"
keywords: "Keywords"
search: "Search"
all_projects: "All projects"
my_projects: "My projects"
projects_to_whom_i_take_part_in: "Projects to whom I take part in"