Commit 74013517 authored by Alexandre's avatar Alexandre

Merge branch 'dev'

parents 69bdf121 5bcf51d8
# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-06-26 20:38
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('data_manager', '0004_auto_20190620_0026'),
]
operations = [
migrations.AddField(
model_name='action',
name='closed',
field=models.BooleanField(default=False, verbose_name='Groupe clôturé ?'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-06-26 20:39
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('data_manager', '0005_action_closed'),
]
operations = [
migrations.AlterField(
model_name='action',
name='closed',
field=models.BooleanField(default=False, verbose_name='Groupe clôturé'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.21 on 2019-07-02 09:34
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('data_manager', '0006_auto_20190626_2239'),
]
operations = [
migrations.AlterField(
model_name='action',
name='members',
field=models.ManyToManyField(blank=True, related_name='actions', to=settings.AUTH_USER_MODEL),
),
]
......@@ -9,16 +9,19 @@ from djangoldp_conversation.models import Conversation, Message
from .permissions import ThreadPermission
from djangoldp.models import Model
from djangoldp.permissions import AnonymousReadOnly, ObjectPermission, WACPermissions
from datetime import date
import json
import itertools
Conversation._meta.permission_classes = [ThreadPermission]
User._meta.serializer_fields = ['@id', 'username', 'first_name', 'last_name', 'email', 'created_actions', 'get_full_name', 'userprofile']
User._meta.rdf_context = {"get_full_name": "rdfs:label"}
User._meta.depth = 1
User._meta.many_depth = 0
User._meta.serializer_fields = ['@id', 'username', 'first_name', 'last_name', 'email', 'actions', 'created_actions', 'get_full_name', 'userprofile']
User._meta.rdf_context = {"get_full_name": "rdfs:label", "photo": "foaf:depiction"}
User._meta.depth = 0
User._meta.get_field('username').verbose_name = "Email"
#def active_actions(self):
# return json.dumps(list(self.actions.filter(date__gte=date.today())))
#User.active_actions=active_actions
class UserProfile(Model):
photo = models.URLField(max_length=9999999, blank=True, verbose_name=u"URL de la photo")
......@@ -41,6 +44,7 @@ class ResourceLink(Model):
return self.title
class Meta:
depth = 0
serializer_fields = ['@id','title', 'url']
......@@ -51,6 +55,9 @@ class ActionTheme(Model):
def __str__(self):
return self.name
class Meta:
depth = 0
class Action(Model):
created_at = models.DateTimeField(auto_now_add=True)
......@@ -62,7 +69,7 @@ class Action(Model):
city = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"Ville")
postcode = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"Code postal")
num_of_members = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"Nombre de participants")
members = models.ManyToManyField(User, blank=True)
members = models.ManyToManyField(User, blank=True, related_name='actions')
actions = models.ManyToManyField("self", blank=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='created_actions', blank=True)
conversation = models.ManyToManyField(Conversation, blank=True)
......@@ -72,7 +79,7 @@ class Action(Model):
crowdfunding = models.URLField(max_length=9999999, blank=True, null=True, verbose_name=u"Lien vers campagne de financement")
start_time = models.CharField(max_length=255, verbose_name=u"Heure de début")
end_time = models.CharField(max_length=255, blank=True, null=True, verbose_name=u"Heure de fin")
closed = models.BooleanField(default=False, verbose_name="Groupe clôturé")
def status(self):
if not self.num_of_members :
......@@ -88,7 +95,6 @@ class Action(Model):
nested_fields=[ "links", "actions", "conversation", "members"]
permission_classes=[AnonymousReadOnly]
depth = 0
many_depth = 0
ordering=['-created_at']
rdf_context = {"geo": 'http://www.w3.org/2003/01/geo/wgs84_pos#', "lat": "geo:lat", "lng": "geo:long"}
......@@ -103,15 +109,12 @@ class Info(Model):
url = models.URLField(max_length=9999999, blank=True, verbose_name=u"URL de l'article")
class Meta:
depth = 0
ordering=['-created_at']
def __str__(self):
return self.newspaper +" "+ self.headline[:20]
@receiver(pre_save, sender=User)
def copy_email_to_username(sender, instance, *args, **kwargs):
instance.username = instance.email
@receiver(post_save, sender=Action)
def save_autojoin_action(sender, instance, created, **kwargs):
if created:
......
from django.conf.urls import url, include
from djangoldp.views import LDPViewSet
from django.contrib.auth.models import User
from .views import ActionViewSet
from . import views
urlpatterns = [
......@@ -9,6 +10,7 @@ urlpatterns = [
url(r'^api/quit_action/(?P<pk>\d+)/', views.quit_action, name='quit_action'),
# API:
url(r'^api/users/', LDPViewSet.urls( model=User, fields = ['@id','first_name', 'last_name', 'username', 'email', 'created_actions', 'get_full_name', 'userprofile'], nested_fields=["created_actions", "userprofile"], permission_classes=(),)),
url(r'^api/users/', LDPViewSet.urls( model=User, fields = ['@id','first_name', 'last_name', 'username', 'email', 'actions', 'created_actions', 'get_full_name', 'userprofile'], nested_fields=['actions', 'created_actions', 'userprofile'], permission_classes=(),)),
url(r'^api/active-actions/', ActionViewSet.urls()),
url(r'^api/', include('djangoldp.urls')),
]
......@@ -8,6 +8,8 @@ from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.models import User
from .models import Action
from django.views.decorators.csrf import csrf_exempt
from datetime import date
from djangoldp.views import LDPViewSet
# TODO add auth required
......@@ -43,3 +45,9 @@ def quit_action(request, pk):
except TypeError:
pass
return HttpResponse(json.dumps(response_data), content_type="application/json")
class ActionViewSet(LDPViewSet):
model=Action
def get_queryset(self, *args, **kwargs):
return super().get_queryset(*args, **kwargs).exclude(date__lt=date.today())
......@@ -2,11 +2,13 @@
ssh risefor-mobilisation@ssh-risefor-mobilisation.happy-dev.fr << EOF
cd risefor-mobilisation/$1/app # staging || production
#git stash
if [ "$1" == "staging" ]; then
git pull origin dev
else
git pull origin master
fi
#git stash apply
python manage.py migrate
sass risefor-mobilisation/static/scss/index.scss risefor-mobilisation/static/css/risefor-mobilisation.css
......
from registration.forms import RegistrationForm
from django.forms import CharField
from django.forms import CharField, ValidationError
from django.contrib.auth.models import User
from data_manager.models import UserProfile
......@@ -12,6 +12,12 @@ class EmailRegistrationForm(RegistrationForm):
self.fields['last_name'].required = False
self.fields['postcode'].required = False
def clean_email(self):
if User.objects.filter(username=self.cleaned_data['email']).exists():
raise ValidationError("Un utilisateur avec cette adresse email existe déjà.")
self.instance.username = self.cleaned_data['email']
return self.cleaned_data['email']
def save(self):
user = super().save()
self.instance.userprofile = UserProfile(postcode=self.cleaned_data['postcode'], user=user)
......
import {
SIBTemplateElement,
Helpers
} from "https://unpkg.com/@startinblox/core@0.7";
} from "https://cdn.happy-dev.fr/sib-core/src/index.js";
import SIBMap from "https://cdn.happy-dev.fr/sib-core/src/elements/sib-map.js";
const base_url = import.meta.url.replace(/\/[^\/]*$/, "");
......@@ -10,6 +10,7 @@ Helpers.importCSS(`${base_url}/../css/risefor-map.css`);
export default class RiseForMap extends SIBTemplateElement {
constructor() {
super();
this.uniqID = this.parentNode.id;
}
static get propsDefinition() {
return {
......@@ -21,24 +22,44 @@ export default class RiseForMap extends SIBTemplateElement {
template({ dataSrc, rangeThemes }) {
return `
<sib-map
data-src="${dataSrc}"
search-fields="header, postcode, theme, create"
search-label-header="Filtrer les actions"
search-label-postcode="Votre code postal"
search-label-theme="Thème"
search-widget-header="sib-form-label"
search-widget-postcode="sib-form-placeholder-text"
search-widget-theme="sib-form-placeholder-dropdown"
search-widget-create="rfm-display-create"
search-label-postcode="Votre code postal"
search-label-theme="Thème"
search-range-theme="${rangeThemes}"
data-src="${dataSrc}"
next="action-detail"
next="action-preview-${this.uniqID}"
></sib-map>
<div id="map-${this.uniqID}" hidden></div>
<div id="action-preview-${this.uniqID}" hidden>
<sib-display
bind-resources
data-fields="status, theme.photo, name, description, date-and-location, cta, close"
set-date-and-location="date, city"
widget-status="rfm-display-status"
widget-theme.photo="rfm-display-img"
widget-date="rfm-display-date"
label-cta="Je participe"
label-close="🞩"
action-cta="action-detail"
action-close="map-${this.uniqID}"
></sib-display>
</div>
<sib-widget name="sib-form-label">
<template>
<div>\$\{label\}</div>
......@@ -52,6 +73,11 @@ export default class RiseForMap extends SIBTemplateElement {
</sib-ac-checker>
</template>
</sib-widget>
<sib-router default-route="map-${this.uniqID}">
<sib-route name="map-${this.uniqID}" hidden></sib-route>
<sib-route name="action-preview-${this.uniqID}" use-id hidden></sib-route>
</sib-router>
`;
}
}
......
......@@ -10,6 +10,7 @@
@import "src/action-edit";
@import "src/map";
@import "src/profile";
@import "src/modals";
@import "src/account-login";
@import "src/account-logout";
@import "src/account-password-reset-form";
......
......@@ -16,6 +16,7 @@ sib-map {
max-width: 1024px;
height: 600px;
margin: auto;
margin-bottom: 4rem;
padding: none;
background: $primary-blue;
......@@ -122,3 +123,108 @@ sib-map {
}
}
}
/* Action preview frame
-------------------- */
risefor-map {
display: block;
position: relative;
#action-preview-,
#action-preview-la-carte {
> sib-display {
display: block;
position: absolute;
top: 7rem;
left: calc(50% - 140px);
z-index: 1000;
width: 240px;
box-shadow: 0 0 8px $secondary-blue;
background: white;
@media only screen and (max-width: 991px) {
top: 23rem;
}
> div {
width: 100%;
height: 25rem;
rfm-display-status div {
position: relative;
height: 1.6rem;
padding: 0.2rem 1rem;
background: $primary-blue;
color: white;
}
rfm-display-status div.open-status {
background: $secondary-blue;
}
rfm-display-status div.closed-status {
background: $cta-red;
}
rfm-display-img {
position: relative;
top: 0;
width: 100%;
img[name="theme.photo"] {
width: 100%;
height: 10.4rem;
object-fit: cover;
}
}
sib-display-value[name="name"] {
display: block;
margin: 0.5rem 0.8rem;
height: 3.2rem;
@extend %title-typo;
font-size: 1.4rem;
@extend %over-text;
}
sib-display-value[name="description"] {
display: block;
height: 2.3rem;
margin: 0.5rem 0.8rem;
@extend %over-text;
}
div[name="date-and-location"] {
margin: 0.5rem 0.8rem 2rem 0.8rem;
color: $secondary-blue;
text-transform: uppercase;
@extend %over-text;
rfm-display-date[name="date"] {
margin-right: 2rem;
}
}
sib-action[name="cta"] {
@extend %blue-button;
margin: 0.8rem;
font-weight: 700;
}
sib-action[name="close"] {
display: block;
position: absolute;
top: 2px;
right: 8px;
color: white;
font-size: 1.2rem;
font-weight: 700;
cursor: pointer;
}
}
}
}
}
......@@ -22,4 +22,14 @@ Properties are ordered by declaration type:
@media only screen and (max-width: 575px) {
padding: 1rem;
}
button {
@extend %blue-button;
margin: 3rem auto;
a {
@extend %title-typo;
color: white;
font-size: 1.1rem;
text-decoration: none;
}
}
}
......@@ -116,7 +116,8 @@ Properties are ordered by declaration type:
padding: 0 1rem 3rem 1rem;
}
#membership-button,
sib-ac-checker sib-link {
sib-ac-checker sib-link,
button#close-action {
@extend %blue-button;
height: 3rem;
......@@ -129,37 +130,46 @@ Properties are ordered by declaration type:
@media only screen and (max-width: 575px) {
margin-left: 1rem;
}
span.is-member {
span.is-member,
span.is-full,
span.is-passed {
display: none;
}
span.is-not-member {
display: contents;
}
span.is-full {
display: none;
}
}
#membership-button.is-member {
span.is-member {
display: contents;
}
span.is-not-member {
display: none;
}
span.is-full {
span.is-not-member,
span.is-full,
span.is-passed {
display: none;
}
}
#membership-button.is-full {
background: $light-grey;
color: $dark-grey;
span.is-member {
span.is-member,
span.is-not-member,
span.is-passed {
display: none;
}
span.is-not-member {
display: none;
span.is-full {
display: contents;
}
}
#membership-button.is-passed {
background: $light-grey;
color: $dark-grey;
span.is-member,
span.is-not-member,
span.is-full {
display: none;
}
span.is-passed {
display: contents;
}
}
......@@ -169,11 +179,17 @@ Properties are ordered by declaration type:
#membership-button {
display: inline-block;
}
/* #membership-button {
@media only screen and (max-width: 575px) {
margin-right: 100%;
}
} */
button#close-action {
background: $cta-red;
}
}
#action-closing-validation {
text-align: center;
button#confirm-action-closing {
@extend %cta-button;
margin: 2rem;
}
}
sib-display[label-links="Liens associés"] div {
......@@ -284,6 +300,9 @@ Properties are ordered by declaration type:
#action-detail-members {
@extend %block-padding;
h2 {
text-align: center;
}
#action-members-sib-display {
div {
display: block;
......@@ -295,8 +314,13 @@ Properties are ordered by declaration type:
text-align: center;
}
}
h2 {
text-align: center;
#action-detail-members-admin {
sib-display-value[name="author.email"] {
display: none;
}
sib-display-value[name="author.email"].show {
display: contents;
}
}
}
......
......@@ -128,6 +128,7 @@ Properties are ordered by declaration type:
margin: 2rem 3rem 0 3rem;
sib-display {
// FRAME OF AN ACTION
width: 30%;
height: 20rem;
margin: 0 1% 2rem 1%;
......@@ -144,7 +145,6 @@ Properties are ordered by declaration type:
// background: lightgrey; // FOR DEBUG
rfm-display-status div {
// FRAME OF AN ACTION
position: absolute;
top: 0;
right: 0;
......@@ -210,3 +210,23 @@ Properties are ordered by declaration type:
@extend %actions-list-nav;
}
}
#mes-actions {
p {
margin: 5rem auto 3rem auto;
text-align: center;
}
button {
display: block;
margin: 2rem auto;
@extend %blue-button;
font-size: 1.1rem;
a {
@extend %title-typo;
color: white;
text-decoration: none;
}
}
}
......@@ -61,6 +61,42 @@ footer {
color: $secondary-blue;
}
}
#mc_embed_signup {
background: $primary-blue;
h3 {
margin: 1rem auto;
color: white;
}
.indicates-required {
display: none;
}
.mc-field-group {
margin: 0.5rem auto;
label {
@extend %text-typo;
color: white;
}
input {
border: 0;
border-radius: 0.2rem;
}
div.mce_inline_error {
max-width: 500px;
margin: 0.5rem auto 1rem auto;
border-radius: 0.3rem;
background: $secondary-blue;
color: $primary-blue;
}
}
#mc-embedded-subscribe {
@extend %cta-button;
margin: 1rem auto;
box-shadow: 0.1rem 0.1rem 0.3rem $dark-grey;
}
}
.social-networks a {
color: $primary-blue;
}
......
......@@ -86,7 +86,7 @@ Properties are ordered by declaration type:
z-index: 10000;
height: 5.5rem;
padding: 1rem 3rem;
padding: 0.5rem 3rem 1rem 3rem;
border-bottom: 2px solid $light-grey;
background: white;
......@@ -102,12 +102,18 @@ Properties are ordered by declaration type:
sib-route {
cursor: pointer;
}
.logo-name {
width: 260px;
div.logo {
width: 140px;
//height: 4rem;
margin-top: 1.5rem;
font-size: 1.4rem;
@media only screen and (max-width: 991px) {
padding-left: 5rem;
width: 200px;
margin-top: 0.8rem;
padding-left: 4rem;
}
img {
width: 100%;
}
}
#main-menu {
......
......@@ -72,6 +72,7 @@ Properties are ordered by declaration type:
a {
@extend %blue-button;
padding: 1rem 1.5rem;
box-shadow: 0.2rem 0.2rem 0.2rem $dark-grey;
@extend %title-typo;
color: $primary-blue;
......
.modal {
display: none;
}
.modal.is-open {
display: block;
}
.modal__overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0,0,0,0.6);
display: flex;
justify-content: center;
align-items: center;
}
.modal__container {