diff --git a/app/javascript/application.js b/app/javascript/application.js index b839039d..1320946e 100644 --- a/app/javascript/application.js +++ b/app/javascript/application.js @@ -51,6 +51,7 @@ import ToggleClasses from './elements/toggle_classes' import AutosizeField from './elements/autosize_field' import GoogleDriveFilePicker from './elements/google_drive_file_picker' import OpenModal from './elements/open_modal' +import BarChart from './elements/bar_chart' import * as TurboInstantClick from './lib/turbo_instant_click' @@ -140,6 +141,7 @@ safeRegisterElement('toggle-classes', ToggleClasses) safeRegisterElement('autosize-field', AutosizeField) safeRegisterElement('google-drive-file-picker', GoogleDriveFilePicker) safeRegisterElement('open-modal', OpenModal) +safeRegisterElement('bar-chart', BarChart) safeRegisterElement('template-builder', class extends HTMLElement { connectedCallback () { diff --git a/app/javascript/elements/bar_chart.js b/app/javascript/elements/bar_chart.js new file mode 100644 index 00000000..32fdfa0f --- /dev/null +++ b/app/javascript/elements/bar_chart.js @@ -0,0 +1,50 @@ +export default class extends HTMLElement { + connectedCallback () { + this.chartLabels = JSON.parse(this.dataset.labels || '[]') + this.chartDatasets = JSON.parse(this.dataset.datasets || '[]') + + this.initChart() + } + + disconnectedCallback () { + if (this.chartInstance) { + this.chartInstance.destroy() + this.chartInstance = null + } + } + + async initChart () { + const { default: Chart } = await import(/* webpackChunkName: "chartjs" */ 'chart.js/auto') + + const canvas = this.querySelector('canvas') + + const ctx = canvas.getContext('2d') + + this.chartInstance = new Chart(ctx, { + type: 'bar', + data: { + labels: this.chartLabels, + datasets: this.chartDatasets + }, + options: { + responsive: true, + maintainAspectRatio: true, + animation: false, + scales: { + y: { + beginAtZero: true, + grace: '20%', + ticks: { + precision: 0 + } + } + }, + plugins: { + legend: { + display: false + } + } + } + }) + } +} diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml index b823f6d1..b9784c04 100644 --- a/config/locales/i18n.yml +++ b/config/locales/i18n.yml @@ -844,6 +844,23 @@ en: &en tablet: Tablet reset_default: Reset default send_signature_request_email: Send signature request email + last_3_months: Last 3 months + last_6_months: Last 6 months + last_year: Last year + all_time: All time + everyone: Everyone + daily: Daily + weekly: Weekly + monthly: Monthly + api: API + embed: Embed + bulk: Bulk + invite: Invite + api_and_embed: API and Embed + period: Period + reports: Reports + completed_submissions: Completed submissions + sms: SMS submission_sources: api: API bulk: Bulk Send @@ -955,6 +972,7 @@ es: &es or_add_from: O agregar desde upload_a_new_document: Subir nuevo documento use_direct_file_attachment_links_in_the_documents: Usar enlaces directos de archivos adjuntos en los documentos + click_here_to_send_a_reset_password_email_html: ' para enviar un correo electrónico de restablecimiento de contraseña.' enabled: Habilitado disabled: Deshabilitado expirable_file_download_links: Enlaces de descarga de archivos con vencimiento @@ -1596,6 +1614,7 @@ es: &es image_field: Campo de Imagen file_field: Campo de Archivo select_field: Campo de Selección + checkbox_field: Campo de Casilla multiple_field: Campo Múltiple radio_field: Campo de Grupo Radio cells_field: Campo de Celdas @@ -1772,6 +1791,23 @@ es: &es tablet: Tableta reset_default: Restablecer por defecto send_signature_request_email: Enviar correo de solicitud de firma + last_3_months: Últimos 3 meses + last_6_months: Últimos 6 meses + last_year: Último año + all_time: Todo el tiempo + everyone: Todos + daily: Diario + weekly: Semanal + monthly: Mensual + api: API + embed: Integrar + bulk: Masivo + invite: Invitación + api_and_embed: API e Integrar + period: Período + reports: Informes + completed_submissions: Envíos completados + sms: SMS submission_sources: api: API bulk: Envío masivo @@ -1912,6 +1948,7 @@ it: &it edit_per_party: Modifica per partito signed: Firmato reply_to: Rispondi a + partially_completed: Parzialmente completato pending_by_me: In sospeso da me add: Aggiungi adding: Aggiungendo @@ -2357,6 +2394,7 @@ it: &it upload_signature: Carica firma integration: Integrazione admin: Amministratore + tenant_admin: Amministratore tenant editor: Editor viewer: Visualizzatore member: Membro @@ -2701,6 +2739,23 @@ it: &it tablet: Tablet reset_default: Reimposta predefinito send_signature_request_email: Invia email di richiesta firma + last_3_months: Ultimi 3 mesi + last_6_months: Ultimi 6 mesi + last_year: Ultimo anno + all_time: Tutto il tempo + everyone: Tutti + daily: Giornaliero + weekly: Settimanale + monthly: Mensile + api: API + embed: Incorporare + bulk: Massivo + invite: Invito + api_and_embed: API e Incorporare + period: Periodo + reports: Rapporti + completed_submissions: Invii completati + sms: SMS submission_sources: api: API bulk: Invio massivo @@ -3627,6 +3682,24 @@ fr: &fr tablet: Tablette reset_default: Réinitialiser par défaut send_signature_request_email: Envoyer un e-mail de demande de signature + last_month: Mois dernier + last_3_months: 3 derniers mois + last_6_months: 6 derniers mois + last_year: Année dernière + all_time: Tout le temps + everyone: Tout le monde + daily: Quotidien + weekly: Hebdomadaire + monthly: Mensuel + api: API + embed: Intégrer + bulk: En masse + invite: Invitation + api_and_embed: API et Intégrer + period: Période + reports: Rapports + completed_submissions: Soumissions terminées + sms: SMS submission_sources: api: API bulk: Envoi en masse @@ -4557,6 +4630,23 @@ pt: &pt tablet: Tablet reset_default: Redefinir para padrão send_signature_request_email: Enviar e-mail de solicitação de assinatura + last_3_months: Últimos 3 meses + last_6_months: Últimos 6 meses + last_year: Último ano + all_time: Todo o tempo + everyone: Todos + daily: Diário + weekly: Semanal + monthly: Mensal + api: API + embed: Incorporar + bulk: Em massa + invite: Convite + api_and_embed: API e Incorporar + period: Período + reports: Relatórios + completed_submissions: Envios concluídos + sms: SMS submission_sources: api: API bulk: Envio em massa @@ -5487,6 +5577,23 @@ de: &de tablet: Tablet reset_default: Standard zurücksetzen send_signature_request_email: Signaturanfrage-E-Mail senden + last_3_months: Letzte 3 Monate + last_6_months: Letzte 6 Monate + last_year: Letztes Jahr + all_time: Gesamte Zeit + everyone: Alle + daily: Täglich + weekly: Wöchentlich + monthly: Monatlich + api: API + embed: Einbetten + bulk: Massenversand + invite: Einladung + api_and_embed: API und Einbetten + period: Zeitraum + reports: Berichte + completed_submissions: Abgeschlossene Übermittlungen + sms: SMS submission_sources: api: API bulk: Massenversand @@ -6778,6 +6885,23 @@ nl: &nl tablet: Tablet reset_default: Standaard herstellen send_signature_request_email: E-mail met handtekeningaanvraag verzenden + last_3_months: Afgelopen 3 maanden + last_6_months: Afgelopen 6 maanden + last_year: Afgelopen jaar + all_time: Altijd + everyone: Iedereen + daily: Dagelijks + weekly: Wekelijks + monthly: Maandelijks + api: API + embed: Insluiten + bulk: Bulk + invite: Uitnodiging + api_and_embed: API en Insluiten + period: Periode + reports: Rapporten + completed_submissions: Voltooide inzendingen + sms: SMS submission_sources: api: API bulk: Bulkverzending diff --git a/package.json b/package.json index 4b664b19..af04328b 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "babel-plugin-dynamic-import-node": "^2.3.3", "babel-plugin-macros": "^3.1.0", "canvas-confetti": "^1.6.0", + "chart.js": "^4.5.1", "codemirror": "^6.0.2", "compression-webpack-plugin": "10.0.0", "css-loader": "^6.7.3", diff --git a/yarn.lock b/yarn.lock index 2faf9648..4b3b5bf0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1355,6 +1355,11 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@kurkle/color@^0.3.0": + version "0.3.4" + resolved "https://registry.yarnpkg.com/@kurkle/color/-/color-0.3.4.tgz#4d4ff677e1609214fc71c580125ddddd86abcabf" + integrity sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w== + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -2341,6 +2346,13 @@ chalk@^4.0, chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chart.js@^4.5.1: + version "4.5.1" + resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-4.5.1.tgz#19dd1a9a386a3f6397691672231cb5fc9c052c35" + integrity sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw== + dependencies: + "@kurkle/color" "^0.3.0" + "chokidar@>=3.0.0 <4.0.0", chokidar@^3.5.3: version "3.5.3" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"