branch feature/component_choice_editor updated (f04ec38 -> 1bad9bf)
This is an automated email from the git hooks/post-receive script. New change to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git omits f04ec38 ajout de la description omits 331303d gestion de l'édition des choix de type resource omits 97d6722 - enrgistrement des choix de type date, datetime et resource - affichage des choix de types resources omits 8463c37 modification du parsing des dates : maintenant on attend le timestamp pour les types date et datetime omits 42a357e - ajout du type datetime dans le modele pour les choix - utilisation du composant de choix dans le formulaire - utilisation des input de type date et time quand supportés omits c302749 debut du composant d'édition de choix adds 729b8a0 enregistrement du la connexion dans le cooki du navigateur adds 8fcff27 Merge branch 'feature/save-login-in-cookie' into 'develop' adds 77b9935 correction dépendance de la session adds a6a1d68 back: remove ui urls from conf adds 9fcf2f6 ajout des urls dans l'uicontext adds 46a5188 ajout d'une fxiture de pollenuicontext adds a3b0092 Merge branch 'feature/delete_ui_url_in_back_conf' into 'develop' adds 36e2bfc Adaptation de l'écran de votes adds 8064e2b fix js conf adds 14536b4 Merge branch 'feature/votes-screen' into 'develop' new 23a5ddb debut du composant d'édition de choix new d94a8fa - ajout du type datetime dans le modele pour les choix - utilisation du composant de choix dans le formulaire - utilisation des input de type date et time quand supportés new 177e153 modification du parsing des dates : maintenant on attend le timestamp pour les types date et datetime new 38c722b - enrgistrement des choix de type date, datetime et resource - affichage des choix de types resources new 8f6b10d gestion de l'édition des choix de type resource new 1fd5df6 ajout de la description new 1bad9bf gestion des images This update added new revisions after undoing existing revisions. That is to say, some revisions that were in the old version of the branch are not in the new version. This situation occurs when a user --force pushes a change and generates a repository containing something like this: * -- * -- B -- O -- O -- O (f04ec38) \ N -- N -- N refs/heads/feature/component_choice_editor (1bad9bf) You should already have received notification emails for all of the O revisions, and so the following emails describe only the N revisions from the common base, B. Any revisions marked "omits" are not gone; other references still refer to them. Any revisions marked "discards" are gone forever. The 7 revisions listed above as "new" are entirely new to this repository and will be described in separate emails. The revisions listed as "adds" were already present in the repository and have only been added to this reference. Detailed log of new commits: commit 1bad9bfdea6777c68dae5d0cf49e3fee041aaadd Author: Kevin Morin <morin@codelutin.com> Date: Fri Mar 10 17:17:06 2017 +0100 gestion des images commit 1fd5df63ccbbd27f383a8c30aa80e240871457a7 Author: Kevin Morin <morin@codelutin.com> Date: Fri Mar 10 16:43:30 2017 +0100 ajout de la description commit 8f6b10d98ca302bba6a8a4b86ff9db57cb1dbd56 Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 17:11:41 2017 +0100 gestion de l'édition des choix de type resource commit 38c722b57699ee42e4fed86a84339e6b2e4fb7ab Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 16:42:57 2017 +0100 - enrgistrement des choix de type date, datetime et resource - affichage des choix de types resources commit 177e15358643effc741e0103222ec61b9d01bb1c Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 16:38:00 2017 +0100 modification du parsing des dates : maintenant on attend le timestamp pour les types date et datetime commit d94a8fac7409b17638c0ef37ac1aa2f1d5bce0b2 Author: Kevin Morin <morin@codelutin.com> Date: Tue Mar 7 18:13:40 2017 +0100 - ajout du type datetime dans le modele pour les choix - utilisation du composant de choix dans le formulaire - utilisation des input de type date et time quand supportés commit 23a5ddbf31b35500d808ce205545f4a8114f2263 Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 2 18:29:54 2017 +0100 debut du composant d'édition de choix Summary of changes: .../org/chorem/pollen/rest/api/v1/PollApi.java | 10 +- .../org/chorem/pollen/rest/api/PollApiTest.java | 3 + pollen-services/src/main/config/PollenServices.ini | 30 - .../org/chorem/pollen/services/PollenFixtures.java | 1 + .../chorem/pollen/services/PollenUIContext.java | 31 + .../pollen/services/service/FixturesService.java | 2 +- .../services/service/NotificationService.java | 8 +- .../pollen/services/service/PollService.java | 9 +- .../services/service/PollenUIUrlRenderService.java | 74 ++- .../pollen/services/service/mail/EmailService.java | 78 +-- pollen-services/src/main/resources/fixtures.yaml | 8 + .../pollen/services/service/PollServiceTest.java | 13 +- .../service/PollenUIUrlRenderServiceTest.java | 48 +- .../services/service/VoteCountingServiceTest.java | 3 +- .../services/service/VoterListServiceTest.java | 5 +- pollen-ui-riot-js/src/main/web/i18n.json | 25 +- pollen-ui-riot-js/src/main/web/js/AuthService.js | 15 +- pollen-ui-riot-js/src/main/web/js/FetchService.js | 10 +- pollen-ui-riot-js/src/main/web/js/Poll.js | 189 ++++++ pollen-ui-riot-js/src/main/web/js/Session.js | 52 +- pollen-ui-riot-js/src/main/web/tag/Header.tag.html | 4 +- pollen-ui-riot-js/src/main/web/tag/Home.tag.html | 9 +- pollen-ui-riot-js/src/main/web/tag/SignIn.tag.html | 7 +- .../src/main/web/tag/poll/Choice.tag.html | 2 - .../src/main/web/tag/poll/Comments.tag.html | 403 ++++++------ .../src/main/web/tag/poll/CreatePoll.tag.html | 2 +- .../src/main/web/tag/poll/Poll.tag.html | 253 ++------ .../src/main/web/tag/poll/Results.tag.html | 113 ++-- .../src/main/web/tag/poll/Votes.tag.html | 708 +++++++++------------ 29 files changed, 1035 insertions(+), 1080 deletions(-) create mode 100644 pollen-ui-riot-js/src/main/web/js/Poll.js -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 23a5ddbf31b35500d808ce205545f4a8114f2263 Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 2 18:29:54 2017 +0100 debut du composant d'édition de choix --- pollen-ui-riot-js/src/main/web/css/main.css | 3 +- .../src/main/web/tag/poll/ChoiceImage.tag.html | 77 ++++++++++++++++++++++ .../src/main/web/tag/poll/Choices.tag.html | 1 + 3 files changed, 79 insertions(+), 2 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/main.css index 0032f71..d51671a 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -62,8 +62,7 @@ input, textarea { .body-container { display: flex; - flex-flow: row wrap; - flex-direction: column; + flex-flow: column wrap; margin-left: auto; diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html new file mode 100644 index 0000000..cd180bc --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html @@ -0,0 +1,77 @@ +<ChoiceImage> + <div id="choice-container"> + <span class="button" alt="texte" onclick="{setTextType}"><i class="fa fa-pencil" aria-hidden="true"/></span><input type="text" class="{choiceType === 'text' ? 'selected' : ''}"/> + <span class="button" alt="image" onclick="{setImageType}"><i class="fa fa-image" aria-hidden="true"/></span><input type="file" class="{choiceType === 'image' ? 'selected' : ''}"/> + <span class="button" alt="date" onclick="{setDateType}"><i class="fa fa-calendar" aria-hidden="true"/></span><input type="date" class="{choiceType.startsWith('date') ? 'selected' : ''}"/> + <span class="button {!choiceType.startsWith('date') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"><i class="fa fa-clock-o" aria-hidden="true"/></span><input type="text" class="{choiceType === 'datetime' ? 'selected' : ''}"/> + </div> + + <script type="es6"> + this.choiceType = "text"; + + this.setTextType = () => { + this.choiceType = "text"; + }; + + this.setImageType = () => { + this.choiceType = "image"; + }; + + this.setDateType = () => { + if (!this.choiceType.startsWith("date")) { + this.choiceType = "date"; + } + }; + + this.toggleTime = () => { + if (this.choiceType === "date") { + this.choiceType = "datetime"; + } else if (this.choiceType === "datetime") { + this.choiceType = "date"; + } + }; + + </script> + + <style> + + #choice-container { + display: flex; + flex-flow: row nowrap; + } + + .button { + width:auto; + opacity: 1; + margin: 0 10px 10px 10px; + transition: opacity 0.3s ease-in-out 0s, width 0s linear 0.5s; + } + + .hidden { + visibility: hidden; + opacity: 0; + width: 0; + } + + input { + display: inline-block; + visibility: hidden; + width: 0; + height: auto; + flex-grow: 0; + margin: 0; + padding: 0; + transition: width 0.5s ease-in-out 0s, + flex-grow 0s linear 0.5s, + visibility 0.5s ease-in-out 0s; + } + + .selected { + visibility: visible; + width: 100%; + flex-grow: 1; + padding: 10px; + } + + </style> +</ChoiceImage> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html index 73ee64c..5e71e43 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html @@ -1,6 +1,7 @@ require("./ChoiceText.tag.html"); require("./ChoiceText.tag.html"); require("./ChoiceDate.tag.html"); +require("./ChoiceImage.tag.html"); <Choices> <div each={choice, index in form.choices} class="o-form-element" -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit d94a8fac7409b17638c0ef37ac1aa2f1d5bce0b2 Author: Kevin Morin <morin@codelutin.com> Date: Tue Mar 7 18:13:40 2017 +0100 - ajout du type datetime dans le modele pour les choix - utilisation du composant de choix dans le formulaire - utilisation des input de type date et time quand supportés --- pollen-persistence/src/main/xmi/pollen.zargo | Bin 21327 -> 21426 bytes pollen-ui-riot-js/src/main/web/css/main.css | 2 - pollen-ui-riot-js/src/main/web/i18n.json | 4 +- pollen-ui-riot-js/src/main/web/js/I18nHelper.js | 4 +- pollen-ui-riot-js/src/main/web/js/PollForm.js | 57 +---- pollen-ui-riot-js/src/main/web/js/Session.js | 15 ++ .../main/web/tag/components/date-picker.tag.html | 230 ++++++++++++++++++++ .../main/web/tag/components/time-picker.tag.html | 240 +++++++++++++++++++++ .../src/main/web/tag/poll/Choice.tag.html | 194 +++++++++++++++++ .../src/main/web/tag/poll/ChoiceImage.tag.html | 77 ------- .../src/main/web/tag/poll/ChoiceText.tag.html | 176 --------------- .../src/main/web/tag/poll/Choices.tag.html | 16 +- 12 files changed, 690 insertions(+), 325 deletions(-) diff --git a/pollen-persistence/src/main/xmi/pollen.zargo b/pollen-persistence/src/main/xmi/pollen.zargo index a5d88ed..b2357c4 100644 Binary files a/pollen-persistence/src/main/xmi/pollen.zargo and b/pollen-persistence/src/main/xmi/pollen.zargo differ diff --git a/pollen-ui-riot-js/src/main/web/css/main.css b/pollen-ui-riot-js/src/main/web/css/main.css index d51671a..11b8a33 100644 --- a/pollen-ui-riot-js/src/main/web/css/main.css +++ b/pollen-ui-riot-js/src/main/web/css/main.css @@ -94,8 +94,6 @@ a { .container { margin: 0 5px; } - - } form .actions { diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 494447a..7d7b0f8 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -228,7 +228,7 @@ "users_VALIDATION": "En cours de validation", "users_DISABLED": "Désactivé", "users_BANNED": "Banni", - "": "" + "date-picker_today": "Aujourd'hui" }, "en": { "pagination_page": "Page", @@ -453,6 +453,6 @@ "users_VALIDATION": "Account validation", "users_DISABLED": "Account disabled", "users_BANNED": "Account banned", - "": "" + "date-picker_today": "Today" } } diff --git a/pollen-ui-riot-js/src/main/web/js/I18nHelper.js b/pollen-ui-riot-js/src/main/web/js/I18nHelper.js index 40b4d91..f0eab00 100644 --- a/pollen-ui-riot-js/src/main/web/js/I18nHelper.js +++ b/pollen-ui-riot-js/src/main/web/js/I18nHelper.js @@ -54,10 +54,10 @@ module.exports = { }, _l(key, ...params) { - return this.format(this.__[key], ...params); + return this.i18nformat(this.__[key], ...params); }, - format(value, params) { + i18nformat(value, params) { if (!params) { return value; } diff --git a/pollen-ui-riot-js/src/main/web/js/PollForm.js b/pollen-ui-riot-js/src/main/web/js/PollForm.js index c14546c..3b4ea42 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollForm.js +++ b/pollen-ui-riot-js/src/main/web/js/PollForm.js @@ -113,6 +113,7 @@ class PollForm { previousStep() { console.info("previousStep:: " + this.step); + console.log (this.choices); this.setStep(this.step - 1); } @@ -160,62 +161,6 @@ class PollForm { this.choices.splice(index, 1); } - fromDomToChoices(form) { - let choices = []; - - let map = {}; - let count = 0; - Array.prototype.forEach.call(form.elements, (e) => { - if (e.name && e.value) { - if (e.name.indexOf("choice") === 0) { - map[e.name] = e.value; - count++; - } - if (e.name.indexOf("description") === 0) { - map[e.name] = e.value; - } - if (e.name.indexOf("id") === 0) { - map[e.name] = e.value; - } - } - }); - - for (let i = 0; i < count; i++) { - let text = map["choice" + i]; - let description = map["description" + i]; - let id = map["id" + i]; - if (this.type !== "add" || !id) { - choices.push(new Choice(this.model.choiceType, text, description, id)); - } - } - console.info("FromTextChoices"); - console.info(choices); - this.choices = choices; - } - - getTextChoice(form, index) { - let map = {}; - - Array.prototype.forEach.call(form.elements, (e) => { - if (e.name && e.value) { - if (e.name.indexOf("choice") === 0) { - map[e.name] = e.value; - } - if (e.name.indexOf("description") === 0) { - map[e.name] = e.value; - } - if (e.name.indexOf("id") === 0) { - map[e.name] = e.value; - } - } - }); - - let text = map["choice" + index]; - let description = map["description" + index]; - let id = map["id" + index]; - return new Choice(this.model.choiceType, text, description, id); - } - setStep(step) { console.info("setStep:: " + step); this.step = Math.min(this.steps.length, Math.max(0, step)); diff --git a/pollen-ui-riot-js/src/main/web/js/Session.js b/pollen-ui-riot-js/src/main/web/js/Session.js index d0d9b5c..6306730 100644 --- a/pollen-ui-riot-js/src/main/web/js/Session.js +++ b/pollen-ui-riot-js/src/main/web/js/Session.js @@ -52,6 +52,21 @@ class Session { this.locale = "fr"; } + let input = document.createElement("input"); + let notADateValue = "not-a-date-nor-time"; + + input.setAttribute("type", "date"); + input.setAttribute("value", notADateValue); + this.dateInputSupported = (input.value !== notADateValue); + + input.setAttribute("type", "time"); + input.setAttribute("value", notADateValue); + this.timeInputSupported = (input.value !== notADateValue); + + input.setAttribute("type", "datetime"); + input.setAttribute("value", notADateValue); + this.datetimeInputSupported = (input.value !== notADateValue); + this.onUnauthorize(() => { this.user = null; }); diff --git a/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html b/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html new file mode 100644 index 0000000..7c2d35a --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html @@ -0,0 +1,230 @@ +<date-picker> + <input type="date" class="calendar-field" onclick="{open}" value="{opts.date.date.format(format)}" readonly="{!session.dateInputSupported}" /> + + <div class="c-calendar c-calendar--higher" if="{opts.date.isvisible && !session.dateInputSupported}"> + <button type="button" class="c-calendar__control" disabled="{ opts.date.min && opts.date.min.isSame(opts.date.date, 'year') }" onclick="{ prevYear }">‹</button> + <div class="c-calendar__header">{ opts.date.date.format(yearFormat) }</div> + <button type="button" class="c-calendar__control" disabled="{ opts.date.max && opts.date.max.isSame(opts.date.date, 'year') }" onclick="{ nextYear }">›</button> + + <button type="button" class="c-calendar__control" disabled="{ opts.date.min && opts.date.min.isSame(opts.date.date, 'month') }" onclick="{ prevMonth }">‹</button> + <div class="c-calendar__header">{ opts.date.date.format(monthFormat) }</div> + <button type="button" class="c-calendar__control" disabled="{ opts.date.max && opts.date.max.isSame(opts.date.date, 'month') }" onclick="{ nextMonth }">›</button> + + <div class="c-calendar__day">{moment.weekdaysMin(1)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(2)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(3)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(4)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(5)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(6)}</div> + <div class="c-calendar__day">{moment.weekdaysMin(0)}</div> + + <button type="button" class="c-calendar__date { 'c-calendar__date--selected': day.selected, 'c-calendar__date--today': day.today }" disabled="{ day.disabled }" each="{ day in startBuffer }" onclick="{ select }">{ day.date.format(dayFormat) }</button> + <button type="button" class="c-calendar__date c-calendar__date--in-month { 'c-calendar__date--selected': day.selected, 'c-calendar__date--today': day.today }" disabled="{ day.disabled }" each="{ day in days }" onclick="{ select }">{ day.date.format(dayFormat) }</button> + <button type="button" class="c-calendar__date { 'c-calendar__date--selected': day.selected, 'c-calendar__date--today': day.today }" disabled="{ day.disabled }" each="{ day in endBuffer }" onclick="{ select }">{ day.date.format(dayFormat) }</button> + + <button type="button" class="c-button c-button--block c-button--primary" disabled="{ opts.date.min && opts.date.min.isAfter(moment(), "day") || opts.date.max && opts.date.max.isBefore(moment(), "day") }" onclick="{ setToday }">{__.today}</button> + </div> + + <script type="es6"> + + this.session = require("../../js/Session"); + + this.moment = require("moment"); + this.moment.locale(this.session.locale); + + this.installBundle(this.session, "date-picker", locale => { + this.opts.date.date.locale(locale); + this.moment.locale(locale); + }); + + let toMoment = d => { + if (!this.moment.isMoment(d)) { + d = this.moment(d); + } + if (d.isValid()) { + return d; + } + return this.moment(); + }; + + let handleClickOutside = e => { + if (!this.root.contains(e.target)) { + this.close(); + } + this.update(); + }; + + let dayObj = dayDate => { + const dateObj = dayDate || this.moment(); + + return { + date: dateObj, + selected: opts.date.date.isSame(dayDate, "day"), + today: this.moment().isSame(dayDate, "day"), + disabled: ( + opts.date.min && opts.date.min.isAfter(dayDate) || + opts.date.max && opts.date.max.isBefore(dayDate) + ) + }; + }; + + let buildCalendar = () => { + this.format = "LL"; + this.yearFormat = "YYYY"; + this.monthFormat = "MMMM"; + this.dayFormat = "DD"; + + this.days = []; + this.startBuffer = []; + this.endBuffer = []; + + const begin = this.moment(opts.date.date).startOf("month"); + const daysInMonth = this.moment(opts.date.date).daysInMonth(); + const end = this.moment(opts.date.date).endOf("month"); + + for (let i = begin.isoWeekday() - 1; i > 0; i -= 1) { + const d = this.moment(begin).subtract(i, "days"); + this.startBuffer.push(dayObj(d)); + } + + for (let i = 0; i < daysInMonth; i++) { + const current = this.moment(begin).add(i, "days"); + this.days.push(dayObj(current)); + } + + for (let i = end.isoWeekday() + 1; i <= 7; i++) { + const d = this.moment(end).add(i - end.isoWeekday(), "days"); + this.endBuffer.push(dayObj(d)); + } + }; + + this.on("mount", () => { + if (!opts.date) { + opts.date = {date: this.moment()}; + } + if (!opts.date.date) { + opts.date.date = this.moment(); + } + opts.date.date = toMoment(opts.date.date); + + if (opts.date.min) { + opts.date.min = toMoment(opts.date.min); + + if (opts.date.min.isAfter(this.moment(), "day")) { + opts.date.date = this.moment(opts.date.min); + } + } + + if (opts.date.max) { + opts.date.max = toMoment(opts.date.max); + + if (opts.date.max.isBefore(this.moment(), "day")) { + opts.date.date = this.moment(opts.date.max); + } + } + + this.on("update", () => { + opts.date.date = toMoment(opts.date.date); + buildCalendar(); + positionDropdown(); + }); + document.addEventListener("click", handleClickOutside); + this.update(); + }); + + this.on("unmount", () => { + document.removeEventListener("click", handleClickOutside); + }); + + this.open = () => { + opts.date.isvisible = true; + this.trigger("open"); + }; + + this.close = () => { + if (opts.date.isvisible) { + opts.date.isvisible = false; + this.trigger("close"); + } + }; + + this.select = e => { + opts.date.date = e.item.day.date; + this.trigger('select', opts.date.date); + }; + + this.setToday = () => { + opts.date.date = this.moment(); + this.trigger("select", opts.date.date); + }; + + this.prevYear = () => { + opts.date.date = opts.date.date.subtract(1, "year"); + }; + + this.nextYear = () => { + opts.date.date = opts.date.date.add(1, "year"); + }; + + this.prevMonth = () => { + opts.date.date = opts.date.date.subtract(1, "month"); + }; + + this.nextMonth = () => { + opts.date.date = opts.date.date.add(1, "month"); + }; + + function getWindowDimensions() { + var w = window, + d = document, + e = d.documentElement, + g = d.getElementsByTagName("body")[0], + x = w.innerWidth || e.clientWidth || g.clientWidth, + y = w.innerHeight || e.clientHeight || g.clientHeight; + return { width: x, height: y }; + }; + + const positionDropdown = () => { + const w = getWindowDimensions(); + const m = this.root.querySelector(".calendar"); + if (!m) { + return; + } + if (!opts.date.isvisible) { + // Reset position + m.style.marginTop = ""; + m.style.marginLeft = ""; + return; + } + const pos = m.getBoundingClientRect(); + if (w.width < pos.left + pos.width) { + // menu is off the right hand of the page + m.style.marginLeft = (w.width - (pos.left + pos.width) - 20) + "px"; + } + if (pos.left < 0) { + // menu is off the right hand of the page + m.style.marginLeft = "20px"; + } + if (w.height < pos.top + pos.height) { + // Popup is off the bottom of the page + m.style.marginTop = (w.height - (pos.top + pos.height) - 20) + "px"; + } + }; + </script> + + <style scoped> + date-picker { + position: relative; + display: inline-block; + cursor: pointer; + } + + .c-calendar { + position: absolute; + min-width: 300px; + margin-top: .5em; + left: 0; + } + </style> + +</date-picker> diff --git a/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html b/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html new file mode 100644 index 0000000..8c9f9d1 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html @@ -0,0 +1,240 @@ +<time-picker> + <input type="time" class="calendar-field" onclick="{open}" value="{opts.time.time.format('HH:mm')}" readonly="{!session.timeInputSupported}" /> + + <div class="c-calendar c-calendar--higher" if="{opts.time.isvisible && !session.timeInputSupported}"> + + <div class="time"> + <div class="prev action-prev" onclick={nextHour}></div> + <div class="ti_tx"><input class="timepicki-input" type="text" value="{opts.time.time.format('HH')}"></div> + <div class="next action-next" onclick={prevHour}></div> + </div> + <div class="colon"> + <div class="colon_tx">:</div> + </div> + <div class="mins"> + <div class="prev action-prev" onclick={nextMinute}></div> + <div class="mi_tx"><input class="timepicki-input" type="text" value="{opts.time.time.format('mm')}"></div> + <div class="next action-next" onclick={prevMinute}></div> + </div> + + </div> + + <script type="es6"> + let session = require("../../js/Session"); + + this.moment = require("moment"); + this.moment.locale(session.locale); + + this.installBundle(session, "time-picker", locale => { + this.opts.time.time.locale(locale); + this.moment.locale(locale); + }); + + let toMoment = d => { + if (!this.moment.isMoment(d)) { + d = this.moment(d); + } + if (d.isValid()) { + return d; + } + return this.moment(); + }; + + let handleClickOutside = e => { + if (!this.root.contains(e.target)) { + this.close(); + } + this.update(); + }; + + this.on("mount", () => { + if (!opts.time) { + opts.time = {time: this.moment()}; + } + if (!opts.time.time) { + opts.time.time = this.moment(); + } + opts.time.time = toMoment(opts.time); + + document.addEventListener("click", handleClickOutside); + }); + + this.on("unmount", () => { + document.removeEventListener("click", handleClickOutside); + }); + + this.open = () => { + opts.time.isvisible = true; + this.trigger("open"); + }; + + this.close = () => { + if (opts.time.isvisible) { + opts.time.isvisible = false; + this.trigger("close"); + } + }; + + this.select = e => { + opts.time.time = e.item.day.date; + this.trigger('select', opts.time.time); + }; + + this.prevHour = () => { + opts.time.time = opts.time.time.subtract(1, "hour"); + }; + + this.nextHour = () => { + opts.time.time = opts.time.time.add(1, "hour"); + }; + + this.prevMinute = () => { + opts.time.time = opts.time.time.subtract(1, "minute"); + }; + + this.nextMinute = () => { + opts.time.time = opts.time.time.add(1, "minute"); + }; + + function getWindowDimensions() { + var w = window, + d = document, + e = d.documentElement, + g = d.getElementsByTagName("body")[0], + x = w.innerWidth || e.clientWidth || g.clientWidth, + y = w.innerHeight || e.clientHeight || g.clientHeight; + return { width: x, height: y }; + }; + + const positionDropdown = () => { + const w = getWindowDimensions(); + const m = this.root.querySelector(".calendar"); + if (!m) { + return; + } + if (!opts.time.isvisible) { + // Reset position + m.style.marginTop = ""; + m.style.marginLeft = ""; + return; + } + const pos = m.getBoundingClientRect(); + if (w.width < pos.left + pos.width) { + // menu is off the right hand of the page + m.style.marginLeft = (w.width - (pos.left + pos.width) - 20) + "px"; + } + if (pos.left < 0) { + // menu is off the right hand of the page + m.style.marginLeft = "20px"; + } + if (w.height < pos.top + pos.height) { + // Popup is off the bottom of the page + m.style.marginTop = (w.height - (pos.top + pos.height) - 20) + "px"; + } + }; + </script> + + <style scoped> + time-picker { + position: relative; + display: inline-block; + cursor: pointer; + } + + .c-calendar { + position: absolute; + margin-top: .5em; + left: 0; + } + + + /* + Created on: 17 Sep, 2014, 4:29:37 PM + Author: senthil + */ + + .ti_tx, + .colon_tx, + .mi_tx { + width: 100%; + text-align: center; + margin: 10px 0; + } + + .time, + .colon, + .mins { + float: left; + margin: 0 10px; + font-size: 20px; + color: #2d2e2e; + font-family: arial; + font-weight: 700; + } + + .time, + .mins { + width: 60px; + } + + .prev, + .next { + cursor: pointer; + padding: 18px; + width: 28%; + border: 1px solid #ccc; + margin: auto; + background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAA4CAYAAAD959hAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJk [...] + border-radius: 5px; + } + + .prev:hover, + .next:hover { + background-color: #ccc; + } + + .next { + background-position: 50% 150%; + } + + .prev { + background-position: 50% -50%; + } + + .time_pick { + position: relative; + } + + .timepicker_wrap { + padding: 10px; + border-radius: 5px; + z-index: 998; + display: none; + box-shadow: 2px 2px 5px 0 rgba(50,50,50,0.35); + background: #f6f6f6; + border: 1px solid #ccc; + float: left; + position: absolute; + top: 27px; + left: 0; + } + + input.timepicki-input { + background: none repeat scroll 0 0 #FFFFFF; + border: 1px solid #CCCCCC; + border-radius: 5px 5px 5px 5px; + float: none; + margin: 0; + text-align: center; + width: 70%; + } + + a.reset_time { + float: left; + margin-top: 5px; + color: #000; + } + + </style> + +</time-picker> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html new file mode 100644 index 0000000..22a40b1 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html @@ -0,0 +1,194 @@ +require("../components/date-picker.tag.html"); +require("../components/time-picker.tag.html"); +<Choice> + <div class="choice-container"> + <button type="button" class="c-button fa fa-pencil" alt="texte" onclick="{setTextType}"/> + <input type="text" ref="choiceText" class="{choiceType === 'TEXT' ? 'selected' : 'hidden'}" value="{choiceType === 'TEXT' ? choice.choiceValue : null}"/> + + <button type="button" class="c-button fa fa-image" alt="image" onclick="{setImageType}"/> + <input type="file" ref="choiceImage" class="{choiceType === 'RESOURCE' ? 'selected' : 'hidden'}"/> + + <button type="button" class="c-button fa fa-calendar" alt="date" onclick="{setDateType}"/> + <date-picker ref="choiceDate" class="{choiceType.startsWith('DATE') ? 'selected' : 'hidden'}" date="{date}"/> + + <button type="button" class="c-button fa fa-clock-o {!choiceType.startsWith('DATE') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"/> + <time-picker ref="choiceTime" class="{choiceType === 'DATETIME' ? 'selected' : 'hidden'}" time="{time}"/> + + <input type="hidden" ref="description" value="{choice.description}"/> + </div> + + <script type="es6"> + let session = require("../../js/Session"); + let moment = require("moment"); + moment.locale(session.locale); + let Choice = require("../../js/Choice"); + + this.installBundle(session, "choice", locale => { + moment.locale(locale); + }); + + this.number = parseInt(this.opts.number, 10); + this.mode = this.opts.mode; + this.edit = this.opts.mode === "create" || this.opts.mode === "edit"; + + if (this.opts.choiceType) { + this.choiceType = this.opts.choiceType; + } else { + this.choiceType = "TEXT"; + } + Object.assign(this.choice = {}, this.opts.choice); + if (this.choiceType === "DATE") { + this.date = { + date: moment(this.opts.choice.choiceValue) + }; + this.time = { + time: moment() + }; + } else if (this.choiceType === "DATETIME") { + this.time = { + time: moment(this.opts.choice.choiceValue) + }; + this.date = { + date: moment() + }; + } else { + this.date = { + date: moment() + }; + this.time = { + time: moment() + }; + } + + this.on("mount", () => { + if (this.number === 0 || this.mode === "edit") { + //this.refs.choice.required = "required"; + } + if (this.mode === "edit") { + //this.refs.edit_choice.classList.add("choice-view"); + } + }); + + this.setTextType = () => { + this.choiceType = "TEXT"; + }; + + this.setImageType = () => { + this.choiceType = "RESOURCE"; + }; + + this.setDateType = () => { + if (!this.choiceType.startsWith("DATE")) { + this.choiceType = "DATE"; + } + }; + + this.toggleTime = () => { + if (this.choiceType === "DATE") { + this.choiceType = "DATETIME"; + } else if (this.choiceType === "DATETIME") { + this.choiceType = "DATE"; + } + }; + + this.getValue = () => { + let choiceValue = {}; + if (this.choiceType === "TEXT") { + console.log("TEXT"); + choiceValue = this.refs.choiceText.value; + } else if (this.choiceType.startsWith("DATE")) { + choiceValue = this.refs.choiceDate.value; + } + console.log(choiceValue); + return new Choice(this.choiceType, choiceValue, this.refs.description.value, this.choice.id); + }; + + /*this.onEditChoice = () => { + this.editing = true; + let ref = this.refs.edit_choice; + ref.classList.add("choice-edit"); + ref.classList.remove("choice-view"); + this.trigger("editChoice", this.number); + Object.assign(this.$choice = {}, this.choice); + // console.info(this.$choice); + }; + + this.cancelEditChoice = () => { + if (this.editing) { + let ref = this.refs.edit_choice; + ref.classList.remove("choice-edit"); + ref.classList.add("choice-view"); + Object.assign(this.choice, this.$choice); + // console.info(this.choice); + this.refs.choice.value = this.choice.choiceValue; + this.refs.description.value = this.choice.description; + + } + this.editing = false; + this.trigger("cancelEditChoice", this.number); + }; + + this.deleteChoice = () => { + if (confirm("Delete choice?")) { + this.trigger("deleteChoice", this.number); + } + };*/ + + </script> + + <style> + + .choice-container { + display: flex; + flex-flow: row nowrap; + } + + .button { + width:auto; + opacity: 1; + margin: 0 10px 10px 10px; + transition: opacity 0.3s ease-in-out 0s, width 0s linear 0.5s; + } + + .choice-container > .hidden { + visibility: hidden; + opacity: 0; + width: 0; + border: none; + } + + .choice-container > input, + .choice-container date-picker, + .choice-container time-picker { + display: inline-block; + opacity: 1; + height: auto; + flex-grow: 0; + margin: 0; + padding: 0; + transition: width 0.5s ease-in-out 0s, + flex-grow 0s linear 0.5s, + visibility 0.5s ease-in-out 0s, + border 0s linear 0s; + } + + .choice-container > .selected { + visibility: visible; + width: 100%; + flex-grow: 1; + } + + .choice-container > input.selected, + .choice-container date-picker.selected .calendar-field, + .choice-container time-picker.selected .calendar-field { + width: 100%; + padding: 10px; + } + + time-picker { + max-width: 100px; + } + + </style> + +</Choice> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html deleted file mode 100644 index cd180bc..0000000 --- a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceImage.tag.html +++ /dev/null @@ -1,77 +0,0 @@ -<ChoiceImage> - <div id="choice-container"> - <span class="button" alt="texte" onclick="{setTextType}"><i class="fa fa-pencil" aria-hidden="true"/></span><input type="text" class="{choiceType === 'text' ? 'selected' : ''}"/> - <span class="button" alt="image" onclick="{setImageType}"><i class="fa fa-image" aria-hidden="true"/></span><input type="file" class="{choiceType === 'image' ? 'selected' : ''}"/> - <span class="button" alt="date" onclick="{setDateType}"><i class="fa fa-calendar" aria-hidden="true"/></span><input type="date" class="{choiceType.startsWith('date') ? 'selected' : ''}"/> - <span class="button {!choiceType.startsWith('date') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"><i class="fa fa-clock-o" aria-hidden="true"/></span><input type="text" class="{choiceType === 'datetime' ? 'selected' : ''}"/> - </div> - - <script type="es6"> - this.choiceType = "text"; - - this.setTextType = () => { - this.choiceType = "text"; - }; - - this.setImageType = () => { - this.choiceType = "image"; - }; - - this.setDateType = () => { - if (!this.choiceType.startsWith("date")) { - this.choiceType = "date"; - } - }; - - this.toggleTime = () => { - if (this.choiceType === "date") { - this.choiceType = "datetime"; - } else if (this.choiceType === "datetime") { - this.choiceType = "date"; - } - }; - - </script> - - <style> - - #choice-container { - display: flex; - flex-flow: row nowrap; - } - - .button { - width:auto; - opacity: 1; - margin: 0 10px 10px 10px; - transition: opacity 0.3s ease-in-out 0s, width 0s linear 0.5s; - } - - .hidden { - visibility: hidden; - opacity: 0; - width: 0; - } - - input { - display: inline-block; - visibility: hidden; - width: 0; - height: auto; - flex-grow: 0; - margin: 0; - padding: 0; - transition: width 0.5s ease-in-out 0s, - flex-grow 0s linear 0.5s, - visibility 0.5s ease-in-out 0s; - } - - .selected { - visibility: visible; - width: 100%; - flex-grow: 1; - padding: 10px; - } - - </style> -</ChoiceImage> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceText.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceText.tag.html deleted file mode 100644 index 475df0c..0000000 --- a/pollen-ui-riot-js/src/main/web/tag/poll/ChoiceText.tag.html +++ /dev/null @@ -1,176 +0,0 @@ -/*- -* #%L -* Pollen :: UI (Riot Js) -* %% -* Copyright (C) 2009 - 2017 CodeLutin -* %% -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU Affero General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU Affero General Public License -* along with this program. If not, see <http://www.gnu.org/licenses/>. -* #L% -*/ -<ChoiceText> - - <div class="choice-body"> - - <div class="choice-actions"> - <div show="{mode =='edit' && !editing}" id="{choice.id}"> - <a onclick="{deleteChoice}"><i class="fa fa-trash danger fa-15x"/></a> - <a onclick="{onEditChoice}"><i class="fa fa-pencil-square-o fa-15x"/></a> - </div> - <div show="{editing}"> - <a onclick="{cancelEditChoice}" class="danger"> - <i class="fa fa-remove fa-15x"/> - </a> - <button class="icon" type="submit" onclick="{prepareSave}"> - <i class="fa fa-check fa-15x"/> - </button> - </div> - </div> - <div ref="edit_choice" id="edit_choice_{number}" class="choice-container"> - <div class="choice-container-child"> - <label class="choice-wide" for="choice{number}">{__.label} {number + 1}</label> - <label class="choice-wider" if="{number == 0}">{__.description}</label> - <label class="choice-wider" if="{number > 0}"/> - </div> - <div class="choice-container-child"> - <input type="hidden" name="id{number}" value="{choice.id}"> - <div class="choice-inputs"> - <input type="text" ref="choice" name="choice{number}" value="{choice.choiceValue}" - disabled="{!edit || (mode==='edit' && !editing && choice.choiceValue)?'disabled':''}" - class="choice-wide" id="choice{number}"> - <input type="text" ref="description" name="description{number}" value="{choice.description}" - disabled="{!edit || (mode==='edit' && !editing && choice.choiceValue)?'disabled':''}" - class="choice-wider"> - </div> - </div> - </div> - </div> - - <script type="es6"> - this.installBundle(this.opts.session, "poll_choices"); - this.number = parseInt(this.opts.number, 10); - this.mode = this.opts.mode; - this.edit = this.opts.mode === "create" || this.opts.mode === "edit"; - this.choice = this.opts.choice; - this.on("mount", () => { - if (this.number === 0 || this.mode === "edit") { - this.refs.choice.required = "required"; - } - if (this.mode === "edit") { - this.refs.edit_choice.classList.add("choice-view"); - } - }); - - this.prepareSave = () => { - this.$choice = { - choiceValue: this.refs.choice.value, - description: this.refs.description.value - }; - }; - this.onEditChoice = () => { - this.editing = true; - let ref = this.refs.edit_choice; - ref.classList.add("choice-edit"); - ref.classList.remove("choice-view"); - this.trigger("editChoice", this.number); - Object.assign(this.$choice = {}, this.choice); - // console.info(this.$choice); - }; - - this.cancelEditChoice = () => { - if (this.editing) { - let ref = this.refs.edit_choice; - ref.classList.remove("choice-edit"); - ref.classList.add("choice-view"); - Object.assign(this.choice, this.$choice); - // console.info(this.choice); - this.refs.choice.value = this.choice.choiceValue; - this.refs.description.value = this.choice.description; - - } - this.editing = false; - this.trigger("cancelEditChoice", this.number); - }; - - this.deleteChoice = () => { - if (confirm("Delete choice?")) { - this.trigger("deleteChoice", this.number); - } - }; - - </script> - - <style> - - .icon { - border-style: none; - background-color: white; - cursor: pointer; - color: #13a2ff; - } - - .danger { - color: red; - } - - .choice-wide { - width: 440px; - } - - .choice-wider { - width: 640px; - } - - .choice-actions { - padding-right: 5px; - } - - .choice-body { - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; - } - - .choice-container { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: center; - } - - .choice-container-child { - display: flex; - } - - .choice-inputs { - display: flex; - flex-direction: row; - justify-content: flex-start; - align-items: center; - } - - .choice-edit { - border: 2px solid #13a2ff; - } - - .choice-view { - border: 2px solid white; - } - - input[disabled=disabled] { - cursor: not-allowed; - } - - </style> -</ChoiceText> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html index 5e71e43..c13fd0c 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choices.tag.html @@ -1,7 +1,4 @@ -require("./ChoiceText.tag.html"); -require("./ChoiceText.tag.html"); -require("./ChoiceDate.tag.html"); -require("./ChoiceImage.tag.html"); +require("./Choice.tag.html"); <Choices> <div each={choice, index in form.choices} class="o-form-element" @@ -9,11 +6,10 @@ require("./ChoiceImage.tag.html"); <div class="c-input-group c-input-group--rounded-left"> <div class="o-field o-field--icon-left"> <i class="c-icon">{index + 1}</i> - <input ref={"choice" + index} + <Choice ref={"choice" + index} class="c-field" - type="text" - name="name" - value="{choice.choiceValue}"> + name={"choice" + index} + choice="{choice}"/> </div> <button type="button" class="c-button c-button--ghost-error" @@ -42,10 +38,10 @@ require("./ChoiceImage.tag.html"); this.submit = () => { this.form.choices.forEach((choice, index) => { - choice.choiceValue = this.refs["choice" + index].value; + let editedChoice = this.refs["choice" + index].getValue(); + Object.assign(choice, editedChoice); }); }; - </script> <style> -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 177e15358643effc741e0103222ec61b9d01bb1c Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 16:38:00 2017 +0100 modification du parsing des dates : maintenant on attend le timestamp pour les types date et datetime --- .../chorem/pollen/services/bean/ChoiceBean.java | 54 +--------------------- .../pollen/services/service/ChoiceService.java | 49 ++++++-------------- 2 files changed, 16 insertions(+), 87 deletions(-) diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java index 6a68116..61df736 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/bean/ChoiceBean.java @@ -51,37 +51,13 @@ public class ChoiceBean extends PollenBean<Choice> { @Override public void fromEntity(Choice entity) { - setEntityId(entity.getTopiaId()); if (entity.getCreator() == null || entity.getCreator().getPermission() == null) { - setPermission(null); - } else { - setPermission(entity.getCreator().getPermission().getToken()); - - } - - - //TODO agarandel 17/07/14 : review code : is switch case required - switch (entity.getChoiceType()) { - - case TEXT: - case DATE: - - setChoiceValue(entity.getChoiceValue()); - break; - - case RESOURCE: - - setChoiceValue(entity.getChoiceValue()); - break; - - default: - throw new UnsupportedOperationException("Unexpected value : " + entity.getChoiceType()); } - + setChoiceValue(entity.getChoiceValue()); setDescription(entity.getDescription()); setChoiceType(entity.getChoiceType()); setChoiceOrder(entity.getChoiceOrder()); @@ -90,35 +66,9 @@ public class ChoiceBean extends PollenBean<Choice> { @Override public Choice toEntity() { - Choice entity = new ChoiceImpl(); - entity.setTopiaId(getEntityId()); - - ChoiceType choiceType = getChoiceType(); - if (choiceType != null) { - - //TODO agarandel 17/07/14 : review code : is switch case required - switch (choiceType) { - case TEXT: - entity.setChoiceValue(getChoiceValue()); - - break; - - case DATE: - case RESOURCE: - - if (getChoiceValue() != null) { - entity.setChoiceValue(getChoiceValue()); - } - - break; - - default: - throw new UnsupportedOperationException("Unexpected value : " + choiceType); - } - } - + entity.setChoiceValue(getChoiceValue()); entity.setDescription(getDescription()); entity.setChoiceType(getChoiceType()); entity.setChoiceOrder(getChoiceOrder()); diff --git a/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java b/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java index 424f59a..ef396dc 100644 --- a/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java +++ b/pollen-services/src/main/java/org/chorem/pollen/services/service/ChoiceService.java @@ -33,9 +33,7 @@ import org.chorem.pollen.services.bean.ChoiceBean; import org.chorem.pollen.services.bean.PollenEntityRef; import org.chorem.pollen.services.service.security.PermissionVerb; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.util.Calendar; import java.util.List; import java.util.Set; import java.util.function.Function; @@ -51,9 +49,6 @@ import static org.nuiton.i18n.I18n.l; public class ChoiceService extends PollenServiceSupport { - private static final SimpleDateFormat DAY_FORMAT = new SimpleDateFormat("YYYY-MM-dd"); - private static final SimpleDateFormat DAY_TIME_FORMAT = new SimpleDateFormat("YYYY-MM-dd'T'HH:mm"); - protected final Function<ChoiceBean, ChoiceBean> choiceBeanFunction = input -> { if (isNotPermitted(PermissionVerb.editChoice, input.getEntityId())) { input.setPermission(null); @@ -228,23 +223,10 @@ public class ChoiceService extends PollenServiceSupport { toSave.setChoiceType(choice.getChoiceType()); - //TODO agarandel 17/07/14 : review code : is switch case required - switch (toSave.getChoiceType()) { - - case TEXT: - case DATE: - - toSave.setChoiceValue(choice.getChoiceValue()); - break; - - case RESOURCE: - - toSave.setChoiceValue(getPollenResourceService().getTopiaIdByReduceId(choice.getChoiceValue())); - break; - - default: - throw new UnsupportedOperationException("Unexpected value : " + toSave.getChoiceType()); - + if (ChoiceType.RESOURCE.equals(toSave.getChoiceType())) { + toSave.setChoiceValue(getPollenResourceService().getTopiaIdByReduceId(choice.getChoiceValue())); + } else { + toSave.setChoiceValue(choice.getChoiceValue()); } toSave.setDescription(choice.getDescription()); @@ -300,20 +282,18 @@ public class ChoiceService extends PollenServiceSupport { } break; - case DATE: - Date choiceDate = null; + case DATE: + case DATETIME: + Calendar choiceDate = null; if (choice.getChoiceValue() != null) { try { - choiceDate = DAY_FORMAT.parse(choice.getChoiceValue()); - - } catch (ParseException e) { - try { - choiceDate = DAY_TIME_FORMAT.parse(choice.getChoiceValue()); - } catch (ParseException e1) { - e1.printStackTrace(); - check(errors, "choiceValue", false, l(getLocale(), "pollen.error.choice.choiceDateInvalid", choice.getChoiceValue())); - } + choiceDate = Calendar.getInstance(); + choiceDate.setTimeInMillis(Long.parseLong(choice.getChoiceValue())); + + } catch (NumberFormatException e) { + e.printStackTrace(); + check(errors, "choiceValue", false, l(getLocale(), "pollen.error.choice.choiceDateInvalid", choice.getChoiceValue())); } if (choiceDate != null) { boolean dateAdded = choiceNames.add(String.valueOf(choiceDate.getTime())); @@ -323,7 +303,6 @@ public class ChoiceService extends PollenServiceSupport { } else { check(errors, "choiceValue", false, l(getLocale(), "pollen.error.choice.choiceDateEmpty")); } - break; case RESOURCE: -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 38c722b57699ee42e4fed86a84339e6b2e4fb7ab Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 16:42:57 2017 +0100 - enrgistrement des choix de type date, datetime et resource - affichage des choix de types resources --- pollen-ui-riot-js/package.json | 1 + pollen-ui-riot-js/src/main/web/js/FetchService.js | 7 +- pollen-ui-riot-js/src/main/web/js/PollForm.js | 85 +++++++++------- .../src/main/web/js/ResourceService.js | 44 +++++++++ .../main/web/tag/components/date-picker.tag.html | 106 +++++++------------- .../main/web/tag/components/time-picker.tag.html | 83 +++++----------- .../src/main/web/tag/poll/Choice.tag.html | 110 +++++++++++++-------- .../src/main/web/tag/poll/CreatePoll.tag.html | 2 +- .../src/main/web/tag/poll/Votes.tag.html | 18 +++- 9 files changed, 246 insertions(+), 210 deletions(-) diff --git a/pollen-ui-riot-js/package.json b/pollen-ui-riot-js/package.json index 6f91f7a..0009670 100644 --- a/pollen-ui-riot-js/package.json +++ b/pollen-ui-riot-js/package.json @@ -38,6 +38,7 @@ "blaze": "^3.2.0", "font-awesome": "4.7.0", "moment": "^2.17.1", + "remarkable": "^1.7.1", "riot": "^3.0.5", "riot-route": "^2.5.0" } diff --git a/pollen-ui-riot-js/src/main/web/js/FetchService.js b/pollen-ui-riot-js/src/main/web/js/FetchService.js index 4ce553c..b7d4589 100644 --- a/pollen-ui-riot-js/src/main/web/js/FetchService.js +++ b/pollen-ui-riot-js/src/main/web/js/FetchService.js @@ -99,15 +99,18 @@ class FetchService { return this.fetch(url, "DELETE", null, body); } - form(url, data) { + form(url, data, doNotStringify) { let formData = null; + console.log(data); if (data) { formData = new FormData(); let keys = Object.keys(data); keys.forEach((key) => { let value = data[key]; - if (typeof value === "object") { + console.log(key); + console.log(value); + if (!doNotStringify && (typeof value === "object")) { formData.set(key, JSON.stringify(value)); } else { formData.set(key, value); diff --git a/pollen-ui-riot-js/src/main/web/js/PollForm.js b/pollen-ui-riot-js/src/main/web/js/PollForm.js index 3b4ea42..cc44013 100644 --- a/pollen-ui-riot-js/src/main/web/js/PollForm.js +++ b/pollen-ui-riot-js/src/main/web/js/PollForm.js @@ -32,7 +32,8 @@ class PollForm { "options", "voters" ]; - this.service = require("./PollService"); + this.pollService = require("./PollService"); + this.resourceService = require("./ResourceService"); this.FormHelper = require("./FormHelper"); this.step = -1; this.isInit = false; @@ -51,7 +52,7 @@ class PollForm { this.choiceType = choiceType; console.info("init form"); - return this.service.empty(this.choiceType).then((poll) => { + return this.pollService.empty(this.choiceType).then((poll) => { this.model = poll; console.info("empty poll"); console.info(this.model); @@ -69,45 +70,63 @@ class PollForm { this.model.participant = []; switch (this.choiceType) { - case "DATE": - this.model.choiceType = "DATE"; - this.choices = [ - new Choice(this.model.choiceType, "2017-01-31T13:45", "Requiem is so powerfull"), - new Choice(this.model.choiceType, "2017-02-01T03:45", "Truit is so nice"), - new Choice(this.model.choiceType, "2017-02-02", "So deep, so dark...") - ]; - break; - - case "IMAGE": - this.model.choiceType = "RESOURCE"; - break; - - default: // "TEXT" - this.model.choiceType = "TEXT"; - this.choices = [ - new Choice(this.model.choiceType, "Mozart", "Requiem is so powerfull"), - new Choice(this.model.choiceType, "Schubert", "Truit is so nice"), - new Choice(this.model.choiceType, "Malher", "So deep, so dark...") - ]; - break; + case "DATE": + this.model.choiceType = "DATE"; + this.choices = [ + new Choice(this.model.choiceType, "2017-01-31T13:45", "Requiem is so powerfull"), + new Choice(this.model.choiceType, "2017-02-01T03:45", "Truit is so nice"), + new Choice(this.model.choiceType, "2017-02-02", "So deep, so dark...") + ]; + break; + + case "IMAGE": + this.model.choiceType = "RESOURCE"; + break; + + default: // "TEXT" + this.model.choiceType = "TEXT"; + this.choices = [ + new Choice(this.model.choiceType, "Mozart", "Requiem is so powerfull"), + new Choice(this.model.choiceType, "Schubert", "Truit is so nice"), + new Choice(this.model.choiceType, "Malher", "So deep, so dark...") + ]; + break; } this.isInit = true; this.step = 0; }); } - create() { + create(success) { console.info("form before create"); console.info(this.form); - return this.service.create(this.model, this.choices).then((result) => { - console.info("Poll created"); - console.info(result); - this.model.id = result.id; - this.model.permission = result.permission; - }).catch((error) => { - console.error("Could not create poll"); - console.error(error); - return Promise.reject(error); + + // if the choice is of type resource, then upload the file and set its id as choice value + let fileUploadPromises = []; + this.choices.forEach((choice, index) => { + if (choice.choiceType === "RESOURCE") { + let promise = new Promise((resolve, reject) => { + this.resourceService.create(choice.choiceValue).then((result) => { + choice.choiceValue = result.id; + resolve(result.id); + }); + }); + fileUploadPromises.push(promise); + } + }); + Promise.all(fileUploadPromises).then(() => { + this.pollService.create(this.model, this.choices).then((result) => { + console.info("Poll created"); + console.info(result); + this.model.id = result.id; + this.model.permission = result.permission; + }) + .then(success) + .catch((error) => { + console.error("Could not create poll"); + console.error(error); + Promise.reject(error); + }); }); } diff --git a/pollen-ui-riot-js/src/main/web/js/ResourceService.js b/pollen-ui-riot-js/src/main/web/js/ResourceService.js new file mode 100644 index 0000000..767a3e3 --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/js/ResourceService.js @@ -0,0 +1,44 @@ +/*- + * #%L + * Pollen :: UI (Riot Js) + * %% + * Copyright (C) 2009 - 2017 CodeLutin + * %% + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * #L% + */ +let singleton = require("./Singleton"); +let FetchService = require("./FetchService"); + +class ResourceService extends FetchService { + + create(resource) { + console.log(resource); + return this.form("/v1/resources", {resource: resource}, true); + } + + getResource(resourceId) { + return this.get("/v1/resources/" + resourceId); + } + + getPreview(resourceId) { + return this.get("/v1/resources/" + resourceId + "/preview"); + } + + delete(resourceId) { + return this.doDelete("/v1/resources/" + resourceId); + } +} + +module.exports = singleton(ResourceService); diff --git a/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html b/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html index 7c2d35a..e16d174 100644 --- a/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/components/date-picker.tag.html @@ -1,7 +1,7 @@ <date-picker> <input type="date" class="calendar-field" onclick="{open}" value="{opts.date.date.format(format)}" readonly="{!session.dateInputSupported}" /> - <div class="c-calendar c-calendar--higher" if="{opts.date.isvisible && !session.dateInputSupported}"> + <div class="c-calendar c-calendar--higher" if="{opts.date.isVisible && !session.dateInputSupported}"> <button type="button" class="c-calendar__control" disabled="{ opts.date.min && opts.date.min.isSame(opts.date.date, 'year') }" onclick="{ prevYear }">‹</button> <div class="c-calendar__header">{ opts.date.date.format(yearFormat) }</div> <button type="button" class="c-calendar__control" disabled="{ opts.date.max && opts.date.max.isSame(opts.date.date, 'year') }" onclick="{ nextYear }">›</button> @@ -59,11 +59,11 @@ return { date: dateObj, - selected: opts.date.date.isSame(dayDate, "day"), + selected: this.opts.date.date.isSame(dayDate, "day"), today: this.moment().isSame(dayDate, "day"), disabled: ( - opts.date.min && opts.date.min.isAfter(dayDate) || - opts.date.max && opts.date.max.isBefore(dayDate) + this.opts.date.min && this.opts.date.min.isAfter(dayDate) || + this.opts.date.max && this.opts.date.max.isBefore(dayDate) ) }; }; @@ -78,9 +78,9 @@ this.startBuffer = []; this.endBuffer = []; - const begin = this.moment(opts.date.date).startOf("month"); - const daysInMonth = this.moment(opts.date.date).daysInMonth(); - const end = this.moment(opts.date.date).endOf("month"); + const begin = this.moment(this.opts.date.date).startOf("month"); + const daysInMonth = this.moment(this.opts.date.date).daysInMonth(); + const end = this.moment(this.opts.date.date).endOf("month"); for (let i = begin.isoWeekday() - 1; i > 0; i -= 1) { const d = this.moment(begin).subtract(i, "days"); @@ -96,120 +96,84 @@ const d = this.moment(end).add(i - end.isoWeekday(), "days"); this.endBuffer.push(dayObj(d)); } - }; + }; this.on("mount", () => { - if (!opts.date) { - opts.date = {date: this.moment()}; + if (!this.opts.date) { + this.opts.date = {date: this.moment()}; } - if (!opts.date.date) { - opts.date.date = this.moment(); + if (!this.opts.date.date) { + this.opts.date.date = this.moment(); } - opts.date.date = toMoment(opts.date.date); + this.opts.date.date = toMoment(this.opts.date.date); - if (opts.date.min) { - opts.date.min = toMoment(opts.date.min); + if (this.opts.date.min) { + this.opts.date.min = toMoment(this.opts.date.min); - if (opts.date.min.isAfter(this.moment(), "day")) { - opts.date.date = this.moment(opts.date.min); + if (this.opts.date.min.isAfter(this.moment(), "day")) { + this.opts.date.date = this.moment(this.opts.date.min); } } - if (opts.date.max) { - opts.date.max = toMoment(opts.date.max); + if (this.opts.date.max) { + this.opts.date.max = toMoment(this.opts.date.max); - if (opts.date.max.isBefore(this.moment(), "day")) { - opts.date.date = this.moment(opts.date.max); + if (this.opts.date.max.isBefore(this.moment(), "day")) { + this.opts.date.date = this.moment(this.opts.date.max); } } this.on("update", () => { - opts.date.date = toMoment(opts.date.date); + this.opts.date.date = toMoment(this.opts.date.date); buildCalendar(); - positionDropdown(); + this.positionDropdown(this.opts.date.isVisible, ".calendar"); }); document.addEventListener("click", handleClickOutside); this.update(); - }); + }); this.on("unmount", () => { document.removeEventListener("click", handleClickOutside); }); this.open = () => { - opts.date.isvisible = true; + this.opts.date.isVisible = true; this.trigger("open"); }; this.close = () => { - if (opts.date.isvisible) { - opts.date.isvisible = false; + if (this.opts.date.isVisible) { + this.opts.date.isVisible = false; this.trigger("close"); } }; this.select = e => { - opts.date.date = e.item.day.date; - this.trigger('select', opts.date.date); + this.opts.date.date = e.item.day.date; + this.trigger('select', this.opts.date.date); }; this.setToday = () => { - opts.date.date = this.moment(); - this.trigger("select", opts.date.date); + this.opts.date.date = this.moment(); + this.trigger("select", this.opts.date.date); }; this.prevYear = () => { - opts.date.date = opts.date.date.subtract(1, "year"); + this.opts.date.date = this.opts.date.date.subtract(1, "year"); }; this.nextYear = () => { - opts.date.date = opts.date.date.add(1, "year"); + this.opts.date.date = this.opts.date.date.add(1, "year"); }; this.prevMonth = () => { - opts.date.date = opts.date.date.subtract(1, "month"); + this.opts.date.date = this.opts.date.date.subtract(1, "month"); }; this.nextMonth = () => { - opts.date.date = opts.date.date.add(1, "month"); + this.opts.date.date = this.opts.date.date.add(1, "month"); }; - function getWindowDimensions() { - var w = window, - d = document, - e = d.documentElement, - g = d.getElementsByTagName("body")[0], - x = w.innerWidth || e.clientWidth || g.clientWidth, - y = w.innerHeight || e.clientHeight || g.clientHeight; - return { width: x, height: y }; - }; - - const positionDropdown = () => { - const w = getWindowDimensions(); - const m = this.root.querySelector(".calendar"); - if (!m) { - return; - } - if (!opts.date.isvisible) { - // Reset position - m.style.marginTop = ""; - m.style.marginLeft = ""; - return; - } - const pos = m.getBoundingClientRect(); - if (w.width < pos.left + pos.width) { - // menu is off the right hand of the page - m.style.marginLeft = (w.width - (pos.left + pos.width) - 20) + "px"; - } - if (pos.left < 0) { - // menu is off the right hand of the page - m.style.marginLeft = "20px"; - } - if (w.height < pos.top + pos.height) { - // Popup is off the bottom of the page - m.style.marginTop = (w.height - (pos.top + pos.height) - 20) + "px"; - } - }; </script> <style scoped> diff --git a/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html b/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html index 8c9f9d1..188b84c 100644 --- a/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/components/time-picker.tag.html @@ -1,7 +1,7 @@ <time-picker> - <input type="time" class="calendar-field" onclick="{open}" value="{opts.time.time.format('HH:mm')}" readonly="{!session.timeInputSupported}" /> + <input type="time" class="calendar-field" onclick="{open}" value="{opts.time.time.format('LT')}" readonly="{!session.timeInputSupported}" /> - <div class="c-calendar c-calendar--higher" if="{opts.time.isvisible && !session.timeInputSupported}"> + <div class="c-calendar c-calendar--higher" if="{opts.time.isVisible && !session.timeInputSupported}"> <div class="time"> <div class="prev action-prev" onclick={nextHour}></div> @@ -20,12 +20,11 @@ </div> <script type="es6"> - let session = require("../../js/Session"); - + this.session = require("../../js/Session"); this.moment = require("moment"); - this.moment.locale(session.locale); + this.moment.locale(this.session.locale); - this.installBundle(session, "time-picker", locale => { + this.installBundle(this.session, "time-picker", locale => { this.opts.time.time.locale(locale); this.moment.locale(locale); }); @@ -48,89 +47,57 @@ }; this.on("mount", () => { - if (!opts.time) { - opts.time = {time: this.moment()}; + if (!this.opts.time) { + this.opts.time = {time: this.moment()}; } - if (!opts.time.time) { - opts.time.time = this.moment(); + if (!this.opts.time.time) { + this.opts.time.time = this.moment(); } - opts.time.time = toMoment(opts.time); + this.opts.time.time = toMoment(this.opts.time.time); + this.on("update", () => { + this.opts.time.time = toMoment(this.opts.time.time); + this.positionDropdown(this.opts.time.isVisible, ".calendar"); + }); document.addEventListener("click", handleClickOutside); - }); + this.update(); + }); this.on("unmount", () => { document.removeEventListener("click", handleClickOutside); }); this.open = () => { - opts.time.isvisible = true; + this.opts.time.isVisible = true; this.trigger("open"); }; this.close = () => { - if (opts.time.isvisible) { - opts.time.isvisible = false; + if (this.opts.time.isVisible) { + this.opts.time.isVisible = false; this.trigger("close"); } }; this.select = e => { - opts.time.time = e.item.day.date; - this.trigger('select', opts.time.time); + this.opts.time.time = e.item.day.date; + this.trigger("select", this.opts.time.time); }; this.prevHour = () => { - opts.time.time = opts.time.time.subtract(1, "hour"); + this.opts.time.time = this.opts.time.time.subtract(1, "hour"); }; this.nextHour = () => { - opts.time.time = opts.time.time.add(1, "hour"); + this.opts.time.time = this.opts.time.time.add(1, "hour"); }; this.prevMinute = () => { - opts.time.time = opts.time.time.subtract(1, "minute"); + this.opts.time.time = this.opts.time.time.subtract(1, "minute"); }; this.nextMinute = () => { - opts.time.time = opts.time.time.add(1, "minute"); - }; - - function getWindowDimensions() { - var w = window, - d = document, - e = d.documentElement, - g = d.getElementsByTagName("body")[0], - x = w.innerWidth || e.clientWidth || g.clientWidth, - y = w.innerHeight || e.clientHeight || g.clientHeight; - return { width: x, height: y }; - }; - - const positionDropdown = () => { - const w = getWindowDimensions(); - const m = this.root.querySelector(".calendar"); - if (!m) { - return; - } - if (!opts.time.isvisible) { - // Reset position - m.style.marginTop = ""; - m.style.marginLeft = ""; - return; - } - const pos = m.getBoundingClientRect(); - if (w.width < pos.left + pos.width) { - // menu is off the right hand of the page - m.style.marginLeft = (w.width - (pos.left + pos.width) - 20) + "px"; - } - if (pos.left < 0) { - // menu is off the right hand of the page - m.style.marginLeft = "20px"; - } - if (w.height < pos.top + pos.height) { - // Popup is off the bottom of the page - m.style.marginTop = (w.height - (pos.top + pos.height) - 20) + "px"; - } + this.opts.time.time = this.opts.time.time.add(1, "minute"); }; </script> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html index 22a40b1..ac65191 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html @@ -3,18 +3,24 @@ require("../components/time-picker.tag.html"); <Choice> <div class="choice-container"> <button type="button" class="c-button fa fa-pencil" alt="texte" onclick="{setTextType}"/> - <input type="text" ref="choiceText" class="{choiceType === 'TEXT' ? 'selected' : 'hidden'}" value="{choiceType === 'TEXT' ? choice.choiceValue : null}"/> + <input type="text" ref="choiceText" class="{choice.choiceType === 'TEXT' ? 'selected' : 'hidden'}" value="{this.opts.choice.choiceType === 'TEXT' ? this.opts.choice.choiceValue : null}"/> - <button type="button" class="c-button fa fa-image" alt="image" onclick="{setImageType}"/> - <input type="file" ref="choiceImage" class="{choiceType === 'RESOURCE' ? 'selected' : 'hidden'}"/> + <button type="button" class="c-button fa fa-image" alt="resource" onclick="{setImageType}"/> + <span if="{originalFile}" class="original-file {choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}"> + <span>{originalFile.name}</span><i class="fa fa-remove" onclick="{deleteFile}"/> + </span> + <input type="file" ref="choiceResource" class="{choice.choiceType === 'RESOURCE' ? 'selected' : 'hidden'}" if="{!originalFile}"/> <button type="button" class="c-button fa fa-calendar" alt="date" onclick="{setDateType}"/> - <date-picker ref="choiceDate" class="{choiceType.startsWith('DATE') ? 'selected' : 'hidden'}" date="{date}"/> + <date-picker ref="choiceDate" class="{choice.choiceType.startsWith('DATE') ? 'selected' : 'hidden'}" date="{date}"/> - <button type="button" class="c-button fa fa-clock-o {!choiceType.startsWith('DATE') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"/> - <time-picker ref="choiceTime" class="{choiceType === 'DATETIME' ? 'selected' : 'hidden'}" time="{time}"/> + <button type="button" class="c-button fa fa-clock-o {!choice.choiceType.startsWith('DATE') ? 'hidden' : ''}" alt="heure" onclick="{toggleTime}"/> + <time-picker ref="choiceTime" class="{choice.choiceType === 'DATETIME' ? 'selected' : 'hidden'}" time="{time}"/> - <input type="hidden" ref="description" value="{choice.description}"/> + <button type="button" class="c-button" alt="description" onclick="{toggleDescription}">...</button> + </div> + <div if="{showDescription}"> + <textarea ref="description" placeholder="{__.description_placeholder}" value="{choice.description}"/> </div> <script type="es6"> @@ -28,79 +34,89 @@ require("../components/time-picker.tag.html"); }); this.number = parseInt(this.opts.number, 10); - this.mode = this.opts.mode; - this.edit = this.opts.mode === "create" || this.opts.mode === "edit"; + //this.mode = this.opts.mode; + //this.edit = this.opts.mode === "create" || this.opts.mode === "edit"; + this.originalFile = this.opts.choice.choiceType === 'RESOURCE' ? this.opts.choice.choiceValue : null; + this.showDescription = false; - if (this.opts.choiceType) { - this.choiceType = this.opts.choiceType; - } else { - this.choiceType = "TEXT"; - } Object.assign(this.choice = {}, this.opts.choice); - if (this.choiceType === "DATE") { + if (this.choice.choiceType.startsWith("DATE")) { this.date = { - date: moment(this.opts.choice.choiceValue) - }; - this.time = { - time: moment() - }; - } else if (this.choiceType === "DATETIME") { - this.time = { - time: moment(this.opts.choice.choiceValue) - }; - this.date = { - date: moment() + date: moment(parseInt(this.opts.choice.choiceValue, 10)) }; } else { this.date = { - date: moment() + date: moment().startOf('day') + }; + } + + if (this.choice.choiceType === "DATETIME") { + this.time = { + time: moment(parseInt(this.opts.choice.choiceValue, 10)) }; + } else { this.time = { - time: moment() + time: moment().startOf('day') }; } - this.on("mount", () => { + /*this.on("mount", () => { if (this.number === 0 || this.mode === "edit") { //this.refs.choice.required = "required"; } if (this.mode === "edit") { //this.refs.edit_choice.classList.add("choice-view"); } - }); + });*/ this.setTextType = () => { - this.choiceType = "TEXT"; + this.choice.choiceType = "TEXT"; }; this.setImageType = () => { - this.choiceType = "RESOURCE"; + this.choice.choiceType = "RESOURCE"; }; this.setDateType = () => { - if (!this.choiceType.startsWith("DATE")) { - this.choiceType = "DATE"; + if (!this.choice.choiceType.startsWith("DATE")) { + this.choice.choiceType = "DATE"; } }; this.toggleTime = () => { - if (this.choiceType === "DATE") { - this.choiceType = "DATETIME"; - } else if (this.choiceType === "DATETIME") { - this.choiceType = "DATE"; + if (this.choice.choiceType === "DATE") { + this.choice.choiceType = "DATETIME"; + } else if (this.choice.choiceType === "DATETIME") { + this.choice.choiceType = "DATE"; } }; + this.deleteFile = () => { + delete this.originalFile; + }; + + this.toggleDescription = () => { + this.showDescription = !this.showDescription; + }; + this.getValue = () => { let choiceValue = {}; - if (this.choiceType === "TEXT") { - console.log("TEXT"); + if (this.choice.choiceType === "RESOURCE") { + choiceValue = this.originalFile ? this.originalFile : this.refs.choiceResource.files[0]; + + } else if (this.choice.choiceType.startsWith("DATE")) { + let selectedMoment = this.date.date; + if (this.choice.choiceType === "DATETIME") { + selectedMoment.set({hour: this.time.time.hour(), minute: this.time.time.minute()}); + } + choiceValue = selectedMoment.valueOf(); + + } else { choiceValue = this.refs.choiceText.value; - } else if (this.choiceType.startsWith("DATE")) { - choiceValue = this.refs.choiceDate.value; } console.log(choiceValue); - return new Choice(this.choiceType, choiceValue, this.refs.description.value, this.choice.id); + console.log(this.refs.description) + return new Choice(this.choice.choiceType, choiceValue, this.refs.description && this.refs.description.value, this.choice.id); }; /*this.onEditChoice = () => { @@ -189,6 +205,14 @@ require("../components/time-picker.tag.html"); max-width: 100px; } + .original-file.selected * { + padding: 10px; + } + + textarea { + width: 100%; + } + </style> </Choice> diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/CreatePoll.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/CreatePoll.tag.html index fd4e53d..26f4e86 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/CreatePoll.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/CreatePoll.tag.html @@ -106,7 +106,7 @@ require("./Created.tag.html"); if (this.form.step !== this.form.steps.length - 1) { this.form.nextStep(); } else { - this.form.create().then(() => { + this.form.create(() => { let route = require("riot-route"); route("poll/" + this.form.model.id + "/vote/" + this.form.model.permission); }); diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html index 1e615aa..bdd817b 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html @@ -24,8 +24,7 @@ </div> </div> <div each={choice in poll.choices} class="choice"> - <div class="choice-value"> - {choice.choiceValue} + <div id="{choice.id}" class="choice-value"> </div> <div class="current-choice"> <input if={poll.voteCountingTypeValue.renderType==='checkbox'} @@ -133,6 +132,9 @@ <script type="es6"> this.loaded = false; let session = require("../../js/Session"); + let Remarkable = require("remarkable"); + this.md = new Remarkable(); + this.installBundle(session, "poll_votes"); session.getUser().then(user => { this.userName = user && user.name; @@ -149,6 +151,18 @@ }).then(() => { this.loaded = true; this.update(); + this.choices.forEach(c => { + if (c.choiceType === "DATE") { + c.choiceValueStr = moment(parseInt(c.choiceValue, 10)).format("LL"); + } else if (c.choiceType === "DATETIME") { + c.choiceValueStr = moment(parseInt(c.choiceValue, 10)).format("LLL"); + } else if (c.choiceType === "RESOURCE") { + c.choiceValueStr = ""; + } else { + c.choiceValueStr = c.choiceValue; + } + document.getElementById(c.id).innerHTML = this.md.render(c.choiceValueStr); + }); }); this.voteId = null; -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 8f6b10d98ca302bba6a8a4b86ff9db57cb1dbd56 Author: Kevin Morin <morin@codelutin.com> Date: Thu Mar 9 17:11:41 2017 +0100 gestion de l'édition des choix de type resource --- pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html | 2 -- 1 file changed, 2 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html index ac65191..8364965 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Choice.tag.html @@ -34,8 +34,6 @@ require("../components/time-picker.tag.html"); }); this.number = parseInt(this.opts.number, 10); - //this.mode = this.opts.mode; - //this.edit = this.opts.mode === "create" || this.opts.mode === "edit"; this.originalFile = this.opts.choice.choiceType === 'RESOURCE' ? this.opts.choice.choiceValue : null; this.showDescription = false; -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 1fd5df63ccbbd27f383a8c30aa80e240871457a7 Author: Kevin Morin <morin@codelutin.com> Date: Fri Mar 10 16:43:30 2017 +0100 ajout de la description --- pollen-ui-riot-js/src/main/web/i18n.json | 2 ++ pollen-ui-riot-js/src/main/web/index.js | 1 + pollen-ui-riot-js/src/main/web/js/FetchService.js | 3 -- pollen-ui-riot-js/src/main/web/js/UIHelper.js | 38 ++++++++++++++++++++++ pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html | 2 -- 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/i18n.json b/pollen-ui-riot-js/src/main/web/i18n.json index 7d7b0f8..9cbb9cb 100644 --- a/pollen-ui-riot-js/src/main/web/i18n.json +++ b/pollen-ui-riot-js/src/main/web/i18n.json @@ -228,6 +228,7 @@ "users_VALIDATION": "En cours de validation", "users_DISABLED": "Désactivé", "users_BANNED": "Banni", + "choice_description_placeholder": "Vous pouvez saisir une description", "date-picker_today": "Aujourd'hui" }, "en": { @@ -453,6 +454,7 @@ "users_VALIDATION": "Account validation", "users_DISABLED": "Account disabled", "users_BANNED": "Account banned", + "choice_description_placeholder": "You can enter a description", "date-picker_today": "Today" } } diff --git a/pollen-ui-riot-js/src/main/web/index.js b/pollen-ui-riot-js/src/main/web/index.js index dbadd47..08e2a76 100644 --- a/pollen-ui-riot-js/src/main/web/index.js +++ b/pollen-ui-riot-js/src/main/web/index.js @@ -19,6 +19,7 @@ // * #L% // */ riot.mixin(require("./js/I18nHelper")); +riot.mixin(require("./js/UIHelper")); require("./tag/Pollen.tag.html"); riot.mount("*"); diff --git a/pollen-ui-riot-js/src/main/web/js/FetchService.js b/pollen-ui-riot-js/src/main/web/js/FetchService.js index b7d4589..2c26359 100644 --- a/pollen-ui-riot-js/src/main/web/js/FetchService.js +++ b/pollen-ui-riot-js/src/main/web/js/FetchService.js @@ -101,15 +101,12 @@ class FetchService { form(url, data, doNotStringify) { let formData = null; - console.log(data); if (data) { formData = new FormData(); let keys = Object.keys(data); keys.forEach((key) => { let value = data[key]; - console.log(key); - console.log(value); if (!doNotStringify && (typeof value === "object")) { formData.set(key, JSON.stringify(value)); } else { diff --git a/pollen-ui-riot-js/src/main/web/js/UIHelper.js b/pollen-ui-riot-js/src/main/web/js/UIHelper.js new file mode 100644 index 0000000..f3808aa --- /dev/null +++ b/pollen-ui-riot-js/src/main/web/js/UIHelper.js @@ -0,0 +1,38 @@ +module.exports = { + getWindowDimensions() { + var w = window, + d = document, + e = d.documentElement, + g = d.getElementsByTagName("body")[0], + x = w.innerWidth || e.clientWidth || g.clientWidth, + y = w.innerHeight || e.clientHeight || g.clientHeight; + return { width: x, height: y }; + }, + + positionDropdown(selector, visible) { + const w = this.getWindowDimensions(); + const m = this.root.querySelector(selector); + if (!m) { + return; + } + if (!visible) { + // Reset position + m.style.marginTop = ""; + m.style.marginLeft = ""; + return; + } + const pos = m.getBoundingClientRect(); + if (w.width < pos.left + pos.width) { + // menu is off the right hand of the page + m.style.marginLeft = (w.width - (pos.left + pos.width) - 20) + "px"; + } + if (pos.left < 0) { + // menu is off the right hand of the page + m.style.marginLeft = "20px"; + } + if (w.height < pos.top + pos.height) { + // Popup is off the bottom of the page + m.style.marginTop = (w.height - (pos.top + pos.height) - 20) + "px"; + } + } +}; diff --git a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html index c57b37d..9075e83 100644 --- a/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/Pollen.tag.html @@ -35,8 +35,6 @@ require("./Users.tag.html"); <script type="es6"> let session = require("../js/Session"); - - session.start().then(() => { // console.info("session started"); }); -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
This is an automated email from the git hooks/post-receive script. New commit to branch feature/component_choice_editor in repository pollen. See https://gitlab.nuiton.org/chorem/pollen.git commit 1bad9bfdea6777c68dae5d0cf49e3fee041aaadd Author: Kevin Morin <morin@codelutin.com> Date: Fri Mar 10 17:17:06 2017 +0100 gestion des images --- .../src/main/web/tag/poll/Votes.tag.html | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html index bdd817b..cdf5f56 100644 --- a/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html +++ b/pollen-ui-riot-js/src/main/web/tag/poll/Votes.tag.html @@ -23,7 +23,7 @@ {error['voter.name']} </div> </div> - <div each={choice in poll.choices} class="choice"> + <div each={choice in poll.choices} class="choice {choice.choiceType === 'RESOURCE' ? 'choice-resource' : ''}"> <div id="{choice.id}" class="choice-value"> </div> <div class="current-choice"> @@ -134,8 +134,13 @@ let session = require("../../js/Session"); let Remarkable = require("remarkable"); this.md = new Remarkable(); + this.moment = require("moment"); + this.moment.locale(session.locale); - this.installBundle(session, "poll_votes"); + this.installBundle(session, "poll_votes", (locale) => { + this.moment.locale(locale); + this.updateChoices(); + }); session.getUser().then(user => { this.userName = user && user.name; }); @@ -151,11 +156,15 @@ }).then(() => { this.loaded = true; this.update(); - this.choices.forEach(c => { + this.updateChoices(); + }); + + this.updateChoices = () => { + this.poll.choices.forEach(c => { if (c.choiceType === "DATE") { - c.choiceValueStr = moment(parseInt(c.choiceValue, 10)).format("LL"); + c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LL"); } else if (c.choiceType === "DATETIME") { - c.choiceValueStr = moment(parseInt(c.choiceValue, 10)).format("LLL"); + c.choiceValueStr = this.moment(parseInt(c.choiceValue, 10)).format("LLL"); } else if (c.choiceType === "RESOURCE") { c.choiceValueStr = ""; } else { @@ -163,7 +172,7 @@ } document.getElementById(c.id).innerHTML = this.md.render(c.choiceValueStr); }); - }); + }; this.voteId = null; this.error = {}; @@ -335,6 +344,10 @@ justify-content: center; } + .voters .fix .choice.choice-resource { + height: 200px; + } + .check { width: 25px; height: 25px; -- To stop receiving notification emails like this one, please contact chorem.org SCM administrator <admin+scm@chorem.org>.
participants (1)
-
chorem.org scm