From c4dc2adcea71c27118269563e377eb019f7d8609 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 24 Apr 2019 12:33:24 +0200 Subject: [PATCH 1/2] Add new type de champ after type de champ on screen --- .../components/TypeDeChamp.js | 9 ++- .../TypeDeChampRepetitionOptions.js | 8 +-- .../components/TypeDeChamps.js | 4 +- .../TypesDeChampEditor/typeDeChampsReducer.js | 55 +++++++++++++++++-- package.json | 1 + yarn.lock | 15 +++++ 6 files changed, 76 insertions(+), 16 deletions(-) diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js index 9038a1424..751f7702b 100644 --- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js +++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js @@ -1,6 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { sortableElement, sortableHandle } from 'react-sortable-hoc'; +import { useInView } from 'react-intersection-observer'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import DescriptionInput from './DescriptionInput'; @@ -29,6 +30,10 @@ const TypeDeChamp = sortableElement( const canBeMandatory = !isHeaderSection && !isExplication && !state.isAnnotation; + const [ref, inView] = useInView({ + threshold: [0.6] + }); + const updateHandlers = createUpdateHandlers( dispatch, typeDeChamp, @@ -42,8 +47,10 @@ const TypeDeChamp = sortableElement( return (
{ + .then(async () => { + if (insertAfter) { + // Move the champ to the correct position server-side + await moveTypeDeChampOperation( + typeDeChamp, + insertAfter.index, + state.queue + ); + } state.flash.success(); done(); - if (state.lastTypeDeChampRef) { - scrollToComponent(state.lastTypeDeChampRef.current); + if (insertAfter) { + scrollToComponent(insertAfter.target.nextElementSibling); } }) .catch(message => state.flash.error(message)); + let newTypeDeChamps = [...typeDeChamps, typeDeChamp]; + if (insertAfter) { + // Move the champ to the correct position client-side + newTypeDeChamps = arrayMove( + newTypeDeChamps, + typeDeChamps.length, + insertAfter.index + ); + } + return { ...state, - typeDeChamps: [...typeDeChamps, typeDeChamp] + typeDeChamps: newTypeDeChamps }; } +function addNewTypeDeChamp(state, typeDeChamps, done) { + return addTypeDeChamp(state, typeDeChamps, findItemToInsertAfter(), done); +} + function addNewRepetitionTypeDeChamp(state, typeDeChamps, typeDeChamp, done) { - return addNewTypeDeChamp( + return addTypeDeChamp( { ...state, defaultTypeDeChampAttributes: { @@ -69,6 +91,7 @@ function addNewRepetitionTypeDeChamp(state, typeDeChamps, typeDeChamp, done) { } }, typeDeChamps, + null, done ); } @@ -182,3 +205,23 @@ function getUpdateHandler(typeDeChamp, { queue, flash }) { } return handler; } + +function findItemToInsertAfter() { + const target = getFirstTarget(); + + return { + target, + index: parseInt(target.dataset.index) + 1 + }; +} + +function getFirstTarget() { + const [target] = document.querySelectorAll('[data-in-view]'); + if (target) { + const parentTarget = target.closest('[data-repetition]'); + if (parentTarget) { + return parentTarget; + } + return target; + } +} diff --git a/package.json b/package.json index 61fbe0f21..6336280f1 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "ramda": "=0.24.1", "react": "^16.8.6", "react-dom": "^16.8.6", + "react-intersection-observer": "^8.23.0", "react-scroll-to-component": "^1.0.2", "react-sortable-hoc": "^1.7.1", "react_ujs": "^2.5.0", diff --git a/yarn.lock b/yarn.lock index 1b9ccd07f..c63e659d9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -688,6 +688,13 @@ "@babel/plugin-transform-react-jsx-self" "^7.0.0" "@babel/plugin-transform-react-jsx-source" "^7.0.0" +"@babel/runtime@^7.0.0": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.4.tgz#dc2e34982eb236803aa27a07fea6857af1b9171d" + integrity sha512-w0+uT71b6Yi7i5SE0co4NioIpSYS6lLiXvCzWzGSKvpK5vdQtCbICHMj+gbAKAOtxiV6HsVh/MBdaF9EQ6faSg== + dependencies: + regenerator-runtime "^0.13.2" + "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" @@ -6737,6 +6744,14 @@ react-dom@^16.8.6: prop-types "^15.6.2" scheduler "^0.13.6" +react-intersection-observer@^8.23.0: + version "8.23.0" + resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.23.0.tgz#1533aaf39cc70300ff8ca37e6551d2d68a589cd0" + integrity sha512-kHXfxhGKvVDNkrvmh9CKCnAWvJBigyB7oSDzMXL54weFDwwI4WfTr58YauZ0RRPkGzoD/hYEuzfS1wipXn23fA== + dependencies: + "@babel/runtime" "^7.0.0" + invariant "^2.2.4" + react-is@^16.8.1: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" From c93b1bb2769079ad2f60f240572a52af80813229 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Wed, 24 Apr 2019 13:17:05 +0200 Subject: [PATCH 2/2] Add intersection-observer polyfill --- app/javascript/shared/polyfills.js | 4 ++++ package.json | 1 + yarn.lock | 11 ++++++++--- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/javascript/shared/polyfills.js b/app/javascript/shared/polyfills.js index a19bbef8c..91124f495 100644 --- a/app/javascript/shared/polyfills.js +++ b/app/javascript/shared/polyfills.js @@ -5,3 +5,7 @@ import '@babel/polyfill'; import 'dom4'; import './polyfills/insertAdjacentElement'; import './polyfills/dataset'; + +if (typeof window.IntersectionObserver === 'undefined') { + import('intersection-observer'); +} diff --git a/package.json b/package.json index 6336280f1..22dbdf814 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "debounce": "^1.2.0", "dom4": "^2.1.4", "highcharts": "^6.1.2", + "intersection-observer": "^0.6.0", "jquery": "^3.4.1", "leaflet": "^1.4.0", "leaflet-freedraw": "^2.10.0", diff --git a/yarn.lock b/yarn.lock index c63e659d9..c54641d3f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4173,9 +4173,14 @@ internal-ip@^4.2.0: ipaddr.js "^1.9.0" interpret@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" + integrity sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ= + +intersection-observer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.6.0.tgz#d64aae04211b4cec051537168f5fa670a4acc770" + integrity sha512-WUVAqGJr08yh73XKe1JhylQ9BiBIytrkt8SH5Knu7Uy44ij5cICi6PbVLIbV/D2eIx9LJVkGBo9WF80R4VXJ+w== invariant@^2.2.2, invariant@^2.2.4: version "2.2.4"