Skip to content
Commits on Source (42)
......@@ -39,7 +39,7 @@ stages:
- !reference [.rules-map, on-dev]
- !reference [.rules-map, not-on-semantic-release-commit]
- !reference [.rules-map, on-branch]
image: hub.eole.education/proxyhub/geoffreybooth/meteor-base:2.12
image: hub.eole.education/proxyhub/geoffreybooth/meteor-base:2.13
cache:
key:
files:
......
......@@ -6,7 +6,7 @@
meteor-base@1.5.1 # Packages every Meteor app needs to have
mobile-experience@1.1.0 # Packages for a great mobile UX
mongo@1.16.6 # The database Meteor supports right now
mongo@1.16.7 # The database Meteor supports right now
reactive-var@1.0.12 # Reactive variable for tracker
tracker@1.3.2 # Meteor's client-side reactive programming library
......
......@@ -20,7 +20,7 @@ ddp@1.4.1
ddp-client@2.6.1
ddp-common@1.4.0
ddp-rate-limiter@1.2.0
ddp-server@2.6.1
ddp-server@2.6.2
diff-sequence@1.1.2
dynamic-import@0.7.3
ecmascript@0.16.7
......@@ -47,7 +47,7 @@ launch-screen@1.3.0
localstorage@1.2.0
logging@1.3.2
mdg:validated-method@1.3.0
meteor@1.11.2
meteor@1.11.3
meteor-base@1.5.1
meteortesting:browser-tests@1.5.1
meteortesting:mocha@2.1.0
......@@ -61,7 +61,7 @@ modern-browsers@0.1.9
modules@0.19.0
modules-runtime@0.13.1
modules-runtime-hot@0.14.2
mongo@1.16.6
mongo@1.16.7
mongo-decimal@0.1.3
mongo-dev-server@1.1.0
mongo-id@1.0.8
......
# The tag here should match the Meteor version of your app, per .meteor/release
FROM hub.eole.education/proxyhub/geoffreybooth/meteor-base:2.12
FROM hub.eole.education/proxyhub/geoffreybooth/meteor-base:2.13
# Copy app package.json and package-lock.json into container
#COPY ./app/package*.json $APP_SOURCE_FOLDER/
......@@ -14,7 +14,7 @@ RUN bash $SCRIPTS_FOLDER/build-meteor-bundle.sh
# Rather than Node 8 latest (Alpine), you can also use the specific version of Node expected by your Meteor release, per https://docs.meteor.com/changelog.html
FROM hub.eole.education/proxyhub/library/node:14.21.3-alpine
FROM hub.eole.education/proxyhub/meteor/node:14.21.4-alpine3.17
ENV APP_BUNDLE_FOLDER /opt/bundle
ENV SCRIPTS_FOLDER /docker
......@@ -37,7 +37,7 @@ RUN bash $SCRIPTS_FOLDER/build-meteor-npm-dependencies.sh --build-from-source
# Start another Docker stage, so that the final image doesn’t contain the layer with the build dependencies
# See previous FROM line; this must match
FROM hub.eole.education/proxyhub/library/node:14.21.3-alpine
FROM hub.eole.education/proxyhub/meteor/node:14.21.4-alpine3.17
ENV APP_BUNDLE_FOLDER /opt/bundle
ENV SCRIPTS_FOLDER /docker
......
......@@ -7,7 +7,11 @@
"services": {
"sondagesUrl": "http://localhost:3010"
},
"laboiteHost": "http://localhost:3000"
"laboiteHost": "http://localhost:3000",
"matomo": {
"siteIdSondage": 1,
"urlBase": ""
}
},
"keycloak": {
"pubkey": "",
......
# Changelog
## [1.9.0](https://gitlab.mim-libre.fr/alphabet/sondage/compare/release/1.8.1...release/1.9.0) (2023-11-07)
### Features
* **calendar:** change button order and set default view ([2b38f41](https://gitlab.mim-libre.fr/alphabet/sondage/commit/2b38f417415b6425cf829fc6fd9c964c2f5f2c2e))
* **calendar:** change default view in meeting answer ([b3559d1](https://gitlab.mim-libre.fr/alphabet/sondage/commit/b3559d134e768d5287bdcd4a14b3e303377314be))
* **date:** add scrolling for date picking in meetings and polls step 2 ([c5ce164](https://gitlab.mim-libre.fr/alphabet/sondage/commit/c5ce164736aa0874931572e83de2ed11296286e2))
* **libs:** update docker node image ([4139076](https://gitlab.mim-libre.fr/alphabet/sondage/commit/4139076d8d3d79e0c44418284b409f4cb058fefb))
* **libs:** updated npm libs to wanted version ([ef25d32](https://gitlab.mim-libre.fr/alphabet/sondage/commit/ef25d32d3c0989c58b4a547548d2ea73da9ddcd8))
* **matomo:** integrate matomo client in App.svelte ([0c6dbc9](https://gitlab.mim-libre.fr/alphabet/sondage/commit/0c6dbc90d315d2f63144307d4277be9940488129))
* **meeting:** add more slots choices ([2a91c68](https://gitlab.mim-libre.fr/alphabet/sondage/commit/2a91c68dc74ec367350c41b1a6f1390a14c5f22d))
* **node:** change node version to previous version ([70c8a4b](https://gitlab.mim-libre.fr/alphabet/sondage/commit/70c8a4b6016f353390c97e0c2d1eba8cf0841dfc))
* **poll:** display author and creation date on poll answer page ([5e35cee](https://gitlab.mim-libre.fr/alphabet/sondage/commit/5e35ceea9a4ff13269b9b461dac71ccde44c7503))
* **style:** add style to redirection page ([2376379](https://gitlab.mim-libre.fr/alphabet/sondage/commit/2376379bfcc352c18c97257b6f2941e428fb5aa8))
### Bug Fixes
* **emails:** don't send email to poll creator (only for meetings) ([1aee8c9](https://gitlab.mim-libre.fr/alphabet/sondage/commit/1aee8c92bce6cc907ab3423f5ff543efe8a85518))
* **fr.json:** spelling correction ([7eb8abb](https://gitlab.mim-libre.fr/alphabet/sondage/commit/7eb8abbfb8f666a4d3d2bb4b03157ad9368f54cb))
* **fr.json:** spelling corrections ([b8c3e4b](https://gitlab.mim-libre.fr/alphabet/sondage/commit/b8c3e4bf0165bc0bed2ddd3b8cec17a1d88cbee5))
* **i18n:** update messages when answer on public meeting ([a3f08a6](https://gitlab.mim-libre.fr/alphabet/sondage/commit/a3f08a68305ff1a49e07e636613ff0104412a84f))
* **meetings:** notification when a meeting has been edited/cancelled ([52d273c](https://gitlab.mim-libre.fr/alphabet/sondage/commit/52d273c08d6eda125a82f5be7e6d3ea6454421f2))
* **poll:** display last modification date instead of creation date ([3d5b197](https://gitlab.mim-libre.fr/alphabet/sondage/commit/3d5b197c9a64977e81eb15af2faa0cda84ef5465))
* **polls:** disable button to not be able to create private polls ([929ef97](https://gitlab.mim-libre.fr/alphabet/sondage/commit/929ef97d0f576ea1981c3984de33f6a60773774d))
* **smtp:** better error message when sending email fails ([ec23333](https://gitlab.mim-libre.fr/alphabet/sondage/commit/ec2333340e7d7454611bef88ada70b720294e05f))
* **timeslots:** sort days at TimeStep and ValidationStep ([135496d](https://gitlab.mim-libre.fr/alphabet/sondage/commit/135496d99006173c3bce2e31249aa213450b85b8))
* **timeslots:** sort poll time slots at validation step ([8950fed](https://gitlab.mim-libre.fr/alphabet/sondage/commit/8950fed1159c063666b1002036d46ab1b695235a))
### [1.8.1](https://gitlab.mim-libre.fr/alphabet/sondage/compare/release/1.8.0...release/1.8.1) (2023-08-28)
......
......@@ -60,7 +60,7 @@ export const adminMeetingTemplate = ({ sender, title, date, url, connected }) =>
</div>
<br/>
<div>
Vous pouvez valider le créneau avec le liens suivant ${url}
Vous pouvez valider le créneau avec le lien suivant ${url}
</div>
<br/>
`;
......@@ -28,14 +28,19 @@ export function sendEmail(poll, answer) {
sender: Meteor.users.findOne(poll.userId),
date: moment(answer.meetingSlot).format('LLL (Z)'),
});
Email.send({
to: answer.email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - Votre rdv du ${moment(answer.meetingSlot).format('L')}`,
icalEvent: cal.toString(),
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
try {
Email.send({
to: answer.email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - Votre rdv du ${moment(answer.meetingSlot).format('L')}`,
icalEvent: cal.toString(),
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
} catch (error) {
console.log(error);
throw new Meteor.Error('api.events.methods.sendEmail', 'api.errors.cannotSendEmail');
}
}
export function sendEmailToCreator(poll, answer, userId) {
......@@ -56,39 +61,54 @@ export function sendEmailToCreator(poll, answer, userId) {
url: `${Meteor.settings.public.services.sondagesUrl}/poll/answer/${poll._id} `,
connected,
});
Email.send({
to: admin.emails[0].address,
from: Meteor.settings.smtp.fromEmail,
subject: `Rendez-vous - nouveau créneau sélectionné pour le rendez-vous ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
try {
Email.send({
to: admin.emails[0].address,
from: Meteor.settings.smtp.fromEmail,
subject: `Rendez-vous - nouveau créneau sélectionné pour le rendez-vous ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
} catch (error) {
console.log(error);
throw new Meteor.Error('api.events.methods.sendEmailToCreator', 'api.errors.cannotSendEmailToCreator');
}
}
export function sendCancelEmail(poll, answer, content) {
const template = meetingCancelTemplate;
const html = template({ date: moment(answer.meetingSlot).format('LLL (Z)'), content });
Email.send({
to: answer.email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - annulation de votre rendez-vous pour ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
try {
Email.send({
to: answer.email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - annulation de votre rendez-vous pour ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
} catch (error) {
console.log(error);
throw new Meteor.Error('api.events.methods.sendCancelEmail', 'api.errors.cannotSendEmail');
}
}
export function sendEditEmail(poll, email, name, meetingSlot) {
const template = meetingEditTemplate;
const html = template({ date: moment(meetingSlot).format('LLL (Z)'), email, name });
Email.send({
to: email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - Edition de votre rendez-vous pour ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
try {
Email.send({
to: email,
from: Meteor.settings.smtp.fromEmail,
subject: `Sondage - Edition de votre rendez-vous pour ${poll.title}`,
inReplyTo: Meteor.settings.smtp.toEmail,
html,
});
} catch (error) {
console.log(error);
throw new Meteor.Error('api.events.methods.sendEditEmail', 'api.errors.cannotSendEmail');
}
}
export function createEventAgendaMeeting(poll, answer, userId) {
......
......@@ -46,8 +46,10 @@ export const getSinglePollToAnswer = new ValidatedMethod({
},
{ fields: { _id: 1 } },
);
const author = Meteor.users.findOne(poll.userId) || { firstName: '', lastName: '' };
const data = {
poll,
author: { firstName: author.firstName, lastName: author.lastName },
selectedGroups: Groups.find({ _id: { $in: poll.groups } }).fetch(),
answer: this.userId ? PollsAnswers.findOne({ pollId, userId: this.userId }) : null,
};
......
......@@ -74,7 +74,7 @@ export const createPollAnswers = new ValidatedMethod({
throw new Meteor.Error('api.polls_answers.methods.create.notAllowed', 'api.errors.notAllowed');
}
} else if ((poll.public || this.userId) && poll.active) {
sendEmailToCreator(poll, data, this.userId);
if (poll.type === POLLS_TYPES.MEETING) sendEmailToCreator(poll, data, this.userId);
return PollsAnswers.update(
{ pollId: data.pollId, email: data.email },
{ $set: { ...data, userId: this.userId, confirmed: false } },
......
<script>
import { Meteor } from 'meteor/meteor';
import { _ } from 'svelte-i18n';
import { SvelteToast } from '@zerodevx/svelte-toast';
import { onMount } from 'svelte';
import Matomo, { matomo } from '@dexlib/svelte-matomo';
import '/imports/utils/locales/index';
import Router from '/imports/ui/Router.svelte';
......@@ -11,9 +14,16 @@
import PackageJSON from '../../package.json';
let version = PackageJSON.version;
const { matomo: matomoSettings } = Meteor.settings.public;
onMount(() => {
if (matomoSettings?.urlBase) {
matomo.trackPageView();
}
});
let width;
const { setState } = globalState();
const checkDeviceSize = () => {
setState({ mobile: width < 768 });
};
......@@ -29,12 +39,18 @@
<Nav />
<main>
{#if matomoSettings?.urlBase}
<Matomo url={matomoSettings.urlBase} siteId={matomoSettings.siteIdSondage} />
{/if}
<Router />
</main>
<Footer />
<style>
:root {
--toastWidth: 24rem;
}
main {
padding-top: calc(52px + var(--space-between));
min-height: calc(100vh - 64px);
......
......@@ -5,8 +5,8 @@
<section class="hero is-medium is-grey is-bold is-centered">
<div class="hero-body">
<div class="container has-text-centered">
<div class="title is-4">{$_('pages.end.title')}</div>
<div class="content is-4">{$_('pages.end.content')}</div>
<div class="title is-4">{$_('pages.end.title')}<i class="fas fa-check-circle ml-4" color="green" /></div>
<span class="content is-4 is-italic">{$_('pages.end.content')}</span>
</div>
</div>
</section>
......
......@@ -76,7 +76,7 @@
});
$: options = {
initialView: 'listWeek',
initialView: 'timeGridWeek',
plugins: [timeGridPlugin, interactionPlugin, listView],
firstDay: 1,
allDaySlot: false,
......@@ -94,7 +94,7 @@
timeGridWeek: $_('pages.answer.timeGridWeek'),
},
headerToolbar: {
left: 'listWeek timeGridWeek',
left: 'timeGridWeek listWeek',
},
locale: $locale,
timeZone: 'local',
......
......@@ -24,6 +24,7 @@
console.log(e);
toast.push($_(e.reason), toasts.error);
} else {
toast.push($_(`components.MeetingAnswerCancel.${emailNotice ? 'userNotified' : 'userNotNotified'}`));
router.goto(ROUTES.ANSWER_POLL_RM(answer.pollId));
}
});
......
......@@ -35,6 +35,7 @@
console.log(e);
toast.push($_(e.reason), toasts.error);
} else {
toast.push($_(`components.MeetingAnswerEdit.${emailNotice ? 'userNotified' : 'userNotNotified'}`));
router.goto(ROUTES.ANSWER_POLL_RM(answer.pollId));
}
});
......
......@@ -28,6 +28,7 @@
export let meta;
let selectedGroups;
let poll = {};
let author = { firstName: '', lastName: '' };
let loading = false;
let askToConnect = false;
let answer = {
......@@ -47,6 +48,7 @@
loading = false;
if (r) {
poll = r.poll;
author = r.author;
selectedGroups = r.selectedGroups;
if (r.answer) {
answer = r.answer;
......@@ -164,12 +166,17 @@
{#if poll._id}
<div class="box">
<div class="columns is-multiline">
<div class="column is-full">
<div class="column is-half">
<div class="field">
<label class="label">{$_('pages.answer.description')}</label>
{poll.description || ''}
</div>
</div>
<div class="column is-half">
<label class="label">{$_('pages.answer.author')}</label>
{author.firstName}
{author.lastName} ({moment(poll.updatedAt).format('LLL')})
</div>
<div class="column is-half">
<div class="field">
<div class="control">
......
......@@ -69,6 +69,12 @@
return '00:10:00';
case '00:15':
return '00:15:00';
case '00:20':
return '00:20:00';
case '00:25':
return '00:25:00';
case '00:45':
return '00:45:00';
default:
return '00:30:00';
}
......
......@@ -200,7 +200,8 @@
</div>
<div class="column is-half-desktop is-full-mobile is-right">
<BigLink
disabled={!$newPollStore.title}
disabled={(!$newPollStore.title || !$newPollStore.public) &&
(!$newPollStore.title || !!$newPollStore.groups.length == 0)}
link={meta.params._id ? ROUTES.EDIT_POLL_RM(meta.params._id, 2) : ROUTES.NEW_POLL_RM(2)}
text={$_('pages.new_poll.next')}
/>
......
......@@ -60,7 +60,6 @@
$newPollStore.dates[i].slots[index] = time;
});
};
</script>
<svelte:head>
......@@ -122,7 +121,7 @@
{/if}
<tbody>
{#each $newPollStore.dates as day}
{#each $newPollStore.dates.sort((a, b) => a.date - b.date) as day}
<tr>
<th>
{moment(day.date).format($_('components.Time.dateFormat'))}
......@@ -195,5 +194,4 @@
.fa-trash {
color: red;
}
</style>