diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 0392fe23..00000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..95976f05 --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +MAPBOX_TOKEN=XXXXXXXXXX +CARTO_USERNAME=XXXXXXXXXX +WDPA_POLY_TABLE=XXXXXXXXXX +WDPA_POINT_TABLE=XXXXXXXXXX +CARTO_API_KEY=XXXXXXXXXX diff --git a/.gitignore b/.gitignore index 92167a41..08eabc1f 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,7 @@ yarn-debug.log* .yarn-integrity -.DS_Store \ No newline at end of file +**/.DS_Store +.DS_Store + +.env diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..93eb7fe7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +## 0.0.1 + +**Ocean+ Habitats first release** + +* Full user journey implementation +* Dyanimic charts +* Mapbox map with WDPA Carto layer and ArcGIS habitats layers +* Import static stats from file diff --git a/Gemfile b/Gemfile index 8c3b5e97..224e6c8d 100644 --- a/Gemfile +++ b/Gemfile @@ -5,7 +5,8 @@ git_source(:github) do |repo_name| "https://github.com/#{repo_name}.git" end - +# prefix rails c commands with ap for pretty results +gem 'awesome_print' # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 5.1.5' # Use postgresql as the database for Active Record @@ -38,6 +39,7 @@ gem 'jbuilder', '~> 2.5' gem 'dotenv-rails', '~> 2.2', '>= 2.2.1' +gem 'httparty', '~> 0.16.2' group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console diff --git a/Gemfile.lock b/Gemfile.lock index 55eb3c69..57fc3a78 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -43,6 +43,7 @@ GEM airbrussh (1.3.0) sshkit (>= 1.6.1, != 1.7.0) arel (8.0.0) + awesome_print (1.8.0) bindex (0.5.0) builder (3.2.3) byebug (10.0.2) @@ -89,6 +90,8 @@ GEM ffi (1.9.25) globalid (0.4.1) activesupport (>= 4.2.0) + httparty (0.16.2) + multi_xml (>= 0.5.2) i18n (1.1.0) concurrent-ruby (~> 1.0) jbuilder (2.7.0) @@ -108,6 +111,7 @@ GEM mini_portile2 (2.3.0) minitest (5.11.3) multi_json (1.13.1) + multi_xml (0.6.0) net-scp (1.2.1) net-ssh (>= 2.6.5) net-ssh (5.0.2) @@ -209,6 +213,7 @@ PLATFORMS ruby DEPENDENCIES + awesome_print byebug capistrano (~> 3.11.0) capistrano-bundler (~> 1.1) @@ -218,6 +223,7 @@ DEPENDENCIES capybara (~> 2.13) coffee-rails (~> 4.2) dotenv-rails (~> 2.2, >= 2.2.1) + httparty (~> 0.16.2) jbuilder (~> 2.5) listen (>= 3.0.5, < 3.2) pg (>= 0.18, < 2.0) diff --git a/README.md b/README.md index 7db80e4c..0cf23e9e 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,30 @@ -# README +# Ocean+ Habitats -This README would normally document whatever steps are necessary to get the -application up and running. +## Setup -Things you may want to cover: +* Install and configure dependencies + - `bundle install` + - `yarn install` + - Please ask for latest `.env` file -* Ruby version +* Setup database + - `bundle exec rake db:drop db:create db:migrate` + - `bundle exec rake db:seed` -* System dependencies +* Import the static CSV data + - `bundle exec rake import:staticstats` -* Configuration +## Data -* Database creation +We are still trying to see if it is feasible to generate map tiles and data dynamically using Carto and in the meantime we are using static data. -* Database initialization +Data is fetched from CartoDB using the `Carto` module defined in `lib/modules`. +Some details about the layers in Carto are in `config/habitats.yml`. -* How to run the test suite +At the moment static data is provided related to the protected areas coverage. +Ideally, the protected areas coverage data should always be dynamically generated, as this depends on the WDPA release +which is updated every month. -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... +Habitats data changes less often, so the coverage calculations are stored in the `Habitat` object. +When the data changes, a new calculation process should be performed using the `calculate_global_coverage` method in +the `Habiat` model. diff --git a/app/assets/.DS_Store b/app/assets/.DS_Store index 0b856ca3..178f12d7 100644 Binary files a/app/assets/.DS_Store and b/app/assets/.DS_Store differ diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store deleted file mode 100644 index dc5e04d8..00000000 Binary files a/app/assets/images/.DS_Store and /dev/null differ diff --git a/app/assets/images/hero.png b/app/assets/images/hero.png new file mode 100644 index 00000000..7cf69bc9 Binary files /dev/null and b/app/assets/images/hero.png differ diff --git a/app/assets/images/icons/aichi-10.svg b/app/assets/images/icons/aichi-10.svg new file mode 100644 index 00000000..36a56ebf --- /dev/null +++ b/app/assets/images/icons/aichi-10.svg @@ -0,0 +1 @@ +Aichi10 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-11.svg b/app/assets/images/icons/aichi-11.svg new file mode 100644 index 00000000..29258a97 --- /dev/null +++ b/app/assets/images/icons/aichi-11.svg @@ -0,0 +1 @@ +Aichi11 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-14.svg b/app/assets/images/icons/aichi-14.svg new file mode 100644 index 00000000..d0065caa --- /dev/null +++ b/app/assets/images/icons/aichi-14.svg @@ -0,0 +1 @@ +Aichi14 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-15.svg b/app/assets/images/icons/aichi-15.svg new file mode 100644 index 00000000..e2008dd0 --- /dev/null +++ b/app/assets/images/icons/aichi-15.svg @@ -0,0 +1 @@ +Aichi15 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-17.svg b/app/assets/images/icons/aichi-17.svg new file mode 100644 index 00000000..2b977f79 --- /dev/null +++ b/app/assets/images/icons/aichi-17.svg @@ -0,0 +1 @@ +Aichi17 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-19.svg b/app/assets/images/icons/aichi-19.svg new file mode 100644 index 00000000..e73927d7 --- /dev/null +++ b/app/assets/images/icons/aichi-19.svg @@ -0,0 +1 @@ +Aichi19 \ No newline at end of file diff --git a/app/assets/images/icons/aichi-5.svg b/app/assets/images/icons/aichi-5.svg new file mode 100644 index 00000000..4e4d2206 --- /dev/null +++ b/app/assets/images/icons/aichi-5.svg @@ -0,0 +1 @@ +Aichi5 \ No newline at end of file diff --git a/app/assets/images/icons/icon-scroll.svg b/app/assets/images/icons/icon-scroll.svg new file mode 100644 index 00000000..c7dcc468 --- /dev/null +++ b/app/assets/images/icons/icon-scroll.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/icons/sdg-goal-12.png b/app/assets/images/icons/sdg-goal-12.png new file mode 100755 index 00000000..5e6db03b Binary files /dev/null and b/app/assets/images/icons/sdg-goal-12.png differ diff --git a/app/assets/images/icons/sdg-goal-14.png b/app/assets/images/icons/sdg-goal-14.png new file mode 100755 index 00000000..832a9aab Binary files /dev/null and b/app/assets/images/icons/sdg-goal-14.png differ diff --git a/app/assets/images/icons/sdg-goal-15.png b/app/assets/images/icons/sdg-goal-15.png new file mode 100755 index 00000000..41f7ce36 Binary files /dev/null and b/app/assets/images/icons/sdg-goal-15.png differ diff --git a/app/assets/images/logos/logo-ocean-plus-habitats.svg b/app/assets/images/logos/logo-ocean-plus-habitats.svg new file mode 100644 index 00000000..206359c2 --- /dev/null +++ b/app/assets/images/logos/logo-ocean-plus-habitats.svg @@ -0,0 +1,78 @@ + + + + +Page 1 +Created with Sketch. + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/images/logos/logo-ocean-plus.svg b/app/assets/images/logos/logo-ocean-plus.svg new file mode 100644 index 00000000..59efdc95 --- /dev/null +++ b/app/assets/images/logos/logo-ocean-plus.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + diff --git a/app/assets/images/social.png b/app/assets/images/social.png new file mode 100644 index 00000000..476f532c Binary files /dev/null and b/app/assets/images/social.png differ diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 6cf470d2..b2cb25ad 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -20,6 +20,7 @@ @import './utilities/flexbox.scss'; @import './utilities/base.scss'; @import './utilities/helpers.scss'; +@import './utilities/mixins-shared.scss'; // components @import './components/*'; diff --git a/app/assets/stylesheets/components-vue/_map.scss b/app/assets/stylesheets/components-vue/_map.scss new file mode 100644 index 00000000..1e39ce1e --- /dev/null +++ b/app/assets/stylesheets/components-vue/_map.scss @@ -0,0 +1,95 @@ +//-------------------------------------------------- +// map variables +//-------------------------------------------------- +$map-panel-width: 430; + +//-------------------------------------------------- +// map +//-------------------------------------------------- +.map { + +//-------------------------------------------------- +// statistics map +//-------------------------------------------------- + &--statistics { + position: relative; + z-index: 1; + + .map { + &__map { + width: 100%; height: rem-calc(210); + + @include breakpoint($small) { height: rem-calc(400); } + @include breakpoint($medium) { + width: calc(100% - #{$map-panel-width}px); height: rem-calc(668); + } + } + + &__panel { + background-color: $primary; + box-shadow: 0 8px 18px -4px rgba($black, .8); + color: $white; + padding-top: rem-calc(30); + padding-bottom: rem-calc(40); + z-index: 1; + + @include breakpoint($medium) { + box-shadow: -8px 0 18px -4px rgba($black, .8); + padding-top: rem-calc(50); + padding-left: rem-calc(44); + width: rem-calc($map-panel-width); height: 100%; + + position: absolute; + top: 0; + right: 0; + } + } + + &__panel-title { + font-size: rem-calc(18); + margin-bottom: 0; + + @include breakpoint($medium) { font-size: rem-calc(25); } + } + + &__panel-stat { + font-size: rem-calc(40); + font-weight: $bold; + line-height: 1.2; + margin-top: rem-calc(10); + margin-bottom: rem-calc(30); + + display: block; + + @include breakpoint($medium) { font-size: rem-calc(50); } + } + + &__panel-layer { + font-size: rem-calc(18); + margin-bottom: rem-calc(8); + + @include breakpoint($medium) { font-size: rem-calc(20); } + + &::before { + background-color: $pink; + border-radius: 100%; + content: ''; + margin-right: rem-calc(16 ); + width: rem-calc(19); height: rem-calc(19); + + display: inline-block; + + transform: translateY(4px); + } + } + + &__panel-layer-habitat::before { + @for $i from 1 through length($names) { + .theme--#{nth($names, $i)} & { + background-color: nth($colours, $i); + } + } + } + } + } +} diff --git a/app/assets/stylesheets/components-vue/_nav.scss b/app/assets/stylesheets/components-vue/_nav.scss index fe9e4689..17f309e9 100644 --- a/app/assets/stylesheets/components-vue/_nav.scss +++ b/app/assets/stylesheets/components-vue/_nav.scss @@ -1,42 +1,51 @@ //-------------------------------------------------- // nav //-------------------------------------------------- -.nav { +.nav-wrapper { height: rem-calc(74); +} + +.nav-scrollable { + @include breakpoint_down($medium) { + overflow-x: scroll; + + display: flex; + } + + &.sticky { + position: fixed; + top: 0; + left: 0; + right: 0; + + z-index: 2; + } +} + +.nav { + background-color: $nav; + width: fit-content; height: rem-calc(74); + + @include breakpoint($medium) { width: auto; } &__a { color: $white; - border: solid 1px $navy; + border: solid 1px $nav; border-radius: $radius-button; - font-size: rem-calc(24); + font-size: rem-calc(20); font-weight: $bold; - padding: rem-calc(8 20); + padding: rem-calc(4 16); text-decoration: none; + white-space: nowrap; - &.active { - &.theme--blue { - color: $theme-blue; - border-color: $theme-blue; - } - - &.theme--green { - color: $theme-green; - border-color: $theme-green; - } - - &.theme--orange { - color: $theme-orange; - border-color: $theme-orange; - } - - &.theme--pink { - color: $theme-pink; - border-color: $theme-pink; - } + @include breakpoint($small) { + font-size: rem-calc(24); + padding: rem-calc(8 20); + } - &.theme--yellow { - color: $theme-yellow; - border-color: $theme-yellow; + &.active { + @for $i from 1 through length($names){ + @include theme_text($i); } } } diff --git a/app/assets/stylesheets/components-vue/_tabs.scss b/app/assets/stylesheets/components-vue/_tabs.scss index a9304947..c779e2a8 100644 --- a/app/assets/stylesheets/components-vue/_tabs.scss +++ b/app/assets/stylesheets/components-vue/_tabs.scss @@ -1,3 +1,12 @@ +//-------------------------------------------------- +// tab variables +//-------------------------------------------------- +$icon-size-small: 60; +$icon-size-medium: 80; + +$icon-margin-small: 14; +$icon-margin-medium: 20; + //-------------------------------------------------- // tabs //-------------------------------------------------- @@ -8,15 +17,74 @@ // tab //-------------------------------------------------- .tab { - &--active { - background-color: $primary; + &-active { + @for $i from 1 through length($names){ + @include theme_text($i); + } } &__triggers { + margin-bottom: rem-calc(20); + @include breakpoint($medium) { margin-bottom: rem-calc(24); } } &__trigger { + border: solid 1px transparent; + border-radius: $radius-button; + cursor: pointer; + font-size: rem-calc(14); + font-weight: $bold; + padding: rem-calc(5 8); + @include breakpoint($small) { + font-size: rem-calc(18); + padding: rem-calc(5 14); + } } + + &__tabs { + + } + + &__content { + @include breakpoint($small) { + justify-content: space-between; + flex-wrap: wrap; + + display: flex; + } + } + + &__content-item { + font-size: rem-calc(16); + margin-bottom: rem-calc(14); + + @include breakpoint($medium) { + font-size: rem-calc(18); + width: 48%; + } + } + + &__content-icon { + margin-right: rem-calc($icon-margin-small); + width: rem-calc($icon-size-small); height: rem-calc($icon-size-small); + + transform: translateY(5px); + + @include breakpoint($small) { + margin-right: rem-calc($icon-margin-medium); + width: rem-calc($icon-size-medium); height: rem-calc($icon-size-medium); + } + } + + &__content-text { + // hack for IE 11 + width: calc(100% - #{$icon-margin-small}px - #{$icon-size-small}px); + + @include breakpoint($small) { + width: calc(100% - #{$icon-margin-medium}px - #{$icon-size-medium}px); + } + // end hack + } } \ No newline at end of file diff --git a/app/assets/stylesheets/components/_button.scss b/app/assets/stylesheets/components/_button.scss index 62b6dc94..8dcb13cd 100644 --- a/app/assets/stylesheets/components/_button.scss +++ b/app/assets/stylesheets/components/_button.scss @@ -13,15 +13,8 @@ //-------------------------------------------------- // styles //-------------------------------------------------- - &--cta { - - } - - &--disabled { - background-color: $grey-light; - cursor: not-allowed; - - &:hover { background-color: $grey-light; } + &--link-white { + color: $white; } //-------------------------------------------------- diff --git a/app/assets/stylesheets/components/_chart.scss b/app/assets/stylesheets/components/_chart.scss index 91b07f30..0a0570f9 100644 --- a/app/assets/stylesheets/components/_chart.scss +++ b/app/assets/stylesheets/components/_chart.scss @@ -1,3 +1,40 @@ +//-------------------------------------------------- +// chart mixins +//-------------------------------------------------- +@mixin chart-content { + @include breakpoint($medium) { + padding-right: rem-calc(49); + width: 32%; + } +} + +@mixin chart-label { + font-size: rem-calc(14); + + @include breakpoint($small) { + font-size: rem-calc(18); + width: rem-calc(134); + } +} + +@mixin bar-label { + color: $grey-dark; + font-weight: $bold; + opacity: 0; + + &.animate { opacity: 1; } +} + +@mixin colour { + position: absolute; + bottom: 0; + left: 0; + + @for $i from 1 through length($names){ + @include theme_background($i); + } +} + //-------------------------------------------------- // chart //-------------------------------------------------- @@ -7,40 +44,72 @@ // column chart //-------------------------------------------------- &--column { + @include breakpoint($medium) { + justify-content: space-between; + + display: flex; + } + .chart { - &__item { + &__content { + @include chart-content; + } + + &__scrollable { + @include breakpoint-down($small) { + overflow-x: auto; + display: flex; + } + + @include breakpoint($medium) { width: 68%; } } - - &__bar { - background-color: $white; - box-shadow: 0 1px 2px 1px rgba($black, 0.2); - width: rem-calc(134); height: rem-calc(390); - position: relative; + &__chart { + @include breakpoint-down($small) { min-width: 200%; } + @include breakpoint($medium) { justify-content: space-between; } } - &__bar-label { - color: $grey-dark; - font-size: rem-calc(30); - font-weight: $bold; + &__bar { + background-color: $white; + box-shadow: 0 1px 2px 1px rgba($black, 0.2); + width: rem-calc(91); height: rem-calc(252); position: relative; - top: rem-calc(22); - } - &__colour { - background-color: $theme-orange; - position: absolute; - right: 0; - bottom: 0; - left: 0; + @include breakpoint($small) { width: rem-calc(134); height: rem-calc(390); } } - &__label { - margin-top: rem-calc(10); - width: rem-calc(134); - } + &__bar-label { + @include bar-label; + font-size: rem-calc(12); + + position: relative; + top: rem-calc(22); + z-index: 1; + + transition: opacity 1s ease-in-out; + + @include breakpoint($small) { font-size: rem-calc(17); } + @include breakpoint($medium) { font-size: rem-calc(18); } + } + + &__colour { + @include colour; + right: 0; + + transform: scaleY(0); + transform-origin: bottom; + transition: transform 1s ease-out; + + &.animate { transform: scaleY(1); } + } + + &__label { + @include chart-label; + margin-top: rem-calc(10); + width: rem-calc(91); + } } } @@ -48,43 +117,87 @@ // row chart //-------------------------------------------------- &--row { + width: 100%; + + @include breakpoint($medium) { + justify-content: space-between; + + display: flex; + } + .chart { + &__content { + @include chart-content; + } + + &__chart { + @include breakpoint($medium) { width: 68%; } + } + &__item { margin-bottom: rem-calc(14); + + position: relative; + + @include breakpoint($medium) { + justify-content: flex-end; + + display: flex; + } } &__bar { background-color: $white; box-shadow: 0 1px 2px 1px rgba($black, 0.2); - width: rem-calc(700); height: rem-calc(84); + width: 100%; height: rem-calc(42); position: relative; + + @include breakpoint($small) { height: rem-calc(84); } + @include breakpoint($medium) { width: rem-calc(690); } } &__bar-label { - color: $grey-dark; - font-size: rem-calc(30); - font-weight: $bold; + @include bar-label; + font-size: rem-calc(20); position: absolute; top: 50%; - right: rem-calc(40); + right: rem-calc(12); z-index: 1; transform: translateY(-50%); + + transition: opacity 1s ease-in-out; + + @include breakpoint($small) { + font-size: rem-calc(30); + + right: rem-calc(40); + } } &__colour { - background-color: $theme-orange; - position: absolute; + @include colour; top: 0; - bottom: 0; - left: 0; + + transform: scaleX(0); + transform-origin: left; + transition: transform 1s ease-out; + + &.animate { transform: scaleX(1); } } &__label { - margin-top: rem-calc(10); - width: rem-calc(134); + @include chart-label; + margin: 0; + + position: absolute; + top: 50%; + left: 0; + z-index: 1; + + transform: translateY(-50%); } } } diff --git a/app/assets/stylesheets/components/_footer.scss b/app/assets/stylesheets/components/_footer.scss index 5883a3bf..29b216c3 100644 --- a/app/assets/stylesheets/components/_footer.scss +++ b/app/assets/stylesheets/components/_footer.scss @@ -2,12 +2,63 @@ // footer //-------------------------------------------------- .footer { - height: rem-calc(128); + @include breakpoint_down($small) { + padding-top: rem-calc(30); + padding-bottom: rem-calc(20); + } + + @include breakpoint($small) { + align-items: center; + justify-content: space-between; + height: rem-calc(90); + + display: flex; + } + + @include breakpoint($medium) { height: rem-calc(77); } + + &__partner-logos { + + } + + &__partner-logo { + @extend .flex; + opacity: .5; + margin: rem-calc(8 10); + width: rem-calc(80); max-height: rem-calc(22); + + @include breakpoint($small) { + margin: rem-calc(0 0 0 18); + width: rem-calc(100); max-height: rem-calc(28); + } + + @include breakpoint($medium) { + margin-left: rem-calc(22); + width: rem-calc(110); max-height: rem-calc(36); + } + + &.logo--site { + margin: 0 auto rem-calc(20) auto; + + @include breakpoint($small) { + margin: 0; + width: rem-calc(100); max-height: rem-calc(28); + } + + @include breakpoint($medium) { width: rem-calc(110); max-height: rem-calc(36); } + } + } - &__partner-logo { + &__copyright { + color: $white; + font-size: rem-calc(13); + font-style: italic; + margin-top: rem-calc(10); opacity: .5; - padding-left: rem-calc(50); - width: rem-calc(200); max-height: rem-calc(42); + @include breakpoint($small) { + font-size: rem-calc(16); + margin: rem-calc(0 0 0 16); + } } } \ No newline at end of file diff --git a/app/assets/stylesheets/components/_header.scss b/app/assets/stylesheets/components/_header.scss index 43b55554..91eb046d 100644 --- a/app/assets/stylesheets/components/_header.scss +++ b/app/assets/stylesheets/components/_header.scss @@ -3,16 +3,43 @@ //-------------------------------------------------- .header { background-color: $grey; + background-image: image_url('hero.png'); + background-size: cover; + background-position: center; color: $white; + padding: rem-calc(40 0 50 0); + min-height: 100vh; position: relative; - @include breakpoint($medium) { - padding: rem-calc(130 0 200 0); + @include breakpoint($small) { + align-items: center; + padding-bottom: rem-calc(108); + + display: flex; } + &__content { + + } + + &__logo { + margin-bottom: rem-calc(40); + + @include breakpoint($small) { margin-bottom: rem-calc(60); } + } + + &__intro { + line-height: 1.6; + } + &__icon { - position: absolute; - bottom: rem-calc(40); + display: none; + + @include breakpoint($small) { + display: block; + position: absolute; + bottom: rem-calc(40); + } } } \ No newline at end of file diff --git a/app/assets/stylesheets/components/_icons.scss b/app/assets/stylesheets/components/_icons.scss index b65aa106..88956ee0 100644 --- a/app/assets/stylesheets/components/_icons.scss +++ b/app/assets/stylesheets/components/_icons.scss @@ -3,10 +3,8 @@ //-------------------------------------------------- .icon { -//-------------------------------------------------- -// social -//-------------------------------------------------- - &--social { - + &--scroll { + background-image: image_url('icons/icon-scroll.svg'); + width: rem-calc(27); height: rem-calc(64); } } \ No newline at end of file diff --git a/app/assets/stylesheets/utilities/_base.scss b/app/assets/stylesheets/utilities/_base.scss index 125b65d6..3a91c712 100644 --- a/app/assets/stylesheets/utilities/_base.scss +++ b/app/assets/stylesheets/utilities/_base.scss @@ -15,30 +15,44 @@ body { } h1 { - font-size: rem-calc(48); + font-size: rem-calc(30); font-weight: $normal; line-height: 1.2; + + @include breakpoint($small) { font-size: rem-calc(48); } } h2 { + } h3 { color: $grey-dark; - font-size: rem-calc(40); + font-size: rem-calc(20); font-weight: $normal; margin-top: 0; - padding-right: rem-calc(49); + + @include breakpoint($small) { font-size: rem-calc(34); } } h4 { + font-size: rem-calc(12); + margin: rem-calc(0 0 10 0); + + @include breakpoint($small) { font-size: rem-calc(14); } + @include breakpoint($medium) { font-size: rem-calc(16); } } p { line-height: $body-line-height; + margin-top: 0; + + @include breakpoint_down($small) { font-size: rem-calc(14); } } a { + color: inherit; + &:hover { text-decoration: none; } &.a--plain { @@ -50,9 +64,11 @@ a { } ul { + } li { + margin-bottom: rem-calc(14); } blockquote { @@ -86,7 +102,7 @@ sup { // site structure //-------------------------------------------------- .site-width { - @include breakpoint($medium){ width: $site-width; } + @include breakpoint($large){ width: $site-width; } } .gutter--left { @@ -113,8 +129,8 @@ sup { &--small { @extend %container; - @include breakpoint($small) { width: 60%; } - @include breakpoint($medium) { width: 40%; } + @include breakpoint($small) { width: 80%; } + @include breakpoint($medium) { width: 50%; } @include breakpoint($large) { width: rem-calc(560); } } } @@ -157,4 +173,21 @@ sup { .section-padding { @extend .section-padding--top; @extend .section-padding--bottom; +} + +.section-padding-small--top { + padding-top: $section-padding-small-top-small; + @include breakpoint($medium) { padding-top: $section-padding-small-top-medium; } + @include breakpoint($large) { padding-top: $section-padding-small-top-large; } +} + +.section-padding-small--bottom { + padding-bottom: $section-padding-small-bottom-small; + @include breakpoint($medium) { padding-bottom: $section-padding-small-bottom-medium; } + @include breakpoint($large) { padding-bottom: $section-padding-small-bottom-large; } +} + +.section-padding-small { + @extend .section-padding-small--top; + @extend .section-padding-small--bottom; } \ No newline at end of file diff --git a/app/assets/stylesheets/utilities/_helpers.scss b/app/assets/stylesheets/utilities/_helpers.scss index bdadc676..ef4e5fe6 100644 --- a/app/assets/stylesheets/utilities/_helpers.scss +++ b/app/assets/stylesheets/utilities/_helpers.scss @@ -22,6 +22,13 @@ strong, .bold { font-weight: $bold; } .italic { font-style: italic; } +.white { color: $white; } + +.text--smallprint { + font-size: rem-calc(10); + @include breakpoint($medium) { font-size: rem-calc(12); } +} + //-------------------------------------------------- // dimensions //-------------------------------------------------- @@ -86,7 +93,7 @@ strong, .bold { font-weight: $bold; } z-index: 0; &:before { - background-color: rgba(black, 0.3); + background-color: rgba(black, 0.5); content: ''; position: absolute; top: 0; diff --git a/app/assets/stylesheets/utilities/_mixins-shared.scss b/app/assets/stylesheets/utilities/_mixins-shared.scss new file mode 100644 index 00000000..72d4be8c --- /dev/null +++ b/app/assets/stylesheets/utilities/_mixins-shared.scss @@ -0,0 +1,21 @@ +//-------------------------------------------------- +// shared mixins +//-------------------------------------------------- +@mixin theme_background ($index) { + $colour: nth($colours, $index); + $name: nth($names, $index); + + .theme--#{$name} & { + background-color: $colour; + } +} + +@mixin theme_text ($index) { + $colour: nth($colours, $index); + $name: nth($names, $index); + + .theme--#{$name} & { + border-color: $colour; + color: $colour; + } +} \ No newline at end of file diff --git a/app/assets/stylesheets/utilities/_variables.scss b/app/assets/stylesheets/utilities/_variables.scss index 2901406c..51ec2d79 100644 --- a/app/assets/stylesheets/utilities/_variables.scss +++ b/app/assets/stylesheets/utilities/_variables.scss @@ -6,6 +6,7 @@ // - dimensions // - breakpoins // - padding +// - project specific // //-------------------------------------------------- // colours @@ -14,6 +15,7 @@ $white: #ffffff; $grey-light: #f4f4f4; $grey: #7f7f7f; $grey-dark: #444444; +$grey-xdark: #202020; $black: #000000; $navy: #293039; @@ -21,13 +23,18 @@ $navy-dark: #1F232A; $navy-xdark: #12161B; $purple: #BA41FF; +$nav: #1E2329; + +$blue-grey: #3A4552; +$pink: #BA41FF; + $theme-blue: #7AB6FF; $theme-green: #3FD18B; $theme-orange: #FF8A75; $theme-pink: #F35F8D; $theme-yellow: #FCDA68; -$primary: $theme-orange; +$primary: $blue-grey; $secondary: $navy; //-------------------------------------------------- @@ -39,7 +46,7 @@ $body-font: $font-roboto; $body-font-color: $black; $body-font-size: rem-calc(18); -$body-line-height: 1.2; +$body-line-height: 1.4; $light: 300; $normal: 400; @@ -83,6 +90,14 @@ $section-padding-bottom-small: rem-calc(30); $section-padding-bottom-medium: rem-calc(60); $section-padding-bottom-large: rem-calc(100); +$section-padding-small-top-small: rem-calc(14); +$section-padding-small-top-medium: rem-calc(20); +$section-padding-small-top-large: rem-calc(24); + +$section-padding-small-bottom-small: rem-calc(10); +$section-padding-small-bottom-medium: rem-calc(16); +$section-padding-small-bottom-large: rem-calc(20); + //-------------------------------------------------- // style //-------------------------------------------------- @@ -95,3 +110,9 @@ $radius-button: rem-calc(26); $topbarHeightSmall: rem-calc(47); $topbarHeightMedium: rem-calc(60); $topbarHeightLarge: rem-calc(93); + +//-------------------------------------------------- +// project specific +//-------------------------------------------------- +$names: ['blue', 'green', 'orange', 'pink', 'yellow']; +$colours: [$theme-blue, $theme-green, $theme-orange, $theme-pink, $theme-yellow]; diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb index 0afcfb71..12594e03 100644 --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -1,79 +1,95 @@ class SiteController < ApplicationController + before_action :load_habitat before_action :load_global + before_action :load_charts_data def warmwater - @title = 'Warm-water corals' - @chart_greatest_coverage = [ - { - label: 'Australia', - value: '94', - percent: '94', - }, - { - label: 'United Kingdom', - value: '63', - percent: '63', - }, - { - label: 'Spain', - value: '75', - percent: '75', - }, - { - label: 'Italy', - value: '50', - percent: '50', - }, - { - label: 'Russia', - value: '10', - percent: '10', - } - ] + @data = YAML.load(File.open("#{Rails.root}/lib/data/content/warmwater.yml", 'r')) - @chart_protected_areas = [ - { - label: 'Australia', - percent: '94', - }, - { - label: 'United Kingdom', - percent: '63', - }, - { - label: 'Spain', - percent: '75', - }, - { - label: 'Italy', - percent: '50', - }, - { - label: 'Russia', - percent: '10', - } + @commitments = [ + @aichi_targets, + @sdgs, + @data['other_targets'] ] end def saltmarshes - @title = 'Saltmarshes' + @data = YAML.load(File.open("#{Rails.root}/lib/data/content/saltmarshes.yml", 'r')) + + @commitments = [ + @aichi_targets, + @sdgs, + @data['other_targets'] + ] end def mangroves - @title = 'Mangroves' + @data = YAML.load(File.open("#{Rails.root}/lib/data/content/mangroves.yml", 'r')) + + @commitments = [ + @aichi_targets, + @sdgs, + @data['other_targets'] + ] end def seagrasses - @title = 'Seagrasses' + @data = YAML.load(File.open("#{Rails.root}/lib/data/content/seagrasses.yml", 'r')) + + @commitments = [ + @aichi_targets, + @sdgs, + @data['other_targets'] + ] end - def coldwater - @title = 'Cold-water corals' + def coldcorals + @data = YAML.load(File.open("#{Rails.root}/lib/data/content/coldwater.yml", 'r')) + + @commitments = [ + @aichi_targets, + @sdgs, + @data['other_targets'] + ] end private - def load_global - @global = YAML.load(File.open("#{Rails.root}/lib/data/content/global.yml", 'r')) + + def load_habitat + @habitat = Habitat.where(name: action_name).first + @habitat ||= Habitat.where(name: 'coralreef').first + @habitat_type = @habitat.type + end + + def load_global + @global = YAML.load(File.open("#{Rails.root}/lib/data/content/global.yml", 'r')) + @aichi_targets = YAML.load(File.open("#{Rails.root}/lib/data/content/aichi-targets.yml", 'r')) + @sdgs = YAML.load(File.open("#{Rails.root}/lib/data/content/sdgs.yml", 'r')) + end + + def load_charts_data + top_five_countries = StaticStat.where(habitat_id: @habitat.id) + .order('total_value DESC') + .first(5) + arbitrary_value = top_five_countries.first.total_value.to_f * 1.05 + @chart_greatest_coverage = top_five_countries.map do |stat| + { + label: stat.country.name, + value: stat.total_value.to_f.round(0), + percent: 100*stat.total_value.to_f/arbitrary_value + } + end + + top_five_country_ids = top_five_countries.map(&:country_id) + top_five_protected_areas = StaticStat.where(habitat: @habitat, country_id: top_five_country_ids) + .order("protected_percentage DESC") + .first(5) + + @chart_protected_areas = top_five_protected_areas.map do |stat| + { + label: stat.country.name, + percent: stat.protected_percentage.to_f.round(1), + } end - + end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be794..4fe43154 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,29 @@ module ApplicationHelper + def site_title + 'The first authoritative online resource on marine habitats' + end + + def site_description + 'Ocean+ Habitats is an evolving tool that provides insight into the known extent, protection and other statistics of ecologically and economically important ocean habitats, such as corals, mangroves, seagrasses and saltmarshes.' + end + + def title_meta_tag(page_title) + page_title == nil ? site_title: "#{page_title} | Ocean+ Habitats" + end + + def url_encode text + ERB::Util.url_encode(text) + end + + def encoded_home_url + url_encode(request.base_url) + end + + def social_image + image_url('social.png') + end + + def social_image_alt + 'Guanaco Torres del Paine Chile Gregoire Dubois' + end end diff --git a/app/helpers/site_helper.rb b/app/helpers/site_helper.rb index f188f70e..5d7d794a 100644 --- a/app/helpers/site_helper.rb +++ b/app/helpers/site_helper.rb @@ -3,4 +3,8 @@ module SiteHelper def active_nav_item?(path) request.fullpath == path ? ' active' : '' end + + def getTables + [@habitat.poly_table, @habitat.point_table].compact + end end diff --git a/app/javascript/app.vue b/app/javascript/app.vue deleted file mode 100644 index e304dc19..00000000 --- a/app/javascript/app.vue +++ /dev/null @@ -1,22 +0,0 @@ - - - - - diff --git a/app/javascript/components/counter/Counter.vue b/app/javascript/components/counter/Counter.vue new file mode 100644 index 00000000..bf90a981 --- /dev/null +++ b/app/javascript/components/counter/Counter.vue @@ -0,0 +1,90 @@ + + + diff --git a/app/javascript/components/map/Mapbox.vue b/app/javascript/components/map/Mapbox.vue new file mode 100644 index 00000000..649683c6 --- /dev/null +++ b/app/javascript/components/map/Mapbox.vue @@ -0,0 +1,186 @@ + + + diff --git a/app/javascript/components/sticky/StickyBar.vue b/app/javascript/components/sticky/StickyBar.vue new file mode 100644 index 00000000..429c8349 --- /dev/null +++ b/app/javascript/components/sticky/StickyBar.vue @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/app/javascript/components/tabs/Tab.vue b/app/javascript/components/tabs/Tab.vue new file mode 100644 index 00000000..96b7b686 --- /dev/null +++ b/app/javascript/components/tabs/Tab.vue @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/app/javascript/components/tabs/Tabs.vue b/app/javascript/components/tabs/Tabs.vue new file mode 100644 index 00000000..83380692 --- /dev/null +++ b/app/javascript/components/tabs/Tabs.vue @@ -0,0 +1,41 @@ + + + \ No newline at end of file diff --git a/app/javascript/packs/application.js b/app/javascript/packs/application.js index 54b106ee..306f9d3c 100644 --- a/app/javascript/packs/application.js +++ b/app/javascript/packs/application.js @@ -1,10 +1,40 @@ -/* eslint no-console:0 */ -// This file is automatically compiled by Webpack, along with any other files -// present in this directory. You're encouraged to place your actual application logic in -// a relevant structure within app/javascript and only use these pack files to reference -// that code so it'll be compiled. -// -// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate -// layout file, like app/views/layouts/application.html.erb - -console.log('Hello World from Webpacker') +// libraries +import Vue from 'vue/dist/vue.esm' +import TurbolinksAdapter from 'vue-turbolinks' +import ScrollMagic from 'scrollmagic' + +Vue.config.productionTip = false + +Vue.use(TurbolinksAdapter) + +// components +import Tab from '../components/tabs/Tab.vue' +import Tabs from '../components/tabs/Tabs.vue' +import Mapbox from '../components/map/Mapbox.vue' +import StickyBar from '../components/sticky/StickyBar.vue' + +// create event hub and export so that it can be imported into .vue files +export const eventHub = new Vue() + +document.addEventListener('turbolinks:load', () => { + const app = new Vue({ + el: '#v-app', + components: { + Tab, + Tabs, + Mapbox, + StickyBar + } + }) + + // add scenes for animated html components + let scrollMagicController = new ScrollMagic.Controller() + + new ScrollMagic.Scene({ triggerElement: '.sm-trigger-column', reverse: false }) + .setClassToggle('.sm-target-column .sm-target-child-column, .sm-target-column', 'animate') + .addTo(scrollMagicController) + + new ScrollMagic.Scene({ triggerElement: '.sm-trigger-row', reverse: false }) + .setClassToggle('.sm-target-row .sm-target-child-row, .sm-target-row', 'animate') + .addTo(scrollMagicController) +}) \ No newline at end of file diff --git a/app/javascript/packs/hello_vue.js b/app/javascript/packs/hello_vue.js deleted file mode 100644 index fd060100..00000000 --- a/app/javascript/packs/hello_vue.js +++ /dev/null @@ -1,71 +0,0 @@ -/* eslint no-console: 0 */ -// Run this example by adding <%= javascript_pack_tag 'hello_vue' %> (and -// <%= stylesheet_pack_tag 'hello_vue' %> if you have styles in your component) -// to the head of your layout file, -// like app/views/layouts/application.html.erb. -// All it does is render
Hello Vue
at the bottom of the page. - -import Vue from 'vue' -import App from '../app.vue' - -document.addEventListener('DOMContentLoaded', () => { - const el = document.body.appendChild(document.createElement('hello')) - const app = new Vue({ - el, - render: h => h(App) - }) - - console.log(app) -}) - - -// The above code uses Vue without the compiler, which means you cannot -// use Vue to target elements in your existing html templates. You would -// need to always use single file components. -// To be able to target elements in your existing html/erb templates, -// comment out the above code and uncomment the below -// Add <%= javascript_pack_tag 'hello_vue' %> to your layout -// Then add this markup to your html template: -// -//
-// {{message}} -// -//
- - -// import Vue from 'vue/dist/vue.esm' -// import App from '../app.vue' -// -// document.addEventListener('DOMContentLoaded', () => { -// const app = new Vue({ -// el: '#hello', -// data: { -// message: "Can you say hello?" -// }, -// components: { App } -// }) -// }) -// -// -// -// If the using turbolinks, install 'vue-turbolinks': -// -// yarn add 'vue-turbolinks' -// -// Then uncomment the code block below: -// -// import TurbolinksAdapter from 'vue-turbolinks' -// import Vue from 'vue/dist/vue.esm' -// import App from '../app.vue' -// -// Vue.use(TurbolinksAdapter) -// -// document.addEventListener('turbolinks:load', () => { -// const app = new Vue({ -// el: '#hello', -// data: { -// message: "Can you say hello?" -// }, -// components: { App } -// }) -// }) diff --git a/app/models/country.rb b/app/models/country.rb new file mode 100644 index 00000000..e0a9ba89 --- /dev/null +++ b/app/models/country.rb @@ -0,0 +1,2 @@ +class Country < ApplicationRecord +end diff --git a/app/models/habitat.rb b/app/models/habitat.rb new file mode 100644 index 00000000..f84e0c0a --- /dev/null +++ b/app/models/habitat.rb @@ -0,0 +1,55 @@ +class Habitat < ApplicationRecord + + def global_coverage_title(habitat_type) + habitat_type == 'points' ? "Total number of #{title.downcase} records globally" : "Total global recorded coverage of #{title.downcase}" + end + + def protected_title + "Percentage of #{title.downcase} that occur within a marine protected area" + end + + def calculate_global_coverage + coverage = Carto.new(name).total_area.first['sum'] + update_attributes(global_coverage: coverage.round) + end + + def total_value_by_country + c = Carto.new(name) + total_value_by_country = 0 + + if name == "coldcorals" + total_value_by_country = c.total_points_by_country + total_value_by_country = sort_country_count(total_value_by_country) + else + total_value_by_country = c.total_area_by_country + total_value_by_country = sum_country_areas(total_value_by_country) + end + total_value_by_country + end + + def type + name == "coldcorals" ? "points" : "area" + end + + private + + def sum_country_areas(total_area_by_country) + country_total_area = {} + total_area_by_country.flatten.each do |country_data| + next if country_data["iso3"].include? "/" #remove areas which have multiple iso + next if country_data["iso3"].include? "ABNJ" #remove ABNJ + country_total_area[country_data["iso3"]] ||= 0 + country_total_area[country_data["iso3"]] += country_data["sum"] + end + country_total_area + end + + def sort_country_count(total_value_by_country) + country_total_points = {} + total_value_by_country.each do |total_value| + next if total_value["iso3"].include? "ABNJ" + country_total_points[total_value["iso3"]] = total_value["count"] + end + country_total_points + end +end diff --git a/app/models/static_stat.rb b/app/models/static_stat.rb new file mode 100644 index 00000000..90307d40 --- /dev/null +++ b/app/models/static_stat.rb @@ -0,0 +1,4 @@ +class StaticStat < ApplicationRecord + belongs_to :habitat + belongs_to :country +end diff --git a/app/views/global/_citations.html.erb b/app/views/global/_citations.html.erb new file mode 100644 index 00000000..e6895264 --- /dev/null +++ b/app/views/global/_citations.html.erb @@ -0,0 +1,7 @@ +
+
+

Citations

+ +

<%= @data['citations'].html_safe %>

+
+
\ No newline at end of file diff --git a/app/views/global/_commitments.html.erb b/app/views/global/_commitments.html.erb new file mode 100644 index 00000000..d70d11bd --- /dev/null +++ b/app/views/global/_commitments.html.erb @@ -0,0 +1,23 @@ +
+
+

Commitments and pledges

+ + + <% @commitments.each do |commitment| %> + + <% commitment['list'].each do |item| %> +
+ <% if item['icon'] %> + <%= image_tag item['icon'], alt: "#{item['title']} icon", class: "tab__content-icon" %> + +

<%= item['text'].html_safe %>

+ <% else %> +

<%= item['text'].html_safe %>

+ <% end %> +
+ <% end %> +
+ <% end %> +
+
+
\ No newline at end of file diff --git a/app/views/global/_disclaimer.html.erb b/app/views/global/_disclaimer.html.erb new file mode 100644 index 00000000..b07a13d0 --- /dev/null +++ b/app/views/global/_disclaimer.html.erb @@ -0,0 +1,9 @@ +
+
+

Disclaimer

+ + <% @global['disclaimer'].each do |p| %> +

<%= p.html_safe %>

+ <% end %> +
+
\ No newline at end of file diff --git a/app/views/global/_footer.html.erb b/app/views/global/_footer.html.erb index ff68fac7..6601b475 100644 --- a/app/views/global/_footer.html.erb +++ b/app/views/global/_footer.html.erb @@ -1,10 +1,25 @@ -