Skip to content

Commit

Permalink
Merge branch 'release/0.18.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
polosson committed Mar 28, 2022
2 parents f6efcd7 + 6de7f39 commit 061f197
Show file tree
Hide file tree
Showing 205 changed files with 6,119 additions and 3,677 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
- uses: actions/setup-node@v2
with: { node-version: '16' }
- run: yarn install --non-interactive --pure-lockfile
- run: yarn lint:js --max-warnings 29 --color
- run: yarn lint:js --max-warnings 26 --color

client-linting-scss:
name : "Client: Linting (SCSS)"
Expand Down Expand Up @@ -68,7 +68,7 @@ jobs:
runs-on : ubuntu-latest
strategy :
matrix:
php: [7.3, 7.4, 8.0]
php: [7.4, 8.0]
defaults : { run: { working-directory: ./server }}
services :
mysql:
Expand Down
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ Tous les changements notables sur le projet sont documentés dans ce fichier.

Ce projet adhère au principe du [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## 0.18.0 (2022-03-28)

- __[CHANGEMENT CRITIQUE]__ Robert2 requiert maintenant au minimum PHP 7.4 pour fonctionner (#327).
- Augmente la taille du champ `degressive_rate` des tables `bills` et `estimates` pour qu'il accepte une valeur jusqu'à 99999,99 (quand un événement est très long), au lieu de juste 99,99 (#329).
- Ajoute la possibilité de configurer les données affichées dans les événements du calendrier
via la page des paramètres de l'application (fin du ticket #302).
- Il est maintenant possible de s'abonner depuis votre application de calendrier préférée (Google Agenda, Apple Calendrier, etc.) au calendrier Robert2 / Loxya.
Pour plus d'informations, rendez-vous dans les paramètres de votre instance Robert2 / Loxya, onglet "Calendrier" (#326).
- Corrige un problème de formatage des données de configuration lors de l'installation (#100).
- Ajoute une limite de taille des fichiers uploadés dans la configuration générale (valeur par défaut 25 Mo) (#332).
- Ouvre le détail du matériel au clic sur son nom ou sa référence dans la liste (#331).
- Sur la fiche de sortie, supprime la mention inutile "autre matériel" de la liste du matériel triée par sous-catégories, quand la catégorie n'a aucune sous-catégorie (#319).
- Sur la fiche de sortie, affiche l'adresse de la société du bénéficiaire (si elle existe), à la place de celle de la personne (#341).
- Enlève la possibilité de trier sur la colonne "quantité restante" dans la liste du matériel (#324).
- Corrige le comportement du sélecteur de la société associée au bénéficiaire, dans le formulaire d'édition, pour qu'il fonctionne avec un grand nombre de sociétés existantes (#340).
- Corrige le tri des bénéficiaires par nom de la société (#342).
- Corrige le problème de rafraîchissement du calcul du matériel disponible après changement des quantités dans l'édition des événements (#348).
- Conserve la sélection des colonnes affichées dans les listings, même après un rechargement de la page (#144).

## 0.17.1 (2022-01-06)

- Corrige l'erreur de l'étape 5 du wizard d'installation (double boot du kernel).
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.17.1
0.18.0
8 changes: 8 additions & 0 deletions client/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ module.exports = {
},
},
},

// - Overrides
overrides: [
{
files: ['**/*.tsx'],
extends: '@pulsanova/react',
},
],
};
12 changes: 11 additions & 1 deletion client/babel.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
module.exports = {
presets: [
'vca-jsx',
'@vue/cli-plugin-babel/preset',
'@vue/babel-preset-app',
'@babel/preset-typescript',
],
overrides: [
{
include: './**/*.tsx',
presets: [
['@vue/babel-preset-app', { jsx: false }],
['@babel/preset-react', { runtime: 'automatic' }],
'@babel/preset-typescript',
],
},
],
};
19 changes: 13 additions & 6 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@
"deep-freeze-strict": "1.1.1",
"invariant": "2.2.4",
"js-cookie": "2.2.1",
"lodash.pick": "4.4.0",
"lodash.times": "4.3.2",
"lodash": "^4.17.21",
"moment": "2.29.1",
"react": "17.0.2",
"react-dom": "17.0.2",
"sweetalert2": "11.0.20",
"v-tooltip": "2.1.3",
"vue": "2.6.14",
"vue-click-outside": "1.1.0",
"vue-fragment": "1.5.2",
"vue-fragment": "1.5.1",
"vue-js-modal": "2.0.0-rc.6",
"vue-query": "1.11.0",
"vue-router": "3.5.2",
Expand All @@ -40,11 +41,17 @@
},
"devDependencies": {
"@babel/core": "7.14.8",
"@babel/preset-react": "7.16.7",
"@babel/preset-typescript": "7.15.0",
"@pulsanova/eslint-config-vue": "2.0.4",
"@pulsanova/eslint-config-react": "2.1.2",
"@pulsanova/eslint-config-vue": "2.1.2",
"@pulsanova/stylelint-config-scss": "2.0.1",
"@types/debounce": "1.2.1",
"@types/lodash.times": "4.3.6",
"@types/debounce": "1.2",
"@types/invariant": "2.2",
"@types/lodash": "^4.14.178",
"@types/react": "17.0",
"@types/react-dom": "17.0",
"@vue/babel-preset-app": "4.5.15",
"@vue/cli-plugin-babel": "4.5.13",
"@vue/cli-plugin-typescript": "4.5.13",
"@vue/cli-plugin-unit-jest": "4.5.13",
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Alert/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const ConfirmDelete = ($t, entityName, isSoft = true) => Swal.fire({
icon: 'warning',
showCancelButton: true,
customClass: {
confirmButton: isSoft ? 'swal2-confirm--trash' : 'swal2-confirm--delete',
confirmButton: isSoft ? 'swal2-confirm--warning' : 'swal2-confirm--danger',
},
confirmButtonText: isSoft ? $t('yes-delete') : $t('yes-permanently-delete'),
cancelButtonText: $t('cancel'),
Expand Down
42 changes: 18 additions & 24 deletions client/src/components/App/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import './index.scss';
import { ref, computed, watch } from '@vue/composition-api';
import queryClient from '@/globals/queryClient';
import useRouter from '@/hooks/useRouter';
import invariant from 'invariant';
import { useQueryProvider } from 'vue-query';
import Header from '@/components/MainHeader';
import Sidebar from '@/components/Sidebar';
import { computed, watch } from '@vue/composition-api';
import queryClient from '@/globals/queryClient';
import useRouter from '@/hooks/vue/useRouter';
import layouts from '@/layouts';

// @vue/component
const App = (props, { root }) => {
const isOpenedSidebar = ref(false);
const isLogged = computed(() => root.$store.getters['auth/isLogged']);
const { route } = useRouter();
useQueryProvider(queryClient);
const { route } = useRouter();
const layout = computed(() => {
const routeMeta = route.value?.meta;
return routeMeta?.layout ?? 'default';
});

// - Configure Axios pour qu'il redirige en cas de soucis de connexion lors des requêtes API.
root.$http.interceptors.response.use((response) => response, (error) => {
Expand All @@ -28,23 +29,16 @@ const App = (props, { root }) => {
// - "Cache" les modales ouvertes entre deux changements de page.
watch(route, () => { root.$modal.hideAll(); });

const handleToggleSidebar = (isOpen) => {
if (isOpen === 'toggle') {
isOpenedSidebar.value = !isOpenedSidebar.value;
return;
}
isOpenedSidebar.value = isOpen;
};
return () => {
invariant(layout.value in layouts, `The "${layout}" layout doesn't exist.`);
const Layout = layouts[layout.value];

return () => (
<div class="App">
{isLogged.value && <Header onToggleMenu={handleToggleSidebar} />}
<div class="App__body">
{isLogged.value && <Sidebar isOpen={isOpenedSidebar.value} />}
return (
<Layout>
<router-view key={route.value.path} />
</div>
</div>
);
</Layout>
);
};
};

export default App;
71 changes: 71 additions & 0 deletions client/src/components/Button/_variables.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@use '~@/style/globals';
@use 'sass:color';

/// Marge entre l'icône et le texte des boutons (quand il y en a une, d'icône)
/// @type Number
$icon-margin: 0.3571rem !default;

//
// - Default variant
//

$default-color: globals.$color-base-button !default;
$default-background: globals.$bg-color-button-default !default;

$default-focused-color: color.adjust(globals.$bg-color-button-default, $lightness: 8%) !default;
$default-focused-background: globals.$color-hover-button !default;

$default-active-color: color.adjust(globals.$bg-color-button-default, $lightness: -8%) !default;
$default-active-background: globals.$color-active-button !default;

//
// - Primary variant
//

$primary-variant-color: #fff !default;
$primary-variant-background: #c35022 !default;

$primary-variant-focused-color: $primary-variant-color !default;
$primary-variant-focused-background: color.adjust(#e14407, $lightness: 5%) !default;

$primary-variant-active-color: $primary-variant-color !default;
$primary-variant-active-background: color.adjust(#e14407, $lightness: -5%) !default;

//
// - Success variant
//

$success-variant-color: #fff !default;
$success-variant-background: globals.$bg-color-button-success !default;

$success-variant-focused-color: $success-variant-color !default;
$success-variant-focused-background: color.adjust(globals.$bg-color-button-success, $lightness: 5%) !default;

$success-variant-active-color: globals.$color-active-button !default;
$success-variant-active-background: color.adjust(globals.$bg-color-button-success, $lightness: -5%) !default;

//
// - Warning variant
//

$warning-variant-color: #fff !default;
$warning-variant-background: #be692d !default;

$warning-variant-focused-color: $warning-variant-color !default;
$warning-variant-focused-background: color.adjust(#be692d, $lightness: 8%) !default;

$warning-variant-active-color: globals.$color-active-button !default;
$warning-variant-active-background: color.adjust(#be692d, $lightness: 8%) !default;

//
// - Danger variant
//

$danger-variant-color: #fff !default;
$danger-variant-background: globals.$bg-color-button-danger !default;

$danger-variant-focused-color: $danger-variant-color !default;
$danger-variant-focused-background: color.adjust(globals.$bg-color-button-danger, $lightness: 8%) !default;

$danger-variant-active-color: globals.$color-active-button !default;
$danger-variant-active-background: color.adjust(globals.$bg-color-button-danger, $lightness: -8%) !default;
97 changes: 97 additions & 0 deletions client/src/components/Button/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import './index.scss';
import { toRefs, computed } from '@vue/composition-api';
import { Fragment } from 'vue-fragment';
import Icon from '@/components/Icon';

const BUTTON_TYPE = ['default', 'success', 'warning', 'danger', 'primary'];

// @vue/component
const Button = (props, { slots, emit }) => {
const { htmlType, icon, disabled, type, to, loading } = toRefs(props);
const _icon = computed(() => {
if (!icon.value) {
return null;
}

if (loading.value) {
return { name: 'spinner', spin: true };
}

if (!icon.value.includes(':')) {
return { name: icon.value };
}

const [iconType, variant] = icon.value.split(':');
return { name: iconType, variant };
});

const _className = computed(() => [
'Button',
`Button--${type.value}`, {
'Button--disabled': disabled.value || loading.value,
'Button--loading': loading.value,
'Button--with-icon': !!_icon,
},
]);

return () => {
const children = slots.default?.();

const content = (
<Fragment>
{_icon.value && <Icon {...{ props: _icon.value }} class="Button__icon" />}
{children && <span class="Button__content">{children}</span>}
</Fragment>
);

if (to.value && !disabled.value) {
return (
<router-link to={to.value} custom>
{({ href, navigate: handleClick }) => (
<a href={href} onClick={handleClick} class={_className.value}>
{content}
</a>
)}
</router-link>
);
}

return (
<button
// eslint-disable-next-line react/button-has-type
type={htmlType.value}
class={_className.value}
disabled={disabled.value || loading.value}
onClick={emit.bind(null, 'click')}
>
{content}
</button>
);
};
};

Button.props = {
htmlType: {
default: 'button',
validator: (value) => (
typeof value === 'string' &&
['button', 'submit', 'reset'].includes(value)
),
},
type: {
type: String,
validator: (value) => BUTTON_TYPE.includes(value),
default: 'default',
},
to: {
type: [String, Object],
default: undefined,
},
icon: { type: String, default: undefined },
loading: { type: Boolean, default: false },
disabled: { type: Boolean, default: false },
};

Button.emits = ['click'];

export default Button;
Loading

0 comments on commit 061f197

Please sign in to comment.