-

Latest

{% trans %}More{% endtrans %} +

Latest

{% trans %}More{% endtrans %} {% set posts = h.get_recent_blog_posts(3) %}
    @@ -24,10 +24,10 @@

    Latest

-

{{ post.title or post.name }}

+

{{ post.title or post.name }}

{{ h.render_datetime(post.publish_date) }} {{ h.markdown_extract(post.content) }} - {% trans %}More{% endtrans %} + {% trans %}More{% endtrans %}
{% endfor %} @@ -38,15 +38,15 @@

-

Showcases

{% trans %}More{% endtrans %} +

Showcases

{% trans %}More{% endtrans %} {% for showcase in h.showcase_list(limit=3) %}
- View + View
{{ _(showcase.package_count) }} Datasets @@ -62,5 +62,5 @@

.module > .module-content.page-header { + margin-left: -9999rem; + margin-right: -9999rem; + padding-left: 9999rem; + padding-right: 9999rem; +} +[role="main"] .wrapper { + border: none; + border-radius: 0; + box-shadow: none; + position: relative; + margin: 0; +} +[role="main"] .wrapper .primary .module-content { + padding-left: 15px; + padding-right: 0; + padding-top: 30px; + margin: 0; +} +[role="main"] .wrapper .primary.span9 .page-header { + margin-left: -20px; + padding-left: 25px; + margin-right: -9999rem; + padding-right: 9999rem; +} +[role="main"] .wrapper aside.secondary .nav-item.active > a, +[role="main"] .wrapper aside.secondary .nav-aside li.active a { + background-color: #8dc63f; +} +[role="main"] .wrapper aside.secondary .nav-item.active > a:before, +[role="main"] .wrapper aside.secondary .nav-aside li.active a:before { + background-image: none; + width: 0; + height: 0; + border-style: solid; + border-width: 17px 0 17px 6px; + border-color: transparent transparent transparent #8dc63f; + -webkit-transform: rotate(360deg); +} +[role="main"] .wrapper aside.secondary .nav-facet .nav-item > a:hover:after { + background-image: none; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + content: "\F055"; +} +[role="main"] .wrapper aside.secondary .nav-facet .nav-item.active > a:after, +[role="main"] .wrapper aside.secondary .nav-facet .nav-aside li.active a:after { + background-image: none; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + content: "\F057"; +} +[role="main"] .wrapper aside.secondary .module .read-more { + color: #4d4d4d; + font-weight: normal; + font-size: 14px; +} +[role="main"] .wrapper .media-grid { + margin-left: -14px; + background-color: transparent; + background-image: none; + border: none; +} +[role="main"] .wrapper .media-grid .media-item { + width: 223px; +} +@media (min-width: 768px) { + [role="main"] .wrapper .media-grid .media-item { + width: 223px; + } +} +@media (min-width: 980px) { + [role="main"] .wrapper .media-grid .media-item { + width: 188px; + } +} +[role="main"] .wrapper.no-nav > .module > .module-content { + padding-left: 0; + padding-right: 0; +} +[role="main"] .wrapper.no-nav > .module > .module-content:first-child { + padding-top: 30px; +} +.stages { + margin-right: 0; +} +.media-heading { + word-break: normal; +} +a { + color: #0c6db7; + text-decoration: underline; +} +a:hover, +a:focus { + color: #095087; +} +.nav-tabs a, +a.no-text, +.nav-item a, +a.label, +a.close { + text-decoration: none; +} +h1, +h2, +h3, +h4, +h5, +h6 { + color: #25374d; + line-height: 1.3; +} +h1 a, +h2 a, +h3 a, +h4 a, +h5 a, +h6 a { + text-decoration: none; +} +h1, +h2, +h3, +h4 { + letter-spacing: -1px; +} +h1 { + font-size: 34px; +} +h2 { + font-size: 30px; +} +h3 { + font-size: 26px; +} +h4 { + font-size: 22px; +} +h5 { + font-size: 18px; +} +h6 { + font-size: 16px; +} +.page-header { + background-color: #f6f7f8; +} +.account-masthead { + background-color: #4d4d4d; +} +.account-masthead .account ul li { + border: none; +} +.account-masthead .account ul li a { + line-height: 40px; + color: #fff; + text-decoration: none; + font-weight: 300; +} +.account-masthead .account ul li a:hover { + background-color: rgba(247, 247, 247, 0.1); + color: #fff; +} +.masthead { + color: #4d4d4d; +} +.masthead .logo { + display: block; + width: 282px; + margin: 22px 0; +} +.masthead .nav-collapse { + background-color: #e8eaed; + clear: both; + position: static; + margin-left: -9999rem; + margin-right: -9999rem; + padding-left: 9999rem; + padding-right: 9999rem; +} +.masthead .site-search { + position: absolute; + top: 31px; + right: 0; +} +.masthead .site-search label { + display: block; + position: absolute; + top: 8px; + background-color: #fff; + width: 30px; + height: 30px; + border-radius: 50%; + text-align: center; + line-height: 30px; + color: rgba(77, 77, 77, 0.25); +} +.masthead .site-search label:after { + display: none; +} +.masthead .site-search label span { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} +.masthead .site-search input { + padding: 12px 50px 12px 45px; + width: 210px; + background-color: #e8eaed; + border-radius: 0; + border-color: #e8eaed; + box-shadow: none; +} +.masthead .site-search input:focus { + border-color: #0c6db7; +} +.masthead .site-search .btn-search { + background-color: #0c6db7; + color: #fff; + height: 100%; + margin-top: 0; + padding: 0 12px; + top: 0; + right: -7px; + bottom: 0; + width: auto; +} +.masthead .site-search .btn-search:hover { + color: #fff; +} +.masthead .nav, +.masthead .navigation .nav-pills { + margin-left: -16px; +} +.masthead .nav > li, +.masthead .navigation .nav-pills > li { + font-size: 17px; +} +.masthead .nav > li > a, +.masthead .navigation .nav-pills > li > a { + padding: 16px; + margin: 0; + color: #25374d; + font-weight: bold; + border-radius: 0; + position: relative; +} +.masthead .nav > li > a:hover, +.masthead .navigation .nav-pills > li > a:hover { + background-color: #dfe2e6; +} +.masthead .nav > li.active > a, +.masthead .navigation .nav-pills > li.active > a { + background-color: transparent; + box-shadow: none; +} +.masthead .nav > li.active > a:after, +.masthead .navigation .nav-pills > li.active > a:after { + content: ''; + width: 0; + height: 0; + border-style: solid; + border-width: 0 5px 6px 5px; + border-color: transparent transparent #dfe2e6 transparent; + position: absolute; + bottom: 0; + left: 50%; + margin-left: -5px; +} +.masthead .nav > li.active > a:hover, +.masthead .navigation .nav-pills > li.active > a:hover { + color: #25374d; +} +.homepage .hero { + padding-bottom: 0; + padding-top: 20px; +} +@media (min-width: 768px) { + .homepage .hero { + background-color: #e8eaed; + border-top: solid 1px #dfe2e6; + } +} +.homepage .featured-groups li { + background-color: #25374d; +} +.homepage .featured-groups li a { + display: table; + color: #fff; + padding: 10px 0; + text-decoration: none; + width: 100%; +} +@media (min-width: 768px) { + .homepage .featured-groups li a { + height: 114px; + overflow: hidden; + } +} +.homepage .featured-groups li a h1, +.homepage .featured-groups li a h2, +.homepage .featured-groups li a h3, +.homepage .featured-groups li a h4, +.homepage .featured-groups li a h5, +.homepage .featured-groups li a h6 { + color: inherit; + margin: 0; + display: table-cell; + vertical-align: middle; + line-height: 1.1; + padding: 0 15px; + width: 100%; +} +.homepage .featured-groups li a:hover { + background-color: rgba(255, 255, 255, 0.2); +} +.homepage .featured-groups li a.ab-light { + color: #4d4d4d; +} +.homepage .featured-groups li a .image { + display: none; +} +@media (min-width: 980px) { + .homepage .featured-groups li a .image { + display: block; + width: 75px; + height: 75px; + border-radius: 50%; + overflow: hidden; + float: left; + margin: 20px 6px 0 24px; + } + .homepage .featured-groups li a .image img { + width: 77px; + max-width: 77px; + margin: -1px 0 0 -1px; + } +} +.homepage .featured-groups li[class*="health"], +.homepage .featured-groups li[class*="property"] { + background-color: #00ABC2; +} +.homepage .featured-groups li[class*="education"], +.homepage .featured-groups li[class*="population"] { + background-color: #34455A; +} +.homepage .featured-groups li[class*="finance"] { + background-color: #247BBE; +} +.homepage .featured-groups li[class*="environment"] { + background-color: #8DC63F; +} +.homepage .featured-groups li[class*="tourism"], +.homepage .featured-groups li[class*="transport"] { + background-color: #9488C1; +} +.homepage .featured-groups li[class*="economy"] { + background-color: #AC3192; +} +@media (min-width: 768px) { + .homepage .latest-posts .post > * { + margin-left: 3px; + margin-right: 3px; + } + .homepage .latest-posts > li:first-child .post > * { + margin-left: 0; + margin-right: 6px; + } + .homepage .latest-posts > li:last-child .post > * { + margin-left: 6px; + margin-right: 0; + } +} +.homepage .latest-posts h4 { + margin-bottom: 5px; +} +.homepage .latest-posts .date { + opacity: 0.6; + display: block; + margin-bottom: 6px; +} +.homepage .latest-posts .text { + display: block; + margin-bottom: 20px; +} +.twitter { + background-color: #0c6db7; + color: #fff; + margin: 0 -20px; + padding: 15px 20px; +} +.twitter h1, +.twitter h2, +.twitter h3, +.twitter h4, +.twitter h55, +.twitter h6 { + font-size: 30px; + margin: 10px 0 0 0; + color: inherit; +} +.twitter a { + color: inherit; + text-decoration: none; + font-weight: bold; +} +.twitter .carousel { + margin-bottom: 0; +} +.twitter ul.carousel-inner { + padding: 20px 0; + margin: 0; +} +.twitter ul.carousel-inner:empty:after { + content: "We haven't tweeted yet. Watch this space!"; + opacity: 0.8; + font-style: italic; +} +.twitter .item { + line-height: 22px; +} +@media (min-width: 768px) { + .twitter .user { + float: left; + height: 36px; + width: 230px; + } +} +.twitter .user span { + display: block; + line-height: 1.2; +} +.twitter .user span[data-scribe="element\3Ascreen_name"] { + font-size: 14px; + font-weight: normal; +} +.twitter .user img { + width: 36px; + height: 36px; + float: left; + margin-right: 15px; + border: solid 6px #fff; + border-radius: 50%; + background-color: #fff; + margin-top: -6px; +} +.twitter .tweet { + display: block; + position: relative; + margin: 10px 10px 0 63px; +} +@media (min-width: 768px) { + .twitter .tweet { + margin: 0 0 0 240px; + } +} +@media (min-width: 768px) { + .twitter .tweet:before, + .twitter .tweet:after { + font-size: 26px; + top: 4px; + position: relative; + } + .twitter .tweet:before { + content: open-quote; + position: absolute; + left: -15px; + } + .twitter .tweet:after { + content: close-quote; + margin-left: 3px; + } +} +.twitter .timePosted { + display: none; +} +.twitter .interact { + margin: 10px 0 0 63px; +} +@media (min-width: 768px) { + .twitter .interact { + margin-left: 240px; + } +} +.twitter .interact a { + display: inline-block; + width: 20px; + height: 20px; + overflow: hidden; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + opacity: 0.7; + margin-right: 5px; +} +.twitter .interact a:hover { + opacity: 1; +} +.twitter .interact a:before { + display: block; + text-align: center; +} +.twitter .interact a.twitter_reply_icon:before { + content: "\F064"; +} +.twitter .interact a.twitter_retweet_icon:before { + content: "\F079"; +} +.twitter .interact a.twitter_fav_icon:before { + content: "\F005"; +} +.twitter .interact-right .tweet { + margin-right: 30px; +} +.twitter .interact-right .interact { + position: absolute; + top: -8px; + right: 0; + margin: 0; +} +.twitter .interact-right .interact a { + display: block; + margin: 0; +} +.site-footer { + margin: 0 -20px; + padding: 30px 20px; + color: #4d4d4d; + font-size: 14px; +} +.site-footer a { + color: inherit; +} +.site-footer .logos > div { + margin-bottom: 20px; +} +@media (min-width: 768px) { + .site-footer .logos > div:nth-child(n+3) { + text-align: right; + } +} +.toolbar { + background-color: #e8eaed; + border-top: solid 1px #dfe2e6; + margin-left: -9999rem; + margin-right: -9999rem; + padding-left: 9999rem; + padding-right: 9999rem; + margin-bottom: 0; +} +.toolbar .breadcrumb { + font-size: 14px; + opacity: 0.8; + color: #25374d; +} +.toolbar .breadcrumb li { + text-shadow: none; +} +.toolbar .breadcrumb li.home .icon-home { + font-size: 16px; +} +.toolbar .breadcrumb li a { + text-decoration: none; + color: inherit; +} +.toolbar .breadcrumb li.active { + color: inherit; + font-weight: normal; +} +.toolbar .breadcrumb li.active a { + font-weight: inherit; +} +[role="main"] .wrapper { + background-image: none; +} +[role="main"] .wrapper:not(.no-nav) aside.secondary .module-heading { + background-color: #e8eaed; + border: none; +} +@media (min-width: 768px) { + [role="main"] .wrapper:not(.no-nav):before { + content: ""; + position: absolute; + top: 0; + bottom: 0; + width: 9600px; + right: 100%; + background-color: #f6f7f8; + display: block; + margin-right: -166px; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary { + background-color: #f6f7f8; + z-index: 1; + position: relative; + padding-top: 30px; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .module-narrow .module-heading, + [role="main"] .wrapper:not(.no-nav) aside.secondary .module-narrow .module-content, + [role="main"] .wrapper:not(.no-nav) aside.secondary .module-narrow .module-footer { + padding-left: 0; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .module-heading { + position: relative; + border-radius: 0; + font-size: 15px; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .module-heading:before { + content: ''; + display: block; + width: 15px; + position: absolute; + top: 0; + bottom: 0; + left: -15px; + background-color: #e8eaed; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .context-info .image > a { + padding: 5px; + background-color: #e8eaed; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .context-info .image > a img { + background-color: #fff; + border-radius: 0; + } + [role="main"] .wrapper:not(.no-nav) aside.secondary .nav { + margin-left: -15px; + } +} +@media (min-width: 768px) and (min-width: 980px) { + [role="main"] .wrapper:not(.no-nav):before { + margin-right: -220px; + } +} +[role="main"] .wrapper .module-resource { + position: relative; +} +[role="main"] .wrapper .primary .dataset-heading { + font-size: 20px; +} +.org-list { + margin: 0; +} +.org-list li { + display: block; +} +.org-list li a { + display: block; + background-color: #f6f7f8; + margin-bottom: 8px; + border-radius: 3px; + padding: 5px; + text-decoration: none; + color: #4d4d4d; +} +.org-list li a img { + margin: -4px 0 0 -2px; + width: 24px; +} +.org-list li a:hover { + background-color: #e8eaed; +} +.org-list li a .count { + display: none; +} +@media (min-width: 768px) { + .org-list li a .count { + display: block; + float: right; + font-size: 13px; + line-height: 25px; + margin-right: 7px; + } +} +.org-list li a span.count { + opacity: 0.2; +} +.org-list li a strong.count { + opacity: 0.5; + font-weight: normal; +} +.hierarchy-tree-top li a, +.hierarchy-tree li a { + position: relative; +} +.hierarchy-tree-top li a span, +.hierarchy-tree li a span { + position: absolute; + right: 0; + top: 0; + background: #0c6db7; + padding: 4px 10px; + color: #f6f7f8; +} +.hierarchy-tree li a span { + background: #00ABC2; +} +.media-grid .media-view { + border: none; +} +.media-grid .media-item { + background-color: #f6f7f8; +} +.media-grid .media-item .media-image { + border-radius: 0; +} +.media-grid .media-item strong.count { + font-weight: normal; +} +.media-grid .media-item.ab-dark { + color: #fff; +} +.media-grid .media-item.ab-dark h1, +.media-grid .media-item.ab-dark h2, +.media-grid .media-item.ab-dark h3, +.media-grid .media-item.ab-dark h4, +.media-grid .media-item.ab-dark h5, +.media-grid .media-item.ab-dark h6 { + color: inherit; +} +.media-grid .media-item.ab-dark span.count { + color: rgba(255, 255, 255, 0.6); +} +.media-grid .media-item.ab-dark strong.count { + color: rgba(255, 255, 255, 0.8); +} +.alert { + border: none; + background-color: #9488c1; + color: #fff; + text-shadow: none; +} +.alert a { + color: inherit; + text-shadow: none; +} +.alert .close { + right: 0; + top: auto; + opacity: 1; +} +.alert.alert-error { + background-color: #c84398; +} +.alert.alert-success { + background-color: #8dc63f; +} +.alert.alert-info { + background-color: #0c6db7; +} +.flash-messages .alert { + margin-left: -9999rem; + margin-right: -9999rem; + padding-left: 9999rem; + padding-right: 9999rem; + margin-bottom: 1px; +} +.label { + text-shadow: none; + letter-spacing: normal; + margin-right: 3px; +} +.label-open { + background-color: #808080 !important; +} +.label-in-progress { + background-color: #4186E0; +} +.label-contacted { + background-color: #4186E0; +} +.label-scheduled { + background-color: #FD9A00; +} +.label-released { + background-color: #2DB55D; +} +.label-cannot-release { + background-color: #E0051E; +} +.label-not-public { + background-color: #E0051E; +} +.expandable-menu, +.expandable-menu ul { + line-height: 1.5; + list-style: none; + padding: 0; + margin: 0; +} +.expandable-menu { + margin-left: -1.5em; +} +.expandable-menu > li { + padding-left: 1.5em; + margin-bottom: 0.5em; +} +.expandable-menu li a { + display: block; + padding: 0.25em; + background: #e8eaed; + color: #444; + text-decoration: none; + margin-top: 5px; + margin-left: 10px; +} +.expandable-menu li a:hover { + background: #dfe2e6; +} +.expandable-menu > li > a { + background: #e8eaed; + color: #25374d; + font-weight: bold; +} +.expandable-menu > li > a:hover { + background: #dfe2e6; +} +.expandable-menu input[type="checkbox"] ~ ul li, +.expandable-menu input[type="checkbox"].current:checked ~ ul li { + height: 0; + overflow: hidden; + transition: 0.2s ease-in; +} +.expandable-menu input[type="checkbox"]:checked ~ ul li, +.expandable-menu input[type="checkbox"].current ~ ul li { + height: auto; +} +.expandable-menu input[type="checkbox"] { + display: none; +} +.expandable-menu label { + display: block; + float: left; + content: ""; + margin-left: -2em; + width: 1.5em; + padding: 6px; + text-align: center; + background: #8cc63f; + color: white; + font-weight: bold; + cursor: pointer; +} +.expandable-menu label:hover { + background: #1b6a43; +} +.expandable-menu label:after { + content: ""; +} +.expandable-menu label:before, +.expandable-menu input[type="checkbox"]:checked.current ~ label:before { + font-family: FontAwesome; + content: "\f0fe"; +} +.expandable-menu input[type="checkbox"]:checked ~ label:before, +.expandable-menu input[type="checkbox"].current ~ label:before { + font-family: FontAwesome; + content: "\f146"; +} +.paddingleft-hack > li > a { + padding-left: 25px; + color: #25374d; +} +#s2id_field-add_groups { + width: unset !important; +} +#s2id_field-add_groups > ul { + max-width: 500px; + min-width: 220px; + width: auto !important; + min-height: 30px !important; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} +#no_content { + display: inline; +} +#no_content:after { + content: ''; +} +/* Custom UI Homepage updates */ +.latest-posts.thumbnails { + margin-top: 30px; +} +.latest-posts.thumbnails li { + border: 1px solid #eee; + margin-left: 17px; + min-height: 501px; +} +.latest-posts.thumbnails li .post { + padding: 10px; +} +.sub-heading { + display: inline; + position: relative; + top: 6px; +} +.more-btn { + margin-left: 10px; + display: inline; +} +.col-7 { + width: 70%; + float: left; +} +.col-3 { + width: 30%; + float: left; + text-align: right; +} +.showcase-item { + padding: 30px 0; + border-bottom: 1px solid #e1e1e1; +} +.showcase-item p { + margin-top: 10px; + color: #7d7d7d; +} +.showcase-item .btn { + position: relative; + top: 15px; + padding: 5px 25px; +} +.showcase-item span { + background-color: #eee; + font-size: 1.1em; + padding: 6px 15px; + font-weight: 600; + color: #7f7f7f; +} +.clearfix { + clear: both; +} +.thumb { + width: 100%; + height: 160px; + overflow: hidden; +} +@media screen and (max-width: 768px) { + .latest-posts .span4 { + width: 100%; + } + .mar-l-0 { + margin-left: 0 !important; + } +} diff --git a/ckanext/opendatani/assets/js/groups.js b/ckanext/opendatani/assets/js/groups.js new file mode 100644 index 0000000..16ba671 --- /dev/null +++ b/ckanext/opendatani/assets/js/groups.js @@ -0,0 +1,10 @@ +$(document).ready(function(){ + var defaults = { + + exclude: [ 'rgb(0,0,0)', 'rgba(255,255,255)', 'rgb(255,255,255)' ], + yiqThreshold: 200, + + }; + $.adaptiveBackground.run(defaults) + +}); diff --git a/ckanext/opendatani/assets/js/home.js b/ckanext/opendatani/assets/js/home.js new file mode 100644 index 0000000..1a85857 --- /dev/null +++ b/ckanext/opendatani/assets/js/home.js @@ -0,0 +1,41 @@ +$(document).ready(function(){ + var defaults = { + + exclude: [ 'rgb(0,0,0)', 'rgba(255,255,255)', 'rgb(255,255,255)' ], + yiqThreshold: 200, + parent: '.group', + + }; + $.adaptiveBackground.run(defaults) + + + // twitter + twitterFetcher.fetch({ + "profile": {"screenName": 'opendatani'}, + "domId": 'tweets', + "maxTweets": 5, + "enableLinks": true, + "customCallback":handleTweets, + }); + + + function handleTweets(tweets){ + var i=0; + var j=tweets.length; + var l=""; + document.getElementById("tweets").innerHTML=l; + var n=(j-1); + + $( "#tweet0" ).addClass( "active" ); + + $('.carousel').carousel({ + interval: 10000 + }) + } + +}); \ No newline at end of file diff --git a/ckanext/opendatani/assets/js/jquery.adaptive-backgrounds.js b/ckanext/opendatani/assets/js/jquery.adaptive-backgrounds.js new file mode 100644 index 0000000..95f23cf --- /dev/null +++ b/ckanext/opendatani/assets/js/jquery.adaptive-backgrounds.js @@ -0,0 +1,136 @@ +/* + * Tweaked version of adaptive-backgrounds.js + * https://github.com/mintcanary/jquery.adaptive-backgrounds.js + */ + +/* jshint debug: true, expr: true */ + +;(function($){ + + /* Constants & defaults. */ + var DATA_COLOR = 'data-ab-color'; + var DATA_PARENT = 'data-ab-parent'; + var DATA_CSS_BG = 'data-ab-css-background'; + var EVENT_CF = 'ab-color-found'; + + var DEFAULTS = { + selector: '[data-adaptive-background]', + parent: null, + exclude: [ 'rgb(0,0,0)', 'rgba(255,255,255)' ], + normalizeTextColor: false, + normalizedTextColors: { + light: "#fff", + dark: "#000" + }, + lumaClasses: { + light: "ab-light", + dark: "ab-dark" + }, + yiqThreshold: '128' + }; + + // Include RGBaster - https://github.com/briangonzalez/rgbaster.js + /* jshint ignore:start */ + !function(n){"use strict";var t=function(){return document.createElement("canvas").getContext("2d")},e=function(n,e){var a=new Image,o=n.src||n;"data:"!==o.substring(0,5)&&(a.crossOrigin="Anonymous"),a.onload=function(){var n=t("2d");n.drawImage(a,0,0);var o=n.getImageData(0,0,a.width,a.height);e&&e(o.data)},a.src=o},a=function(n){return["rgb(",n,")"].join("")},o=function(n){return n.map(function(n){return a(n.name)})},r=5,i=10,c={};c.colors=function(n,t){t=t||{};var c=t.exclude||[],u=t.paletteSize||i;e(n,function(e){for(var i=n.width*n.height||e.length,m={},s="",d=[],f={dominant:{name:"",count:0},palette:Array.apply(null,new Array(u)).map(Boolean).map(function(){return{name:"0,0,0",count:0}})},l=0;i>l;){if(d[0]=e[l],d[1]=e[l+1],d[2]=e[l+2],s=d.join(","),m[s]=s in m?m[s]+1:1,-1===c.indexOf(a(s))){var g=m[s];g>f.dominant.count?(f.dominant.name=s,f.dominant.count=g):f.palette.some(function(n){return g>n.count?(n.name=s,n.count=g,!0):void 0})}l+=4*r}if(t.success){var p=o(f.palette);t.success({dominant:a(f.dominant.name),secondary:p[0],palette:p})}})},n.RGBaster=n.RGBaster||c}(window); + /* jshint ignore:end */ + + + /* + Our main function declaration. + */ + $.adaptiveBackground = { + run: function( options ){ + var opts = $.extend({}, DEFAULTS, options); + + /* Loop over each element, waiting for it to load + then finding its color, and triggering the + color found event when color has been found. + */ + $( opts.selector ).each(function(index, el){ + var $this = $(this); + + /* Small helper functions which applies + colors, attrs, triggers events, etc. + */ + var handleColors = function () { + var img = useCSSBackground() ? getCSSBackground() : $this[0]; + + RGBaster.colors(img, { + paletteSize: 20, + exclude: opts.exclude, + success: function(colors) { + $this.attr(DATA_COLOR, colors.dominant); + $this.trigger(EVENT_CF, { color: colors.dominant, palette: colors.palette }); + } + }); + + }; + + var useCSSBackground = function(){ + var attr = $this.attr( DATA_CSS_BG ); + return (typeof attr !== typeof undefined && attr !== false); + }; + + var getCSSBackground = function(){ + var str = $this.css('background-image'); + var regex = /\(([^)]+)\)/; + var match = regex.exec(str)[1].replace(/"/g, '') + return match; + }; + + /* Subscribe to our color-found event. */ + $this.on( EVENT_CF, function(ev, data){ + + // Try to find the parent. + var $parent; + if ( opts.parent && $this.parents( opts.parent ).length ) { + $parent = $this.parents( opts.parent ); + } + else if ( $this.attr( DATA_PARENT ) && $this.parents( $this.attr( DATA_PARENT ) ).length ){ + $parent = $this.parents( $this.attr( DATA_PARENT ) ); + } + else if ( useCSSBackground() ){ + $parent = $this; + } + else if (opts.parent) { + $parent = $this.parents( opts.parent ); + } + else { + $parent = $this.parent(); + } + + $parent.css({ backgroundColor: data.color }); + + // Helper function to calculate yiq - http://en.wikipedia.org/wiki/YIQ + var getYIQ = function(color){ + var rgb = data.color.match(/\d+/g); + return ((rgb[0]*299)+(rgb[1]*587)+(rgb[2]*114))/1000; + }; + + var getNormalizedTextColor = function (color){ + return getYIQ(color) >= opts.yiqThreshold ? opts.normalizedTextColors.dark : opts.normalizedTextColors.light; + }; + + var getLumaClass = function (color){ + return getYIQ(color) <= opts.yiqThreshold ? opts.lumaClasses.dark : opts.lumaClasses.light; + }; + + // Normalize the text color based on luminance. + if ( opts.normalizeTextColor ) + $parent.css({ color: getNormalizedTextColor(data.color) }); + + // Add a class based on luminance. + $parent.addClass( getLumaClass(data.color) ) + .attr('data-ab-yaq', getYIQ(data.color)); + + opts.success && opts.success($this, data); + }); + + /* Handle the colors. */ + handleColors(); + + }); + }, + }; + +})(jQuery); diff --git a/ckanext/opendatani/assets/js/privacy.js b/ckanext/opendatani/assets/js/privacy.js new file mode 100644 index 0000000..9f90f0b --- /dev/null +++ b/ckanext/opendatani/assets/js/privacy.js @@ -0,0 +1,10 @@ +function privacyFunction(){ + var privacy = document.getElementById("field-privacy").checked; + if (privacy === true) { + return true + } + else { + alert('Consent to process has not been provided, user account cannot be created'); + return false + } +} \ No newline at end of file diff --git a/ckanext/opendatani/assets/js/twitterFetcher.js b/ckanext/opendatani/assets/js/twitterFetcher.js new file mode 100644 index 0000000..d42a7c0 --- /dev/null +++ b/ckanext/opendatani/assets/js/twitterFetcher.js @@ -0,0 +1,466 @@ +/********************************************************************* +* #### Twitter Post Fetcher v18.0.2 #### +* Coded by Jason Mayes 2015. A present to all the developers out there. +* www.jasonmayes.com +* Please keep this disclaimer with my code if you use it. Thanks. :-) +* Got feedback or questions, ask here: +* http://www.jasonmayes.com/projects/twitterApi/ +* Github: https://github.com/jasonmayes/Twitter-Post-Fetcher +* Updates will be posted to this site. +*********************************************************************/ +(function(root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals. + factory(); + } +}(this, function() { + var domNode = ''; + var maxTweets = 20; + var parseLinks = true; + var queue = []; + var inProgress = false; + var printTime = true; + var printUser = true; + var formatterFunction = null; + var supportsClassName = true; + var showRts = true; + var customCallbackFunction = null; + var showInteractionLinks = true; + var showImages = false; + var useEmoji = false; + var targetBlank = true; + var lang = 'en'; + var permalinks = true; + var dataOnly = false; + var script = null; + var scriptAdded = false; + + function handleTweets(tweets){ + if (customCallbackFunction === null) { + var x = tweets.length; + var n = 0; + var element = document.getElementById(domNode); + var html = '
    '; + while(n < x) { + html += '
  • ' + tweets[n] + '
  • '; + n++; + } + html += '
'; + element.innerHTML = html; + } else { + customCallbackFunction(tweets); + } + } + + function strip(data) { + return data.replace(/]*>(.*?)<\/b>/gi, function(a,s){return s;}) + .replace(/class="(?!(tco-hidden|tco-display|tco-ellipsis))+.*?"|data-query-source=".*?"|dir=".*?"|rel=".*?"/gi, + ''); + } + + function targetLinksToNewWindow(el) { + var links = el.getElementsByTagName('a'); + for (var i = links.length - 1; i >= 0; i--) { + links[i].setAttribute('target', '_blank'); + links[i].setAttribute('rel', 'noopener'); + } + } + + function getElementsByClassName (node, classname) { + var a = []; + var regex = new RegExp('(^| )' + classname + '( |$)'); + var elems = node.getElementsByTagName('*'); + for (var i = 0, j = elems.length; i < j; i++) { + if(regex.test(elems[i].className)){ + a.push(elems[i]); + } + } + return a; + } + + function extractImageUrl(image_data) { + if (image_data !== undefined && image_data.innerHTML.indexOf('data-image') >= 0) { + var data_src = image_data.innerHTML.match(/data-image=\"([A-z0-9]+:\/\/[A-z0-9]+\.[A-z0-9]+\.[A-z0-9]+\/[A-z0-9]+\/[A-z0-9\-]+)/i)[1]; + return decodeURIComponent(data_src) + '.jpg'; + } + } + + + var twitterFetcher = { + fetch: function(config) { + if (config.maxTweets === undefined) { + config.maxTweets = 20; + } + if (config.enableLinks === undefined) { + config.enableLinks = true; + } + if (config.showUser === undefined) { + config.showUser = true; + } + if (config.showTime === undefined) { + config.showTime = true; + } + if (config.dateFunction === undefined) { + config.dateFunction = 'default'; + } + if (config.showRetweet === undefined) { + config.showRetweet = true; + } + if (config.customCallback === undefined) { + config.customCallback = null; + } + if (config.showInteraction === undefined) { + config.showInteraction = true; + } + if (config.showImages === undefined) { + config.showImages = false; + } + if (config.useEmoji === undefined) { + config.useEmoji = false; + } + if (config.linksInNewWindow === undefined) { + config.linksInNewWindow = true; + } + if (config.showPermalinks === undefined) { + config.showPermalinks = true; + } + if (config.dataOnly === undefined) { + config.dataOnly = false; + } + + if (inProgress) { + queue.push(config); + } else { + inProgress = true; + + domNode = config.domId; + maxTweets = config.maxTweets; + parseLinks = config.enableLinks; + printUser = config.showUser; + printTime = config.showTime; + showRts = config.showRetweet; + formatterFunction = config.dateFunction; + customCallbackFunction = config.customCallback; + showInteractionLinks = config.showInteraction; + showImages = config.showImages; + useEmoji = config.useEmoji; + targetBlank = config.linksInNewWindow; + permalinks = config.showPermalinks; + dataOnly = config.dataOnly; + + var head = document.getElementsByTagName('head')[0]; + if (script !== null) { + head.removeChild(script); + } + script = document.createElement('script'); + script.type = 'text/javascript'; + if (config.list !== undefined) { + script.src = 'https://syndication.twitter.com/timeline/list?' + + 'callback=__twttrf.callback&dnt=false&list_slug=' + + config.list.listSlug + '&screen_name=' + config.list.screenName + + '&suppress_response_codes=true&lang=' + (config.lang || lang) + + '&rnd=' + Math.random(); + } else if (config.profile !== undefined) { + script.src = 'https://syndication.twitter.com/timeline/profile?' + + 'callback=__twttrf.callback&dnt=false' + + '&screen_name=' + config.profile.screenName + + '&suppress_response_codes=true&lang=' + (config.lang || lang) + + '&rnd=' + Math.random(); + } else if (config.likes !== undefined) { + script.src = 'https://syndication.twitter.com/timeline/likes?' + + 'callback=__twttrf.callback&dnt=false' + + '&screen_name=' + config.likes.screenName + + '&suppress_response_codes=true&lang=' + (config.lang || lang) + + '&rnd=' + Math.random(); + } else { + script.src = 'https://cdn.syndication.twimg.com/widgets/timelines/' + + config.id + '?&lang=' + (config.lang || lang) + + '&callback=__twttrf.callback&' + + 'suppress_response_codes=true&rnd=' + Math.random(); + } + head.appendChild(script); + } + }, + callback: function(data) { + if (data === undefined || data.body === undefined) { + inProgress = false; + + if (queue.length > 0) { + twitterFetcher.fetch(queue[0]); + queue.splice(0,1); + } + return; + } + + // Remove emoji and summary card images. + if(!useEmoji){ + data.body = data.body.replace(/(]*>)|(]*>)/g, ''); + } + + // Remove display images. + if (!showImages) { + data.body = data.body.replace(/(]*>|(]*>))/g, ''); + } + // Remove avatar images. + if (!printUser) { + data.body = data.body.replace(/(]*>)/g, ''); + } + + var div = document.createElement('div'); + div.innerHTML = data.body; + if (typeof(div.getElementsByClassName) === 'undefined') { + supportsClassName = false; + } + + function swapDataSrc(element) { + var avatarImg = element.getElementsByTagName('img')[0]; + if (avatarImg) { + avatarImg.src = avatarImg.getAttribute('data-src-2x'); + } else { + var screenName = element.getElementsByTagName('a')[0] + .getAttribute('href').split('twitter.com/')[1]; + var img = document.createElement('img'); + img.setAttribute('src', 'https://twitter.com/' + screenName + + '/profile_image?size=bigger'); + element.prepend(img); + } + return element; + } + + var tweets = []; + var authors = []; + var times = []; + var images = []; + var rts = []; + var tids = []; + var permalinksURL = []; + var x = 0; + + if (supportsClassName) { + var tmp = div.getElementsByClassName('timeline-Tweet'); + while (x < tmp.length) { + if (tmp[x].getElementsByClassName('timeline-Tweet-retweetCredit').length > 0) { + rts.push(true); + } else { + rts.push(false); + } + if (!rts[x] || rts[x] && showRts) { + tweets.push(tmp[x].getElementsByClassName('timeline-Tweet-text')[0]); + tids.push(tmp[x].getAttribute('data-tweet-id')); + if (printUser) { + authors.push(swapDataSrc(tmp[x].getElementsByClassName('timeline-Tweet-author')[0])); + } + times.push(tmp[x].getElementsByClassName('dt-updated')[0]); + permalinksURL.push(tmp[x].getElementsByClassName('timeline-Tweet-timestamp')[0]); + if (tmp[x].getElementsByClassName('timeline-Tweet-media')[0] !== + undefined) { + images.push(tmp[x].getElementsByClassName('timeline-Tweet-media')[0]); + } else { + images.push(undefined); + } + } + x++; + } + } else { + var tmp = getElementsByClassName(div, 'timeline-Tweet'); + while (x < tmp.length) { + if (getElementsByClassName(tmp[x], 'timeline-Tweet-retweetCredit').length > 0) { + rts.push(true); + } else { + rts.push(false); + } + if (!rts[x] || rts[x] && showRts) { + tweets.push(getElementsByClassName(tmp[x], 'timeline-Tweet-text')[0]); + tids.push(tmp[x].getAttribute('data-tweet-id')); + if (printUser) { + authors.push(swapDataSrc(getElementsByClassName(tmp[x],'timeline-Tweet-author')[0])); + } + times.push(getElementsByClassName(tmp[x], 'dt-updated')[0]); + permalinksURL.push(getElementsByClassName(tmp[x], 'timeline-Tweet-timestamp')[0]); + if (getElementsByClassName(tmp[x], 'timeline-Tweet-media')[0] !== undefined) { + images.push(getElementsByClassName(tmp[x], 'timeline-Tweet-media')[0]); + } else { + images.push(undefined); + } + } + x++; + } + } + + if (tweets.length > maxTweets) { + tweets.splice(maxTweets, (tweets.length - maxTweets)); + authors.splice(maxTweets, (authors.length - maxTweets)); + times.splice(maxTweets, (times.length - maxTweets)); + rts.splice(maxTweets, (rts.length - maxTweets)); + images.splice(maxTweets, (images.length - maxTweets)); + permalinksURL.splice(maxTweets, (permalinksURL.length - maxTweets)); + } + + var arrayTweets = []; + var x = tweets.length; + var n = 0; + if (dataOnly) { + while (n < x) { + arrayTweets.push({ + tweet: tweets[n].innerHTML, + author: authors[n] ? authors[n].innerHTML : 'Unknown Author', + author_data: { + profile_url: authors[n] ? authors[n].querySelector('[data-scribe="element:user_link"]').href : null, + profile_image: authors[n] ? + 'https://twitter.com/' + authors[n].querySelector('[data-scribe="element:screen_name"]').title.split('@')[1] + '/profile_image?size=bigger' : null, + profile_image_2x: authors[n] ? 'https://twitter.com/' + authors[n].querySelector('[data-scribe="element:screen_name"]').title.split('@')[1] + '/profile_image?size=original' : null, + screen_name: authors[n] ? authors[n].querySelector('[data-scribe="element:screen_name"]').title : null, + name: authors[n] ? authors[n].querySelector('[data-scribe="element:name"]').title : null + }, + time: times[n].textContent, + timestamp: times[n].getAttribute('datetime').replace('+0000', 'Z').replace(/([\+\-])(\d\d)(\d\d)/, '$1$2:$3'), + image: extractImageUrl(images[n]), + rt: rts[n], + tid: tids[n], + permalinkURL: (permalinksURL[n] === undefined) ? + '' : permalinksURL[n].href + }); + n++; + } + } else { + while (n < x) { + if (typeof(formatterFunction) !== 'string') { + var datetimeText = times[n].getAttribute('datetime'); + var newDate = new Date(times[n].getAttribute('datetime') + .replace(/-/g,'/').replace('T', ' ').split('+')[0]); + var dateString = formatterFunction(newDate, datetimeText); + times[n].setAttribute('aria-label', dateString); + + if (tweets[n].textContent) { + // IE hack. + if (supportsClassName) { + times[n].textContent = dateString; + } else { + var h = document.createElement('p'); + var t = document.createTextNode(dateString); + h.appendChild(t); + h.setAttribute('aria-label', dateString); + times[n] = h; + } + } else { + times[n].textContent = dateString; + } + } + var op = ''; + if (parseLinks) { + if (targetBlank) { + targetLinksToNewWindow(tweets[n]); + if (printUser) { + targetLinksToNewWindow(authors[n]); + } + } + if (printUser) { + op += '
' + strip(authors[n].innerHTML) + + '
'; + } + op += '

' + strip(tweets[n].innerHTML) + '

'; + if (printTime) { + if (permalinks) { + op += '

' + times[n].getAttribute('aria-label') + '

'; + } else { + op += '

' + + times[n].getAttribute('aria-label') + '

'; + } + } + } else { + if (tweets[n].textContent) { + if (printUser) { + op += '

' + authors[n].textContent + '

'; + } + op += '

' + tweets[n].textContent + '

'; + if (printTime) { + op += '

' + times[n].textContent + '

'; + } + + } else { + if (printUser) { + op += '

' + authors[n].textContent + '

'; + } + op += '

' + tweets[n].textContent + '

'; + if (printTime) { + op += '

' + times[n].textContent + '

'; + } + } + } + if (showInteractionLinks) { + op += '

' + + '

'; + } + if (showImages && images[n] !== undefined && extractImageUrl(images[n]) !== undefined) { + op += '
' + + 'Image from tweet' + '
'; + } + if (showImages) { + arrayTweets.push(op); + } else if (!showImages && tweets[n].textContent.length) { + arrayTweets.push(op); + } + + n++; + } + } + + handleTweets(arrayTweets); + inProgress = false; + + if (queue.length > 0) { + twitterFetcher.fetch(queue[0]); + queue.splice(0,1); + } + } + }; + + // It must be a global variable because it will be called by JSONP. + window.__twttrf = twitterFetcher; + window.twitterFetcher = twitterFetcher; + return twitterFetcher; +})); + + +// Prepend polyfill for IE/Edge. +(function (arr) { + arr.forEach(function (item) { + if (item.hasOwnProperty('prepend')) { + return; + } + Object.defineProperty(item, 'prepend', { + configurable: true, + enumerable: true, + writable: true, + value: function prepend() { + var argArr = Array.prototype.slice.call(arguments), + docFrag = document.createDocumentFragment(); + + argArr.forEach(function (argItem) { + var isNode = argItem instanceof Node; + docFrag.appendChild(isNode ? argItem : document.createTextNode(String(argItem))); + }); + + this.insertBefore(docFrag, this.firstChild); + } + }); + }); +})([Element.prototype, Document.prototype, DocumentFragment.prototype]); diff --git a/ckanext/opendatani/assets/js/twitterFetcher.min.js b/ckanext/opendatani/assets/js/twitterFetcher.min.js new file mode 100644 index 0000000..5d4d4b2 --- /dev/null +++ b/ckanext/opendatani/assets/js/twitterFetcher.min.js @@ -0,0 +1,67 @@ +/********************************************************************* +* #### Twitter Post Fetcher v18.0.2 #### +* Coded by Jason Mayes 2015. A present to all the developers out there. +* www.jasonmayes.com +* Please keep this disclaimer with my code if you use it. Thanks. :-) +* Got feedback or questions, ask here: +* http://www.jasonmayes.com/projects/twitterApi/ +* Github: https://github.com/jasonmayes/Twitter-Post-Fetcher +* Updates will be posted to this site. +*********************************************************************/ +(function(root,factory){if(typeof define==='function'&&define.amd){define([],factory);}else if(typeof exports==='object'){module.exports=factory();}else{factory();}}(this,function(){var domNode='';var maxTweets=20;var parseLinks=true;var queue=[];var inProgress=false;var printTime=true;var printUser=true;var formatterFunction=null;var supportsClassName=true;var showRts=true;var customCallbackFunction=null;var showInteractionLinks=true;var showImages=false;var useEmoji=false;var targetBlank=true;var lang='en';var permalinks=true;var dataOnly=false;var script=null;var scriptAdded=false;function handleTweets(tweets){if(customCallbackFunction===null){var x=tweets.length;var n=0;var element=document.getElementById(domNode);var html='
    ';while(n'+tweets[n]+'';n++;} +html+='
';element.innerHTML=html;}else{customCallbackFunction(tweets);}} +function strip(data){return data.replace(/]*>(.*?)<\/b>/gi,function(a,s){return s;}).replace(/class="(?!(tco-hidden|tco-display|tco-ellipsis))+.*?"|data-query-source=".*?"|dir=".*?"|rel=".*?"/gi,'');} +function targetLinksToNewWindow(el){var links=el.getElementsByTagName('a');for(var i=links.length-1;i>=0;i--){links[i].setAttribute('target','_blank');links[i].setAttribute('rel','noopener');}} +function getElementsByClassName(node,classname){var a=[];var regex=new RegExp('(^| )'+classname+'( |$)');var elems=node.getElementsByTagName('*');for(var i=0,j=elems.length;i=0){var data_src=image_data.innerHTML.match(/data-image=\"([A-z0-9]+:\/\/[A-z0-9]+\.[A-z0-9]+\.[A-z0-9]+\/[A-z0-9]+\/[A-z0-9\-]+)/i)[1];return decodeURIComponent(data_src)+'.jpg';}} +var twitterFetcher={fetch:function(config){if(config.maxTweets===undefined){config.maxTweets=20;} +if(config.enableLinks===undefined){config.enableLinks=true;} +if(config.showUser===undefined){config.showUser=true;} +if(config.showTime===undefined){config.showTime=true;} +if(config.dateFunction===undefined){config.dateFunction='default';} +if(config.showRetweet===undefined){config.showRetweet=true;} +if(config.customCallback===undefined){config.customCallback=null;} +if(config.showInteraction===undefined){config.showInteraction=true;} +if(config.showImages===undefined){config.showImages=false;} +if(config.useEmoji===undefined){config.useEmoji=false;} +if(config.linksInNewWindow===undefined){config.linksInNewWindow=true;} +if(config.showPermalinks===undefined){config.showPermalinks=true;} +if(config.dataOnly===undefined){config.dataOnly=false;} +if(inProgress){queue.push(config);}else{inProgress=true;domNode=config.domId;maxTweets=config.maxTweets;parseLinks=config.enableLinks;printUser=config.showUser;printTime=config.showTime;showRts=config.showRetweet;formatterFunction=config.dateFunction;customCallbackFunction=config.customCallback;showInteractionLinks=config.showInteraction;showImages=config.showImages;useEmoji=config.useEmoji;targetBlank=config.linksInNewWindow;permalinks=config.showPermalinks;dataOnly=config.dataOnly;var head=document.getElementsByTagName('head')[0];if(script!==null){head.removeChild(script);} +script=document.createElement('script');script.type='text/javascript';if(config.list!==undefined){script.src='https://syndication.twitter.com/timeline/list?'+'callback=__twttrf.callback&dnt=false&list_slug='+ +config.list.listSlug+'&screen_name='+config.list.screenName+'&suppress_response_codes=true&lang='+(config.lang||lang)+'&rnd='+Math.random();}else if(config.profile!==undefined){script.src='https://syndication.twitter.com/timeline/profile?'+'callback=__twttrf.callback&dnt=false'+'&screen_name='+config.profile.screenName+'&suppress_response_codes=true&lang='+(config.lang||lang)+'&rnd='+Math.random();}else if(config.likes!==undefined){script.src='https://syndication.twitter.com/timeline/likes?'+'callback=__twttrf.callback&dnt=false'+'&screen_name='+config.likes.screenName+'&suppress_response_codes=true&lang='+(config.lang||lang)+'&rnd='+Math.random();}else{script.src='https://cdn.syndication.twimg.com/widgets/timelines/'+ +config.id+'?&lang='+(config.lang||lang)+'&callback=__twttrf.callback&'+'suppress_response_codes=true&rnd='+Math.random();} +head.appendChild(script);}},callback:function(data){if(data===undefined||data.body===undefined){inProgress=false;if(queue.length>0){twitterFetcher.fetch(queue[0]);queue.splice(0,1);} +return;} +if(!useEmoji){data.body=data.body.replace(/(]*>)|(]*>)/g,'');} +if(!showImages){data.body=data.body.replace(/(]*>|(]*>))/g,'');} +if(!printUser){data.body=data.body.replace(/(]*>)/g,'');} +var div=document.createElement('div');div.innerHTML=data.body;if(typeof(div.getElementsByClassName)==='undefined'){supportsClassName=false;} +function swapDataSrc(element){var avatarImg=element.getElementsByTagName('img')[0];if(avatarImg){avatarImg.src=avatarImg.getAttribute('data-src-2x');}else{var screenName=element.getElementsByTagName('a')[0].getAttribute('href').split('twitter.com/')[1];var img=document.createElement('img');img.setAttribute('src','https://twitter.com/'+screenName+'/profile_image?size=bigger');element.prepend(img);} +return element;} +var tweets=[];var authors=[];var times=[];var images=[];var rts=[];var tids=[];var permalinksURL=[];var x=0;if(supportsClassName){var tmp=div.getElementsByClassName('timeline-Tweet');while(x0){rts.push(true);}else{rts.push(false);} +if(!rts[x]||rts[x]&&showRts){tweets.push(tmp[x].getElementsByClassName('timeline-Tweet-text')[0]);tids.push(tmp[x].getAttribute('data-tweet-id'));if(printUser){authors.push(swapDataSrc(tmp[x].getElementsByClassName('timeline-Tweet-author')[0]));} +times.push(tmp[x].getElementsByClassName('dt-updated')[0]);permalinksURL.push(tmp[x].getElementsByClassName('timeline-Tweet-timestamp')[0]);if(tmp[x].getElementsByClassName('timeline-Tweet-media')[0]!==undefined){images.push(tmp[x].getElementsByClassName('timeline-Tweet-media')[0]);}else{images.push(undefined);}} +x++;}}else{var tmp=getElementsByClassName(div,'timeline-Tweet');while(x0){rts.push(true);}else{rts.push(false);} +if(!rts[x]||rts[x]&&showRts){tweets.push(getElementsByClassName(tmp[x],'timeline-Tweet-text')[0]);tids.push(tmp[x].getAttribute('data-tweet-id'));if(printUser){authors.push(swapDataSrc(getElementsByClassName(tmp[x],'timeline-Tweet-author')[0]));} +times.push(getElementsByClassName(tmp[x],'dt-updated')[0]);permalinksURL.push(getElementsByClassName(tmp[x],'timeline-Tweet-timestamp')[0]);if(getElementsByClassName(tmp[x],'timeline-Tweet-media')[0]!==undefined){images.push(getElementsByClassName(tmp[x],'timeline-Tweet-media')[0]);}else{images.push(undefined);}} +x++;}} +if(tweets.length>maxTweets){tweets.splice(maxTweets,(tweets.length-maxTweets));authors.splice(maxTweets,(authors.length-maxTweets));times.splice(maxTweets,(times.length-maxTweets));rts.splice(maxTweets,(rts.length-maxTweets));images.splice(maxTweets,(images.length-maxTweets));permalinksURL.splice(maxTweets,(permalinksURL.length-maxTweets));} +var arrayTweets=[];var x=tweets.length;var n=0;if(dataOnly){while(n';} +op+='

'+strip(tweets[n].innerHTML)+'

';if(printTime){if(permalinks){op+='

'+times[n].getAttribute('aria-label')+'

';}else{op+='

'+ +times[n].getAttribute('aria-label')+'

';}}}else{if(tweets[n].textContent){if(printUser){op+='

'+authors[n].textContent+'

';} +op+='

'+tweets[n].textContent+'

';if(printTime){op+='

'+times[n].textContent+'

';}}else{if(printUser){op+='

'+authors[n].textContent+'

';} +op+='

'+tweets[n].textContent+'

';if(printTime){op+='

'+times[n].textContent+'

';}}} +if(showInteractionLinks){op+='

'+'

';} +if(showImages&&images[n]!==undefined&&extractImageUrl(images[n])!==undefined){op+='
'+'Image from tweet'+'
';} +if(showImages){arrayTweets.push(op);}else if(!showImages&&tweets[n].textContent.length){arrayTweets.push(op);} +n++;}} +handleTweets(arrayTweets);inProgress=false;if(queue.length>0){twitterFetcher.fetch(queue[0]);queue.splice(0,1);}}};window.__twttrf=twitterFetcher;window.twitterFetcher=twitterFetcher;return twitterFetcher;}));(function(arr){arr.forEach(function(item){if(item.hasOwnProperty('prepend')){return;} +Object.defineProperty(item,'prepend',{configurable:true,enumerable:true,writable:true,value:function prepend(){var argArr=Array.prototype.slice.call(arguments),docFrag=document.createDocumentFragment();argArr.forEach(function(argItem){var isNode=argItem instanceof Node;docFrag.appendChild(isNode?argItem:document.createTextNode(String(argItem)));});this.insertBefore(docFrag,this.firstChild);}});});})([Element.prototype,Document.prototype,DocumentFragment.prototype]); \ No newline at end of file diff --git a/ckanext/opendatani/assets/webassets.yml b/ckanext/opendatani/assets/webassets.yml new file mode 100644 index 0000000..1b9878c --- /dev/null +++ b/ckanext/opendatani/assets/webassets.yml @@ -0,0 +1,22 @@ +theme_css: + output: odni/%(version)s_theme_css.css + filters: cssrewrite + contents: + - css/theme.css + +main: + output: odni/%(version)s_main.js + filters: rjsmin + contents: + - js/groups.js + - js/home.js + - js/twitterFetcher.js + - js/jquery.adaptive-backgrounds.js + +adaptive_backgroudjs: + output: odni/%(version)s_adaptive_background.js + filters: rjsmin + contents: + - js/jquery.adaptive-backgrounds.js + + From ac32afad66ae35aee7eba47694621bbec546aab4 Mon Sep 17 00:00:00 2001 From: steveoni Date: Fri, 24 Sep 2021 16:37:15 +0000 Subject: [PATCH 04/39] [blueprint][l]: create blueprint for the custom routes --- ckanext/opendatani/blueprints/__init__.py | 6 + ckanext/opendatani/blueprints/dashboard.py | 85 +++++++++++++ ckanext/opendatani/blueprints/dataset.py | 116 ++++++++++++++++++ ckanext/opendatani/blueprints/organization.py | 70 +++++++++++ .../blueprints/publisher_reports.py | 101 +++++++++++++++ .../blueprints/static_controller.py | 76 ++++++++++++ ckanext/opendatani/blueprints/user.py | 114 +++++++++++++++++ 7 files changed, 568 insertions(+) create mode 100644 ckanext/opendatani/blueprints/__init__.py create mode 100644 ckanext/opendatani/blueprints/dashboard.py create mode 100644 ckanext/opendatani/blueprints/dataset.py create mode 100644 ckanext/opendatani/blueprints/organization.py create mode 100644 ckanext/opendatani/blueprints/publisher_reports.py create mode 100644 ckanext/opendatani/blueprints/static_controller.py create mode 100644 ckanext/opendatani/blueprints/user.py diff --git a/ckanext/opendatani/blueprints/__init__.py b/ckanext/opendatani/blueprints/__init__.py new file mode 100644 index 0000000..f80b759 --- /dev/null +++ b/ckanext/opendatani/blueprints/__init__.py @@ -0,0 +1,6 @@ +from .dashboard import dashboard_blueprint +from .dataset import dataset_blueprint +from .organization import organization_blueprint +from .publisher_reports import publisher_blueprint +from .user import user_blueprint +from .static_controller import static_blueprint diff --git a/ckanext/opendatani/blueprints/dashboard.py b/ckanext/opendatani/blueprints/dashboard.py new file mode 100644 index 0000000..ac72a37 --- /dev/null +++ b/ckanext/opendatani/blueprints/dashboard.py @@ -0,0 +1,85 @@ +import ckan.lib.base as base +from ckan.views.dataset import ( + _get_pkg_template, _get_package_type, _setup_template_variables +) + +import ckan.plugins.toolkit as toolkit +import ckan.logic as logic +from ckanext.opendatani import helpers +import logging +import datetime as dt +import requests +import os +import csv +from io import StringIO + +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer + +from flask import Blueprint + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + +dashboard_blueprint = Blueprint('odni_dashboard', __name__, url_prefix=u'/dashboard') + +def _stale_datasets_for_user(data): + def frequency_to_timedelta(frequency): + frequency_periods = { + "daily": dt.timedelta(days=2), + "weekly": dt.timedelta(days=7), + "fortnightly": dt.timedelta(days=14), + "monthly": dt.timedelta(days=30), + "quarterly": dt.timedelta(days=91), + "annually": dt.timedelta(days=365), + } + if not frequency: + pass + else: + return frequency_periods[frequency] + + stale_datasets = [] + if data: + for pkg in data: + if 'frequency' in pkg: + pkg['metadata_created'] = h.date_str_to_datetime( + pkg['metadata_created']) + pkg['metadata_modified'] = h.date_str_to_datetime( + pkg['metadata_modified']) + pkg['frequency'] = pkg.get('frequency', '') + if pkg['frequency']: + if pkg['frequency'] != 'irregular' and pkg['frequency'] != 'notPlanned': + if pkg['metadata_modified'].date() != pkg['metadata_created'].date(): + now = dt.datetime.now() + diff = now - pkg['metadata_modified'] + if diff > frequency_to_timedelta(pkg['frequency']): + stale_datasets.append(pkg) + return stale_datasets + +def dashboard_update_notifications(): + user = toolkit.get_action('user_show')( + {}, {'id': toolkit.c.userobj.id, 'include_datasets': True}) + data = user['datasets'] + c.stale_datasets = _stale_datasets_for_user(data) + context = {'for_view': True, 'user': c.user, + 'auth_user_obj': c.userobj} + data_dict = {'user_obj': c.userobj, 'stale_datasets': c.stale_datasets} + _setup_template_variables(context, data_dict) + return toolkit.render('user/dashboard_update.html') + + +dashboard_blueprint.add_url_rule( + rule='/update_notifications', + view_func=dashboard_update_notifications, + methods=[u'GET', u'POST'], +) \ No newline at end of file diff --git a/ckanext/opendatani/blueprints/dataset.py b/ckanext/opendatani/blueprints/dataset.py new file mode 100644 index 0000000..a483dda --- /dev/null +++ b/ckanext/opendatani/blueprints/dataset.py @@ -0,0 +1,116 @@ +import ckan.lib.base as base +from ckan.views.dataset import ( + _get_pkg_template, _get_package_type, _setup_template_variables +) + +import ckan.plugins.toolkit as toolkit +import ckan.logic as logic +from ckanext.opendatani import helpers +import logging +import datetime as dt +import requests +import os +import csv +from io import StringIO + +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer + +from flask import Blueprint + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + +dataset_blueprint = Blueprint('odni_dataset', __name__, url_prefix=u'/dataset') + + +def resource_read(id, resource_id): + context = {'model': model, 'session': model.Session, + 'user': c.user, + 'auth_user_obj': c.userobj, + 'for_view': True} + + try: + c.package = get_action('package_show')(context, {'id': id}) + except (NotFound, NotAuthorized): + abort(404, _('Dataset not found')) + + for resource in c.package.get('resources', []): + if resource['id'] == resource_id: + c.resource = resource + break + if not c.resource: + abort(404, _('Resource not found')) + + # required for nav menu + c.pkg = context['package'] + c.pkg_dict = c.package + dataset_type = c.pkg.type or 'dataset' + + # get package license info + license_id = c.package.get('license_id') + try: + c.package['isopen'] = model.Package.\ + get_license_register()[license_id].isopen() + except KeyError: + c.package['isopen'] = False + + # TODO: find a nicer way of doing this + c.datastore_api = '%s/api/action' % \ + config.get('ckan.site_url', '').rstrip('/') + + # c.resource['can_be_previewed'] = self._resource_preview( + # {'resource': c.resource, 'package': c.package}) + + resource_views = get_action('resource_view_list')( + context, {'id': resource_id}) + c.resource['has_views'] = len(resource_views) > 0 + + current_resource_view = None + view_id = request.GET.get('view_id') + if c.resource['can_be_previewed'] and not view_id: + current_resource_view = None + elif c.resource['has_views']: + if view_id: + current_resource_view = [rv for rv in resource_views + if rv['id'] == view_id] + if len(current_resource_view) == 1: + current_resource_view = current_resource_view[0] + else: + abort(404, _('Resource view not found')) + else: + current_resource_view = resource_views[0] + + vars = {'resource_views': resource_views, + 'current_resource_view': current_resource_view, + 'dataset_type': dataset_type} + print(MAX_FILE_SIZE) + if c.resource['url_type'] != 'upload': + try: + r = requests.head(c.resource['url']) + if r.status_code not in (400, 403, 405) and r.ok: + size = r.headers.get('content-length') + if size and int(size) > MAX_FILE_SIZE: + h.flash_error('Sorry, this file is too large to be able to display in the browser, please download the data resource to examine it further.') + except Exception as e: + print(e) + h.flash_error('Unable to get resource') + template = _get_pkg_template(dataset_type) + return render(template, extra_vars=vars) + + +dataset_blueprint.add_url_rule( + rule='/{id}/resource/{resource_id}', + view_func=resource_read, + methods=[u'GET', u'POST'], +) \ No newline at end of file diff --git a/ckanext/opendatani/blueprints/organization.py b/ckanext/opendatani/blueprints/organization.py new file mode 100644 index 0000000..00908cd --- /dev/null +++ b/ckanext/opendatani/blueprints/organization.py @@ -0,0 +1,70 @@ +import ckan.lib.base as base +from ckan.views.dataset import ( + _get_pkg_template, _get_package_type, _setup_template_variables +) + +import ckan.plugins.toolkit as toolkit +import ckan.logic as logic +from ckanext.opendatani import helpers +import logging +import datetime as dt +import requests +import os +import csv +from io import StringIO + +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer + +from flask import Blueprint + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + +organization_blueprint = Blueprint('odni_organization', __name__, url_prefix=u'/organization') + + +def add_groups(id): + context = {'model': model, 'session': model.Session, + 'user': c.user} + data_dict = {'id': id, 'all_fields': True} + c.group_dict = toolkit.get_action( + 'organization_show')(context, data_dict) + c.packages = toolkit.get_action( + 'current_package_list_with_resources')(context, data_dict) + c.groups = toolkit.get_action('group_list')(context, data_dict) + + if request.method == 'POST': + selected_groups = request.POST.getall('group') + selected_datasets = request.POST.getall('dataset') + for group in selected_groups: + for pkg in selected_datasets: + data_dict = {"id": group, + "object": pkg, + "object_type": 'package', + "capacity": 'public'} + try: + get_action('member_create')(context, data_dict) + except NotFound: + abort(404, _('Group not found')) + controller = 'ckanext.opendatani.controller:CustomPackageController' + url = h.url_for(controller=controller, action='add_groups', id=id) + h.redirect_to(url) + return toolkit.render('organization/add_groups.html') + + +organization_blueprint.add_url_rule( + rule='/add_groups/{id}', + view_func=add_groups, + methods=[u'GET', u'POST'], +) \ No newline at end of file diff --git a/ckanext/opendatani/blueprints/publisher_reports.py b/ckanext/opendatani/blueprints/publisher_reports.py new file mode 100644 index 0000000..b25dee5 --- /dev/null +++ b/ckanext/opendatani/blueprints/publisher_reports.py @@ -0,0 +1,101 @@ +import ckan.lib.base as base +from ckan.views.dataset import ( + _get_pkg_template, _get_package_type, _setup_template_variables +) + +import ckan.plugins.toolkit as toolkit +import ckan.logic as logic +from ckanext.opendatani import helpers +import logging +import datetime as dt +import requests +import os +import csv +from io import StringIO + +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer + +from flask import Blueprint + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + +publisher_blueprint = Blueprint('odni_publisher', __name__, url_prefix=u'/publisher-reports') + + +def prepare_report(org): + """ + Creates a CSV publisher report and returns it as a string + :param org: organization + :type org: string + :return: a CSV string + :rtype: string + """ + + try: + data_dict = {'org_name': org} + + if org == '@complete': + data_dict = {} + # Use 'complete' in the file name for full reports + org = org[1:] + else: + # Use 'org-' in the file name for per org reports + org = 'org-' + org + + resource = toolkit.get_action( + 'report_resources_by_organization')({}, data_dict) + + # We need this in case no datasets exist for the given organization + # or the organization doesn't exist + if not resource: + toolkit.abort(404, _('Either the organization does not exist, \ + or it has no datasets.')) + + csvout = StringIO() + csvwriter = csv.writer( + csvout, + dialect='excel', + quoting=csv.QUOTE_NONNUMERIC + ) + + fields = resource[0].keys() + csvwriter.writerow(fields) + + for data in resource: + # We need to encode here due to unicode errors + csvwriter.writerow( + [unicode(d).encode('utf-8') for d in data.values()]) + + csvout.seek(0) + filename = 'publisher-report-{0}-{1}.csv'.format(org, + dt.date.today()) + toolkit.response.headers['Content-Type'] = 'application/csv' + toolkit.response.headers['Content-Disposition'] = \ + 'attachment; filename={0}'.format(filename) + + return csvout.read() + + except Exception as ex: + error = 'Preparing the CSV report failed. Error: {0}'.format(ex) + log.error(error) + h.flash_error(error) + raise + + +publisher_blueprint.add_url_rule( + rule='/publisher-report-{org}.csv', + view_func=prepare_report, + methods=[u'GET', u'POST'], +) \ No newline at end of file diff --git a/ckanext/opendatani/blueprints/static_controller.py b/ckanext/opendatani/blueprints/static_controller.py new file mode 100644 index 0000000..1cc9525 --- /dev/null +++ b/ckanext/opendatani/blueprints/static_controller.py @@ -0,0 +1,76 @@ +import datetime as dt +import requests +import os +import csv +from io import StringIO +import logging +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer +import ckan.logic as logic +from flask import Blueprint + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + +static_blueprint = Blueprint('odni_static', __name__) + +def cookies(): + return base.render('static/cookies.html') + +def codeofconduct(): + return base.render('static/codeofconduct.html') + +def termsandconditions(): + return base.render('static/termsandconditions.html') + +def privacy(): + return base.render('static/privacy.html') + +def privacy_notice_reg(): + return base.render('static/privacy_notice_reg.html') + + +static_blueprint.add_url_rule( + rule='/privacy', + view_func=privacy, + methods=[u'GET'], +) + + +static_blueprint.add_url_rule( + rule='/terms-and-conditions', + view_func=termsandconditions, + methods=[u'GET'], +) + + +static_blueprint.add_url_rule( + rule='/cookies', + view_func=cookies, + methods=[u'GET'], +) + + +static_blueprint.add_url_rule( + rule='/code-of-conduct', + view_func=codeofconduct, + methods=[u'GET'], +) + + +static_blueprint.add_url_rule( + rule='/privacy_notice_reg', + view_func=privacy_notice_reg, + methods=[u'GET'], +) + diff --git a/ckanext/opendatani/blueprints/user.py b/ckanext/opendatani/blueprints/user.py new file mode 100644 index 0000000..ee6327c --- /dev/null +++ b/ckanext/opendatani/blueprints/user.py @@ -0,0 +1,114 @@ +import ckan.lib.base as base +from ckan.views.dataset import ( + _get_pkg_template, _get_package_type, _setup_template_variables +) + +import ckan.plugins.toolkit as toolkit +import ckan.logic as logic +from ckanext.opendatani import helpers +import logging +import datetime as dt +import requests +import os +import csv +from io import StringIO + +import ckan.lib.base as base +from ckan import model +import ckan.lib.helpers as h +import ckan.lib.mailer as mailer + +from flask import Blueprint + +user_blueprint = Blueprint('odni_user', __name__, url_prefix=u'/user') + + +log = logging.getLogger(__name__) + +render = base.render +abort = base.abort + +NotFound = logic.NotFound +NotAuthorized = logic.NotAuthorized +get_action = logic.get_action +ValidationError = logic.ValidationError + + + +def request_reset(): + context = {'model': model, 'session': model.Session, + 'user': toolkit.c.user, + 'auth_user_obj': toolkit.c.userobj} + data_dict = {'id': toolkit.request.params.get('user')} + try: + toolkit.check_access('request_reset', context) + except toolkit.NotAuthorized: + toolkit.abort(401, + toolkit._('Unauthorized to request reset password.')) + + if toolkit.request.method == 'POST': + id = toolkit.request.params.get('user') + + context = {'model': model, + 'user': toolkit.c.user} + + data_dict = {'id': id} + user_obj = None + try: + toolkit.get_action('user_show')(context, data_dict) + user_obj = context['user_obj'] + except toolkit.ObjectNotFound: + h.flash_error(toolkit._('No such user: %s') % id) + + if user_obj: + try: + mailer.send_reset_link(user_obj) + h.flash_success(toolkit._('Please check your inbox for ' + 'a reset code.')) + h.redirect_to('/') + except mailer.MailerException as e: + h.flash_error(toolkit._('Could not send reset link: %s') % + unicode(e)) + return toolkit.render('user/request_reset.html') + + +def activity(id, offset=0): + '''Render this user's public activity stream page.''' + + context = {'model': model, 'session': model.Session, + 'user': c.user, 'auth_user_obj': c.userobj, + 'for_view': True} + data_dict = {'id': id, 'user_obj': c.userobj, + 'include_num_followers': True} + try: + toolkit.check_access('sysadmin', context, data_dict) + except NotAuthorized: + abort(403, _('Not authorized to see this page')) + + _setup_template_variables(context, data_dict) + + try: + c.user_activity_stream = get_action('user_activity_list_html')( + context, {'id': c.user_dict['id'], 'offset': offset}) + except ValidationError: + base.abort(400) + + return render('user/activity_stream.html') + +user_blueprint.add_url_rule( + rule='/reset', + view_func=request_reset, + methods=[u'GET', u'POST'], +) + +user_blueprint.add_url_rule( + rule='/activity/{id}/{offset}', + view_func=activity, + methods=[u'GET', u'POST'], +) + +user_blueprint.add_url_rule( + rule='/activity/{id}', + view_func=activity, + methods=[u'GET', u'POST'], +) \ No newline at end of file From b8c62a7394e0196bbe1a61ff69e0c60e08e11b6e Mon Sep 17 00:00:00 2001 From: steveoni Date: Fri, 24 Sep 2021 16:38:00 +0000 Subject: [PATCH 05/39] [base.html][m]: update base to contain js and css assets --- ckanext/opendatani/templates/base.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ckanext/opendatani/templates/base.html b/ckanext/opendatani/templates/base.html index 741417e..6645d66 100644 --- a/ckanext/opendatani/templates/base.html +++ b/ckanext/opendatani/templates/base.html @@ -2,12 +2,13 @@ {% block styles %} {{ super() }} - {% resource 'opendatani/css/theme.css' %} + {% asset 'odni/theme_css' %} + {% endblock %} {% block scripts %} {{ super() }} - {% resource 'opendatani/js/jquery.adaptive-backgrounds.js' %} + {% asset 'odni/adaptive_backgroudjs' %} {% endblock %} {% block googleanalytics %} From ceb97d9d1497c507857e5dcfc762a1dfc4a100d0 Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 18:55:58 +0000 Subject: [PATCH 06/39] [plugin][s]: change basestring to str --- ckanext/opendatani/plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ckanext/opendatani/plugin.py b/ckanext/opendatani/plugin.py index 465c97f..90ddd5c 100644 --- a/ckanext/opendatani/plugin.py +++ b/ckanext/opendatani/plugin.py @@ -324,7 +324,7 @@ def custom_user_password_validator(key, data, errors, context): if isinstance(value, Missing): pass - elif not isinstance(value, basestring): + elif not isinstance(value, str): errors[('password',)].append(_('Passwords must be strings')) elif value == '': pass @@ -341,7 +341,7 @@ def _callable(key, data, errors, context): value = data.get(key) _number_of_tags = int(number_of_tags) - if not isinstance(value, basestring): + if not isinstance(value, str): return value = value.split(',') From c8831bee075d24c17d62c4ab28deb291b6301cc1 Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 18:56:38 +0000 Subject: [PATCH 07/39] [dashboard][s]: update template extra vars --- ckanext/opendatani/blueprints/dashboard.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ckanext/opendatani/blueprints/dashboard.py b/ckanext/opendatani/blueprints/dashboard.py index ac72a37..a32e206 100644 --- a/ckanext/opendatani/blueprints/dashboard.py +++ b/ckanext/opendatani/blueprints/dashboard.py @@ -2,6 +2,7 @@ from ckan.views.dataset import ( _get_pkg_template, _get_package_type, _setup_template_variables ) +from ckan.views.user import _extra_template_variables import ckan.plugins.toolkit as toolkit import ckan.logic as logic @@ -17,6 +18,7 @@ from ckan import model import ckan.lib.helpers as h import ckan.lib.mailer as mailer +from ckan.common import c from flask import Blueprint @@ -74,8 +76,8 @@ def dashboard_update_notifications(): context = {'for_view': True, 'user': c.user, 'auth_user_obj': c.userobj} data_dict = {'user_obj': c.userobj, 'stale_datasets': c.stale_datasets} - _setup_template_variables(context, data_dict) - return toolkit.render('user/dashboard_update.html') + extra_vars = _extra_template_variables(context, data_dict) + return toolkit.render('user/dashboard_update.html', extra_vars) dashboard_blueprint.add_url_rule( From d6c235b27e73a4f50d9d70df0dd1d0c206695530 Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 19:20:10 +0000 Subject: [PATCH 08/39] import c from ckan.common --- ckanext/opendatani/blueprints/dataset.py | 1 + ckanext/opendatani/blueprints/organization.py | 1 + 2 files changed, 2 insertions(+) diff --git a/ckanext/opendatani/blueprints/dataset.py b/ckanext/opendatani/blueprints/dataset.py index a483dda..eeba7bd 100644 --- a/ckanext/opendatani/blueprints/dataset.py +++ b/ckanext/opendatani/blueprints/dataset.py @@ -17,6 +17,7 @@ from ckan import model import ckan.lib.helpers as h import ckan.lib.mailer as mailer +from ckan.common import c from flask import Blueprint diff --git a/ckanext/opendatani/blueprints/organization.py b/ckanext/opendatani/blueprints/organization.py index 00908cd..19154d5 100644 --- a/ckanext/opendatani/blueprints/organization.py +++ b/ckanext/opendatani/blueprints/organization.py @@ -17,6 +17,7 @@ from ckan import model import ckan.lib.helpers as h import ckan.lib.mailer as mailer +from ckan.common import c from flask import Blueprint From 319be047c05e1e7d49a912f2f9935c11621ddd90 Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 19:20:42 +0000 Subject: [PATCH 09/39] [webassets][s]: addjs assest for group.js --- ckanext/opendatani/assets/webassets.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ckanext/opendatani/assets/webassets.yml b/ckanext/opendatani/assets/webassets.yml index 1b9878c..73c97c8 100644 --- a/ckanext/opendatani/assets/webassets.yml +++ b/ckanext/opendatani/assets/webassets.yml @@ -19,4 +19,8 @@ adaptive_backgroudjs: contents: - js/jquery.adaptive-backgrounds.js - +group: + output: odni/%(version)s_group.js + filters: rjsmin + contents: + - js/groups.js From 6984d8ba94a2cd042875a62a44adec50baa8a2a3 Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 19:21:15 +0000 Subject: [PATCH 10/39] [user][s]: add extra vars to user template --- ckanext/opendatani/blueprints/user.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ckanext/opendatani/blueprints/user.py b/ckanext/opendatani/blueprints/user.py index ee6327c..82177f4 100644 --- a/ckanext/opendatani/blueprints/user.py +++ b/ckanext/opendatani/blueprints/user.py @@ -17,6 +17,7 @@ from ckan import model import ckan.lib.helpers as h import ckan.lib.mailer as mailer +from ckan.common import c from flask import Blueprint @@ -85,7 +86,7 @@ def activity(id, offset=0): except NotAuthorized: abort(403, _('Not authorized to see this page')) - _setup_template_variables(context, data_dict) + extra_vars = _setup_template_variables(context, data_dict) try: c.user_activity_stream = get_action('user_activity_list_html')( @@ -93,7 +94,7 @@ def activity(id, offset=0): except ValidationError: base.abort(400) - return render('user/activity_stream.html') + return render('user/activity_stream.html', extra_vars) user_blueprint.add_url_rule( rule='/reset', From eb58c83119cb8e6b056286ea2b5c5a678d59908b Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 19:21:51 +0000 Subject: [PATCH 11/39] [footer][l]: fix footer links --- ckanext/opendatani/templates/footer.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ckanext/opendatani/templates/footer.html b/ckanext/opendatani/templates/footer.html index fc29f96..a10d2fc 100644 --- a/ckanext/opendatani/templates/footer.html +++ b/ckanext/opendatani/templates/footer.html @@ -6,7 +6,7 @@ NI Direct

- Digital NI + Digital NI
CKAN @@ -16,6 +16,6 @@
- Cookies | Data protection | Code of conduct | Terms & conditions | CKAN API + Cookies | Data protection | Code of conduct | Terms & conditions | CKAN API {% endblock %} From 74e0d04322f47c9ad4ef982619ce6396f05422bc Mon Sep 17 00:00:00 2001 From: steveoni Date: Tue, 28 Sep 2021 19:22:51 +0000 Subject: [PATCH 12/39] [header.html][l]: fix header links --- ckanext/opendatani/templates/header.html | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ckanext/opendatani/templates/header.html b/ckanext/opendatani/templates/header.html index 36c0d3d..4d88189 100644 --- a/ckanext/opendatani/templates/header.html +++ b/ckanext/opendatani/templates/header.html @@ -2,25 +2,25 @@ {% block header_account_logged %}
  • - +
  • - +
  • {% if c.userobj.sysadmin %}
  • - + {{ _('Admin') }}
  • {% endif %}
  • - + {{ h.gravatar((c.userobj.email_hash if c and c.userobj else ''), size=22) }} {{ c.userobj.display_name }} @@ -29,7 +29,7 @@ {% set stale_datasets = h.get_user_num_stale_datasets() %}
  • {% set notifications_tooltip = ngettext('Dashboard (%(num)d new item)', 'Dashboard (%(num)d new items)', new_activities+stale_datasets|int) %} - + {{ _('Dashboard') }} {{ new_activities + stale_datasets|int }} @@ -37,7 +37,7 @@
  • {% block header_account_settings_link %}
  • - + {{ _('Settings') }} @@ -45,7 +45,7 @@ {% endblock %} {% block header_account_log_out_link %}
  • - + {{ _('Log out') }} @@ -54,9 +54,9 @@ {% endblock %} {% block header_account_notlogged %} -
  • {% link_for _('Log in'), controller='user', action='login' %}
  • +
  • {% link_for _('Log in'), named_route='user.login' %}
  • {% if h.check_access('user_create') %} -
  • {% link_for _('Register'), controller='ckanext.opendatani.controller:StaticController', action='privacy_notice_reg', class_='sub' %}
  • +
  • {% link_for _('Register'), named_route='odni_static.privacy_notice_reg', class_='sub' %}
  • {% endif %} {% endblock %} @@ -68,19 +68,19 @@ ('home', _('Home')), ('search', _('Datasets')), ('organizations_index', _('Publisher')), - ('ckanext_showcase_index', _('Showcases')), - ('datarequests_index', _('Suggest Data') + h.get_open_datarequests_badge()), + ('showcase_blueprint.index', _('Showcases')), + ('datarequests.index', _('Suggest Data') + h.get_open_datarequests_badge()), ) }} {% endblock %}
  • {{ _('News') }}
  • -
  • {{ _('About').format(g.site_title) }}
  • +
  • {{ _('About').format(g.site_title) }}
  • {{ _('Contact') }}
  • {% endblock %} {% block header_site_search %} -