diff --git a/templates/tutorial/member/online.html b/templates/tutorial/member/online.html index 171035d892..9d31b3fd70 100644 --- a/templates/tutorial/member/online.html +++ b/templates/tutorial/member/online.html @@ -31,7 +31,7 @@

Tutoriels publiés par {{ usr.username }} {% for tutorial in tutorials %} - {% include 'tutorial/includes/tutorial_item.part.html' with beta=True %} + {% include 'tutorial/includes/tutorial_item.part.html' %} {% endfor %} {% else %} diff --git a/zds/article/models.py b/zds/article/models.py index 319afe9f34..29fe606c76 100644 --- a/zds/article/models.py +++ b/zds/article/models.py @@ -5,6 +5,7 @@ from django.core.files.uploadedfile import SimpleUploadedFile from django.db import models from math import ceil +from git import Repo import os import string import uuid @@ -25,15 +26,11 @@ from zds.utils import get_current_user from zds.utils import slugify -from zds.utils.articles import export_article +from zds.utils.articles import export_article, get_blob from zds.utils.models import SubCategory, Comment, Licence from django.core.urlresolvers import reverse -IMAGE_MAX_WIDTH = 480 -IMAGE_MAX_HEIGHT = 100 - - def image_path(instance, filename): """Return path to an image.""" ext = filename.split('.')[-1] @@ -141,6 +138,30 @@ def load_json(self, path=None, online=False): else: return None + def load_json_for_public(self): + repo = Repo(self.get_path()) + manarticle = get_blob(repo.commit(self.sha_public).tree, 'manifest.json') + data = json_reader.loads(manarticle) + + return data + + def load_dic(self, article_version): + article_version['pk'] = self.pk + article_version['slug'] = slugify(article_version['title']) + article_version['image'] = self.image + article_version['pubdate'] = self.pubdate + article_version['is_locked'] = self.is_locked + article_version['sha_draft'] = self.sha_draft + article_version['sha_validation'] = self.sha_validation + article_version['sha_public'] = self.sha_public + article_version['get_reaction_count'] = self.get_reaction_count + article_version['get_absolute_url'] = reverse('zds.article.views.view', + args=[self.pk, self.slug]) + article_version['get_absolute_url_online'] = reverse('zds.article.views.view_online', + args=[self.pk,slugify(article_version['title'])]) + + return article_version + def dump_json(self, path=None): if path is None: man_path = os.path.join(self.get_path(), 'manifest.json') diff --git a/zds/article/urls.py b/zds/article/urls.py index f1b2532f12..40c472c366 100644 --- a/zds/article/urls.py +++ b/zds/article/urls.py @@ -29,7 +29,7 @@ url(r'^nouveau/$', 'zds.article.views.new'), url(r'^editer/$', 'zds.article.views.edit'), url(r'^modifier/$', 'zds.article.views.modify'), - url(r'^recherche/(?P\d+)/$', + url(r'^recherche/(?P\d+)/$', 'zds.article.views.find_article'), diff --git a/zds/article/views.py b/zds/article/views.py index b08d78a184..742934eefa 100644 --- a/zds/article/views.py +++ b/zds/article/views.py @@ -55,20 +55,26 @@ def index(request): tag = None if tag is None: - article = Article.objects\ + articles = Article.objects\ .filter(sha_public__isnull=False).exclude(sha_public="")\ .order_by('-pubdate')\ .all() else: # The tag isn't None and exist in the system. We can use it to retrieve # all articles in the subcategory specified. - article = Article.objects\ + articles = Article.objects\ .filter(sha_public__isnull=False, subcategory__in=[tag])\ .exclude(sha_public="").order_by('-pubdate')\ .all() + + article_versions = [] + for article in articles: + article_version = article.load_json_for_public() + article_version = article.load_dic(article_version) + article_versions.append(article_version) return render_template('article/index.html', { - 'articles': article, + 'articles': article_versions, 'tag': tag, }) @@ -83,10 +89,6 @@ def view(request, article_pk, article_slug): if not request.user.has_perm('article.change_article'): raise PermissionDenied - # The slug of the article must to be right. - if article_slug != slugify(article.title): - return redirect(article.get_absolute_url()) - # Retrieve sha given by the user. This sha must to be exist. # If it doesn't exist, we take draft version of the article. try: @@ -105,17 +107,8 @@ def view(request, article_pk, article_slug): manifest = get_blob(repo.commit(sha).tree, 'manifest.json') article_version = json_reader.loads(manifest) - article_version['txt'] = get_blob( - repo.commit(sha).tree, - article_version['text']) - article_version['pk'] = article.pk - article_version['slug'] = article.slug - article_version['image'] = article.image - article_version['pubdate'] = article.pubdate - article_version['sha_draft'] = article.sha_draft - article_version['sha_validation'] = article.sha_validation - article_version['sha_public'] = article.sha_public - article_version['get_absolute_url_online'] = article.get_absolute_url_online() + article_version['txt'] = get_blob(repo.commit(sha).tree, article_version['text']) + article_version = article.load_dic(article_version) validation = Validation.objects.filter(article__pk=article.pk, version=sha)\ @@ -135,28 +128,14 @@ def view_online(request, article_pk, article_slug): """Show the given article if exists and is visible.""" article = get_object_or_404(Article, pk=article_pk) - # The slug of the article must to be right. - if article_slug != slugify(article.title): - return redirect(article.get_absolute_url_online()) - # Load the article. - article_version = article.load_json() - txt = open( - os.path.join( - article.get_path(), - article_version['text'] + - '.html'), - "r") + article_version = article.load_json_for_public() + txt = open(os.path.join(article.get_path(), + article_version['text'] + '.html'), + "r") article_version['txt'] = txt.read() txt.close() - article_version['pk'] = article.pk - article_version['slug'] = article.slug - article_version['image'] = article.image - article_version['pubdate'] = article.pubdate - article_version['is_locked'] = article.is_locked - article_version['get_reaction_count'] = article.get_reaction_count - article_version['get_absolute_url'] = article.get_absolute_url() - article_version['get_absolute_url_online'] = article.get_absolute_url_online() + article_version = article.load_dic(article_version) # If the user is authenticated if request.user.is_authenticated(): @@ -364,16 +343,23 @@ def edit(request): }) -def find_article(request, name): +def find_article(request, pk_user): """Find an article from his author.""" - user = get_object_or_404(User, pk=name) + user = get_object_or_404(User, pk=pk_user) articles = Article.objects\ .filter(authors__in=[user], sha_public__isnull=False).exclude(sha_public="")\ .order_by('-pubdate')\ .all() + + article_versions = [] + for article in articles: + article_version = article.load_json_for_public() + article_version = article.load_dic(article_version) + article_versions.append(article_version) + # Paginator return render_template('article/find.html', { - 'articles': articles, 'usr': user, + 'articles': article_versions, 'usr': user, }) diff --git a/zds/member/views.py b/zds/member/views.py index e6f664dbfb..bfc4e5da18 100644 --- a/zds/member/views.py +++ b/zds/member/views.py @@ -117,18 +117,30 @@ def details(request, user_name): fchart = os.path.join(img_path, "mod-{}.svg".format(str(usr.pk))) dot_chart.render_to_file(fchart) my_articles = Article.objects.filter(sha_public__isnull=False).order_by( - "-pubdate").filter(authors__in=[usr]).all() + "-pubdate").filter(authors__in=[usr]).all()[:5] my_tutorials = \ Tutorial.objects.filter(sha_public__isnull=False) \ .filter(authors__in=[usr]) \ .order_by("-pubdate" - ).all() + ).all()[:5] + + my_tuto_versions = [] + for my_tutorial in my_tutorials: + mandata = my_tutorial.load_json_for_public() + mandata = my_tutorial.load_dic(mandata) + my_tuto_versions.append(mandata) + my_article_versions = [] + for my_article in my_articles: + article_version = my_article.load_json_for_public() + article_version = my_article.load_dic(article_version) + my_article_versions.append(article_version) + my_topics = \ Topic.objects\ .filter(author=usr)\ .exclude(Q(forum__group__isnull=False) & ~Q(forum__group__in=request.user.groups.all()))\ .prefetch_related("author")\ - .order_by("-pubdate").all() + .order_by("-pubdate").all()[:5] form = OldTutoForm(profile) oldtutos = [] @@ -142,9 +154,9 @@ def details(request, user_name): "usr": usr, "profile": profile, "bans": bans, - "articles": my_articles[:5], - "tutorials": my_tutorials[:5], - "topics": my_topics[:5], + "articles": my_article_versions, + "tutorials": my_tuto_versions, + "topics": my_topics, "form": form, "old_tutos": oldtutos, }) diff --git a/zds/pages/views.py b/zds/pages/views.py index e372c970a7..14b0e961e8 100644 --- a/zds/pages/views.py +++ b/zds/pages/views.py @@ -29,20 +29,14 @@ def home(request): tutos = [] for tuto in get_last_tutorials(): data = tuto.load_json_for_public() - data['pk'] = tuto.pk - data['image'] = tuto.image - data['gallery'] = tuto.gallery - data['pubdate'] = tuto.pubdate - data['update'] = tuto.update - data['subcategory'] = tuto.subcategory - data['get_absolute_url_online'] = reverse( - 'zds.tutorial.views.view_tutorial_online', - args=[ - tuto.pk, - slugify( - data['title'])]) - + data = tuto.load_dic(data) tutos.append(data) + + articles = [] + for article in get_last_articles(): + data = article.load_json_for_public() + data = article.load_dic(data) + articles.append(data) try: with open(os.path.join(SITE_ROOT, 'quotes.txt'), 'r') as fh: @@ -51,9 +45,8 @@ def home(request): quote = u'Zeste de Savoir, la connaissance pour tous et sans pépins !' return render_template('home.html', { - 'last_topics': get_last_topics(request.user), 'last_tutorials': tutos, - 'last_articles': get_last_articles(), + 'last_articles': articles, 'quote': quote, }) diff --git a/zds/tutorial/models.py b/zds/tutorial/models.py index a429fd318d..31171594b8 100644 --- a/zds/tutorial/models.py +++ b/zds/tutorial/models.py @@ -183,7 +183,9 @@ def get_prod_path(self): str(self.pk) + '_' + slugify(data['title'])) def load_dic(self, mandata): - mandata['get_absolute_url_online'] = self.get_absolute_url_online() + mandata['get_absolute_url_online'] = reverse('zds.tutorial.views.view_tutorial_online', + args=[self.pk, slugify(mandata["title"])]) + mandata['get_absolute_url_beta'] = self.get_absolute_url_beta() mandata['get_absolute_url'] = self.get_absolute_url() mandata['get_introduction_online'] = self.get_introduction_online() mandata['get_conclusion_online'] = self.get_conclusion_online() @@ -203,7 +205,9 @@ def load_dic(self, mandata): return mandata - def load_json_for_public(self): + def load_json_for_public(self, sha=None): + if sha is None: + sha = self.sha_public repo = Repo(self.get_path()) mantuto = get_blob(repo.commit(self.sha_public).tree, 'manifest.json') data = json_reader.loads(mantuto) @@ -241,13 +245,21 @@ def dump_json(self, path=None): json_data.write(data.encode('utf-8')) json_data.close() - def get_introduction(self): - path = os.path.join(self.get_path(), self.introduction) - intro = open(path, "r") - intro_contenu = intro.read() - intro.close() - - return intro_contenu.decode('utf-8') + def get_introduction(self, sha=None): + # find hash code + if sha is None: + sha = self.sha_draft + repo = Repo(self.get_path()) + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "introduction" in tutorial_version: + path_tuto = tutorial_version["introduction"] + + if path_tuto: + return get_blob(repo.commit(sha).tree, path_tuto) + else: + return None def get_introduction_online(self): intro = open( @@ -261,12 +273,21 @@ def get_introduction_online(self): return intro_contenu.decode('utf-8') - def get_conclusion(self): - conclu = open(os.path.join(self.get_path(), self.conclusion), "r") - conclu_contenu = conclu.read() - conclu.close() - - return conclu_contenu.decode('utf-8') + def get_conclusion(self, sha=None): + # find hash code + if sha is None: + sha = self.sha_draft + repo = Repo(self.get_path()) + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "introduction" in tutorial_version: + path_tuto = tutorial_version["conclusion"] + + if path_tuto: + return get_blob(repo.commit(sha).tree, path_tuto) + else: + return None def get_conclusion_online(self): conclu = open( @@ -522,16 +543,27 @@ def get_path(self, relative=False): else: return os.path.join(settings.REPO_PATH, self.tutorial.get_phy_slug(), self.get_phy_slug()) - def get_introduction(self): - intro = open( - os.path.join( - self.tutorial.get_path(), - self.introduction), - "r") - intro_contenu = intro.read() - intro.close() - - return intro_contenu.decode('utf-8') + def get_introduction(self, sha=None): + + tutorial = self.tutorial + + # find hash code + if sha is None: + sha = tutorial.sha_draft + repo = Repo(tutorial.get_path()) + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "parts" in tutorial_version: + for part in tutorial_version["parts"]: + if part["pk"] == self.pk: + path_part = part["introduction"] + break + + if path_part: + return get_blob(repo.commit(sha).tree, path_part) + else: + return None def get_introduction_online(self): intro = open( @@ -545,16 +577,27 @@ def get_introduction_online(self): return intro_contenu.decode('utf-8') - def get_conclusion(self): - conclu = open( - os.path.join( - self.tutorial.get_path(), - self.conclusion), - "r") - conclu_contenu = conclu.read() - conclu.close() - - return conclu_contenu.decode('utf-8') + def get_conclusion(self, sha=None): + + tutorial = self.tutorial + + # find hash code + if sha is None: + sha = tutorial.sha_draft + repo = Repo(tutorial.get_path()) + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "parts" in tutorial_version: + for part in tutorial_version["parts"]: + if part["pk"] == self.pk: + path_part = part["conclusion"] + break + + if path_part: + return get_blob(repo.commit(sha).tree, path_part) + else: + return None def get_conclusion_online(self): conclu = open( @@ -702,25 +745,34 @@ def get_path(self, relative=False): return chapter_path - def get_introduction(self): - if self.introduction: - if self.tutorial: - path = os.path.join( - self.tutorial.get_path(), - self.introduction) - else: - path = os.path.join( - self.part.tutorial.get_path(), - self.introduction) + def get_introduction(self, sha=None): - if os.path.isfile(path): - intro = open(path, "r") - intro_contenu = intro.read() - intro.close() - - return intro_contenu.decode('utf-8') - else: - return None + if self.tutorial: + tutorial = self.tutorial + else: + tutorial = self.part.tutorial + repo = Repo(tutorial.get_path()) + + # find hash code + if sha is None: + sha = tutorial.sha_draft + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "parts" in tutorial_version: + for part in tutorial_version["parts"]: + if "chapters" in part: + for chapter in part["chapters"]: + if chapter["pk"] == self.pk: + path_chap = chapter["introduction"] + break + if "chapter" in tutorial_version: + chapter = tutorial_version["chapter"] + if chapter["pk"] == self.pk: + path_chap = chapter["introduction"] + + if path_chap: + return get_blob(repo.commit(sha).tree, path_chap) else: return None @@ -748,23 +800,34 @@ def get_introduction_online(self): else: return None - def get_conclusion(self): - if self.conclusion: - if self.tutorial: - path = os.path.join(self.tutorial.get_path(), self.conclusion) - else: - path = os.path.join( - self.part.tutorial.get_path(), - self.conclusion) - - if os.path.isfile(path): - conclu = open(path, "r") - conclu_contenu = conclu.read() - conclu.close() + def get_conclusion(self, sha=None): - return conclu_contenu.decode('utf-8') - else: - return None + if self.tutorial: + tutorial = self.tutorial + else: + tutorial = self.part.tutorial + repo = Repo(tutorial.get_path()) + + # find hash code + if sha is None: + sha = tutorial.sha_draft + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "parts" in tutorial_version: + for part in tutorial_version["parts"]: + if "chapters" in part: + for chapter in part["chapters"]: + if chapter["pk"] == self.pk: + path_chap = chapter["conclusion"] + break + if "chapter" in tutorial_version: + chapter = tutorial_version["chapter"] + if chapter["pk"] == self.pk: + path_chap = chapter["conclusion"] + + if path_chap: + return get_blob(repo.commit(sha).tree, path_chap) else: return None @@ -802,7 +865,9 @@ def update_children(self): self.introduction = os.path.join("introduction.md") self.conclusion = os.path.join("conclusion.md") self.save() + for extract in self.get_extracts(): + extract.text = extract.get_path(relative=True) extract.save() class Extract(models.Model): @@ -884,20 +949,38 @@ def get_prod_path(self): str(ext['pk']) + "_" + slugify(ext['title'])) \ + '.md.html' - def get_text(self): + def get_text(self, sha=None): + if self.chapter.tutorial: - path = os.path.join(self.chapter.tutorial.get_path(), self.text) + tutorial = self.chapter.tutorial else: - path = os.path.join( - self.chapter.part.tutorial.get_path(), - self.text) - - if os.path.isfile(path): - text = open(path, "r") - text_contenu = text.read() - text.close() - - return text_contenu.decode('utf-8') + tutorial = self.chapter.part.tutorial + repo = Repo(tutorial.get_path()) + + # find hash code + if sha is None: + sha = tutorial.sha_draft + + manifest = get_blob(repo.commit(sha).tree, "manifest.json") + tutorial_version = json_reader.loads(manifest) + if "parts" in tutorial_version: + for part in tutorial_version["parts"]: + if "chapters" in part: + for chapter in part["chapters"]: + if "extracts" in chapter: + for extract in chapter["extracts"]: + if extract["pk"] == self.pk: + path_ext = extract["text"] + break + if "chapter" in tutorial_version: + chapter = tutorial_version["chapter"] + if "extracts" in chapter: + for extract in chapter["extracts"]: + path_ext = extract["text"] + break + + if path_ext: + return get_blob(repo.commit(sha).tree, path_ext) else: return None diff --git a/zds/tutorial/tests.py b/zds/tutorial/tests.py index a909dbf77c..b54efefd4c 100644 --- a/zds/tutorial/tests.py +++ b/zds/tutorial/tests.py @@ -2,12 +2,13 @@ import os import shutil - +import HTMLParser from django.conf import settings from django.core import mail from django.core.urlresolvers import reverse from django.test import TestCase from django.test.utils import override_settings +from django.utils import html from zds.member.factories import ProfileFactory, StaffProfileFactory from zds.gallery.factories import GalleryFactory, UserGalleryFactory, ImageFactory @@ -476,7 +477,7 @@ def test_url_for_guest(self): def test_workflow_tuto(self): """Test workflow of tutorial.""" - + # logout before self.client.logout() # login with simple member @@ -508,7 +509,7 @@ def test_workflow_tuto(self): { 'title': u"Partie 1", 'introduction':u"Présentation", - 'conclusion': u"Fin de la présenation", + 'conclusion': u"Fin de la présentation", }, follow=False) self.assertEqual(result.status_code, 302) @@ -526,7 +527,7 @@ def test_workflow_tuto(self): p1.slug]), follow=True) self.assertContains(response=result, text = u"Présentation") - self.assertContains(response=result, text = u"Fin de la présenation") + self.assertContains(response=result, text = u"Fin de la présentation") #add part 2 result = self.client.post( @@ -699,6 +700,108 @@ def test_workflow_tuto(self): follow=True) self.assertContains(response=result, text = u"Mon premier chapitre d'une autre partie") + # add extract 1 of chapter 3 + result = self.client.post( + reverse('zds.tutorial.views.add_extract') + '?chapitre={}'.format(c3.pk), + { + 'title': u"Extrait 1", + 'text':"Prune", + }, + follow=False) + self.assertEqual(result.status_code, 302) + self.assertEqual(Extract.objects.filter(chapter=c3).count(), 1) + e1 = Extract.objects.filter(chapter=c3).last() + + # add extract 2 of chapter 3 + result = self.client.post( + reverse('zds.tutorial.views.add_extract') + '?chapitre={}'.format(c3.pk), + { + 'title': u"Extrait 2", + 'text':"Citron", + }, + follow=False) + self.assertEqual(result.status_code, 302) + self.assertEqual(Extract.objects.filter(chapter=c3).count(), 2) + e2 = Extract.objects.filter(chapter=c3).last() + + # add extract 3 of chapter 2 + result = self.client.post( + reverse('zds.tutorial.views.add_extract') + '?chapitre={}'.format(c2.pk), + { + 'title': u"Extrait 3", + 'text':"Kiwi", + }, + follow=False) + self.assertEqual(result.status_code, 302) + self.assertEqual(Extract.objects.filter(chapter=c2).count(), 1) + e3 = Extract.objects.filter(chapter=c2).last() + + #check content edit part + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p1.pk), + follow=True) + self.assertContains(response=result, text = u"Présentation") + self.assertContains(response=result, text = u"Fin de la présentation") + + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p2.pk), + follow=True) + self.assertContains(response=result, text = u"Analyse") + self.assertContains(response=result, text = "Fin de l'analyse") + + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p3.pk), + follow=True) + self.assertContains(response=result, text = u"Expérimentation") + self.assertContains(response=result, text = u"est terminé") + + #check content edit chapter + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c1.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 1") + self.assertContains(response=result, text = u"Mon premier chapitre") + self.assertContains(response=result, text = u"Fin de mon premier chapitre") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c2.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 2") + self.assertContains(response=result, text = u"Mon deuxième chapitre") + self.assertContains(response=result, text = u"Fin de mon deuxième chapitre") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c3.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 2") + self.assertContains(response=result, text = u"Mon troisième chapitre homonyme") + self.assertContains(response=result, text = u"Fin de mon troisième chapitre") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c4.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 1") + self.assertContains(response=result, text = u"Mon premier chapitre d'une autre partie") + + #check content edit extract + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e1.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 1") + self.assertContains(response=result, text = u"Prune") + + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e2.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 2") + self.assertContains(response=result, text = u"Citron") + + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e3.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 3") + self.assertContains(response=result, text = u"Kiwi") + #edit part 2 result = self.client.post( reverse('zds.tutorial.views.edit_part') + '?partie={}'.format(p2.pk), @@ -714,7 +817,7 @@ def test_workflow_tuto(self): self.assertContains(response=result, text = u"Expérimentation : edition d'introduction") self.assertContains(response=result, text = u"C'est terminé : edition de conlusion") self.assertEqual(Part.objects.filter(tutorial=tuto).count(), 3) - + #edit chapter 3 result = self.client.post( reverse('zds.tutorial.views.edit_chapter') + '?chapitre={}'.format(c3.pk), @@ -731,6 +834,7 @@ def test_workflow_tuto(self): self.assertContains(response=result, text = u"Edition de conlusion") self.assertEqual(Chapter.objects.filter(part=p2.pk).count(), 3) p2 = Part.objects.filter(pk=p2.pk).first() + #edit part 2 result = self.client.post( reverse('zds.tutorial.views.edit_part') + '?partie={}'.format(p2.pk), @@ -762,6 +866,85 @@ def test_workflow_tuto(self): self.assertContains(response=result, text = u"Edition d'introduction") self.assertContains(response=result, text = u"Edition de conlusion") self.assertEqual(Chapter.objects.filter(part=p2.pk).count(), 3) + + #edit extract 2 + result = self.client.post( + reverse('zds.tutorial.views.edit_extract') + '?extrait={}'.format(e2.pk), + { + 'title': u"Extrait 2 : edition de titre", + 'text': u"Agrume", + "last_hash": compute_hash([os.path.join(e2.get_path())]) + }, + follow=True) + self.assertContains(response=result, text = u"Extrait 2 : edition de titre") + self.assertContains(response=result, text = u"Agrume") + + #check content edit part + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p1.pk), + follow=True) + self.assertContains(response=result, text = u"Présentation") + self.assertContains(response=result, text = u"Fin de la présentation") + + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p2.pk), + follow=True) + self.assertContains(response=result, text = u"Partie 2 : seconde edition de titre") + self.assertContains(response=result, text = "Expérimentation : seconde edition d'introduction") + self.assertContains(response=result, text = "C'est terminé : seconde edition de conlusion") + + result = self.client.get( + reverse('zds.tutorial.views.edit_part')+"?partie={}".format(p3.pk), + follow=True) + self.assertContains(response=result, text = u"Expérimentation") + self.assertContains(response=result, text = u"est terminé") + + #check content edit chapter + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c1.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 1") + self.assertContains(response=result, text = u"Mon premier chapitre") + self.assertContains(response=result, text = u"Fin de mon premier chapitre") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c2.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 2 : edition de titre") + self.assertContains(response=result, text = u"Edition d'introduction") + self.assertContains(response=result, text = u"Edition de conlusion") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c3.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 3 : edition de titre") + self.assertContains(response=result, text = u"Edition d'introduction") + self.assertContains(response=result, text = u"Edition de conlusion") + + result = self.client.get( + reverse('zds.tutorial.views.edit_chapter')+"?chapitre={}".format(c4.pk), + follow=True) + self.assertContains(response=result, text = u"Chapitre 1") + self.assertContains(response=result, text = u"Mon premier chapitre d'une autre partie") + + #check content edit extract + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e1.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 1") + self.assertContains(response=result, text = u"Prune") + + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e2.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 2 : edition de titre") + self.assertContains(response=result, text = u"Agrume") + + result = self.client.get( + reverse('zds.tutorial.views.edit_extract')+"?extrait={}".format(e3.pk), + follow=True) + self.assertContains(response=result, text = u"Extrait 3") + self.assertContains(response=result, text = u"Kiwi") #move chapter 1 against 2 result = self.client.post( diff --git a/zds/tutorial/views.py b/zds/tutorial/views.py index bb0a52d5cf..8070d47e6b 100644 --- a/zds/tutorial/views.py +++ b/zds/tutorial/views.py @@ -89,7 +89,13 @@ def index(request): tutorials = Tutorial.objects.filter( sha_public__isnull=False, subcategory__in=[tag]).exclude(sha_public="").order_by("-pubdate").all() - return render_template("tutorial/index.html", {"tutorials": tutorials, "tag": tag}) + + tuto_versions = [] + for tutorial in tutorials: + mandata = tutorial.load_json_for_public() + mandata = tutorial.load_dic(mandata) + tuto_versions.append(mandata) + return render_template("tutorial/index.html", {"tutorials": tuto_versions, "tag": tag}) # Staff actions. @@ -219,10 +225,6 @@ def history(request, tutorial_pk, tutorial_slug): if not request.user.has_perm("tutorial.change_tutorial"): raise PermissionDenied - # Make sure the URL is well-formed - - if not tutorial_slug == slugify(tutorial.title): - return redirect(tutorial.get_absolute_url()) repo = Repo(tutorial.get_path()) logs = repo.head.reference.log() logs = sorted(logs, key=attrgetter("time"), reverse=True) @@ -1924,6 +1926,7 @@ def edit_extract(request): if not request.user.has_perm("tutorial.change_tutorial"): raise PermissionDenied + if request.method == "POST": data = request.POST if content_has_changed([extract.get_path()], data["last_hash"]): @@ -2082,20 +2085,33 @@ def find_tuto(request, pk_user): type = request.GET["type"] except KeyError: type = None - u = get_object_or_404(User, pk=pk_user) + display_user = get_object_or_404(User, pk=pk_user) if type == "beta": tutorials = Tutorial.objects.all().filter( - authors__in=[u], + authors__in=[display_user], sha_beta__isnull=False).exclude(sha_beta="").order_by("-pubdate") + + tuto_versions = [] + for tutorial in tutorials: + mandata = tutorial.load_json_for_public(sha=tutorial.sha_beta) + mandata = tutorial.load_dic(mandata) + tuto_versions.append(mandata) + return render_template("tutorial/member/beta.html", - {"tutorials": tutorials, "usr": u}) + {"tutorials": tuto_versions, "usr": display_user}) else: tutorials = Tutorial.objects.all().filter( - authors__in=[u], + authors__in=[display_user], sha_public__isnull=False).exclude(sha_public="").order_by("-pubdate") + + tuto_versions = [] + for tutorial in tutorials: + mandata = tutorial.load_json_for_public() + mandata = tutorial.load_dic(mandata) + tuto_versions.append(mandata) - return render_template("tutorial/member/online.html", {"tutorials": tutorials, - "usr": u}) + return render_template("tutorial/member/online.html", {"tutorials": tuto_versions, + "usr": display_user}) def upload_images(images, tutorial): @@ -2880,7 +2896,6 @@ def MEP(tutorial, sha): get_url_images(md_file_contenu, tutorial.get_prod_path()) # convert to out format - out_file = open(os.path.join(tutorial.get_prod_path(), fichier), "w") if md_file_contenu is not None: out_file.write(markdown_to_out(md_file_contenu.encode("utf-8")))