commit
ae5ed9af88
9 changed files with 102 additions and 51 deletions
1
app/assets/images/icons/move-handle.svg
Normal file
1
app/assets/images/icons/move-handle.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" data-prefix="fas" data-icon="arrows-alt-v" class="svg-inline--fa fa-arrows-alt-v fa-w-8 fa-lg" width="32" height="32"><path d="M19.04 20.763h-1.656v-9.526h1.656c.768 0 2.494.242.61-1.6l-3.094-3.362a.815.815 0 0 0-1.22 0l-3.093 3.361c-1.643 1.831-.159 1.6.61 1.6h1.655v9.527h-1.655c-.769 0-2.235-.244-.61 1.6l3.093 3.362a.815.815 0 0 0 1.22 0l3.094-3.361c1.884-1.795.158-1.6-.61-1.6z" fill="currentColor"/><rect width="9" height="2" y="11" ry=".402"/><rect ry=".402" y="19" height="2" width="9"/><rect width="9" height="2" y="15" ry=".402"/><rect ry=".402" y="11" x="23" height="2" width="9"/><rect width="9" height="2" x="23" y="19" ry=".402"/><rect ry=".402" y="15" x="23" height="2" width="9"/></svg>
|
After Width: | Height: | Size: 761 B |
|
@ -131,4 +131,8 @@
|
||||||
&.delete {
|
&.delete {
|
||||||
background-image: image-url("icons/trash.svg");
|
background-image: image-url("icons/trash.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.move-handle {
|
||||||
|
background-image: image-url("icons/move-handle.svg");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,64 @@
|
||||||
@import "constants";
|
@import "constants";
|
||||||
|
|
||||||
.type-de-champ {
|
.type-de-champ {
|
||||||
background-color: $white;
|
width: 100%;
|
||||||
|
background-color: #FAFDFF;
|
||||||
border: 1px solid $border-grey;
|
border: 1px solid $border-grey;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
margin-bottom: 10px;
|
margin-bottom: $default-padding * 2;
|
||||||
width: 100%;
|
box-shadow: 0px 2px 4px -4px;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.handle {
|
.handle.icon {
|
||||||
cursor: ns-resize;
|
width: 32px;
|
||||||
margin-right: 10px;
|
height: 32px;
|
||||||
|
background-size: 32px;
|
||||||
|
margin-left: 7px;
|
||||||
|
margin-right: 16px;
|
||||||
|
align-self: center;
|
||||||
|
cursor: grab;
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.move {
|
.move {
|
||||||
|
height: 44px;
|
||||||
|
border-radius: 25px;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
margin-bottom: 5px;
|
|
||||||
|
&:first-of-type {
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-of-type {
|
||||||
|
border-top-left-radius: 0;
|
||||||
|
border-top-right-radius: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
background-color: #D9ECFF;
|
||||||
|
|
||||||
|
select {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.type-header-section {
|
&.type-header-section {
|
||||||
|
&,
|
||||||
|
.head {
|
||||||
background-color: $blue;
|
background-color: $blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head .icon {
|
||||||
|
filter: contrast(0%) brightness(200%);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
color: $light-grey;
|
color: $light-grey;
|
||||||
|
@ -36,6 +76,7 @@
|
||||||
border-bottom: 1px solid $border-grey;
|
border-bottom: 1px solid $border-grey;
|
||||||
|
|
||||||
&.head {
|
&.head {
|
||||||
|
border-bottom: 1px solid #D4E5F5;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,12 +85,6 @@
|
||||||
margin-left: 55px;
|
margin-left: 55px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.head {
|
|
||||||
select {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.delete {
|
&.delete {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -88,21 +123,24 @@
|
||||||
|
|
||||||
.champs-editor {
|
.champs-editor {
|
||||||
.footer {
|
.footer {
|
||||||
margin-bottom: 40px;
|
margin-bottom: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin: 0px;
|
margin-left: -30px;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0px;
|
bottom: 0px;
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
max-width: $page-width;
|
max-width: 1100px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid $border-grey;
|
border: 1px solid $border-grey;
|
||||||
padding: 10px;
|
padding: 30px;
|
||||||
border-top-left-radius: 5px;
|
border-top-left-radius: 5px;
|
||||||
border-top-right-radius: 5px;
|
border-top-right-radius: 5px;
|
||||||
|
border-bottom: none;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
padding-top: 15px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,23 @@ import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
function MoveButton({ isVisible, icon, onClick }) {
|
function MoveButton({ isEnabled, icon, title, onClick }) {
|
||||||
if (isVisible) {
|
|
||||||
return (
|
return (
|
||||||
<button className="button small icon-only move" onClick={onClick}>
|
<button
|
||||||
|
className="button small icon-only move"
|
||||||
|
disabled={!isEnabled}
|
||||||
|
title={title}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
<FontAwesomeIcon icon={icon} />
|
<FontAwesomeIcon icon={icon} />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveButton.propTypes = {
|
MoveButton.propTypes = {
|
||||||
isVisible: PropTypes.bool,
|
isEnabled: PropTypes.bool,
|
||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
onClick: PropTypes.func
|
onClick: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -76,8 +76,9 @@ const TypeDeChamp = sortableElement(
|
||||||
>
|
>
|
||||||
<div className="flex column justify-start">
|
<div className="flex column justify-start">
|
||||||
<MoveButton
|
<MoveButton
|
||||||
isVisible={!isFirstItem}
|
isEnabled={!isFirstItem}
|
||||||
icon="arrow-up"
|
icon="arrow-up"
|
||||||
|
title="Déplacer le champ vers le haut"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'moveTypeDeChampUp',
|
type: 'moveTypeDeChampUp',
|
||||||
|
@ -86,8 +87,9 @@ const TypeDeChamp = sortableElement(
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<MoveButton
|
<MoveButton
|
||||||
isVisible={!isLastItem}
|
isEnabled={!isLastItem}
|
||||||
icon="arrow-down"
|
icon="arrow-down"
|
||||||
|
title="Déplacer le champ vers le bas"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'moveTypeDeChampDown',
|
type: 'moveTypeDeChampDown',
|
||||||
|
@ -162,9 +164,10 @@ TypeDeChamp.propTypes = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const DragHandle = sortableHandle(() => (
|
const DragHandle = sortableHandle(() => (
|
||||||
<div className="handle button small icon-only">
|
<div
|
||||||
<FontAwesomeIcon icon="arrows-alt-v" size="lg" />
|
className="handle small icon-only icon move-handle"
|
||||||
</div>
|
title="Déplacer le champ vers le haut ou vers le bas"
|
||||||
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
function createUpdateHandler(dispatch, typeDeChamp, field, index, prefix) {
|
function createUpdateHandler(dispatch, typeDeChamp, field, index, prefix) {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useReducer, useRef } from 'react';
|
import React, { useReducer, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import { SortableContainer, addChampLabel } from '../utils';
|
import { SortableContainer, addChampLabel } from '../utils';
|
||||||
import TypeDeChamp from './TypeDeChamp';
|
import TypeDeChamp from './TypeDeChamp';
|
||||||
|
@ -46,6 +47,8 @@ function TypeDeChampRepetitionOptions({
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<FontAwesomeIcon icon="plus" size="sm" />
|
||||||
|
|
||||||
{addChampLabel(state.isAnnotation)}
|
{addChampLabel(state.isAnnotation)}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import React, { useReducer, useRef } from 'react';
|
import React, { useReducer, useRef } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
|
||||||
import { SortableContainer, addChampLabel } from '../utils';
|
import { SortableContainer, addChampLabel } from '../utils';
|
||||||
import TypeDeChamp from './TypeDeChamp';
|
import TypeDeChamp from './TypeDeChamp';
|
||||||
|
@ -51,6 +52,8 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
<FontAwesomeIcon icon="plus" size="sm" />
|
||||||
|
|
||||||
{addChampLabel(state.isAnnotation)}
|
{addChampLabel(state.isAnnotation)}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
faArrowDown,
|
faArrowDown,
|
||||||
faArrowsAltV,
|
faArrowsAltV,
|
||||||
faArrowUp,
|
faArrowUp,
|
||||||
|
faPlus,
|
||||||
faTrash
|
faTrash
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
@ -12,32 +13,26 @@ import Flash from './Flash';
|
||||||
import OperationsQueue from './OperationsQueue';
|
import OperationsQueue from './OperationsQueue';
|
||||||
import TypeDeChamps from './components/TypeDeChamps';
|
import TypeDeChamps from './components/TypeDeChamps';
|
||||||
|
|
||||||
library.add(faArrowDown, faArrowsAltV, faArrowUp, faTrash);
|
library.add(faArrowDown, faArrowsAltV, faArrowUp, faPlus, faTrash);
|
||||||
|
|
||||||
class TypesDeChampEditor extends Component {
|
class TypesDeChampEditor extends Component {
|
||||||
constructor({
|
constructor(props) {
|
||||||
baseUrl,
|
super(props);
|
||||||
typeDeChampsTypes,
|
|
||||||
directUploadUrl,
|
|
||||||
isAnnotation,
|
|
||||||
typeDeChamps
|
|
||||||
}) {
|
|
||||||
super({ typeDeChamps });
|
|
||||||
const defaultTypeDeChampAttributes = {
|
const defaultTypeDeChampAttributes = {
|
||||||
type_champ: 'text',
|
type_champ: 'text',
|
||||||
types_de_champ: [],
|
types_de_champ: [],
|
||||||
private: isAnnotation,
|
private: props.isAnnotation,
|
||||||
libelle: `${isAnnotation ? 'Nouvelle annotation' : 'Nouveau champ'} ${
|
libelle: `${
|
||||||
typeDeChampsTypes[0][0]
|
props.isAnnotation ? 'Nouvelle annotation' : 'Nouveau champ'
|
||||||
}`
|
} ${props.typeDeChampsTypes[0][0]}`
|
||||||
};
|
};
|
||||||
this.state = {
|
this.state = {
|
||||||
flash: new Flash(isAnnotation),
|
flash: new Flash(props.isAnnotation),
|
||||||
queue: new OperationsQueue(baseUrl),
|
queue: new OperationsQueue(props.baseUrl),
|
||||||
defaultTypeDeChampAttributes,
|
defaultTypeDeChampAttributes,
|
||||||
typeDeChampsTypes,
|
typeDeChampsTypes: props.typeDeChampsTypes,
|
||||||
directUploadUrl,
|
directUploadUrl: props.directUploadUrl,
|
||||||
isAnnotation
|
isAnnotation: props.isAnnotation
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
%span.icon.phone
|
%span.icon.phone
|
||||||
%span.icon.clock
|
%span.icon.clock
|
||||||
%span.icon.download
|
%span.icon.download
|
||||||
|
%span.icon.move-handle
|
||||||
%span.icon.frown
|
%span.icon.frown
|
||||||
%span.icon.meh
|
%span.icon.meh
|
||||||
%span.icon.smile
|
%span.icon.smile
|
||||||
|
|
Loading…
Reference in a new issue