Create Release Notes archive in the Documentation section.
authorJonathan S. Katz <jonathan.katz@excoventures.com>
Tue, 12 Feb 2019 19:50:48 +0000 (20:50 +0100)
committerJonathan S. Katz <jonathan.katz@excoventures.com>
Fri, 8 Mar 2019 19:19:25 +0000 (11:19 -0800)
This creates a consolidated area to reference all of the notes from
previous releases of PostgreSQL, as current releases only keep the
the notes for that specific major release of PostgreSQL.

media/css/main.css
pgweb/core/templatetags/pgfilters.py
pgweb/docs/views.py
pgweb/urls.py
pgweb/util/contexts.py
pgweb/util/db.py [new file with mode: 0644]
templates/docs/release_notes.html [new file with mode: 0644]

index e0462ad25c343952857684da40ef497542d0608d..489ac9160ad7dcdfb44ecf3fffd23d75222a2e1a 100644 (file)
@@ -1294,6 +1294,35 @@ table.sponsor-table tbody tr td:nth-child(3) {
     width: 30%;
 }
 
+/** Release Notes */
+#release-notes .navheader,
+#release-notes .navfooter,
+#release-notes .NAVHEADER,
+#release-notes .NAVFOOTER,
+#release-notes .titlepage,
+#release-notes h1.SECT1,
+#release-notes .toc {
+    display: none;
+}
+
+#release-notes .version-list h2:after {
+    content: none;
+}
+
+.release-notes-list {
+    list-style-type: none;
+}
+
+.release-notes-list :not(.collapsed) > .right,
+.release-notes-list .collapsed > .down {
+    display: none;
+}
+
+.release-notes-list .collapsed > .right,
+.release-notes-list :not(.collapsed) > .down {
+    display: block;
+}
+
 
 /** ALL RESPONSIVE QUERIES HERE */
 /* Small devices (landscape phones, 576px and up)*/
index 13f2470c11068b39fac15f634d97d79eee4ca36d..4edeb95cdf9813bb8e38fa77a8fda44cd8cbc7a1 100644 (file)
@@ -70,3 +70,12 @@ def dictlookup(value, key):
 @register.filter(name='json')
 def tojson(value):
     return json.dumps(value)
+
+@register.filter()
+def release_notes_pg_minor_version(minor_version, major_version):
+    """Formats the minor version number to the appropriate PostgreSQL version.
+    This is particularly for very old version of PostgreSQL.
+    """
+    if str(major_version) in ['0', '1']:
+        return str(minor_version)[2:4]
+    return minor_version
index 4577f0ce0e37f9503ad216d3011e0cc0dd4b4ade..62f0abb3ce6ebacfbf3fab663065a1ba7d680224 100644 (file)
@@ -13,6 +13,7 @@ from pgweb.util.helpers import template_to_string
 from pgweb.util.misc import send_template_mail
 
 from pgweb.core.models import Version
+from pgweb.util.db import exec_to_dict
 
 from .models import DocPage
 from .forms import DocCommentForm
@@ -140,6 +141,103 @@ def manualarchive(request):
         'versions': [_VersionPdfWrapper(v) for v in versions],
     })
 
+def release_notes(request, major_version=None, minor_version=None):
+    """Contains the main archive of release notes."""
+    # this query gets a list of a unique set of release notes for each version of
+    # PostgreSQL. From PostgreSQL 9.4+, release notes are only present for their
+    # specific version of PostgreSQL, so all legacy release notes are present in
+    # 9.3 and older
+    # First the query identifies all of the release note files that have been loaded
+    # into the docs. We will limit our lookup to release notes from 9.3 on up,
+    # given 9.3 has all the release notes for PostgreSQL 9.3 and older
+    # From there, it parses the version the release notes are for
+    # from the file name, and breaks it up into "major" and "minor" version from
+    # our understanding of how PostgreSQL version numbering is handled, which is
+    # in 3 camps: 1 and older, 6.0 - 9.6, 10 - current
+    # It is then put into a unique set
+    # Lastly, we determine the next/previous versions (lead/lag) so we are able
+    # to easily page between the different versions in the unique release note view
+    # We only include the content if we are doing an actual lookup on an exact
+    # major/minor release pair, to limit how much data we load into memory
+    sql = """
+    SELECT
+        {content}
+        file, major, minor,
+        lag(minor) OVER (PARTITION BY major ORDER BY minor) AS previous,
+        lead(minor) OVER (PARTITION BY major ORDER BY minor) AS next
+    FROM (
+        SELECT DISTINCT ON (file, major, minor)
+            {content}
+            file,
+            CASE
+                WHEN v[1]::int >= 10 THEN v[1]::numeric
+                WHEN v[1]::int <= 1 THEN v[1]::int
+                ELSE array_to_string(v[1:2], '.')::numeric END AS major,
+            COALESCE(
+                CASE
+                    WHEN v[1]::int >= 10 THEN v[2]
+                    WHEN v[1]::int <= 1 THEN '.' || v[2]
+                    ELSE v[3]
+                END::numeric, 0
+            ) AS minor
+        FROM (
+            SELECT
+                {content}
+                file,
+                string_to_array(regexp_replace(file, 'release-(.*)\.htm.*', '\\1'), '-') AS v
+            FROM docs
+            WHERE file ~ '^release-\d+' AND version >= 9.3
+        ) r
+    ) rr
+    """
+    params = []
+    # if the major + minor version are provided, then we want to narrow down
+    # the results to all the release notes for the minor version, as we need the
+    # list of the entire set in order to generate the nice side bar in the release
+    # notes
+    # otherwise ensure the release notes are returned in order
+    if major_version is not None and minor_version is not None:
+        # at this point, include the content
+        sql = sql.format(content="content,")
+        # restrict to the major version, order from latest to earliest minor
+        sql = """{}
+        WHERE rr.major = %s
+        ORDER BY rr.minor DESC""".format(sql)
+        params += [major_version]
+    else:
+        sql = sql.format(content="")
+        sql += """
+        ORDER BY rr.major DESC, rr.minor DESC;
+        """
+    # run the query, loading a list of dict that contain all of the release
+    # notes that are filtered out by the query
+    release_notes = exec_to_dict(sql, params)
+    # determine which set of data to pass to the template:
+    # if both major/minor versions are present, we will load the release notes
+    # if neither are present, we load the list of all of the release notes to list out
+    if major_version is not None and minor_version is not None:
+        # first, see if any release notes were returned; if not, raise a 404
+        if not release_notes:
+            raise Http404()
+        # next, see if we can find the specific release notes we are looking for
+        # format what the "minor" version should look like
+        try:
+            minor = Decimal('0.{}'.format(minor_version) if major_version in ['0', '1'] else minor_version)
+        except TypeError:
+            raise Http404()
+        release_note = [r for r in release_notes if r['minor'] == minor][0]
+        # of course, if nothing is found, return a 404
+        if not release_note:
+            raise Http404()
+        context = {
+            'major_version': major_version,
+            'minor_version': minor_version,
+            'release_note': release_note,
+            'release_notes': release_notes
+        }
+    else:
+        context = { 'release_notes': release_notes }
+    return render_pgweb(request, 'docs', 'docs/release_notes.html', context)
 
 @login_required
 def commentform(request, itemid, version, filename):
index d8c664f22284a267b23da45ab17aefc7dafa4500..80913c3fc23eaec66dde0a55f7df8ad6b1097d34 100644 (file)
@@ -58,6 +58,8 @@ urlpatterns = [
     url(r'^docs/$', pgweb.docs.views.root),
     url(r'^docs/manuals/$', pgweb.docs.views.manuals),
     url(r'^docs/manuals/archive/$', pgweb.docs.views.manualarchive),
+    url(r'^docs/release/$', pgweb.docs.views.release_notes),
+    url(r'^docs/release/((?P<major_version>(\d+\.\d+)|\d+)\.(?P<minor_version>\d+))/$', pgweb.docs.views.release_notes),
     # Legacy URLs for accessing the docs page; provides a permanent redirect
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(static|interactive)/((.*).html?)?$', pgweb.docs.views.docspermanentredirect),
     url(r'^docs/(current|devel|\d+(?:\.\d)?)/(.*).html?$', pgweb.docs.views.docpage),
index 25c4787e500b60a91473cddc6158b1b6149c6337..c38f2480e16b88fa65013d859937341ca459c34e 100644 (file)
@@ -34,6 +34,7 @@ sitenav = {
             {'title': 'Japanese', 'link': 'http://www.postgresql.jp/document/'},
             {'title': 'Russian', 'link': 'https://postgrespro.ru/docs/postgresql'},
         ]},
+        {'title': 'Release Notes', 'link': '/docs/release/'},
         {'title': 'Books', 'link': '/docs/books/'},
         {'title': 'Online Resources', 'link': '/docs/online-resources/'},
         {'title': 'Wiki', 'link': 'https://wiki.postgresql.org'},
diff --git a/pgweb/util/db.py b/pgweb/util/db.py
new file mode 100644 (file)
index 0000000..a1efae0
--- /dev/null
@@ -0,0 +1,7 @@
+from django.db import connection
+
+def exec_to_dict(query, params=None):
+    curs = connection.cursor()
+    curs.execute(query, params)
+    columns = [col[0] for col in curs.description]
+    return [dict(list(zip(columns, row))) for row in curs.fetchall()]
diff --git a/templates/docs/release_notes.html b/templates/docs/release_notes.html
new file mode 100644 (file)
index 0000000..ca74e8d
--- /dev/null
@@ -0,0 +1,104 @@
+{% extends "base/page.html" %}
+{% load pgfilters %}
+
+{% block extrahead %}
+{% if major_version is not None and minor_version is not None %}
+  <base href="/docs/{{ major_version }}/" />
+{% endif %}
+{% endblock extrahead %}
+
+{%block title%}Release Notes{%endblock%}
+
+{% block contents %}
+{% regroup release_notes by major as release_note_groups %}
+
+<div id="release-notes" class="row">
+  {% if major_version is not None and minor_version is not None %}
+    <div class="col-md-10">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+        <h2>
+          {% if major_version == '0' %}Postgres95{% else %}PostgreSQL{% endif %}
+          {{ major_version }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}
+        </h2>
+      </section>
+      <div id="docContent">
+        {{ release_note.content|safe }}
+      </div>
+      <div class="row">
+        <div class="col-md-3">
+          {% if release_note.previous is not None %}
+            <a href="/docs/release/{{ major_version }}.{{ release_note.previous|release_notes_pg_minor_version:major_version }}/">
+              Previous
+            </a>
+          {% endif %}
+        </div>
+        <div class="col-md-6 text-center">
+          <p>
+            <a href="/docs/release/">
+              Return to the Release Notes Archive
+            </a>
+          </p>
+        </div>
+        <div class="col-md-3 text-right">
+          {% if release_note.next is not None %}
+            <a href="/docs/release/{{ major_version }}.{{ release_note.next|release_notes_pg_minor_version:major_version }}/">
+              Next
+            </a>
+          {% endif %}
+        </div>
+      </div>
+    </div>
+    <div class="col-md-2 version-list">
+      <section>
+        <h2>Versions</h2>
+      </section>
+      <ul>
+        {% for r in release_notes %}
+          <li>
+            {% if r.minor == release_note.minor %}
+              <strong>
+                {{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}
+              </strong>
+            {% else %}
+              <a href="/docs/release/{{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}/">
+                {{ major_version }}.{{ r.minor|release_notes_pg_minor_version:major_version }}
+              </a>
+            {% endif %}
+          </li>
+        {% endfor %}
+      </ul>
+    </div>
+  {% else %}
+    <div class="col-md-9">
+      <section>
+        <h1>Release Notes <i class="far fa-file-alt"></i></h1>
+      </section>
+      <p>Below is the complete archive of release notes for every version of PostgreSQL.</p>
+      <ul class="release-notes-list fa-ul">
+        {% for release_note_group in release_note_groups %}
+          {% with major_version=release_note_group.grouper %}
+            <li>
+              <a class="collapsed" href="#release{{ major_version }}" data-toggle="collapse" role="button" aria-expanded="false" aria-controls="release{{ major_version }}">
+                <span class="fa-li right"><i class="fas fa-angle-right"></i></span>
+                <span class="fa-li down"><i class="fas fa-angle-down"></i></span>
+                {% if major_version == 0 %}Postgres95{% else %}PostgreSQL {{ major_version }}{% endif %}
+              </a>
+              <ul class="collapse release-notes-list" id="release{{ major_version }}">
+                {% for release_note in release_note_group.list %}
+                  <li>
+                    <a href="/docs/release/{{ major_version }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}/">
+                      {{ major_version }}.{{ release_note.minor|release_notes_pg_minor_version:major_version }}
+                    </a>
+                  </li>
+                {% endfor %}
+              </ul>
+            </li>
+          {% endwith %}
+        {% endfor %}
+      </ul>
+    </div>
+  {% endif %}
+</div>
+
+{% endblock %}