Page Templates - Observatory

The demographic observatory

Analytic view with KPIs and charts

<div class="observatory" ng-init="values.modalswitchstatus = false">
    <div class="backdrop"
         ng-click="values.modalswitchstatus = !values.modalswitchstatus"
         ng-class="{'backdrop-active':values.modalswitchstatus}">
    </div>

    <div class="container">
        <ods-dataset-context context="ctx1,ctx2,ctx3"
                             ctx1-dataset="buildingref-france-bpe-all-geolocated"
                             ctx1-parameters="{'disjunctive.epci_name':true}"
                             ctx1-domain="public"
                             ctx2-dataset="buildingref-france-bpe-all-geolocated"
                             ctx2-parameters="{'disjunctive.epci_name':true,'refine.category':'Services aux particuliers'}"
                             ctx2-domain="public"
                             ctx3-dataset="buildingref-france-bpe-all-geolocated"
                             ctx3-parameters="{'disjunctive.epci_name':true,'refine.category':'Santé'}"
                             ctx3-domain="public">

            <!-- Analyses -->
            <span ods-aggregation="agg"
                  ods-aggregation-context="ctx1"
                  ods-aggregation-function="COUNT">
          {{ values.nbequip = agg ; '' }}
        </span>
            <span ods-aggregation="services"
                  ods-aggregation-context="ctx2"
                  ods-aggregation-function="COUNT">
          {{ values.services = services ; '' }}
        </span>
            <span ods-aggregation="sante"
                  ods-aggregation-context="ctx3"
                  ods-aggregation-function="COUNT">
          {{ values.sante = sante ; '' }}
        </span>


            <!-- THE RIGHT MODAL -->
            <div class="rightmodal">
                <div class="cl-modal"
                     ng-class="{'cl-modal-active':values.modalswitchstatus}">
                    <div class="cl-modal__rightside">
                        <div class="cl-modal__header"
                             ng-click="values.modalswitchstatus = !values.modalswitchstatus">
                            <a href="#"
                               class="closebtn">
                                Fermer <i class="fa fa-times-circle" aria-hidden="true"></i>
                            </a>
                        </div>
                        <div class="cl-modal__content">
                            <ods-facets context="ctx1">
                                <h3>
                                    Région
                                </h3>
                                <ods-facet name="reg_name" refine-also="[ctx2,ctx3]"></ods-facet>
                                <h3>
                                    Département
                                </h3>
                                <ods-facet name="dep_name" refine-also="[ctx2,ctx3]"></ods-facet>
                                <h3>
                                    Code DROM
                                </h3>
                                <ods-facet name="com_arm_area_code" refine-also="[ctx2,ctx3]"></ods-facet>
                                <h3>
                                    EPCI
                                </h3>
                                <ods-facet name="epci_name" refine-also="[ctx2,ctx3]"></ods-facet>
                            </ods-facets>
                        </div>
                        <div class="cl-modal__footer">
                            <div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="level">
                <div class="level-left">
                    <h1 class="titre">
                        Un modèle d'observation des équipements en France
                    </h1>
                    <div class="edito">
                        <p>Bien que ... <q>Il n'y a pas de modèle pour qui cherche ce qu'il n'a jamais vu.</q> Paul
                            Éluard
                        </p>
                    </div>
                </div>
                <div class="level-right">
                    <button ng-click="values.modalswitchstatus = !values.modalswitchstatus">
                        <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
                             stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
                             class="feather feather-filter">
                            <polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
                        </svg>
                        Filtrer les données
                    </button>
                </div>
            </div>

            <div id="resume">
                <p>
                    L'objectif de la Base Permanente des Équipements (BPE) est de proposer annuellement une base
                    d'équipements géolocalisés construite à partir de sources administratives diverses.
                </p>
                <p>
                    La classification des équipements en gammes a pour objectif de réunir des équipements qui présentent
                    des logiques d'implantation voisines, en ce sens qu'ils sont fréquemment présents dans les mêmes
                    communes. Ces regroupements permettent d'élaborer des indicateurs synthétiques reflétant
                    l'organisation hiérarchisée des territoires en termes de services à la population.
                </p>
                <p>
                    Les gammes d’équipements sont actualisées chaque année pour une nouvelle version de la Base
                    Permanente des Équipements. En effet, d’une part de nouveaux équipements peuvent être introduits
                    dans la base et, d’autre part, l’implantation des équipements dans les communes peut être modifiée,
                    tout cela pouvant avoir des conséquences sur la composition des gammes.
                </p>
            </div>

            <ods-filter-summary context="ctx1">
                {{ refinements }}
            </ods-filter-summary>

            <div class="row">
                <div class="box col-md-6">
                    <div class="grey-box half-box">
                        <h2 class="title">
                            Nombre d'équipements en 2019
                        </h2>
                        <h3 class="description">
                            Données INSEE issu de la BPE (Base permanente des équipements)
                        </h3>
                        <p class="kpi">
                            {{ values.nbequip | number }}
                        </p>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
                <div ng-if="!ctx1.parameters['refine.reg_name']"
                     class="box col-md-6">
                    <div class="grey-box half-box">
                        <h2 class="title">
                            Top 5 Région
                        </h2>
                        <h3 class="description">
                            Nombre d'équipements des 5 régions les mieux équipées
                        </h3>
                        <ods-chart single-y-axis="true" scientific-display="true" display-legend="false"
                                   labels-x-length="20" align-month="false">
                            <ods-chart-query context="ctx1" field-x="reg_name" maxpoints="5" sort="serie1-1">
                                <ods-chart-serie chart-type="bar" function-y="COUNT" color="#000000"
                                                 scientific-display="true">
                                </ods-chart-serie>
                            </ods-chart-query>
                        </ods-chart>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
                <div ng-if="ctx1.parameters['refine.reg_name']"
                     class="box col-md-6">
                    <div class="grey-box half-box">
                        <h2 class="title">
                            Top 5 Département
                        </h2>
                        <h3 class="description">
                            Nombre d'équipements des 5 départements les mieux équipées
                        </h3>
                        <ods-chart single-y-axis="true" scientific-display="true" display-legend="false"
                                   labels-x-length="20" align-month="false">
                            <ods-chart-query context="ctx1" field-x="dep_name" maxpoints="5" sort="serie1-1">
                                <ods-chart-serie chart-type="bar" function-y="COUNT" color="#000000"
                                                 scientific-display="true">
                                </ods-chart-serie>
                            </ods-chart-query>
                        </ods-chart>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="box col-md-12">
                    <div class="grey-box">
                        <h2 class="title">
                            Répartis en grandes catégories
                        </h2>
                        <h3 class="description">
                            La Base Permanente des Équipements est réparti en 7 grands domaines : services aux
                            particuliers ; commerces ; enseignement ; santé ; transports et déplacements ; sports,
                            loisirs et culture ; tourisme.
                        </h3>
                        <ods-chart labels-x-length="30" align-month="true">
                            <ods-chart-query context="ctx1" field-x="category" maxpoints="0" sort="serie1-1"
                                             category-colors="{'Services aux particuliers':'#D8D8DD','Santé':'#D1F1FF','Commerces':'#CCEFC2','Sports, loisirs et culture':'#E5E2A7','Enseignement':'#E9D9FF','Transports et déplacements':'#FFFFFF','Tourisme':'#F4C5C8'}">
                                <ods-chart-serie chart-type="treemap" function-y="COUNT" color="range-PiYG"
                                                 scientific-display="false">
                                </ods-chart-serie>
                            </ods-chart-query>
                        </ods-chart>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>

            <h2>
                Observons ses deux principales catégories
            </h2>
            <div class="row">
                <div class="box col-md-6">
                    <div class="grey-box half-box colored services">
                        <h2 class="title">
                            Les Services aux particuliers
                        </h2>
                        <h3 class="description">
                            qui représentent
                        </h3>
                        <p class="kpi">
                            {{ (values.services / values.nbequip * 100) | number : 1 }} %
                        </p>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
                <div class="box col-md-6">
                    <div class="grey-box half-box colored sante">
                        <h2 class="title">
                            et la Santé
                        </h2>
                        <h3 class="description">
                            qui représente
                        </h3>
                        <p class="kpi">
                            {{ (values.sante / values.nbequip * 100) | number : 1 }} %
                        </p>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>
            <div class="row">
                <div class="box col-md-6">
                    <div class="grey-box colored services">
                        <h2 class="title">
                            Principaux équipement de services aux particuliers
                        </h2>
                        <h3 class="description">
                            Description du TOP 20 de cette catégorie
                        </h3>
                        <ods-chart labels-x-length="40" align-month="true">
                            <ods-chart-query context="ctx2" field-x="equipment_name" maxpoints="20" sort="serie1-1">
                                <ods-chart-serie chart-type="bar" function-y="COUNT" color="#D8D8DD"
                                                 scientific-display="true" label-y="Nb. équipements">
                                </ods-chart-serie>
                            </ods-chart-query>
                        </ods-chart>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
                <div class="box col-md-6">
                    <div class="grey-box colored sante">
                        <h2 class="title">
                            Principaux équipements de Santé
                        </h2>
                        <h3 class="description">
                            Description du TOP 20 de cette catégorie
                        </h3>
                        <ods-chart labels-x-length="40" align-month="true">
                            <ods-chart-query context="ctx3" field-x="equipment_name" maxpoints="20" sort="serie1-1">
                                <ods-chart-serie chart-type="bar" function-y="COUNT" color="#D1F1FF"
                                                 scientific-display="true" label-y="Nb. équipements">
                                </ods-chart-serie>
                            </ods-chart-query>
                        </ods-chart>
                        <div class="kpi-footer">
                            <span class="kpi-footer-date">{{ ctx1.dataset.metas.data_processed | date }}</span>
                            <a href="{{ 'https://' + ctx1.dataset.metas.domain + '.opendatasoft.com/explore/dataset/' + ctx1.dataset.datasetid }}"
                               title="{{ ctx1.dataset.metas.title }}"
                               class="kpi-footer-source">Source <i class="fa fa-long-arrow-right"
                                                                   aria-hidden="true"></i>
                            </a>
                        </div>
                    </div>
                </div>
            </div>

        </ods-dataset-context>

    </div>
</div>
:root {
    /* change values by the size of the header & the footer to make the modal fit your page properly */
    --header-size: 20px;
    --footer-size: 20px;
    --modal-margin: calc(var(--header-size) + var(--footer-size));
}

/* ALL PAGE CONTAINER */
.observatory {
    background-color: #F6F8FB !important;
    /* prerequisite for full height modal bar */
    position: relative;
    /* prevent the page to be shrinked if the content is less than the browser height, force a minimal height */
    min-height: calc(100vh - var(--modal-margin));
}

.level {
    margin: 70px 0 40px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
button {
    background-color: black;
    color: white;
    line-height: 36px;
    padding: 0 13px;
    border-radius: 100000px;
    font-size: 1.1em;
    border: 1px solid #142e7b;
    display: flex;
    align-items: center;
    min-width: max-content;
}
button svg {
    margin-right: 6px;
}
button:hover {
    opacity: 0.65;
}
.level button {
    margin-top: 13px;
}
@media screen and (min-width: 768px) {
    .level {
        justify-content: space-between;
        flex-direction: row;
    }
    .level button {
        margin-top: 0;
    }
}


h1 .smaller {
    font-size: 0.5em;
}
h2 .smaller {
    font-size: 0.8em;
}
.ods-box {
    border-radius: 0px;
}
.titre {
    font-size: 37px;
    margin: 26px 0 6px;
}
.edito {
    margin: 0;
    font-size: 19px;
}
.edito q {
    font-style: italic;
}
#resume {
    text-align: justify;
    font-size: 1.1em;
    line-height: 1.8em;
}

.row ~ h2 {
    font-size: 2em;
    margin: 26px 0;
}
/* BOX */
.box {
    padding-left: 12.5px;
    padding-right: 12.5px;
}
.grey-box {
    position: relative;
    background: white;
    border-radius: 6px;
    padding: 20px;
    margin-bottom: 25px;
    height: 453px;
}
.grey-box.half-box {
    height: 213.5px;
}
.grey-box.colored:before {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 9px;
    content: '';
}
.grey-box.colored.services:before {
    background-color: #D8D8DD;
}
.grey-box.colored.sante:before {
    background-color: #D1F1FF;
}



/* BOX CONTENT */
.title {
    font-size: 1.2em;
    margin: 0 auto 6px;
}
.description {
    margin: 0 auto;
    color: #565656;
    font-size: 1em;
    font-weight: 400;
}
.kpi {
    color: black;
    font-size: 2.2em;
    margin-top: 35px;
    font-weight: 500;
    text-align: center;
}
.kpi-footer {
    font-size: 0.8em;
}
.kpi-footer-date {
    position: absolute;
    bottom: 6px;
    left: 13px;
}
a.kpi-footer-source {
    position: absolute;
    bottom: 6px;
    right: 13px;
    color: black;
    text-decoration: underline;
}
a.kpi-footer-source {
    color: blue;
}
a.kpi-footer-source:hover {
    opacity: 0.65;
}
/* BOX Title Line */
h2.grey-box {
    height: 70px;
    font-size: 1.3em;
    display: flex;
    align-items: center;
}
/* CHARTS */
.ods-chart {
    min-height: inherit;
}
.grey-box .ods-chart {
    height: 350px;
}
.grey-box.half-box .ods-chart {
    height: 130px;
}
.odswidget-charts {
    margin-top: 10px;
}
.odswidget-table {
    height: 338px;
    margin-top: 10px;
}
rect.highcharts-background {
    fill: transparent !important;
}





/** FILTER SUMMARY */
ul.odswidget.odswidget-filter-summary {
    font-size: 1.2em;
    margin: 15px 0;
    position: relative;
}
@media (min-width: 420px) {
    ul.odswidget.odswidget-filter-summary {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
    }
}
li.odswidget-filter-summary__active-filter:first-child {
    margin-left: 110px;
}
li.odswidget-filter-summary__active-filter:first-child:before {
    content: 'Filtres actifs: ';
    font-weight: 600;
    line-height: 1.8em;
    position: absolute;
    left: 0;
}

li.odswidget-filter-summary__active-filter,
li.odswidget-filter-summary__clear-all {
    border-radius: 3px;
    margin: 2px 4px;
    padding: 0;
}
li.odswidget-filter-summary__active-filter {
    background-color: #f3f3f3;
}
li.odswidget-filter-summary__active-filter-label {
    font-size: 1rem;
}
a.odswidget-filter-summary__active-filter-link,
a.odswidget-clear-all-filters {
    border-left: none;
    margin: 0;
    padding: 2px 4px 2px 2px;
    display: flex;
    align-items: center;
}
a.odswidget-clear-all-filters {
    align-items: center;
}
a.odswidget-clear-all-filters i {
    margin-right: 3px;
}



/* BACKDROP (black screen when modal active) */
.backdrop {
    visibility: hidden;
    opacity: 0;
    position: absolute;
    height: 100%;
    width: 100%;
    z-index: 900;
    background-color: #000;
    cursor: default;
    -webkit-transition: visibility .5s,opacity .5s;
    transition: visibility .5s,opacity .5s;
}
.backdrop-active {
    visibility: visible;
    opacity: .6; /* make a more or less darker backdrop, 1:totally dark, 0:totally transparent (invisibile) */
}
/* MODAL */
/* The modal is composed of 2 parts:
the leftside, that is the banner that is always visible, and contains an icon on top to click and actiavte the modal
the right side, that contains filters, searchbar, charts etc... that is not visible, activated on demand
the modal default size (width) is 57px, it correspond to the leftside width */
.cl-modal {
    display: flex;
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 0;
    background-color: white;
    z-index: 1000;
    overflow: hidden; /* Disable horizontal scroll */
    transition: ease-in 0.3s;
}
.cl-modal-active {
    width: 400px; /* size of the modal when active */
}
/* specific because charts are loaded inside */
.cl-modal__content {
    width: 400px;
}
@media (max-width: 420px) {
    .cl-modal-active {
        width: 100%;
    }
    .cl-modal__content {
        width: 100vw;
    }
}

/* SHOW/HIDE SIDE */
.cl-modal__rightside {
    display: flex;
    flex-direction: column;
    border-left: solid 1px lightgrey;
}
.cl-modal__header,
.cl-modal__footer {
    min-height: 35px;
    background-color: white;
    padding: 0 10px;
    display: flex;
    align-items: center;
    justify-content: start;
    opacity: 0;
    transition: opacity 0s;
}
.cl-modal-active .cl-modal__header, .cl-modal-active .cl-modal__footer {
    opacity: 1;
    transition-delay: 0.3s;
}
/* CONTENT OF THE MODAL */
/* HEADER / UPPER PART */
.cl-modal__header {
    border-bottom: 1px solid lightgrey;
}
/* FOOTER / LOWER PART (optionnal) */
.cl-modal__footer {
    border-top: 1px solid lightgrey;
}
/* THEN THE MIDDLE / CONTENT */
.cl-modal__content {
    height: 100%;
    overflow-y: auto;
    padding: 25px;
    opacity: 0;
    transition: opacity 0s;
}
/* WARNING ! This part is very important : it renders the content only after the end of the openning of the modal
ie. when the modal is resized, nothing is visible, after 0.3s of resizing, it's displays the content
this trick is very important to avoid the browser the resize all the content during the modal opening */
.cl-modal-active .cl-modal__content {
    opacity: 1;
    transition-delay: 0.3s;
}