diff options
| -rw-r--r-- | python/fatcat_web/graphics.py | 42 | ||||
| -rw-r--r-- | python/fatcat_web/routes.py | 20 | ||||
| -rw-r--r-- | python/fatcat_web/search.py | 22 | ||||
| -rw-r--r-- | python/fatcat_web/templates/entity_macros.html | 12 | ||||
| -rw-r--r-- | python/fatcat_web/web_config.py | 3 | 
5 files changed, 80 insertions, 19 deletions
diff --git a/python/fatcat_web/graphics.py b/python/fatcat_web/graphics.py index 7d6e5702..a8e217e3 100644 --- a/python/fatcat_web/graphics.py +++ b/python/fatcat_web/graphics.py @@ -37,14 +37,17 @@ def ia_coverage_histogram(rows: List[Tuple]) -> pygal.Graph:      chart.add('Missing', [y['missing'] for y in years])      return chart -def preservation_by_year_histogram(rows: List[Dict]) -> pygal.Graph: +def preservation_by_year_histogram(rows: List[Dict], merge_shadows: bool = False) -> pygal.Graph:      """      Note: this returns a raw pygal chart; it does not render it to SVG/PNG      """      years = sorted(rows, key=lambda x: x['year']) -    CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen") +    if merge_shadows: +        CleanStyle.colors = ("red", "darkolivegreen", "limegreen") +    else: +        CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen")      label_count = len(years)      if len(years) > 30:          label_count = 10 @@ -55,20 +58,26 @@ def preservation_by_year_histogram(rows: List[Dict]) -> pygal.Graph:      chart.x_title = "Year"      #chart.y_title = "Count"      chart.x_labels = [str(y['year']) for y in years] -    chart.add('None', [y['none'] for y in years]) -    chart.add('Shadow', [y['shadows_only'] for y in years]) +    if merge_shadows: +        chart.add('None', [y['none'] + y['shadows_only'] for y in years]) +    else: +        chart.add('None', [y['none'] for y in years]) +        chart.add('Shadow', [y['shadows_only'] for y in years])      chart.add('Dark', [y['dark'] for y in years])      chart.add('Bright', [y['bright'] for y in years])      return chart -def preservation_by_date_histogram(rows: List[Dict]) -> pygal.Graph: +def preservation_by_date_histogram(rows: List[Dict], merge_shadows: bool = False) -> pygal.Graph:      """      Note: this returns a raw pygal chart; it does not render it to SVG/PNG      """      dates = sorted(rows, key=lambda x: x['date']) -    CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen") +    if merge_shadows: +        CleanStyle.colors = ("red", "darkolivegreen", "limegreen") +    else: +        CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen")      label_count = len(dates)      if len(dates) > 30:          label_count = 10 @@ -79,20 +88,26 @@ def preservation_by_date_histogram(rows: List[Dict]) -> pygal.Graph:      chart.x_title = "Date"      #chart.y_title = "Count"      chart.x_labels = [str(y['date']) for y in dates] -    chart.add('None', [y['none'] for y in dates]) -    chart.add('Shadow', [y['shadows_only'] for y in dates]) +    if merge_shadows: +        chart.add('None', [y['none'] + y['shadows_only'] for y in dates]) +    else: +        chart.add('None', [y['none'] for y in dates]) +        chart.add('Shadow', [y['shadows_only'] for y in dates])      chart.add('Dark', [y['dark'] for y in dates])      chart.add('Bright', [y['bright'] for y in dates])      return chart -def preservation_by_volume_histogram(rows: List[Dict]) -> pygal.Graph: +def preservation_by_volume_histogram(rows: List[Dict], merge_shadows: bool = False) -> pygal.Graph:      """      Note: this returns a raw pygal chart; it does not render it to SVG/PNG      """      volumes = sorted(rows, key=lambda x: x['volume']) -    CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen") +    if merge_shadows: +        CleanStyle.colors = ("red", "darkolivegreen", "limegreen") +    else: +        CleanStyle.colors = ("red", "darkred", "darkolivegreen", "limegreen")      label_count = len(volumes)      if len(volumes) >= 30:          label_count = 10 @@ -103,8 +118,11 @@ def preservation_by_volume_histogram(rows: List[Dict]) -> pygal.Graph:      chart.x_title = "Volume"      #chart.y_title = "Count"      chart.x_labels = [str(y['volume']) for y in volumes] -    chart.add('None', [y['none'] for y in volumes]) -    chart.add('Shadow', [y['shadows_only'] for y in volumes]) +    if merge_shadows: +        chart.add('None', [y['none'] + y['shadows_only'] for y in volumes]) +    else: +        chart.add('None', [y['none'] for y in volumes]) +        chart.add('Shadow', [y['shadows_only'] for y in volumes])      chart.add('Dark', [y['dark'] for y in volumes])      chart.add('Bright', [y['bright'] for y in volumes])      return chart diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py index 1281a617..bcfa133b 100644 --- a/python/fatcat_web/routes.py +++ b/python/fatcat_web/routes.py @@ -754,10 +754,16 @@ def coverage_search():          coverage_type_preservation = get_elastic_preservation_by_type(query)          if query.recent:              date_histogram = get_elastic_preservation_by_date(query) -            date_histogram_svg = preservation_by_date_histogram(date_histogram).render_data_uri() +            date_histogram_svg = preservation_by_date_histogram( +                date_histogram, +                merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION, +            ).render_data_uri()          else:              year_histogram = get_elastic_preservation_by_year(query) -            year_histogram_svg = preservation_by_year_histogram(year_histogram).render_data_uri() +            year_histogram_svg = preservation_by_year_histogram( +                year_histogram, +                merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION, +            ).render_data_uri()      return render_template(          'coverage_search.html',          query=query, @@ -886,7 +892,10 @@ def container_ident_preservation_by_year_svg(ident):      except Exception as ae:          app.log.error(ae)          abort(503) -    return preservation_by_year_histogram(histogram).render_response() +    return preservation_by_year_histogram( +        histogram, +        merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION, +    ).render_response()  @app.route('/container/<ident>/preservation_by_volume.json', methods=['GET', 'OPTIONS'])  @crossdomain(origin='*',headers=['access-control-allow-origin','Content-Type']) @@ -914,7 +923,10 @@ def container_ident_preservation_by_volume_svg(ident):      except Exception as ae:          app.log.error(ae)          abort(503) -    return preservation_by_volume_histogram(histogram).render_response() +    return preservation_by_volume_histogram( +        histogram, +        merge_shadows=Config.FATCAT_MERGE_SHADOW_PRESERVATION, +    ).render_response()  @app.route('/release/<ident>.bib', methods=['GET'])  def release_bibtex(ident): diff --git a/python/fatcat_web/search.py b/python/fatcat_web/search.py index b0d27b2e..7d9ce69f 100644 --- a/python/fatcat_web/search.py +++ b/python/fatcat_web/search.py @@ -402,6 +402,9 @@ def get_elastic_search_coverage(query: ReleaseQuery) -> dict:      for k in ('bright', 'dark', 'shadows_only', 'none'):          if not k in preservation_bucket:              preservation_bucket[k] = 0 +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        preservation_bucket['none'] += preservation_bucket['shadows_only'] +        preservation_bucket['shadows_only'] = 0      stats = {          'total': resp.hits.total,          'preservation': preservation_bucket, @@ -464,6 +467,9 @@ def get_elastic_container_stats(ident, issnl=None):      for k in ('bright', 'dark', 'shadows_only', 'none'):          if not k in preservation_bucket:              preservation_bucket[k] = 0 +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        preservation_bucket['none'] += preservation_bucket['shadows_only'] +        preservation_bucket['shadows_only'] = 0      release_type_bucket = agg_to_dict(resp.aggregations.release_type)      stats = {          'ident': ident, @@ -602,6 +608,10 @@ def get_elastic_preservation_by_year(query) -> List[dict]:          year_dicts[num] = dict(year=num, bright=0, dark=0, shadows_only=0, none=0)      for row in buckets:          year_dicts[int(row['key']['year'])][row['key']['preservation']] = int(row['doc_count']) +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        for k in year_dicts.keys(): +            year_dicts[k]['none'] += year_dicts[k]['shadows_only'] +            year_dicts[k]['shadows_only'] = 0      return sorted(year_dicts.values(), key=lambda x: x['year']) @@ -675,6 +685,10 @@ def get_elastic_preservation_by_date(query) -> List[dict]:          this_date = this_date + datetime.timedelta(days=1)      for row in buckets:          date_dicts[row['key']['date'][0:10]][row['key']['preservation']] = int(row['doc_count']) +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        for k in date_dicts.keys(): +            date_dicts[k]['none'] += date_dicts[k]['shadows_only'] +            date_dicts[k]['shadows_only'] = 0      return sorted(date_dicts.values(), key=lambda x: x['date'])  def get_elastic_container_preservation_by_volume(container_id: str) -> List[dict]: @@ -728,6 +742,10 @@ def get_elastic_container_preservation_by_volume(container_id: str) -> List[dict      for row in buckets:          if row['key']['volume'].isdigit():              volume_dicts[int(row['key']['volume'])][row['key']['preservation']] = int(row['doc_count']) +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        for k in volume_dicts.keys(): +            volume_dicts[k]['none'] += volume_dicts[k]['shadows_only'] +            volume_dicts[k]['shadows_only'] = 0      return sorted(volume_dicts.values(), key=lambda x: x['volume'])  def get_elastic_preservation_by_type(query: ReleaseQuery) -> List[dict]: @@ -797,4 +815,8 @@ def get_elastic_preservation_by_type(query: ReleaseQuery) -> List[dict]:      for k in type_set:          for p in ('bright', 'dark', 'shadows_only', 'none'):              type_dicts[k]['total'] += type_dicts[k][p] +    if app.config['FATCAT_MERGE_SHADOW_PRESERVATION']: +        for k in type_set: +            type_dicts[k]['none'] += type_dicts[k]['shadows_only'] +            type_dicts[k]['shadows_only'] = 0      return sorted(type_dicts.values(), key=lambda x: x['total'], reverse=True) diff --git a/python/fatcat_web/templates/entity_macros.html b/python/fatcat_web/templates/entity_macros.html index c3ae099a..718c071c 100644 --- a/python/fatcat_web/templates/entity_macros.html +++ b/python/fatcat_web/templates/entity_macros.html @@ -265,7 +265,6 @@ yellow    {% set frac_bright = stats.bright/stats.total %}    {% set frac_dark = stats.dark/stats.total %} -  {% set frac_shadows_only = stats.shadows_only/stats.total %}    {% set frac_none = stats.none/stats.total %}    <div class="ui {{ extra_class }} multiple progress" data-percent="0,0,0,0" style="margin-bottom: 0.1em;"> @@ -275,9 +274,12 @@ yellow      <div class="green bar" style="border-radius: 0; min-width: 0; width: {{ (frac_dark*100)|round(method='ceil') }}%; background-color: darkgreen;" title="dark">        <div class="progress">{# {{ (frac_dark*100)|int }}% #}</div>      </div> +    {% if stats.shadows_only %} +  {% set frac_shadows_only = stats.shadows_only/stats.total %}      <div class="red bar" style="border-radius: 0; min-width: 0; width: {{ (frac_shadows_only*100)|round(method='ceil') }}%; background-color: darkred;" title="shadows only">        <div class="progress">{# {{ (frac_shadows_only*100)|int }}% #}</div>      </div> +    {% endif %}      <div class="red bar" style="border-radius: 0; min-width: 0; width: {{ (frac_none*100)|round(method='ceil') }}%;" title="no preservation">        <div class="progress">{# {{ (frac_none*100)|int }}% #}</div>      </div> @@ -290,7 +292,6 @@ yellow    {% set frac_bright = stats.bright/stats.total %}    {% set frac_dark = stats.dark/stats.total %} -  {% set frac_shadows_only = stats.shadows_only/stats.total %}    {% set frac_none = stats.none/stats.total %}    <table class="ui very basic very compact collapsing table" style="font-weight: bold; margin-left: 1em;"> @@ -305,11 +306,14 @@ yellow          <td class="right aligned" >{{ "{:,}".format(stats.dark) }}          <td class="right aligned" >{{ (frac_dark*100)|round(2,method='ceil') }}%          <td>preserved but not publicly accessible (dark) +      {% if stats.shadows_only %} +      {% set frac_shadows_only = stats.shadows_only/stats.total %}        <tr>          <td style="background-color: darkred;">          <td class="right aligned" >{{ "{:,}".format(stats.shadows_only) }}          <td class="right aligned" >{{ (frac_shadows_only*100)|round(2,method='ceil') }}%          <td>only independently preserved in "shadow" libraries +      {% endif %}        <tr>          <td style="background-color: #db2828;">          <td class="right aligned" >{{ "{:,}".format(stats.none) }} @@ -324,7 +328,6 @@ yellow    {% set frac_bright = stats.bright/stats.total %}    {% set frac_dark = stats.dark/stats.total %} -  {% set frac_shadows_only = stats.shadows_only/stats.total %}    {% set frac_none = stats.none/stats.total %}    <table class="ui very basic very compact collapsing table"> @@ -337,10 +340,13 @@ yellow          <td style="background-color: darkgreen;">          <td class="right aligned" >{{ "{:,}".format(stats.dark) }}          <td>preserved, inaccessible (dark) +      {% if stats.shadows_only %} +      {% set frac_shadows_only = stats.shadows_only/stats.total %}        <tr>          <td style="background-color: darkred;">          <td class="right aligned" >{{ "{:,}".format(stats.shadows_only) }}          <td>shadow library only +      {% endif %}        <tr>          <td style="background-color: #db2828;">          <td class="right aligned" >{{ "{:,}".format(stats.none) }} diff --git a/python/fatcat_web/web_config.py b/python/fatcat_web/web_config.py index 344f1c2a..22a704d9 100644 --- a/python/fatcat_web/web_config.py +++ b/python/fatcat_web/web_config.py @@ -52,6 +52,9 @@ class Config(object):      IA_XAUTH_CLIENT_ID = os.environ.get("IA_XAUTH_CLIENT_ID", default=None)      IA_XAUTH_CLIENT_SECRET = os.environ.get("IA_XAUTH_CLIENT_SECRET", default=None) +    # controls granularity of "shadow_only" preservation category +    FATCAT_MERGE_SHADOW_PRESERVATION = os.environ.get("FATCAT_MERGE_SHADOW_PRESERVATION", default=False) +      # CSRF on by default, but only for WTF forms (not, eg, search, lookups, GET      # forms)      WTF_CSRF_CHECK_DEFAULT = False  | 
