diff --git a/app/apps/api/serializers.py b/app/apps/api/serializers.py index 0258fabbbfda79283394c8f184153e4765b09d76..705c455a951f9d37fee0902a23c30a87b918b976 100644 --- a/app/apps/api/serializers.py +++ b/app/apps/api/serializers.py @@ -81,14 +81,6 @@ class UserOnboardingSerializer(serializers.ModelSerializer): model = User fields = ('onboarding',) - def __init__(self, user, *args, **kwargs): - self.user = user - super().__init__(*args, **kwargs) - - def complete(self): - self.user.onboarding = self.validated_data['onboarding'] - self.user.save() - class BlockTypeSerializer(serializers.ModelSerializer): class Meta: diff --git a/app/apps/api/tests.py b/app/apps/api/tests.py index 808f42fb9e866a953dc3095c64ba074965edbc3d..7de43df764c53d7866b4daccbc8f45c40bf61945 100644 --- a/app/apps/api/tests.py +++ b/app/apps/api/tests.py @@ -11,6 +11,26 @@ from django.urls import reverse from core.models import Block, Line, Transcription, LineTranscription from core.tests.factory import CoreFactoryTestCase +class UserViewSetTestCase(CoreFactoryTestCase): + + def setUp(self): + super().setUp() + + def test_onboarding(self): + user = self.factory.make_user() + self.client.force_login(user) + uri = reverse('api:user-onboarding') + resp = self.client.put(uri, { + 'onboarding' : 'False', + }, content_type='application/json') + + user.refresh_from_db() + self.assertEqual(resp.status_code, 200) + self.assertEqual(user.onboarding, False) + + + + class DocumentViewSetTestCase(CoreFactoryTestCase): def setUp(self): diff --git a/app/apps/api/urls.py b/app/apps/api/urls.py index 80ec98c616d72aa863494911c224ebcafb27930d..3c773a394e07c9b1ea1c7c874d82c0b67cb53188 100644 --- a/app/apps/api/urls.py +++ b/app/apps/api/urls.py @@ -14,7 +14,7 @@ from api.views import (DocumentViewSet, router = routers.DefaultRouter() router.register(r'documents', DocumentViewSet) -router.register(r'users', UserViewSet) +router.register(r'user', UserViewSet) router.register(r'types/block', BlockTypeViewSet) router.register(r'types/line', LineTypeViewSet) documents_router = routers.NestedSimpleRouter(router, r'documents', lookup='document') diff --git a/app/apps/api/views.py b/app/apps/api/views.py index 87e3430aa6de19b7755c1c8fcfb0bb6e56090f0b..4a059bc4dc16971b4ed073e7bc875317a26f61fe 100644 --- a/app/apps/api/views.py +++ b/app/apps/api/views.py @@ -50,9 +50,9 @@ class UserViewSet(ModelViewSet): @action(detail=False, methods=['put']) def onboarding(self, request): - serializer = UserOnboardingSerializer(data=request.data, user=self.request.user) + serializer = UserOnboardingSerializer(self.request.user,data=request.data, partial=True) if serializer.is_valid(raise_exception=True): - serializer.complete() + serializer.save() return Response(status=status.HTTP_200_OK) diff --git a/app/apps/core/static/js/edit/components/trans_modal.js b/app/apps/core/static/js/edit/components/trans_modal.js index 0686ad6969044459622b6423c75829139c93d0c0..eebfeb4b73e939c8a69a52efcbfae0a4e08f4561 100644 --- a/app/apps/core/static/js/edit/components/trans_modal.js +++ b/app/apps/core/static/js/edit/components/trans_modal.js @@ -163,6 +163,6 @@ const TranscriptionModal = Vue.component('transcriptionmodal', { } else { overlay.style.display = 'none'; } - }, + } }, }); diff --git a/app/apps/core/views.py b/app/apps/core/views.py index 7e38f7ff518bbeccc36eeb2b25eb4d6886b9a502..1304370de8fdd3aaf3ab4f5d816bf53623224d3f 100644 --- a/app/apps/core/views.py +++ b/app/apps/core/views.py @@ -147,8 +147,6 @@ class DocumentImages(LoginRequiredMixin, DocumentMixin, DetailView): context['process_form'] = DocumentProcessForm(self.object, self.request.user) context['import_form'] = ImportForm(self.object, self.request.user) context['export_form'] = ExportForm(self.object, self.request.user) - context['onboarding'] = self.request.user.onboarding - return context diff --git a/app/apps/users/admin.py b/app/apps/users/admin.py index d052098e307f0c509c5c8f547780418d2fbf7789..6af1d512c76cdf156087be1e68471861792ddc2a 100644 --- a/app/apps/users/admin.py +++ b/app/apps/users/admin.py @@ -32,7 +32,7 @@ class MyUserAdmin(UserAdmin): add_form = MyUserCreationForm list_display = UserAdmin.list_display + ('last_login',) fieldsets = UserAdmin.fieldsets + ( - (None, {'fields': ('fields',)}), # second fields refers to research fields + (None, {'fields': ('fields','onboarding')}), # second fields refers to research fields ) diff --git a/app/apps/users/models.py b/app/apps/users/models.py index 95acf46467b39554eacf93e8ddcd88bfd045449d..482b912f183b1e285f4c05cde7331f7c111a89ca 100644 --- a/app/apps/users/models.py +++ b/app/apps/users/models.py @@ -21,7 +21,7 @@ class User(AbstractUser): fields = models.ManyToManyField('ResearchField', blank=True) onboarding = models.BooleanField( - _('first connection'), + _('Show onboarding'), default=True ) diff --git a/app/apps/users/views.py b/app/apps/users/views.py index e594848afeb36c7ad7d67a0190bbd744a5fde123..a597d1e6bc9a2475a9300b2baa18f280950923f6 100644 --- a/app/apps/users/views.py +++ b/app/apps/users/views.py @@ -102,6 +102,7 @@ class Profile(SuccessMessageMixin, UpdateView): page_number = self.request.GET.get('page') context['is_paginated'] = paginator.count != 0 context['page_obj'] = paginator.get_page(page_number) + return context class ContactUsView(SuccessMessageMixin, CreateView): diff --git a/app/escriptorium/static/css/escriptorium.css b/app/escriptorium/static/css/escriptorium.css index b2aa36a70b98ae5fe16d69ad30a45766e4aaebad..8c4d07e1387d8163cc2b391d9577e1fbd30d3803 100644 --- a/app/escriptorium/static/css/escriptorium.css +++ b/app/escriptorium/static/css/escriptorium.css @@ -644,5 +644,8 @@ i.panel-icon { } #contact-form{ - width: 100%; + width: 100%; } +#reset-onboarding{ + margin-top: 5%; +} \ No newline at end of file diff --git a/app/escriptorium/static/js/onboarding.js b/app/escriptorium/static/js/onboarding.js index 4e2180f7d94d30c4c1207e2cc6e8cdd898ffc92f..440c15d974e3ec91568945f612f68d79d7dc8bc5 100644 --- a/app/escriptorium/static/js/onboarding.js +++ b/app/escriptorium/static/js/onboarding.js @@ -1,73 +1,143 @@ -var document_images_intro = introJs(); -document_images_intro.setOptions({ -steps: [ -{ - element: '#nav-doc-tab', - intro: 'Update Document description (Name, Text direction or metadata).<br>', - position: 'bottom' -}, -{ - element: '#nav-edit-tab', - intro: 'Edit Document Part. Panels to update transcriptions, baselines and masks', - position: 'bottom' -}, -{ - element: '#nav-models-tab', - intro: 'Handle Transcription and Segmentation models related to this document.', - position: 'bottom' -}, { - element: '#document-image-dropzone', - intro: 'Upload a new document part image.', - position: 'bottom' -}, -{ - element: '#import-selected', - intro: 'Import document part. <br> accepted formats : IIIF, Pagexml, Alto.', - position: 'bottom' -}, -{ - element: '#document-export', - intro: 'Import document part. <br> accepted formats : Text, Pagexml, Alto.', - position: 'bottom' -}, -{ - element: '#train-selected', - intro: 'Train a Segmentation or Transcription model', - position: 'bottom' -}, -{ - element: '#binarize-selected', - intro: 'Binarize the color of selected images.', - position: 'bottom' -}, -{ - element: '#segment-selected', - intro: 'Segment selected images.', - position: 'bottom' -}, -{ - element: '#transcribe-selected', - intro: 'Transcribe automatically the selected images.', - position: 'top' -}, -{ - element: '#js-edit', - intro: 'Transcribe, Segment Manually the image.', - position: 'bottom' -}, -]}); +/* +Just set ONBOARDING_PAGE in the page before the scripts block.super eg: -function exitonboarding() { - $.ajax({type: 'PUT', url:'/api/users/onboarding/', - contentType: "application/json; charset=utf-8", - data:JSON.stringify({ - onboarding : "False", - }) +const ONBOARDING_PAGE = 'onboarding_document_form'; - }).done($.proxy(function(data){ - console.log("success",data) - }, this)).fail(function(data) { - alert(data); +*/ + +if (typeof ONBOARDING_PAGE !== 'undefined') { + var onboarding_page_done = userProfile.get(ONBOARDING_PAGE) || false; + + if (!onboarding_page_done) { + var intro = introJs().setOptions({'skipLabel': "Skip"}); + intro.oncomplete(function() { + userProfile.set(ONBOARDING_PAGE, true); + }) + intro.onexit(function(aa) { + if (!userProfile.get(ONBOARDING_PAGE, true)) { + if (confirm("Are you sure you want to avoid further help?")) { + exitOnboarding(); + } + } + }); + + //document_form + if (ONBOARDING_PAGE == 'onboarding_document_form') { + intro.setOptions({ + steps: [ + { + element: '#nav-doc-tab', + intro: 'Update Document description (Name, Text direction or metadata).', + position: 'bottom', + }, + { + element: '#nav-img-tab', + intro: 'Upload images and changes their orders, import and export transcriptions, launch mass automatic segmentation or transcription.', + position: 'bottom', + }, + { + element: '#nav-edit-tab', + intro: 'Panels to update transcriptions, baselines and masks.', + position: 'bottom', + }, + { + element: '#nav-models-tab', + intro: 'Handle Transcription and Segmentation models related to this document.', + position: 'bottom' + }, + ] + }); + + } else if (ONBOARDING_PAGE == 'onboarding_images') { + intro.setOptions({ + steps: [ + { + element: '#import-selected', + intro: 'Import images, segmentation and/or transcriptions. <br> accepted formats : IIIF, Pagexml, Alto.', + position: 'bottom' + }, + { + element: '#document-export', + intro: 'Export segmentation and/or transcriptions. <br> accepted formats : Text, Pagexml, Alto.', + position: 'bottom' + }, + { + element: '#train-selected', + intro: 'Train a Segmentation or Transcription model.', + position: 'bottom' + }, + { + element: '#binarize-selected', + intro: 'Binarize the color of selected images.', + position: 'bottom' + }, + { + element: '#segment-selected', + intro: 'Segment selected images.', + position: 'bottom' + }, + { + element: '#transcribe-selected', + intro: 'Transcribe automatically the selected images.', + position: 'left' + }, + { + element: "#cards-container", + intro: 'This shows all the images for your manuscript. You can select one or multiple images for training, segmentation, transcribing, or export. Clicking on the [fas fa-edit] icon allows you to edit the segmentation and text. The [fa-align-left] icon shows you if the page has been segmented (green = yes, black = no, ‘pulsing’ green = segmentation in progress). The blue progress bar shows the amount of text that has been entered.\n', + position: 'top' + } + ] }); + } else if (ONBOARDING_PAGE == 'onboarding_edit') { + intro.setOptions({ + steps: [ + // { + // element: '#document-transcriptions', + // intro: 'Here you can select which transcription to display. You may have several transcriptions for a given page,<br> for instance a manual one and one created automatically, or two different editions that you have imported.', + // position: 'bottom', + // }, + { + element: '#seg-panel-btn', + intro: 'In this panel you can manually segment the image or correct the segmentation. You can draw regions or lines onto the image, or change existing lines or regions,<br> and you can also add categories to the different regions and lines (‘main text’, ‘marginal gloss’, ‘page number’ etc.)', + position: 'left', + }, + { + element: '#trans-panel-btn', + intro: 'In this pane you can enter or correct a transcription line-by-line.<br> Clicking on a line of text will bring up a window showing the image of that line, and a box where you can enter or correct the transcription.', + position: 'left', + }, + { + element: '#diplo-panel-btn', + intro: 'This shows another form for entering transcription.<br> Here you can enter and work with multiple lines at a time, for instance copying and pasting a block of text from another source.\n.', + position: 'left', + }, + ] + }); + } else if (ONBOARDING_PAGE == 'onboarding_models') { + intro.setOptions({ + doneLabel: null, + steps: [{ + element: '#models-table', + intro: 'Here you manage Transcription and Segmentation models related to this document.', + position: 'bottom' + }] + }); + } + + document.addEventListener('DOMContentLoaded', function() { + intro.start(); + }); + } +} + +function exitOnboarding() { + $.ajax({ + type: 'PUT', + url: '/api/user/onboarding/', + contentType: "application/json; charset=utf-8", + data: JSON.stringify({ + onboarding: "False", + }) + }); } diff --git a/app/escriptorium/static/vendor/introjs/introjs.css b/app/escriptorium/static/vendor/introjs/introjs.css index f97441f81e8f05efdd7097a80c308965f90bdfbe..e5048806cda32e8639a3429a2c2af99d8794be16 100644 --- a/app/escriptorium/static/vendor/introjs/introjs.css +++ b/app/escriptorium/static/vendor/introjs/introjs.css @@ -117,7 +117,7 @@ padding: 10px; background-color: white; min-width: 200px; - max-width: 300px; + max-width: 100%; border-radius: 3px; box-shadow: 0 1px 10px rgba(0,0,0,.4); -webkit-transition: opacity 0.1s ease-out; diff --git a/app/escriptorium/templates/base.html b/app/escriptorium/templates/base.html index cf925d3630758be39af63348ee68abef46cbb22d..7b3c0feecf0e29666189af0df57b28364ca65deb 100644 --- a/app/escriptorium/templates/base.html +++ b/app/escriptorium/templates/base.html @@ -27,6 +27,7 @@ <link href="{% static '/vendor/fontawesome/all.min.css' %}" rel="stylesheet" type="text/css"> <link href="{% static '/css/escriptorium.css' %}" rel="stylesheet" type="text/css"> <link href="{% static '/css/rtl.css' %}" rel="stylesheet" type="text/css"> + <link href="{% static 'vendor/introjs/introjs.css' %}" rel="stylesheet" type="text/css"> {% endcompress %} {% endblock styles %} @@ -112,6 +113,10 @@ <script src="{% static 'js/messages.js' %}"></script> {% include 'includes/messages.html' %} <script src="{% static 'js/profile.js' %}"></script> + {% if user.onboarding %} + <script src="{% static 'vendor/introjs/intro.js' %}"></script> + <script src="{% static 'js/onboarding.js' %}"></script> + {% endif %} {% endif %} {% endblock scripts %} </body> diff --git a/app/escriptorium/templates/core/document_form.html b/app/escriptorium/templates/core/document_form.html index 95a8a82f1395f242ccc8df296b9c235ef722ab19..f88f7efe9a2620cca9f377cbdae28bca6ff18b5f 100644 --- a/app/escriptorium/templates/core/document_form.html +++ b/app/escriptorium/templates/core/document_form.html @@ -166,6 +166,11 @@ {% endblock %} {% block scripts %} +<script type="text/javascript"> + {% if user.onboarding %} + const ONBOARDING_PAGE = 'onboarding_document_form'; + {% endif %} +</script> {{ block.super }} <script src="{% static 'js/document_form.js' %}"></script> <script src="{% static 'js/help.js' %}"></script> diff --git a/app/escriptorium/templates/core/document_images.html b/app/escriptorium/templates/core/document_images.html index 40acff572e69b15d684e319cbcc0cf1a764734bc..f2abcc0cd85ee5dd8aee2c232b055d598dfe6ab6 100644 --- a/app/escriptorium/templates/core/document_images.html +++ b/app/escriptorium/templates/core/document_images.html @@ -4,7 +4,6 @@ {% block styles %} <link href="{% static 'vendor/dropzone/basic.min.css' %}" rel="stylesheet" type="text/css"> <link href="{% static 'vendor/dropzone/dropzone.min.css' %}" rel="stylesheet" type="text/css"> -<link href="{% static 'vendor/introjs/introjs.css' %}" rel="stylesheet" type="text/css"> {# custom jquery ui build with draggable and resizable only #} <link href="{% static 'vendor/jquery/jquery-ui.min.css' %}" rel="stylesheet" type="text/css"> @@ -113,42 +112,31 @@ {% endblock %} {% block scripts %} -{{ block.super }} <script type="text/javascript"> -'use strict'; -const DOCUMENT_ID = {{ document.pk }}; -const onboarding = "{{ onboarding }}"; -$(document).ready(function() { - // join the ws room - msgSocket.addEventListener('open', function(ev) { - msgSocket.send('{"type": "join-room", "object_cls": "document", "object_pk": {{ document.pk }}}'); - }); -}); + 'use strict'; + const DOCUMENT_ID = {{ document.pk }}; + {% if user.onboarding %} + const ONBOARDING_PAGE = 'onboarding_images'; + {% endif %} </script> -{% compress js file document_images %} - - <script src="{% static 'vendor/dropzone/dropzone.min.js' %}"></script> - <script src="{% static 'vendor/jquery/jquery-ui.min.js' %}"></script> - <script src="{% static 'vendor/introjs/intro.js' %}"></script> - <script src="{% static 'js/image_cards.js' %}"></script> - <script src="{% static 'js/lazyload.js' %}"></script> - <script src="{% static 'js/help.js' %}"></script> - <script src="{% static 'js/onboarding.js' %}"></script> -{% endcompress %} +{{ block.super }} <script type="text/javascript"> -if (onboarding == "True") -{ - document_images_intro.start(); - document_images_intro.onexit(function() { - exitonboarding(); - }); - - document_images_intro.oncomplete(function() { - exitonboarding(); - }); + 'use strict'; -} + $(document).ready(function() { + // join the ws room + msgSocket.addEventListener('open', function(ev) { + msgSocket.send('{"type": "join-room", "object_cls": "document", "object_pk": {{ document.pk }}}'); + }); + }); </script> +{% compress js file document_images %} +<script src="{% static 'vendor/dropzone/dropzone.min.js' %}"></script> +<script src="{% static 'vendor/jquery/jquery-ui.min.js' %}"></script> +<script src="{% static 'js/image_cards.js' %}"></script> +<script src="{% static 'js/lazyload.js' %}"></script> +<script src="{% static 'js/help.js' %}"></script> +{% endcompress %} {% endblock %} diff --git a/app/escriptorium/templates/core/document_nav.html b/app/escriptorium/templates/core/document_nav.html index f92433b626d92b35c93fab6685455a49854ba419..06263243935d6f6092a82b811d30880704bffb5d 100644 --- a/app/escriptorium/templates/core/document_nav.html +++ b/app/escriptorium/templates/core/document_nav.html @@ -1,5 +1,5 @@ {% extends 'base.html' %} -{% load i18n bootstrap %} +{% load i18n staticfiles bootstrap %} {% block head_title %}{% if object %}{% trans "Update a Document" %}{% else %}{% trans "Create a new Document" %}{% endif %}{% endblock %} {% block body %} diff --git a/app/escriptorium/templates/core/document_part_edit.html b/app/escriptorium/templates/core/document_part_edit.html index 7a151dc01ba523497611de918700b1b591f6f7b6..a51bf6bd0e39fbd6e0c86e411ebeb881d814f106 100644 --- a/app/escriptorium/templates/core/document_part_edit.html +++ b/app/escriptorium/templates/core/document_part_edit.html @@ -62,26 +62,30 @@ {% endblock %} {% block extra_nav %} - <div class="nav-item ml-auto"> + <div class="nav-item ml-auto" id="toggle-panels"> <button type="button" + id="source-panel-btn" @click="togglePanel" data-target="source" class="open-panel nav-item btn" v-bind:class="[ show.source ? 'btn-primary' : 'btn-secondary' ]" title="{% trans "Source Image" %}"><i class="click-through fas fa-eye"></i></button> <button type="button" + id="seg-panel-btn" @click="togglePanel" data-target="segmentation" class="open-panel nav-item btn" v-bind:class="[ show.segmentation ? 'btn-primary' : 'btn-secondary' ]" title="{% trans "Segmentation" %}"><i class="click-through fas fa-align-left"></i></button> <button type="button" + id="trans-panel-btn" @click="togglePanel" data-target="visualisation" class="open-panel nav-item btn" v-bind:class="[ show.visualisation ? 'btn-primary' : 'btn-secondary' ]" title="{% trans "Transcription" %}"><i class="click-through fas fa-language"></i></button> <button type="button" + id="diplo-panel-btn" @click="togglePanel" data-target="diplomatic" class="open-panel nav-item btn" @@ -171,6 +175,7 @@ <SegmentationPanel v-if="show.segmentation && part.loaded" v-bind:fullsizeimage="fullsizeimage" v-bind:part="part" + id="segmentation-panel" ref="segPanel" inline-template> <div class="col panel"> <div class="tools"> @@ -333,6 +338,7 @@ <keep-alive> <VisuPanel v-if="show.visualisation && part.loaded" v-bind:part="part" + id="transcription-panel" ref="visuPanel" inline-template> <div class="col panel"> <div class="tools"> @@ -538,8 +544,7 @@ </TranscriptionModal> </div> </VisuPanel> - </keep-alive> - + </keep-alive> <keep-alive> <DiploPanel id="diplo-panel" v-bind:part="part" @@ -601,17 +606,23 @@ </a> {% endif %} </div> - </div> - {% endblock %} + </div> + {% endblock %} - {% block scripts %} - {{ block.super }} - <script type="text/javascript"> - const READ_DIRECTION = '{{document.read_direction}}'; - const TEXT_DIRECTION = '{{document.main_script.text_direction}}'; - const DOCUMENT_ID = '{{document.id}}'; - var PART_ID = {{part.id}}; // can be changed with next & previous pages - </script> + {% block scripts %} + + <script type="text/javascript"> + const READ_DIRECTION = '{{document.read_direction}}'; + const TEXT_DIRECTION = '{{document.main_script.text_direction}}'; + const DOCUMENT_ID = '{{document.id}}'; + var PART_ID = {{part.id}}; // can be changed with next & previous pages + {% if user.onboarding %} + const ONBOARDING_PAGE = "onboarding_edit"; + {% endif %} + var models_url = "{% url 'document-models' document_pk=document.pk %}"; + </script> + + {{ block.super }} <script type="text/javascript"> 'use strict'; diff --git a/app/escriptorium/templates/core/models_list.html b/app/escriptorium/templates/core/models_list.html index 5e65d0cdf94baefa750535ff40522df15497ca53..741ccdf6ff539006d05dbfdef25aa703dfb4b3ef 100644 --- a/app/escriptorium/templates/core/models_list.html +++ b/app/escriptorium/templates/core/models_list.html @@ -35,13 +35,13 @@ <i class="fas fa-save"></i> </button> {% endif %} - + {% if model.file %} <a href="{{ model.file.url }}" class="btn btn-sm btn-primary" title="{% trans "Download" %}" role="button"> <i class="fas fa-file-download"></i> </a> {% endif %} - + {% if model.owner == request.user and not model.training %} <form method="POST" class="inline-form" action="{% url 'model-delete' model.pk %}?next={{request.path}}"> {% csrf_token %} @@ -54,7 +54,7 @@ </tr> {% for version in model.history %} <tr id="model-version-{{version.revision}}" class="versions-{{model.pk}} collapse"> - + <td title="{% trans "Model name" %}" class="pl-5">{{ version.name }} (epoch #{{version.training_epoch}})</td> <td></td> <td title="{% trans "Accuracy" %}">{{ version.accuracy_percent|floatformat:1 }}%</td> @@ -62,7 +62,7 @@ <td> <a href="{{ version.file.url }}"> <button type="button" class="btn btn-sm btn-primary" title="{% trans "Download" %}"> - <i class="fas fa-file-download"></i> + <i class="fas fa-file-download"></i> </button> </td> </tr> @@ -72,6 +72,13 @@ {% endblock %} {% block scripts %} +<script type="text/javascript"> + 'use strict'; + {% if user.onboarding %} + const ONBOARDING_PAGE = "onboarding_models"; + {% endif %} +</script> + {{ block.super }} <script type="text/javascript"> 'use strict'; diff --git a/app/escriptorium/templates/users/profile.html b/app/escriptorium/templates/users/profile.html index 8c6e7bc998bf261957e6d8de777bd01eb512bbf4..3063f8ed66a5c47ee7aedca92b05f4ecec3ffaf4 100644 --- a/app/escriptorium/templates/users/profile.html +++ b/app/escriptorium/templates/users/profile.html @@ -22,6 +22,8 @@ <input type="submit" value="{% trans 'Save' %}" class="btn btn-lg btn-success btn-block"> </fieldset> </form> + + <button id="reset-onboarding" style="" class="btn btn-lg btn-primary btn-block">Reset onboarding</button> </div> <div class="tab-pane fade show" id="key-tab" role="tabpanel" aria-labelledby="v-pills-home-tab"> @@ -71,6 +73,32 @@ history.replaceState(null, null, newUrl); updatePagination(hash); }); + + $('#reset-onboarding').on('click',function () { + + userProfile.set('onboarding_document_form', false); + userProfile.set('onboarding_images', false); + userProfile.set('onboarding_edit', false); + userProfile.set('onboarding_trans', false); + userProfile.set('onboarding_models', false); + + $.ajax({ + type: 'PUT', + url: '/api/user/onboarding/', + contentType: "application/json; charset=utf-8", + data: JSON.stringify({ + onboarding: "True", + }) + }) + .done($.proxy(function(data) { + Alert.add(Date.now(), "Help was reset.", 'success'); + }, this)) + .fail(function(data) { + Alert.add(Date.now(), "Couldn't reset help.", 'error'); + }); + }); + }, false); + </script> {% endblock %}