diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 09a91c65f..4cbf13f61 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,9 +55,26 @@ jobs: git_remote_url: 'ssh://dokku@liiweb2.africanlii.org:22/ulii-peachjam' git_push_flags: '--force' + deploy-gazettes: + if: ${{ !cancelled() }} + needs: deploy-gazettes + name: Deploy to gazettes.africa + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: git push to gazettes.africa + uses: dokku/github-action@master + with: + ssh_private_key: ${{ secrets.SSH_DEPLOYMENT_KEY }} + git_remote_url: 'ssh://dokku@liiweb2.africanlii.org:22/gazettes' + git_push_flags: '--force' + deploy-zanzibarlii: if: ${{ !cancelled() }} - needs: deploy-lawlibrary + needs: deploy-gazettes name: Deploy to zanzibarlii runs-on: ubuntu-latest steps: diff --git a/gazettes/__init__.py b/gazettes/__init__.py new file mode 100644 index 000000000..50e968285 --- /dev/null +++ b/gazettes/__init__.py @@ -0,0 +1 @@ +default_app_config = "gazettes.apps.GazettesAfricaConfig" diff --git a/gazettes/apps.py b/gazettes/apps.py new file mode 100644 index 000000000..774251935 --- /dev/null +++ b/gazettes/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class GazettesAfricaConfig(AppConfig): + name = "gazettes" + verbose_name = "Gazettes.Africa" diff --git a/gazettes/context_processors.py b/gazettes/context_processors.py new file mode 100644 index 000000000..0b035d2a4 --- /dev/null +++ b/gazettes/context_processors.py @@ -0,0 +1,5 @@ +from gazettes.jurisdictions import jurisdiction_list + + +def jurisdictions(request): + return {"jurisdictions": jurisdiction_list()} diff --git a/gazettes/jurisdictions.py b/gazettes/jurisdictions.py new file mode 100644 index 000000000..c2d28211f --- /dev/null +++ b/gazettes/jurisdictions.py @@ -0,0 +1,211 @@ +from dataclasses import dataclass +from typing import List + + +@dataclass +class Jurisdiction: + code: str + name: str + parent_code: str = None + publication: str = "Government Gazette" + sub_publication_label: str = "Sub-publication" + sub_publication_required: bool = False + sub_publications: List[str] = None + number_short: str = "no" + number_long: str = "number" + stitched_supplements: bool = False + ident_requires_last_page: bool = False + + @property + def parent(self): + if self.parent_code: + return JURISDICTION_MAP[self.parent_code] + + @property + def full_name(self): + if self.parent_code: + return f"{self.name}, {self.parent.name}" + return self.name + + @property + def full_name_for_search(self): + if self.parent_code: + return f"{self.parent.name} - {self.name}" + return self.name + + @property + def children(self): + return sorted( + [x for x in JURISDICTIONS if x.parent_code == self.code], + key=lambda x: x.name, + ) + + @property + def place_code(self): + return self.code + + +JURISDICTIONS = [ + Jurisdiction("dz", "Algeria"), + Jurisdiction( + "ao", + "Angola", + sub_publications=["Series I", "Series II", "Series III"], + sub_publication_label="Series", + sub_publication_required=True, + ), + Jurisdiction("bw", "Botswana"), + Jurisdiction("cg", "Congo", publication="Journal Officiel"), + Jurisdiction("aa", "African Regional Bodies"), + Jurisdiction("aa-eac", "East African Community", "aa", publication="Gazette"), + Jurisdiction( + "aa-ecowas", + "Economic Community of West African States", + "aa", + publication="Official Journal", + number_short="vol", + number_long="volume", + ), + Jurisdiction("gh", "Ghana"), + Jurisdiction("ke", "Kenya"), + Jurisdiction("ls", "Lesotho"), + Jurisdiction("mu", "Mauritius"), + Jurisdiction("mw", "Malawi"), + Jurisdiction( + "mz", + "Mozambique", + sub_publications=["Series I", "Series II", "Series III"], + sub_publication_label="Series", + sub_publication_required=True, + ), + Jurisdiction("na", "Namibia"), + Jurisdiction("ng", "Nigeria"), + Jurisdiction("rw", "Rwanda"), + Jurisdiction("sc", "Seychelles", stitched_supplements=True), + Jurisdiction("sl", "Sierra Leone"), + Jurisdiction("sz", "Eswatini"), + Jurisdiction("tz", "Tanzania"), + Jurisdiction("tz-znz", "Zanzibar", "tz"), + Jurisdiction("ug", "Uganda"), + Jurisdiction("zm", "Zambia"), + # ZW supplements require the date from the last page + Jurisdiction( + "zw", "Zimbabwe", ident_requires_last_page=True, stitched_supplements=True + ), + Jurisdiction( + "za", + "South Africa", + sub_publications=[ + "Regulation Gazette", + "Legal Notices A", + "Legal Notices B", + "Legal Notices C", + "Legal Notices D", + ], + ), + Jurisdiction("za-wc", "Western Cape", "za", "Provincial Gazette"), + Jurisdiction("za-ec", "Eastern Cape", "za", "Provincial Gazette"), + Jurisdiction("za-gp", "Gauteng", "za", "Provincial Gazette"), + Jurisdiction("za-kzn", "KwaZulu-Natal", "za", "Provincial Gazette"), + Jurisdiction("za-lp", "Limpopo", "za", "Provincial Gazette"), + Jurisdiction("za-mp", "Mpumalanga", "za", "Provincial Gazette"), + Jurisdiction("za-nw", "North-West", "za", "Provincial Gazette"), + Jurisdiction("za-nc", "Northern Cape", "za", "Provincial Gazette"), + Jurisdiction("za-fs", "Free State", "za", "Provincial Gazette"), + Jurisdiction("za-transvaal", "Transvaal", "za", "Provincial Gazette"), + Jurisdiction("ng-la", "Lagos State", "ng", "Official Gazette"), + Jurisdiction("ma", "Morocco", publication="Bulletin Officiel"), + Jurisdiction("so", "Somalia"), + Jurisdiction("so-sl", "Somaliland", "so", "Official Gazette"), +] +JURISDICTION_MAP = {x.code: x for x in JURISDICTIONS} +JURISDICTION_CHOICES = [(x.code, x.name) for x in JURISDICTIONS] + +COMMUNITIES = {"aa-eac", "aa-ecowas"} + +CONTRIBUTORS = { + "sz": [ + { + "name": "Werksmans", + "url": "https://www.werksmans.com/", + "img": "werksmans-logo.png", + } + ], + "bw": [ + { + "name": "Werksmans", + "url": "https://www.werksmans.com/", + "img": "werksmans-logo.png", + } + ], + "za": [ + { + "name": "GIZ", + "url": "https://www.giz.de/", + "img": "giz-logo.gif", + }, + { + "name": "Webber Wentzel", + "url": "https://www.webberwentzel.com", + "img": "ww-logo.png", + }, + ], + "za-fs": [ + { + "name": "Free State Province", + "url": "http://www.premier.fs.gov.za", + "img": "za-fs-logo.jpg", + } + ], + "zw": [ + { + "name": "Veritas Zimbabwe", + "url": "https://www.veritaszim.net/", + "img": "veritas-logo.png", + } + ], + None: [ + { + "name": "The Indigo Trust", + "url": "https://indigotrust.org.uk/", + "img": "indigo-trust-logo.png", + }, + { + "name": "UCT Government Publications", + "url": "http://www.governmentpublications.lib.uct.ac.za/", + "img": "uct-logo.png", + }, + { + "name": "C4ADS", + "url": "https://c4ads.org", + "img": "c4ads-logo.png", + }, + ], +} +ALL_CONTRIBUTORS = sorted( + list({c["name"]: c for x in CONTRIBUTORS.values() for c in x}.values()), + key=lambda c: c["name"], +) + + +def get_country_locality(code): + from countries_plus.models import Country + + from peachjam.models import Locality + + if "-" in code: + ctry, loc = code.split("-", 1) + else: + ctry = code + loc = None + + ctry = Country.objects.get(pk=ctry.upper()) + if loc: + loc = Locality.objects.get(jurisdiction=ctry, code=loc) + + return ctry, loc + + +def jurisdiction_list(): + """List of (code, name) tuples for active jurisdictions.""" + return sorted(JURISDICTIONS, key=lambda j: j.name) diff --git a/gazettes/middleware.py b/gazettes/middleware.py new file mode 100644 index 000000000..0abfc8b7e --- /dev/null +++ b/gazettes/middleware.py @@ -0,0 +1,41 @@ +from django.conf import settings +from django.http import HttpResponseNotFound, HttpResponsePermanentRedirect +from django.utils.deprecation import MiddlewareMixin + + +class RedirectMiddleware(MiddlewareMixin): + """Middleware that redirects requests to: + + - the legacy archive.gazettes.laws.africa + - www.gazettes.africa + + to gazettes.africa. + """ + + def process_request(self, request): + host = request.get_host() + if host in ["archive.gazettes.laws.africa", "www.gazettes.africa"]: + uri = f"https://gazettes.africa{request.get_full_path()}" + return HttpResponsePermanentRedirect(uri) + + +class NoIPMiddleware(MiddlewareMixin): + """Middleware that forces a 404 for an request that does not use a + domain name. + + We use this because otherwise Google indexes the gazettes archive using + the IP of the server, for some odd reason. + + Note that during deployment, the dokku aliveness check comes from a local host + with an ip, but with ':5000' + """ + + def process_request(self, request): + host = request.get_host() + if ( + not settings.DEBUG + and "africa" not in host + and "localhost" not in host + and not host.endswith(":5000") + ): + return HttpResponseNotFound("not found") diff --git a/gazettes/settings.py b/gazettes/settings.py new file mode 100644 index 000000000..73a5c8ca6 --- /dev/null +++ b/gazettes/settings.py @@ -0,0 +1,55 @@ +from peachjam.settings import * # noqa + +# Application definition +INSTALLED_APPS = [ + "gazettes", + "django.contrib.humanize", +] + INSTALLED_APPS # noqa + + +MIDDLEWARE = [ + "gazettes.middleware.RedirectMiddleware", + "gazettes.middleware.NoIPMiddleware", + "allauth.account.middleware.AccountMiddleware", +] + MIDDLEWARE # noqa + + +# allow cross-site access from all secure origins +CORS_ALLOWED_ORIGIN_REGEXES = [r"^https://.*"] +CORS_ALLOW_CREDENTIALS = True +CORS_URLS_REGEX = r"^.*$" + + +ROOT_URLCONF = "gazettes.urls" + + +# Database +# https://docs.djangoproject.com/en/3.2/ref/settings/#databases +default_db_url = "postgres://gazettes:gazettes@localhost:5432/gazettes" +db_config = dj_database_url.config( # noqa + default=os.environ.get("DATABASE_URL", default_db_url) # noqa +) +db_config["ATOMIC_REQUESTS"] = True # noqa +DATABASES["default"] = db_config # noqa + + +SECURE_BROWSER_XSS_FILTER = True +SECURE_CONTENT_TYPE_NOSNIFF = True + +X_FRAME_OPTIONS = "SAMEORIGIN" + + +LANGUAGES = [ + ("en", "English"), +] + + +PEACHJAM["APP_NAME"] = "Gazettes.Africa" # noqa +PEACHJAM["ES_INDEX"] = "gazettemachine" # noqa +PEACHJAM["SEARCH_JURISDICTION_FILTER"] = True # noqa +PEACHJAM["MULTIPLE_JURISDICTIONS"] = True # noqa + + +TEMPLATES[0]["OPTIONS"]["context_processors"].append( # noqa + "gazettes.context_processors.jurisdictions" +) diff --git a/gazettes/static/css/_core.scss b/gazettes/static/css/_core.scss new file mode 100644 index 000000000..27a71935a --- /dev/null +++ b/gazettes/static/css/_core.scss @@ -0,0 +1,188 @@ +.lawsafrica-site-header { + padding: 5px 0px; + text-align: right; + background-color: #e9ecef; +} + +.site-main { + min-height: 80vh; +} + +.site-footer { + margin-top: $spacer * 5; + background-color: $light-grey; +} + +.site-footer__body { + padding: ($spacer * 4) 0px; +} + +.site-footer__bottom-redline { + height: 15px; + width: 100%; + background-color: $primary; +} + +.highlighter-rouge pre.highlight { + background-color: $light-grey; + border-radius: 0.75em; + padding: 0.75em; +} + +.sans-serif { + font-family: $font-family-sans-serif; +} + +// home page styling + +.gazettes_nav_btn { + border: none; + background-color: lighten($primary, 40%); + color: #ffffff; + padding: 10px; + font-weight: 600; + margin-bottom: 20px; + width: 100%; + height: 200px; + background-size: cover; + border-radius: 5px; + cursor: pointer; + + &:hover { + background-color: lighten($primary, 35%); + box-shadow: 2px 3px 10px 1px rgba(0,0,0,0.43); + } +} + +// Jurisdiction detail page + +.status-box { + margin: 10px 0px; + .status-border { + border: 1px solid #f7f7f7; + padding: 10px; + } + .status-stats { + text-align: center; + h2 { font-size: 35px; } + i { color: lighten($primary, 20%); } + .status-up { + padding: 10px; + } + } +} + +// year nav + +.year-nav { + list-style-type: none; + padding-left: 0px; + + li { + display: inline; + margin-right: 15px; + + a, + a:visited { + color: $link-color; + } + + a.active, + a.active:visited { + color: black; + font-weight: 500; + } + } +} + +// Stats + +.jurisdiction-stats, .year-stats { + svg { + rect { + fill: #e8e8e8 !important; + + &:hover { + fill: $primary !important; + cursor: pointer; + } + } + + .axis { + font: 10px sans-serif; + + path, line { + fill: none; + stroke: #000; + shape-rendering: crispEdges; + } + + text { + fill: lighten($primary, 30%); + font-family: 'Open Sans', sans-serif; + } + } + + .domain, .tick > line { + display: none; + } + } + + h2 { + font-weight: 600; + } + + .monthly-chart { + margin: 10px 0 20px 0; + } + + text.bar { + fill: lighten($primary, 20%); + font-size: 9px; + font-family: 'Open Sans', sans-serif; + opacity: 0; + } +} + +.gazette-page { + box-shadow: 2px 2px 6px 2px rgba(0, 0, 0, 0.25); + font-size: 75%; +} + +.site-banner { + background-color: $pale-red; +} + +nav { + .dropdown-menu { + @include media-breakpoint-down(sm) { + width: 100%; + a { + white-space: normal; + } + } + } +} + +.flag { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; +} + +.flag__image { + width: 200px; + height: 135px; + margin-bottom: 10px; + object-fit: cover; + object-position: center; + + &[alt="ecowas"] { + object-fit: contain; + } +} + +select.homepage-search-jurisdiction { + max-width: 10em; +} diff --git a/gazettes/static/css/_utilities.scss b/gazettes/static/css/_utilities.scss new file mode 100644 index 000000000..2179bff83 --- /dev/null +++ b/gazettes/static/css/_utilities.scss @@ -0,0 +1,7 @@ +.bg-lawsafrica-pale-red { + background-color: lighten($primary, 30%); +} + +.fg-lawsafrica-pale-red { + color: lighten($primary, 30%); +} diff --git a/gazettes/static/css/_variables.scss b/gazettes/static/css/_variables.scss new file mode 100644 index 000000000..97c54b4ca --- /dev/null +++ b/gazettes/static/css/_variables.scss @@ -0,0 +1,8 @@ +// Bootstrap variable overrides +$primary: #e6372b; + +// Additional colors +$pale-red: #fad7d5; +$light-grey: #f4f4f4; + +$min-contrast-ratio: 3; diff --git a/gazettes/static/css/main.scss b/gazettes/static/css/main.scss new file mode 100644 index 000000000..0c17d50a3 --- /dev/null +++ b/gazettes/static/css/main.scss @@ -0,0 +1,7 @@ +//Bootstrap overrides +@import "variables"; +//Base styles +@import "stylesheets/peachjam"; + +@import 'core'; +@import 'utilities'; diff --git a/gazettes/static/images/favicon-16x16.png b/gazettes/static/images/favicon-16x16.png new file mode 100644 index 000000000..ae3612a20 Binary files /dev/null and b/gazettes/static/images/favicon-16x16.png differ diff --git a/gazettes/static/images/favicon-180x180.png b/gazettes/static/images/favicon-180x180.png new file mode 100644 index 000000000..aceaf148d Binary files /dev/null and b/gazettes/static/images/favicon-180x180.png differ diff --git a/gazettes/static/images/favicon-32x32.png b/gazettes/static/images/favicon-32x32.png new file mode 100644 index 000000000..c940342c0 Binary files /dev/null and b/gazettes/static/images/favicon-32x32.png differ diff --git a/gazettes/static/images/favicon-96x96.png b/gazettes/static/images/favicon-96x96.png new file mode 100644 index 000000000..2ef24de77 Binary files /dev/null and b/gazettes/static/images/favicon-96x96.png differ diff --git a/gazettes/static/images/favicon.ico b/gazettes/static/images/favicon.ico new file mode 100644 index 000000000..d138b86cc Binary files /dev/null and b/gazettes/static/images/favicon.ico differ diff --git a/gazettes/static/images/icon.png b/gazettes/static/images/icon.png new file mode 100644 index 000000000..bd4b131fe Binary files /dev/null and b/gazettes/static/images/icon.png differ diff --git a/gazettes/static/img/africanlii-logo.svg b/gazettes/static/img/africanlii-logo.svg new file mode 100644 index 000000000..ff601cd08 --- /dev/null +++ b/gazettes/static/img/africanlii-logo.svg @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/c4ads-logo.png b/gazettes/static/img/c4ads-logo.png new file mode 100644 index 000000000..5bbfcc41e Binary files /dev/null and b/gazettes/static/img/c4ads-logo.png differ diff --git a/gazettes/static/img/flags/aa-eac.svg b/gazettes/static/img/flags/aa-eac.svg new file mode 100644 index 000000000..eb8ee2240 --- /dev/null +++ b/gazettes/static/img/flags/aa-eac.svg @@ -0,0 +1,469 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/aa-ecowas.svg b/gazettes/static/img/flags/aa-ecowas.svg new file mode 100644 index 000000000..f30e63660 --- /dev/null +++ b/gazettes/static/img/flags/aa-ecowas.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/ao.svg b/gazettes/static/img/flags/ao.svg new file mode 100644 index 000000000..865b6e5c8 --- /dev/null +++ b/gazettes/static/img/flags/ao.svg @@ -0,0 +1 @@ + diff --git a/gazettes/static/img/flags/bw.svg b/gazettes/static/img/flags/bw.svg new file mode 100644 index 000000000..d40236979 --- /dev/null +++ b/gazettes/static/img/flags/bw.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/gazettes/static/img/flags/cg.svg b/gazettes/static/img/flags/cg.svg new file mode 100644 index 000000000..10759ca74 --- /dev/null +++ b/gazettes/static/img/flags/cg.svg @@ -0,0 +1,6 @@ + + Flag of the Congo + + + + diff --git a/gazettes/static/img/flags/dz.svg b/gazettes/static/img/flags/dz.svg new file mode 100644 index 000000000..6894b2195 --- /dev/null +++ b/gazettes/static/img/flags/dz.svg @@ -0,0 +1 @@ + diff --git a/gazettes/static/img/flags/gh.svg b/gazettes/static/img/flags/gh.svg new file mode 100644 index 000000000..333140a15 --- /dev/null +++ b/gazettes/static/img/flags/gh.svg @@ -0,0 +1,7 @@ + + Flag of Ghana + + + + + diff --git a/gazettes/static/img/flags/ke.svg b/gazettes/static/img/flags/ke.svg new file mode 100644 index 000000000..0b2010334 --- /dev/null +++ b/gazettes/static/img/flags/ke.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/ls.svg b/gazettes/static/img/flags/ls.svg new file mode 100644 index 000000000..82edbc564 --- /dev/null +++ b/gazettes/static/img/flags/ls.svg @@ -0,0 +1,7 @@ + + Flag of Lesotho + + + + + diff --git a/gazettes/static/img/flags/ma.svg b/gazettes/static/img/flags/ma.svg new file mode 100644 index 000000000..48800fccc --- /dev/null +++ b/gazettes/static/img/flags/ma.svg @@ -0,0 +1,4 @@ + + + + diff --git a/gazettes/static/img/flags/mu.svg b/gazettes/static/img/flags/mu.svg new file mode 100644 index 000000000..e83d4ae5f --- /dev/null +++ b/gazettes/static/img/flags/mu.svg @@ -0,0 +1 @@ + diff --git a/gazettes/static/img/flags/mw.svg b/gazettes/static/img/flags/mw.svg new file mode 100644 index 000000000..71039c9a0 --- /dev/null +++ b/gazettes/static/img/flags/mw.svg @@ -0,0 +1 @@ + diff --git a/gazettes/static/img/flags/mz.svg b/gazettes/static/img/flags/mz.svg new file mode 100644 index 000000000..ebb67e916 --- /dev/null +++ b/gazettes/static/img/flags/mz.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/na.svg b/gazettes/static/img/flags/na.svg new file mode 100644 index 000000000..104973308 --- /dev/null +++ b/gazettes/static/img/flags/na.svg @@ -0,0 +1,16 @@ + + Flag of Namibia + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/ng.svg b/gazettes/static/img/flags/ng.svg new file mode 100644 index 000000000..b08f01273 --- /dev/null +++ b/gazettes/static/img/flags/ng.svg @@ -0,0 +1,5 @@ + + Flag of Nigeria + + + diff --git a/gazettes/static/img/flags/rw.svg b/gazettes/static/img/flags/rw.svg new file mode 100644 index 000000000..e6f2563dc --- /dev/null +++ b/gazettes/static/img/flags/rw.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/sc.svg b/gazettes/static/img/flags/sc.svg new file mode 100644 index 000000000..05ede6fc3 --- /dev/null +++ b/gazettes/static/img/flags/sc.svg @@ -0,0 +1,8 @@ + + Flag of Seychelles + + + + + + diff --git a/gazettes/static/img/flags/sl.svg b/gazettes/static/img/flags/sl.svg new file mode 100644 index 000000000..d152839ce --- /dev/null +++ b/gazettes/static/img/flags/sl.svg @@ -0,0 +1 @@ + diff --git a/gazettes/static/img/flags/so.svg b/gazettes/static/img/flags/so.svg new file mode 100644 index 000000000..5c3aa2e85 --- /dev/null +++ b/gazettes/static/img/flags/so.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/sz.svg b/gazettes/static/img/flags/sz.svg new file mode 100644 index 000000000..5ce53b8e0 --- /dev/null +++ b/gazettes/static/img/flags/sz.svg @@ -0,0 +1,184 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/tz.svg b/gazettes/static/img/flags/tz.svg new file mode 100644 index 000000000..bfc4d06d0 --- /dev/null +++ b/gazettes/static/img/flags/tz.svg @@ -0,0 +1,14 @@ + + Flag of Tanzania + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/ug.svg b/gazettes/static/img/flags/ug.svg new file mode 100644 index 000000000..cf9da5c3a --- /dev/null +++ b/gazettes/static/img/flags/ug.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/za.svg b/gazettes/static/img/flags/za.svg new file mode 100644 index 000000000..0c686b423 --- /dev/null +++ b/gazettes/static/img/flags/za.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/gazettes/static/img/flags/zm.svg b/gazettes/static/img/flags/zm.svg new file mode 100644 index 000000000..92c8ec28c --- /dev/null +++ b/gazettes/static/img/flags/zm.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/flags/zw.svg b/gazettes/static/img/flags/zw.svg new file mode 100644 index 000000000..59c6518e5 --- /dev/null +++ b/gazettes/static/img/flags/zw.svg @@ -0,0 +1,323 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/giz-logo.gif b/gazettes/static/img/giz-logo.gif new file mode 100644 index 000000000..034b09818 Binary files /dev/null and b/gazettes/static/img/giz-logo.gif differ diff --git a/gazettes/static/img/indigo-trust-logo.png b/gazettes/static/img/indigo-trust-logo.png new file mode 100644 index 000000000..2e98e74e5 Binary files /dev/null and b/gazettes/static/img/indigo-trust-logo.png differ diff --git a/gazettes/static/img/lawsafrica-logo-horizontal.png b/gazettes/static/img/lawsafrica-logo-horizontal.png new file mode 100644 index 000000000..7ed63abbb Binary files /dev/null and b/gazettes/static/img/lawsafrica-logo-horizontal.png differ diff --git a/gazettes/static/img/lawsafrica-logo.png b/gazettes/static/img/lawsafrica-logo.png new file mode 100644 index 000000000..8abd1ad15 Binary files /dev/null and b/gazettes/static/img/lawsafrica-logo.png differ diff --git a/gazettes/static/img/logo-grey.png b/gazettes/static/img/logo-grey.png new file mode 100644 index 000000000..695f6492a Binary files /dev/null and b/gazettes/static/img/logo-grey.png differ diff --git a/gazettes/static/img/logo-sm.png b/gazettes/static/img/logo-sm.png new file mode 100644 index 000000000..a0b0ed85d Binary files /dev/null and b/gazettes/static/img/logo-sm.png differ diff --git a/gazettes/static/img/logo.png b/gazettes/static/img/logo.png new file mode 100644 index 000000000..a0b0ed85d Binary files /dev/null and b/gazettes/static/img/logo.png differ diff --git a/gazettes/static/img/mapAfrica.svg b/gazettes/static/img/mapAfrica.svg new file mode 100644 index 000000000..c9bc3acb6 --- /dev/null +++ b/gazettes/static/img/mapAfrica.svg @@ -0,0 +1,497 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1000 km + + + 1000 km + + + + + + + + + + + + 1000 mi + + + 1000 mi + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + 0 + + + 0 + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/mu.svg b/gazettes/static/img/mu.svg new file mode 100644 index 000000000..00f9398e7 --- /dev/null +++ b/gazettes/static/img/mu.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/gazettes/static/img/sc.svg b/gazettes/static/img/sc.svg new file mode 100644 index 000000000..677c91408 --- /dev/null +++ b/gazettes/static/img/sc.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gazettes/static/img/survey-banner.png b/gazettes/static/img/survey-banner.png new file mode 100644 index 000000000..a941a07dc Binary files /dev/null and b/gazettes/static/img/survey-banner.png differ diff --git a/gazettes/static/img/uct-logo.png b/gazettes/static/img/uct-logo.png new file mode 100644 index 000000000..84602d972 Binary files /dev/null and b/gazettes/static/img/uct-logo.png differ diff --git a/gazettes/static/img/veritas-logo.png b/gazettes/static/img/veritas-logo.png new file mode 100644 index 000000000..e9d837205 Binary files /dev/null and b/gazettes/static/img/veritas-logo.png differ diff --git a/gazettes/static/img/werksmans-logo.png b/gazettes/static/img/werksmans-logo.png new file mode 100644 index 000000000..2c3f09a9f Binary files /dev/null and b/gazettes/static/img/werksmans-logo.png differ diff --git a/gazettes/static/img/ww-logo.png b/gazettes/static/img/ww-logo.png new file mode 100644 index 000000000..a698bc42b Binary files /dev/null and b/gazettes/static/img/ww-logo.png differ diff --git a/gazettes/static/img/za-fs-logo.jpg b/gazettes/static/img/za-fs-logo.jpg new file mode 100644 index 000000000..8fff194e9 Binary files /dev/null and b/gazettes/static/img/za-fs-logo.jpg differ diff --git a/gazettes/templates/gazettes/_contributors.html b/gazettes/templates/gazettes/_contributors.html new file mode 100644 index 000000000..26389ba11 --- /dev/null +++ b/gazettes/templates/gazettes/_contributors.html @@ -0,0 +1,17 @@ +{% load static %} +

Partners

+ diff --git a/gazettes/templates/gazettes/_year_nav.html b/gazettes/templates/gazettes/_year_nav.html new file mode 100644 index 000000000..31251a8c1 --- /dev/null +++ b/gazettes/templates/gazettes/_year_nav.html @@ -0,0 +1,8 @@ + diff --git a/gazettes/templates/gazettes/home.html b/gazettes/templates/gazettes/home.html new file mode 100644 index 000000000..3d8a6cf4a --- /dev/null +++ b/gazettes/templates/gazettes/home.html @@ -0,0 +1,127 @@ +{% extends 'peachjam/layouts/main.html' %} +{% load static humanize %} +{% block title %}Gazettes for Africa{% endblock %} +{% block page-content %} +
+
+

Gazettes.Africa

+

The largest digital collection of free African Gazettes.

+

{{ num_gazettes|intcomma }} gazettes and growing daily.

+
+
+
+ + + +
+
+
+
+
+ + Laws.Africa logo + +
+
+ + AfricanLII logo + +
+
+
+ Gazettes.Africa is a project by Laws.Africa and AfricanLII. +
+
+
+
+
+

National Gazettes

+
+ {% for juri in country_jurisdictions %} + + {% endfor %} +
+ {% if community_jurisdictions %} +

Economic Communities Gazettes

+
+ {% for juri in community_jurisdictions %} + + {% endfor %} +
+ {% endif %} +
+
+
+
+ We welcome donations of gazette collections. We will scan and digitise gazettes for free. +
+ Donate gazettes +
+
+
+
+

Partners & Funders

+
+ {% for contrib in contributors %} + + {% endfor %} +
+
+
+{% endblock %} diff --git a/gazettes/templates/peachjam/_footer.html b/gazettes/templates/peachjam/_footer.html new file mode 100644 index 000000000..c285a060e --- /dev/null +++ b/gazettes/templates/peachjam/_footer.html @@ -0,0 +1,78 @@ +{% load static %} + diff --git a/gazettes/templates/peachjam/_header.html b/gazettes/templates/peachjam/_header.html new file mode 100644 index 000000000..92d1051eb --- /dev/null +++ b/gazettes/templates/peachjam/_header.html @@ -0,0 +1,76 @@ +{% load static %} +
+
+ + A Laws.Africa project + +
+
+ + diff --git a/gazettes/templates/peachjam/gazette_detail.html b/gazettes/templates/peachjam/gazette_detail.html new file mode 100644 index 000000000..a3b5de1fa --- /dev/null +++ b/gazettes/templates/peachjam/gazette_detail.html @@ -0,0 +1,7 @@ +{% extends 'peachjam/gazette_detail.html' %} +{% block document-relationships-content %} + {{ block.super }} + {% if contributors %} +
{% include 'gazettes/_contributors.html' %}
+ {% endif %} +{% endblock %} diff --git a/gazettes/templates/peachjam/gazette_list.html b/gazettes/templates/peachjam/gazette_list.html new file mode 100644 index 000000000..65cb7c598 --- /dev/null +++ b/gazettes/templates/peachjam/gazette_list.html @@ -0,0 +1,20 @@ +{% extends 'peachjam/gazette_list.html' %} +{% load i18n %} +{% block localities %} +
+
{{ block.super }}
+ {% if contributors %} +
{% include 'gazettes/_contributors.html' %}
+ {% endif %} +
+{% endblock %} +{% block page-content %} + {{ block.super }} +
+
+ We welcome donations of gazette collections. We will scan and digitise gazettes for free. +
+ Donate gazettes +
+
+{% endblock %} diff --git a/gazettes/templates/peachjam/gazette_year.html b/gazettes/templates/peachjam/gazette_year.html new file mode 100644 index 000000000..66ac53d4e --- /dev/null +++ b/gazettes/templates/peachjam/gazette_year.html @@ -0,0 +1,10 @@ +{% extends 'peachjam/gazette_year.html' %} +{% load i18n %} +{% block preamble %} +
+
{{ block.super }}
+ {% if contributors %} +
{% include 'gazettes/_contributors.html' %}
+ {% endif %} +
+{% endblock %} diff --git a/gazettes/templates/peachjam/layouts/main.html b/gazettes/templates/peachjam/layouts/main.html new file mode 100644 index 000000000..fdc46886e --- /dev/null +++ b/gazettes/templates/peachjam/layouts/main.html @@ -0,0 +1,7 @@ +{% extends 'peachjam/layouts/main.html' %} +{% load sass_tags %} +{% block head-css %} + +{% endblock %} diff --git a/gazettes/urls.py b/gazettes/urls.py new file mode 100644 index 000000000..5c5544d37 --- /dev/null +++ b/gazettes/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls import url +from django.urls import include, path +from django.views.generic import RedirectView + +from gazettes import views + +urlpatterns = [ + # gazettes.africa + path("", views.JurisdictionListView.as_view(), name="home"), + path("archive/", views.ArchiveView.as_view(), name="archive"), + path("gazettes", RedirectView.as_view(pattern_name="home")), + path("gazettes//", views.JurisdictionView.as_view(), name="jurisdiction"), + path("gazettes//", views.YearView.as_view(), name="year"), + url( + r"^gazettes/(?P.{5,})$", views.OldGazetteView.as_view(), name="gazette_old" + ), + path("", include("peachjam.urls")), +] diff --git a/gazettes/views.py b/gazettes/views.py new file mode 100644 index 000000000..982a8bf6e --- /dev/null +++ b/gazettes/views.py @@ -0,0 +1,79 @@ +from django.core.cache import cache +from django.shortcuts import get_list_or_404 +from django.views.generic import RedirectView, TemplateView + +from gazettes.jurisdictions import ( + ALL_CONTRIBUTORS, + COMMUNITIES, + CONTRIBUTORS, + JURISDICTION_MAP, + jurisdiction_list, +) +from peachjam.models import Gazette +from peachjam.views import GazetteListView, GazetteYearView + + +class ArchiveView(RedirectView): + def get_redirect_url(self, path, *args, **kwargs): + return f"https://archive.gazettes.africa/archive/{path}" + + +class JurisdictionListView(TemplateView): + template_name = "gazettes/home.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + jurisdictions = jurisdiction_list() + context["country_jurisdictions"] = [ + x + for x in jurisdictions + if x.code not in COMMUNITIES and not x.parent_code and x.code != "aa" + ] + context["community_jurisdictions"] = [ + x for x in jurisdictions if x.code in COMMUNITIES + ] + context["num_gazettes"] = self.count_gazettes() + context["contributors"] = ALL_CONTRIBUTORS + return context + + def count_gazettes(self): + count = cache.get("n_gazettes") + if count is None: + count = Gazette.objects.count() + # cache for an hour + cache.set("n_gazettes", count, 60 * 60) + return count + + +class JurisdictionView(GazetteListView): + def get(self, request, code, *args, **kwargs): + self.jurisdiction = JURISDICTION_MAP[code] + return super().get(request, code, *args, **kwargs) + + def get_localities(self, context): + return self.jurisdiction.children + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["jurisdiction"] = self.jurisdiction + context["contributors"] = CONTRIBUTORS.get(self.jurisdiction.code) + return context + + +class YearView(GazetteYearView): + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["jurisdiction"] = juri = JURISDICTION_MAP[self.kwargs["code"]] + context["contributors"] = CONTRIBUTORS.get(juri.code) + return context + + +class OldGazetteView(RedirectView): + """Redirect old URLs to the new peachjam URLs.""" + + queryset = Gazette.objects + + def get_redirect_url(self, key, *args, **kwargs): + # we don't have a unique index on key, so we have to get the first one + gazette = get_list_or_404(self.queryset, key=key)[0] + return gazette.get_absolute_url()