Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature User needs a help center with FAQ’s, help videos, live chat #35

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Procfile
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
release: bash ./pre-release.sh
release: ./manage.py migrate
web: gunicorn hc.wsgi:application
20 changes: 20 additions & 0 deletions hc/accounts/migrations/0011_auto_20180719_1857.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2018-07-19 18:57
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0010_merge_20180714_0612'),
]

operations = [
migrations.AlterField(
model_name='profile',
name='report_frequency',
field=models.CharField(default='month', max_length=20),
),
]
16 changes: 16 additions & 0 deletions hc/accounts/migrations/0012_merge_20180723_1342.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2018-07-23 13:42
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('accounts', '0011_merge_20180716_1253'),
('accounts', '0011_auto_20180719_1857'),
]

operations = [
]
31 changes: 30 additions & 1 deletion hc/api/admin.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.contrib import admin
from django.core.paginator import Paginator
from django.db import connection
from hc.api.models import Channel, Check, Notification, Ping
from hc.api.models import Channel, Check, Notification, Ping, Faq, Video


class OwnershipListFilter(admin.SimpleListFilter):
Expand Down Expand Up @@ -200,3 +200,32 @@ def channel_kind(self, obj):

def channel_value(self, obj):
return obj.channel.value


@admin.register(Video)
class VideoAdmin(admin.ModelAdmin):

class Media:
css = {
'all': ('css/admin/checks.css',)
}

search_fields = ["header"]
list_display = ("id", "header", "description", "video_link")
list_filter = ["header"]
list_display_links = ('id', 'header')


@admin.register(Faq)
class FaqAdmin(admin.ModelAdmin):

class Media:
css = {
'all': ('css/admin/checks.css',)
}

search_fields = ["question", "answer"]
list_display = ("id", "question", "answer")

list_filter = ["question", "answer"]
list_display_links = ("id", "question")
42 changes: 42 additions & 0 deletions hc/api/migrations/0051_auto_20180719_1857.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2018-07-19 18:57
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0050_merge_20180716_0922'),
]

operations = [
migrations.CreateModel(
name='Faq',
fields=[
('id', models.AutoField(auto_created=True,
primary_key=True, serialize=False,
verbose_name='ID')),
('question', models.TextField(blank=True)),
('answer', models.TextField(blank=True)),
],
),
migrations.CreateModel(
name='Video',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True,
serialize=False, verbose_name='ID')),
('header', models.TextField(blank=True)),
('description', models.TextField(blank=True)),
('video_link', models.URLField(
help_text='https://www.youtube.com/watch?v=5sMKX22BHeEM')),
],
),
migrations.AlterField(
model_name='check',
name='twilio_number',
field=models.TextField(
blank=True, default='+00000000000', null=True),
),
]
20 changes: 20 additions & 0 deletions hc/api/migrations/0052_auto_20180723_1254.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2018-07-23 12:54
from __future__ import unicode_literals

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('api', '0051_auto_20180719_1857'),
]

operations = [
migrations.AlterField(
model_name='video',
name='video_link',
field=models.URLField(),
),
]
16 changes: 16 additions & 0 deletions hc/api/migrations/0053_merge_20180723_1342.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2018-07-23 13:42
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('api', '0052_merge_20180718_0911'),
('api', '0052_auto_20180723_1254'),
]

operations = [
]
11 changes: 11 additions & 0 deletions hc/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,3 +306,14 @@ class Meta:
channel = models.ForeignKey(Channel)
created = models.DateTimeField(auto_now_add=True)
error = models.CharField(max_length=200, blank=True)


class Faq(models.Model):
question = models.TextField(blank=True, null=False)
answer = models.TextField(blank=True, null=False)


class Video(models.Model):
header = models.TextField(blank=True, null=False)
description = models.TextField(blank=True, null=False)
video_link = models.URLField(blank=False, null=False)
2 changes: 2 additions & 0 deletions hc/api/tests/test_sendalerts_until_resolved.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ def test_it_handles_unresolved(self, mock):

result = Command().handle_many()
self.assertEqual(result, True)

# def test_set_priority_level(self)
17 changes: 17 additions & 0 deletions hc/front/tests/test_help_center.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from hc.test import BaseTestCase
from django.urls import reverse


class HelpCenterTestCase(BaseTestCase):
def setUp(self):
super(HelpCenterTestCase, self).setUp()

def test_faq_works(self):
self.client.login(username="[email protected]", password="password")
response = self.client.get(reverse("hc-faqs"))
self.assertEqual(response.status_code, 200)

def test_help_videos_work(self):
self.client.login(username="[email protected]", password="password")
response = self.client.get(reverse("hc-help-videos"))
self.assertEqual(response.status_code, 200)
2 changes: 2 additions & 0 deletions hc/front/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,6 @@
url(r'^about/$', views.about, name="hc-about"),
url(r'^privacy/$', views.privacy, name="hc-privacy"),
url(r'^terms/$', views.terms, name="hc-terms"),
url(r'^faqs/$', views.faq, name="hc-faqs"),
url(r'^help_videos/$', views.help_videos, name="hc-help-videos"),
]
41 changes: 32 additions & 9 deletions hc/front/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@
from django.utils.crypto import get_random_string
from django.utils.six.moves.urllib.parse import urlencode
from hc.api.decorators import uuid_or_400
from hc.api.models import DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check, Ping
from hc.front.forms import (AddChannelForm,
AddWebhookForm,
NameTagsDepartmentForm,
TimeoutForm,
NagIntervalForm,
ShopifyForm,
PriorityForm)
import shopify

from hc.api.models import (DEFAULT_GRACE, DEFAULT_TIMEOUT, Channel, Check,
Ping, Video, Faq)
from hc.front.forms import (AddChannelForm, AddWebhookForm,
TimeoutForm, NagIntervalForm, PriorityForm,
ShopifyForm, NameTagsDepartmentForm)

# from itertools recipes:


def pairwise(iterable):
"s -> (s0,s1), (s1,s2), (s2, s3), ..."
a, b = tee(iterable)
Expand Down Expand Up @@ -733,3 +731,28 @@ def unresolved_checks(request):
}

return render(request, "front/unresolved_checks.html", ctx)


@login_required
def help_videos(request):
q = Video.objects.order_by("id")
videos = list(q)

ctx = {
"page": "help_videos",
"help_videos": videos
}

return render(request, "front/help_videos.html", ctx)


@login_required
def faq(request):
q = Faq.objects.order_by("id")
faqs = list(q)

ctx = {
"page": "faqs",
"faqs": faqs
}
return render(request, "front/faqs.html", ctx)
2 changes: 1 addition & 1 deletion hc/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
'hc.accounts',
'hc.api',
'hc.front',
'hc.payments'
'hc.payments',
)


Expand Down
2 changes: 1 addition & 1 deletion hc/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
url(r'^accounts/', include('hc.accounts.urls')),
url(r'^', include('hc.api.urls')),
url(r'^', include('hc.front.urls')),
url(r'^', include('hc.payments.urls'))
url(r'^', include('hc.payments.urls')),
]
18 changes: 18 additions & 0 deletions templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,24 @@
<li {% if page == 'about' %} class="active" {% endif %}>
<a href="{% url 'hc-about' %}">About</a>
</li>
{% if request.user.is_authenticated %}
<li {% if page == 'helpcenter' %} class="active check-menu dropdown" {% endif %}>
<a class="dropdown-toggle" href="#" data-toggle="dropdown">Help Center</a>
<ul class="dropdown-menu">
<li {% if page == 'faqs' %} class="active" {% endif %}>
<a href="{% url 'hc-faqs' %}" class="faqs">
FAQs
</a>
</li>
<li role="separator" class="divider"></li>
<li {% if page == 'videos' %} class="active" {% endif %}>
<a href="{% url 'hc-help-videos' %}" >
videos
</a>
</li>
</ul>
</li>
{% endif %}
</ul>


Expand Down
28 changes: 28 additions & 0 deletions templates/front/faqs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% extends "base.html" %}
{% load staticfiles %}
{% block title %}FAQs - healthchecks.io{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-12">
<h3>Frequently Asked Questions </h3>
<div class="panel-group" id="accordion">
{% if faqs %}
{% for faq in faqs %}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#{{ faq.id }}">{{ faq.question }}</a>
</h4>
</div>
<div id="{{ faq.id }}" class="panel-collapse collapse">
<div class="panel-body">{{ faq.answer }}</div>
</div>
</div>
{% endfor %}
{% else %}
<div class="alert alert-info">No FAQs available.</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}
32 changes: 32 additions & 0 deletions templates/front/help_videos.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{% extends "base.html" %}
{% load staticfiles %}

{% block title %}Help Center - healthchecks.io{% endblock %}

{% block content %}
<div class="row">
<div class="col-sm-12">

<h3>Welcome to the help videos </h3>
<p>
Healthchecks.io is an open source project on
<a href="https://github.com/healthchecks/healthchecks">GitHub</a>
</p>
<div class="row">
<div class="col-sm-12">
{% if help_videos %}
{% for help_video in help_videos %}
<h3>{{ help_video.header }}</h3>
<p>{{ help_video.description }}</p>
<iframe width="960" height="615" src="{{ help_video.video_link }}"
frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
{% endfor %}
{% else %}
<div class="alert alert-info">There are currently no videos available.</div>
{% endif %}
</div>
</div>

</div>
</div>
{% endblock %}
11 changes: 11 additions & 0 deletions templates/front/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,17 @@ <h2 class="tour-title">A quick peek of what's inside:</h2>
<script src="{% static 'js/collapse-native.js' %}"></script>
<script src="{% static 'js/tab-native.js' %}"></script>
<script src="{% static 'js/welcome.js' %}"></script>
<!-- Start of LiveChat (www.livechatinc.com) code -->
<script type="text/javascript">
window.__lc = window.__lc || {};
window.__lc.license = 9953335;
(function() {
var lc = document.createElement('script'); lc.type = 'text/javascript'; lc.async = true;
lc.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'cdn.livechatinc.com/tracking.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(lc, s);
})();
</script>
<!-- End of LiveChat code -->
{% endcompress %}
{% endblock %}

Expand Down