This commit is contained in:
root 2020-07-21 14:41:07 +00:00
parent 0c881c919b
commit 4a97c240eb
16 changed files with 217 additions and 59 deletions

View file

@ -25,7 +25,7 @@ export default class EmailService {
pass: process.env.SMTP_PASSWORD,
}
}
console.log(config)
//console.log(config)
return nodemailer.createTransport(config)
}
@ -73,7 +73,7 @@ export default class EmailService {
} else {
this.nativeSend(config).then(res => {
console.log('> A "' + templateName + '" email was sent')
resolve()
resolve(res)
}).catch(err => {
console.log('> A "' + templateName + '" email failed to be sent')
console.error(err)

View file

@ -19,6 +19,8 @@ export default class AdminOrganizationController {
}
static import(req: express.Request, res: express.Response) {
// first column is always name
// second column is always email
const data = req.body.csv
res.json({
success: true,
@ -69,8 +71,8 @@ export default class AdminOrganizationController {
.then(data => {
// generate extra slugs
let extra: any = {}
if (req.body.name !== undefined) {
let slug = slugify(req.body.name)
if (req.body.adminName !== undefined) {
let slug = slugify(req.body.adminName)
// only add this slug if the proposed slug is not found in the list of current slug
let currentSlugs: string[] = []
if (data !== null && Array.isArray(data.get('slugs'))) {
@ -164,6 +166,22 @@ export default class AdminOrganizationController {
const publishedVersion: any = data.get('publishedVersion')
const proposedVersion: any = data.get('proposedVersion')
// generate extra slugs
// in case of a change by the organization it self, we need to keep up to date the slug
let extra: any = {}
let slug = slugify(proposedVersion.name)
// only add this slug if the proposed slug is not found in the list of current slug
let currentSlugs: string[] = []
if (Array.isArray(data.get('slugs'))) {
currentSlugs = data.get('slugs')
}
if (currentSlugs.filter(s => s === slug).length === 0) {
extra.slugs = currentSlugs.concat([slug])
}
extra.adminName = proposedVersion.name
extra.email = proposedVersion.contacts.email
/**
* Clean all the unused media from the publishedVersion
*/
@ -203,6 +221,7 @@ export default class AdminOrganizationController {
*/
Organization.updateOne({ _id: req.params.id }, {
...extra,
publishedVersion: data.get('proposedVersion'),
rejectionDescription: '',
validationState: 'published',

View file

@ -59,15 +59,17 @@ export default class DefaultController {
static async sendEmail(req: express.Request, res: express.Response) {
// create reusable transporter object using the default SMTP transport
EmailService.getTransporter().sendMail({
from: '"Some Sender" <noreply@somedomain.com>',
to: "spamfree@matthieubessat.fr",
subject: "Hello ✔",
text: "Hello world? Comment va tu Earum facilis libero excepturi sunt fuga eveniet autem. Illo odit quae aperiam et praesentium. Error dignissimos atque omnis. Ea iste in doloribus praesentium corrupti. Ut consequatur eius eveniet quia aut. Nam a rerum quis. Repudiandae sit nobis esse. Eaque ipsum qui enim. Expedita laudantium officia omnis maxime. Odio exercitationem recusandae quis consequatur voluptatum.",
html: "<p><b>Hello world?</b> Comment va tu Earum facilis libero excepturi sunt fuga eveniet autem. Illo odit quae aperiam et praesentium. Error dignissimos atque omnis. Ea iste in doloribus praesentium corrupti. Ut consequatur eius eveniet quia aut. Nam a rerum quis. Repudiandae sit nobis esse. Eaque ipsum qui enim. Expedita laudantium officia omnis maxime. Odio exercitationem recusandae quis consequatur voluptatum.</p>",
}).then(info => {
console.log("Message sent: %s", info.messageId);
console.log("Preview URL: %s", nodemailer.getTestMessageUrl(info));
EmailService.send(
'matthieu.bessat.27@gmail.com',
"Email de test",
"token",
{
adminName: "Assos de test",
token: "tokendetest",
link: EmailService.getWebUiBaseUrl() + '/delegate?delegateToken=tokendetest'
}
).then(info => {
console.log(info)
}).catch(err => {
console.error(err)
})

View file

@ -22,6 +22,7 @@ export default class PublicController {
// })
Tag.find().then(tags => {
let isProposed = Utils.isStrUsable(req.query, 'only')
// @ts-ignore
if (isProposed && !mongoose.Types.ObjectId.isValid(req.query.only)) {
return ErrorController.handleServerError({ stack: 'Invalid object id in only query param'}, req, res, [])
}
@ -105,10 +106,19 @@ export default class PublicController {
return media
})
}
version.cutDescription = Utils.isStrUsable(version, 'descriptionLong') && version.descriptionLong.length > 200
// if (version.cutDescription) {
// version.descriptionFirstHalf = version.descriptionLong.substr(0, 200) // not gonna lie
// version.descriptionSecondHalf = version.descriptionLong.substr(200)
// }
let hour = lastPublished.toLocaleTimeString('fr-FR', { timezone: '+2' })
if (hour.charAt(1) === ':') {
hour = '0' + hour
}
res.render('organization.twig', {
layout: 'standalone',
data: version,
lastPublished: lastPublished.toLocaleDateString('fr-FR') + ' ' + lastPublished.toLocaleTimeString('fr-FR', { timezone: '+2' }).substr(0, 5),
lastPublished: lastPublished.toLocaleDateString('fr-FR') + ' ' + hour.substr(0, 5),
isProposed,
id: org.get('_id')
})

View file

@ -58,7 +58,13 @@ const OrganizationVersion = {
address: { type: String },
person: { type: String },
email: { type: String },
phone: { type: String }
phone: { type: String },
peoples: [{
name: { type: String },
email: { type: String },
phone: { type: String },
role: { type: String }
}]
},
schedule: [{
name: { type: String, required: true },

View file

@ -181,15 +181,16 @@
margin-bottom: 1em;
box-shadow: 0 0 8px 0px rgba(0,0,0,0.1);
transition: all 0.2s;
height: 12em;
overflow: hidden;
text-decoration: none;
}
.card:hover {
text-decoration: none;
transform: scale(1.02);
}
.card-image {
.card-image-container {
border-right: 1px solid #C4C4C4;
display: flex;
@ -199,8 +200,12 @@
padding: 1em;
}
.card-image img {
.card-image {
height: 12em;
width: 12em;
background-position: center;
background-size: cover;
}
.card-content {
@ -332,9 +337,13 @@
.card {
display: block;
}
.card-image {
.card-image-container {
padding: 0;
margin: 0;
border-right: 0;
border-bottom: 1px solid #C4C4C4;
margin: 0;
}
.card-content {
width: auto;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View file

@ -15,12 +15,12 @@ navEnabler.onclick = async () => {
// open the menu
oldNavText = navEnablerText.textContent
navEnablerText.textContent = "Minimiser le menu"
navEnablerIcon.style.transform = "rotate(0deg)"
navEnablerIcon.style.transform = "rotate(90eg)"
navContent.style.maxHeight = navContent.scrollHeight + "px"
} else {
// close the menu
navEnablerText.textContent = oldNavText
navEnablerIcon.style.transform = "rotate(-90deg)"
navEnablerIcon.style.transform = "rotate(0deg)"
navContent.style.maxHeight = null
}
navOpened = !navOpened
@ -82,12 +82,12 @@ function setAttributes(node, attrs) {
}
function renderCard(organization) {
let card = createEl('card')
let card = createEl('card', 'a')
// image
let image = createEl('card-image')
let imageTag = createEl(0, 'img')
imageTag.src = organization.thumbnail
let image = createEl('card-image-container')
let imageTag = createEl('card-image')
imageTag.style = `background-image: url('${organization.thumbnail}')`
image.appendChild(imageTag)
card.appendChild(image)
@ -117,14 +117,15 @@ function renderCard(organization) {
let description = createEl('card-description')
description.textContent = organization.description
//let link = createEl('card-link')
let aTag = createEl('card-link', 'a')
aTag.href = "/association/" + organization.slugs[organization.slugs.length - 1]
let goTo = "/association/" + organization.slugs[organization.slugs.length - 1]
if (organization.isProposed) {
aTag.href += "?version=proposed"
goTo += "?version=proposed"
}
aTag.textContent = "En savoir plus"
description.appendChild(aTag)
// let link = createEl('card-link')
// let aTag = createEl('card-link', 'a')
// aTag.href =
// aTag.textContent = "En savoir plus"
// description.appendChild(aTag)
upperContent.appendChild(description)
//link.appendChild(aTag)
@ -132,9 +133,11 @@ function renderCard(organization) {
//content.appendChild(link)
card.appendChild(content)
card.onclick = () => {
window.location = aTag.href
}
card.href = goTo
// card.onclick = () => {
// window.location = goTo
// }
return card
}

View file

@ -9,17 +9,43 @@ document.querySelectorAll('.schedule-category').forEach(node => {
header.onclick = () => {
if (!opened) {
// open the table
icon.style.transform = "rotate(180deg)"
icon.style.transform = "rotate(0deg)"
content.style.maxHeight = content.scrollHeight + "px"
} else {
// close the table
icon.style.transform = "rotate(0deg)"
icon.style.transform = "rotate(180deg)"
content.style.maxHeight = null
}
opened = !opened
}
})
/**
* Description
*/
let description = document.querySelector('.description-cutted')
let descriptionActions = document.querySelector('.description-actions-container')
let descriptionOpened = false
let defaultMaxHeight = ""
if (description !== null) {
let btn = document.querySelector('.description-btn')
btn.onclick = () => {
if (!descriptionOpened) {
// open the full description
descriptionActions.className = descriptionActions.className.replace(' closed', '')
defaultMaxHeight = description.style.maxHeight
description.style.maxHeight = description.scrollHeight + "px"
btn.textContent = "Fermer la description"
} else {
// initial max Height
descriptionActions.className += ' closed'
description.style.maxHeight = defaultMaxHeight
btn.textContent = "Ouvrir la description"
}
descriptionOpened = !descriptionOpened
}
}
/**
* Gallery modal to view media in large
*/
@ -70,7 +96,21 @@ let openModal = (url, isVideo) => {
//document.body.style.height = '100vh'
document.body.style.overflow = 'hidden'
document.body.style.touchAction = 'none'
setTimeout(() => {
const outsideClickListener = event => {
if (!mediaModalContent.contains(event.target) && isVisible(mediaModalContent)) {
closeModal()
document.removeEventListener('click', outsideClickListener)
}
}
document.addEventListener('click', outsideClickListener)
}, 100)
}
const isVisible = elem => !!elem && !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length )
let closeModal = () => {
mediaModal.style.visibility = 'hidden'

View file

@ -53,6 +53,19 @@ body {
color: white;
}
.btn {
padding: .5em 1em;
color: white;
border-radius: 7px;
background: #2c3e50;
border: 0;
}
.btn:focus {
outline: 0;
opacity: 0.8;
}
@media (max-width: 1600px) {
.container {
width: 70%;

View file

@ -57,7 +57,7 @@
.cover {
height: 13em;
margin-top: -13em;
background-color: rgba(230, 126, 34, 0.78);
background-color: rgba(230, 126, 34, 0.4);
background-size: cover;
}
@ -294,7 +294,7 @@ section {
text-align: justify;
margin: 0 auto;
width: 80%;
margin-top: 1.5em;
margin-top: 1em;
margin-bottom: .5em;
}
@ -332,16 +332,37 @@ section {
padding-left: 1em;
}
.description-cutted {
max-height: 13em;
overflow: hidden;
transition: max-height 0.1s ease-out;
}
.description-actions-container {
display: flex;
justify-content: center;
align-items: center;
margin-top: 1em;
}
.description-actions-container.closed {
box-shadow: 0px -16px 16px -3px rgb(255, 255, 255);
background: rgba(255,255,255,0.8);
position: relative;
top: -62px;
height: 62px;
margin-bottom: -62px;
}
/* *****************************************************************************
* SCHEDULE
********************************************************************************/
.schedule {
}
.schedule-category {
margin-bottom: 1em;
}
@ -357,13 +378,13 @@ section {
}
.schedule-category-collapse-icon {
transform: rotate(180deg);
color: #B12008;
width: 1.5em;
transition: all 0.1s ease-out;
}
.schedule-category-table {
max-height: 0;
overflow: hidden;
transition: max-height 0.1s ease-out;
@ -376,7 +397,7 @@ section {
margin-left: 2em;
margin-top: 1em;
margin-bottom: 1em;
margin-right: 40em;
margin-right: 20em;
padding: 1em 2em 1em 2em;
}
@ -395,6 +416,14 @@ section {
margin-bottom: 0;
}
.schedule-category-hours {
color: #2c3e50;
}
.schedule-category-hours .spearator {
color: #bdc3c7;
}
/* *****************************************************************************
* PRICING
@ -450,7 +479,7 @@ section {
********************************************************************************/
.contact {
.org-container {
margin: 0 auto;
width: 70%;
}
@ -541,13 +570,15 @@ section {
.mentions {
display: flex;
justify-content: center;
width: 100%;
padding-left: 1em;
padding-right: 1em;
flex-direction: column;
text-align: center;
color: #d35400;
margin-top: 2em;
margin-bottom: .5em;
margin-top: 1em;
margin-bottom: 1em;
}
.mentions div {
margin-bottom: .5em;
}
@ -589,17 +620,17 @@ RESPONSIVE
@media (max-width: 900px) {
.cover-background {
height: 30em;
height: 23em;
width: 100%;
}
.cover {
height: 30em;
margin-top: -30em;
height: 23em;
margin-top: -23em;
}
.cover-content {
height: 30em;
height: 23em;
flex-direction: column;
justify-content: center;
@ -628,6 +659,10 @@ RESPONSIVE
}
/* Mosaic level 2 */
.mosaic-2 {
grid-template-rows: 1fr 1fr;
}
.mosaic-2, .mosaic-3 {
grid-template-columns: 1fr;
}
@ -684,7 +719,7 @@ RESPONSIVE
margin-bottom: 1em;
}
.contact {
.org-container {
width: 100%;
}
@ -720,4 +755,7 @@ RESPONSIVE
.media-modal {
width: 90%;
}
.description {
width: 95%;
}
}

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

View file

@ -35,7 +35,7 @@ Github: https://github.com/lefuturiste
class="header-sub-title">
Espace Condorcet Centre Social
</a>
<h1 class="header-title">Forum des associations</h1>
<h1 class="header-title">Forum des associations 2020</h1>
<div class="header-description">
Cette année nous vous invitons à découvrir le forum virtuel des associations.
</div>

7
views/emails/test.twig Normal file
View file

@ -0,0 +1,7 @@
<p>
This is a test
</p>
<p>
Date: {{ date }}
</p>

View file

@ -73,8 +73,17 @@
<div class="section-divider"></div>
</div>
<div class="description">
{% if data.descriptionLong is not null and data.descriptionLong|length > 7 %}
{% if data.descriptionLong is not null and data.descriptionLong|length > 7 and not data.cutDescription %}
{{ data.descriptionLong|raw }}
{% elseif data.cutDescription %}
<div class="description-cutted">
{{ data.descriptionLong }}
</div>
<div class="description-actions-container closed">
<button class="btn description-btn">
Ouvrir la description
</button>
</div>
{% else %}
{{ data.descriptionShort }}
{% endif %}
@ -88,8 +97,9 @@
<h2>Crénaux</h2>
<div class="section-divider"></div>
</div>
<div class="schedule">
<div class="schedule org-container">
{% for item in data.schedule %}
{% if item.when|length > 0 %}
<div class="schedule-category">
<div class="schedule-category-header" title="Déroulez">
<div class="schedule-category-name">
@ -120,6 +130,7 @@
</div>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</section>
@ -155,7 +166,7 @@
<h2>Contact</h2>
<div class="section-divider"></div>
</div>
<div class="contact">
<div class="org-container contact">
{% if data.contacts.person|length > 0 %}
<div class="contact-item person">
<div class="contact-icon">