From c495a1257c7e22a45644920d56e2ea23c8d92f9d Mon Sep 17 00:00:00 2001 From: Sukma Gladys Date: Tue, 5 Nov 2024 20:42:12 +0700 Subject: [PATCH] feat: add print to pdf feature --- .../src/drizzle/seeds/questionSeeder.ts | 1187 ++++++++++++++++- apps/frontend/package.json | 1 + apps/frontend/src/routeTree.gen.ts | 194 ++- .../assessmentResult/index.lazy.tsx | 279 ++-- apps/frontend/src/types/html2pdf.d.ts | 1 + pnpm-lock.yaml | 162 +++ 6 files changed, 1695 insertions(+), 129 deletions(-) create mode 100644 apps/frontend/src/types/html2pdf.d.ts diff --git a/apps/backend/src/drizzle/seeds/questionSeeder.ts b/apps/backend/src/drizzle/seeds/questionSeeder.ts index ab91f6d..749261d 100644 --- a/apps/backend/src/drizzle/seeds/questionSeeder.ts +++ b/apps/backend/src/drizzle/seeds/questionSeeder.ts @@ -8,7 +8,7 @@ const questionSeeder = async () => { { question: "Apakah organisasi Anda membuat program pemahaman kesadaran keamanan informasi untuk semua karyawan secara berkala (setidaknya setiap tahun sekali) dalam rangka memastikan mereka memahami serta menunjukkan behavior dan skill yang diperlukan untuk memastikan keamanan informasi di organisasi? Jika ada, apakah program kesadaran keamanan organisasi dilakukan secara berkelanjutan?", needFile: false, - subAspectName: "Kesadaran" + subAspectName: "Kesadaran", }, { question: "Apakah organisasi Anda memastikan bahwa terdapat program kesadaran keamanan informasi diperbarui secara berkala untuk mnyesuaikan terhadap teknologi terbaru, standar, dan persyaratan bisnis serta mengatasi adanya ancaman?", @@ -155,6 +155,1191 @@ const questionSeeder = async () => { needFile: false, subAspectName: "Kontrol" }, + { + question: "Apakah semua tanggungjawab keamanan informasi telah ditentukan dan dialokasi oleh organisasi sehingga terkoordinir dengan baik?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah manajemen organisasi mewajibkan semua karyawan dan kontraktor untuk menerapkan keamanan informasi sesuai dengan kebijakan yang ditetapkan dan prosedur organisasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi telah membuat persyaratan keamanan informasi terkait akses supplier terhadap aset organisasi dan telah didokumentasikan dengan baik?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah dilakukan pengujian terhadap keberadaan informasi yang dapat berguna bagi penyerang seperti network diagram, file konfigurasi, laporan uji penetrasi, email atau dokumen yang berisi kata sandi atau informasi lain yang penting untuk sistem operasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda menetapkan program untuk vulnerability assessment atau penetrating testing secara berkala kepada aplikasi web, aplikasi client-based, aplikasi mobile, wireless, server dan perangkat jaringan?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda membentuk Red Team dan Blue Team serta melakukan pengujian secara berkala dalam mengukur kesiapan organisasi untuk mengidentifikasi dan menghentikan serangan atau merespon dengan cepat dan efektif dari insiden keamanan yang terjadi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda melakukan pemisahan environment antara sistem production dan development? Dan apakah organisasi mengizinkan akses kepada pengembang tanpa pengawasan dari bagian keamanan organisasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Untuk aplikasi yang mengandalkan database, apakah organisasi menggunakan standar hardening configuration template? Apakah dilakukan pengujian pada semua sistem (software) yang menjadi bagian penting dari proses bisnis organisasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda melindungi aplikasi web organisasi menggunakan firewall aplikasi web (WAFs)?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah firewall atau perlindungan yang sejenis berjalan di semua perangkat komputasi end user (PC/Laptop)?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah alamat IP internal di organisasi Anda dilindungi oleh NAT (Network Addresss Translation)?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Bagaimana penggunaan IDS/IPS di organisasi Anda?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi anda mengimplementasikan software anti virus dan anti malware secara terpusat dan selalu update terhadap perangkat endpoint?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi anda menggunakan DLP (Data Loss Prevention) atau NAC (Network Access Control) ?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda melaksanakan risk assessment terhadap keamanan informasi secara berkala?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda melakukan pencegahan, atau pengurangan terhadap dampak/efek yang tidak diinginkan dari risk maupun opportunities yang dimiliki organisasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda melakukan reviu secara berkala terhadap penerapan kontrol keamanan untuk meminimalisir risiko?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah risk register terkait keamanan informasi yang diperoleh berdasarkan probabilitas dan dampak yang disesuaikan dengan kriteria organisasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda menerapkan continual improvement terhadap keamanan informasi?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda mengimplementasikan kebijakan Domain-based Message Authentication Reporting and Conformance (DMARC) atau protokol otentikasi email untuk melindungi domain dari penggunaan yang tidak sah agar tidak digunakan dalam serangan penyusupan email bisnis, email phishing, penipuan email, email palsu dan aktivitas ancaman cyber lainnya?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah dilakukan filterisasi terhadap seluruh jenis file lampiran email?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah organisasi Anda sudah menerapkan metode sandbox terhadap seluruh lampiran email guna mencegah dan analisis keamanan lebih lanjut terhadap malicious behaviour?", + needFile: false, + subAspectName: "Kontrol" + }, + { + question: "Apakah seluruh peraturan perundang-undangan, peraturan, persyaratan kontrak, dan peraturan lainnya secara eksplisit diidentifikasi, didokumentasi, dan terus diperbaharui untuk setiap sistem informasi?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda mengukur kepatuhan pengguna terhadap Kebijakan Keamanan Informasi organisasi?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda menerapkan kontrol kriptografi sesuai dengan semua perjanjian, undang-undang, dan peraturan yang berlaku?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda telah menerapkan prosedur untuk memastikan kepatuhan terhadap peraturan perundang-undangan dan persyaratan kontrak yang berhubungan dengan hak kekayaan intelektual serta penggunaan produk perangkat lunak proprietary?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah seluruh dokumentasi yang dimiliki organisasi dilindungi dan dijaga agar tidak hilang, hancur, dipalsukan, diakses oleh pihak yang tidak sah sesuai dengan persyaratan perundang-undangan, peraturan, dan kontrak?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah terdapat Kebijakan Perlindungan Data stakeholder / klien / konsumen / pelanggan secara spesifik atau dokumen khusus yang termasuk dalam Kebijakan Keamanan Informasi?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah privasi dan perlindungan informasi pribadi telah dipastikan sesuai dengan persyaratan dalam undang-undang dan peraturan terkait lainnya yang berlaku?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah ada kebijakan atau prosedur mengenai pemberitahuan jika terjadi pelanggaran terhadap data pribadi dan apakah didokumentasikan?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah terdapat Business Continuity Plan dan Disaster Recovery Plan yang mencakup backup dan restoration dari data pribadi?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah ada orang yang ditunjuk secara khusus bertanggungjawab untuk pengembangan dan implementasi kebijakan dan prosedur perlindungan data pribadi?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda menyampaikan kebijakan data privasi kepada stakeholder / klien / konsumen / pelanggan Anda segera setelah terjalin kerjasama?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah ada kebijakan dan prosedur yang terdokumentasi terkait pemberitahuan dan keputusan stakeholder untuk memilih tidak membagikan data mereka?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda berkomunikasi dengan stakeholder / klien / konsumen / pelanggan Anda setidaknya setiap tahun terkait kebijakan data pribadi mereka yang Anda gunakan?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Dalam memberikan data stakeholder / klien / konsumen / pelanggan kepada pihak ketiga, apakah stakeholder / klien / konsumen / pelanggan Anda memiliki kewenangan untuk mengetahui mengenai distribusi data milik mereka?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah terdapat kegiatan penelusuran yang memastikan bahwa data stakeholder / klien / konsumen / pelanggan yang disimpan adalah data yang akurat?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah ada batasan berapa lama data stakeholder disimpan?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda melakukan analisis statis dan/atau dinamis untuk memverifikasi bahwa praktik secure coding benar-benar diterapkan pada software yang dikembangkan secara internal?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Dalam pengembangan software, apakah dilakukan verifikasi bahwa versi semua software yang diperoleh dari luar organisasi Anda masih didukung oleh pengembang atau dipertegas berdasarkan rekomendasi keamanan pengembang?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda melakukan risk analisis untuk keamanan TI terkait keamanan fisik dan sistem elektronik?", + needFile: false, + subAspectName: "Pemenuhan" + }, + { + question: "Apakah organisasi Anda memiliki kebijakan yang menetapkan sanksi yang dijatuhkan terhadap karyawan yang tidak patuh pada kebijakan yang berkaitan dengan keamanan siber?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah organisasi Anda memiliki kebijakan keamanan informasi yang telah disetujui manajemen? Jika ada, apakah kebijakan tersebut telah dipublikasi dan dikomunikasikan kepada karyawan dan pihak eksternal yang terkait?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah kebijakan keamanan informasi dan hasil evaluasi pelaksanaan kebijakan keamanan informasi dijadikan acuan oleh pimpinan dalam menentukan strategi organisasi?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah kebijakan keamanan informasi mengatur mengenai single ID yang unik untuk melakukan semua otentikasi?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah ada kebijakan yang mengatur semua akun di organisasi Anda memiliki tenggat waktu kadaluarsa?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah kebijakan terminasi diterapkan dengan masa tenggang yang diizinkan terkait hak akses karyawan ke dalam sistem informasi?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah terdapat kebijakan yang mengakomodir laporan karyawan / pelanggan / stakeholder terkait kehilangan perangkat laptop/smartphone yang kemungkinan dapat digunakan sebagai kegiatan penipuan/kejahatan?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah organisasi Anda memiliki kebijakan metode penghapusan data?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah organisasi Anda memiliki dokumen BCP dan DRP?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah organisasi Anda menetapkan proses untuk menerima dan menangani laporan kerentanan software, termasuk menyediakan sarana bagi entitas eksternal untuk menghubungi bagian keamanan organisasi Anda?", + needFile: false, + subAspectName: "Kebijakan" + }, + { + question: "Apakah kebijakan dan prosedur keamanan informasi dikembangkan sesuai dengan kerangka kerja dan standar yang diakui (ISO 27001, PCI-DSS, HIPAA, NIST, CIS, SANS, dll.)?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah keamanan informasi termasuk dalam fase perencanaan, pembangunan, dan pengembangan di semua proyek TI?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda menerapkan praktik secure coding yang sesuai dengan bahasa pemrograman dan development environment yang digunakan?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Dalam pengembangan software secara mandiri, apakah organisasi memastikan bahwa pengecekan kesalahan secara eksplisit dilakukan dan didokumentasikan untuk semua input, termasuk ukuran, tipe data, dan rentang atau format yang diterapkan?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah source code yang dibuat secara mandiri dilakukan reviu kerentanannya terlebih dahulu sebelum masuk ke production?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda dalam pengembangan software oleh organisasi, melakukan kerjasama dengan pihak ketiga yang tepercaya?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda menghimpun dan menjaga informasi dari pihak ketiga yang akan digunakan untuk melaporkan insiden keamanan, seperti penegakan hukum, departemen pemerintah terkait, vendor, dan mitra ISAC?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda melakukan penetrating testing menggunakan pihak eksternal dan internal secara berkala?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda melakukan threat hunting secara berkala?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah ada proses formal untuk manajemen terhadap perubahan dan pengujian semua perubahan konfigurasi router, switch, dan firewall?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah konfigurasi firewall terdokumentasi dengan baik dan dilakukan reviu terhadap konfigurasi router dan switch minimal setiap 6 bulan?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah switch dan router startup configs selalu disinkronkan dengan running configs?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah konfigurasi dan akun default selalu diubah sebelum digunakan?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah ada prosedur untuk menambah / mengubah / menghapus hak akses ketika terjadi perpindahan karyawan?", + needFile: false, + subAspectName: "Proses" + }, + { + question: "Apakah organisasi Anda melakukan perencanaan kapasitas secara berkala untuk memastikan bahwa semua aset perangkat dan aplikasi sesuai dengan kebutuhan?", + needFile: false, + subAspectName: "Manajemen Aset" + }, + { + question: "Apakah organisasi Anda telah mendokumentasikan proses dan prosedur untuk manajemen patch semua aset perangkat dan aplikasi?", + needFile: false, + subAspectName: "Manajemen Aset" + }, + { + question: "Apakah organisasi Anda memiliki system configuration management tools untuk otomatisasi konfigurasi perangkat keras dan perangkat lunak?", + needFile: false, + subAspectName: "Manajemen Aset" + }, + { + question: "Apakah organisasi Anda menerapkan patch keamanan pada semua perangkat keras dan perangkat lunak saat ada update patch yang sudah dirilis?", + needFile: false, + subAspectName: "Manajemen Aset" + }, + { + question: "Apakah organisasi Anda melakukan inventarisasi data yang ada pada semua aset perangkat keras?", + needFile: false, + subAspectName: "Inventaris" + }, + { + question: "Apakah organisasi Anda melakukan inventarisasi data yang ada pada semua aset perangkat lunak?", + needFile: false, + subAspectName: "Inventaris" + }, + { + question: "Apakah aset yang diidentifikasi telah disusun berdasarkan klasifikasi kritikalitas (berdasarkan analisis risiko operasional, analisis bisnis, dan analisis strategis organisasi) serta telah ditetapkan penanggung jawab untuk setiap aset tersebut?", + needFile: false, + subAspectName: "Inventaris" + }, + { + question: "Apakah organisasi Anda mengidentifikasi dan membatasi akses perangkat yang tidak diizinkan oleh organisasi?", + needFile: false, + subAspectName: "Inventaris" + }, + { + question: "Apakah organisasi Anda melakukan klasifikasi informasi (rahasia, terbatas, umum) dan melakukan inventarisasi?", + needFile: false, + subAspectName: "Inventaris" + }, + { + question: "Apakah organisasi Anda melakukan analisa keterkaitan antara keamanan dan kenyamanan dari penggunaan aset perangkat dan aplikasi dalam rangka penyusunan standar keamanan informasi?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah terdapat kebijakan pembatasan penggunaan aset organisasi untuk kepentingan pribadi?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah karyawan diiizinkan memiliki akses sebagai administrator pada perangkat (laptop, personal computer, dll) milik organisasi?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah pihak ketiga diizinkan untuk menggunakan aset mereka pada jaringan organisasi Anda?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah ada dokumentasi mengenai alur informasi yang memproses data stakeholder / klien / konsumen / pelanggan termasuk yang dikelola oleh pihak ketiga?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah hal-hal yang berkaitan dengan pemrosesan data stakeholder / klien / konsumen / pelanggan dicatat, dimonitoring, dan dilaporkan secara berkala?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah ada kebijakan dan implementasi mengenai retensi data sensitif termasuk data stakeholder / klien / konsumen / pelanggan di organisasi Anda sesuai dengan kebijakan regulasi dan kebutuhan bisnis?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah data sensitif termasuk data stakeholder / klien / konsumen / pelanggan yang disimpan (secara elektronik dan hardcopy) memuat metadata informasi periode retensi, pemilik data, dan penggunaan data tersebut?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah organisasi Anda melakukan vulnerability scanning dan/atau penetration testing terhadap semua aset perangkat dan aplikasi?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah organisasi Anda menon-aktifkan aset perangkat dan aplikasi yang tidak diperlukan oleh organisasi? (contoh: port USB, DVD, akses smartphone, dll)", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah ada data otentikasi yang disimpan diperangkat browser end user? (contoh: username, password, PIN, dll)", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah dilakukan pemeringkatan pada kerentanan yang teridentifikasi berdasarkan pedoman / standar / acuan organisasi?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah ada risk register yang terdokumentasi untuk semua aplikasi yang memproses data stakeholder / klien / konsumen / pelanggan?", + needFile: false, + subAspectName: "Manajemen Risiko" + }, + { + question: "Apakah organisasi Anda memperbaharui roadmap keamanan TI organisasi dalam jangka waktu tertentu?", + needFile: false, + subAspectName: "Prioritas" + }, + { + question: "Apakah aspek keamanan menjadi pertimbangan dalam pengambilan keputusan TI?", + needFile: false, + subAspectName: "Prioritas" + }, + { + question: "Apakah organisasi Anda memiliki Business Impact Analysis terhadap perangkat dan aplikasi TI dan direviu secara berkala?", + needFile: false, + subAspectName: "Prioritas" + }, + { + question: "Apakah organisasi Anda melakukan prioritasi upaya remediasi dengan memanfaatkan level risiko dari hasil penilaian risiko?", + needFile: false, + subAspectName: "Prioritas" + }, + { + question: "Apakah organisasi Anda melakukan prioritasi terkait langkah proteksi keamanan siber termasuk strategi untuk memprioritaskan perlindungan data dan aset kritis?", + needFile: false, + subAspectName: "Prioritas" + }, + { + question: "Bagaimana pengelolaan data log keamanan informasi digunakan di organisasi Anda?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah aspek keamanan mempertimbangkan kapasitas server dan perangkat jaringan?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah profil keamanan informasi mencakup prioritas kerentanan dan rencana mitigasinya?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda memiliki metode atau standar untuk klasifikasi data?", + needFile: false, + subAspectName: "Klasifikasi" + }, + { + question: "Apakah organisasi Anda memiliki metode / standar untuk klasifikasi aset TI? Dan apakah dilakukan reviu secara berkala?", + needFile: false, + subAspectName: "Klasifikasi" + }, + { + question: "Apakah organisasi Anda melakukan klasifikasi terhadap cyber threats yang ditemukan pada organisasi Anda?", + needFile: false, + subAspectName: "Klasifikasi" + }, + { + question: "Apakah organisasi Anda melakukan segmentasi jaringan berdasarkan fungsionalitas (segmen bagian development, keuangan, SDM, dll)?", + needFile: false, + subAspectName: "Klasifikasi" + }, + { + question: "Apakah organisasi Anda memiliki IPS?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah akses nirkabel di organisasi Anda dikonfigurasikan dengan menggunakan sistem enkripsi?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah koneksi ke perangkat server dan jaringan di organisasi Anda menggunakan protokol terenkripsi seperti SSH, secure RDP, dll?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah semua perangkat jaringan menggunakan otentikasi terpusat?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah firewall atau ACL di organisasi Anda mengimplementasikan implicit or explicit deny any/any rule?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah inbound network traffic hanya mengizinkan traffic yang dibutuhkan oleh organisasi?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah outbond network traffic hanya mengizinkan lalu lintas yang dibutuhkan oleh organisasi?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah inbound network traffic di filter untuk memeriksa malware dan mencegah eksploitasi terhadap kerentanan?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda menerapkan port access control sebagai pengendalian terhadap otentikasi perangkat yang dapat terhubung ke jaringan?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda menerapkan firewall filtering antar segmen jaringan lokal?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda menonaktifkan komunikasi antar worskstation untuk mencegah potensi terjadinya serangan siber (compromise neighboring systems) dalam satu jaringan yang sama?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah karyawan di organisasi Anda mengaktifkan fitur wireless (bluetooth, NFC, wireless access, dsb) pada perangkatnya hanya sesuai kebutuhan organisasi?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda melakukan disable peer-to-peer pada wireless client di perangkat endpoint ?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda menerapkan DNS filtering services?", + needFile: false, + subAspectName: "Jaringan" + }, + { + question: "Apakah organisasi Anda membatasi aplikasi yang diunduh, diinstal, dan dioperasikan?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah semua aplikasi yang dipakai organisasi Anda menggunakan server terpisah baik fisik maupun virtual?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Bagaimana pengelolaan patch pada aplikasi di organisasi Anda? (termasuk didalamnya operating system dan software dari pihak ketiga)", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah email system di organisasi Anda (termasuk yang ada di cloud) memiliki pengecekan otomatis terhadap spam / phishing / malware?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah penggunaan cloud resources dan services form dijadikan dasar untuk menentukan RTO dan RPO di dalam dokumen Business Continuity Plan (BCP) organisasi?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah penerapan whitelist aplikasi di organisasi Anda juga memastikan bahwa hanya authorized software library (seperti: *.dll, *.so, *.ocx, *.exe, dsb) dan signed script (seperti: *.py, *.ps1, *.js, *.jar, dsb) yang dapat dijalankan oleh sistem?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah dilakukan pembatasan penggunaan scripting tools (seperti: Microsoft PowerShell dan Python) di organisasi Anda? ", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah master images tersimpan pada server yang dikonfigurasi secara aman?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah organisasi Anda memastikan web browser, email client yang digunakan pada perangkat milik organisasi masih mendapatkan update support ?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah organisasi Anda memastikan penggunaan add-on dan plugin aplikasi sudah sesuai dengan ketentuan organisasi?", + needFile: false, + subAspectName: "Aplikasi" + }, + { + question: "Apakah organisasi Anda menggunakan Next Generation Endpoint Protection?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah semua perangkat endpoints termasuk server menggunakan anti virus?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah web URL filtering, device control, dan application control diimplementasikan pada semua perangkat endpoint pengguna?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah dilakukan enkripsi pada semua perangkat mobile (laptop, handphone) karyawan di organisasi Anda?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah semua laptop karyawan secara otomatis meminta kata sandi setelah beberapa saat tidak aktif?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah organisasi Anda tidak mengijinkan fitur auto-run content terhadap perangkat portable yang terhubung ke sistem atau perangkat di organisasi Anda?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah organisasi Anda menerapkan pengaturan akses (read/write) terhadap perangkat USB/media penyimpanan eksternal?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah dilakukan enkripsi pada semua media penyimpanan eksternal di organisasi Anda?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah di organisasi Anda menerapkan pembatasan akun pada laptop/PC milik organisasi yang digunakan untuk aktivitas tertentu seperti: browsing internet, email, akses ke sosial media, transfer file via media eksternal, dan sebagainya?", + needFile: false, + subAspectName: "Pengguna" + }, + { + question: "Apakah identity and access management systems digunakan untuk seluruh operating system?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah informasi identitas dan akses pengguna digunakan untuk membatasi hak akses dari dalam jaringan Anda?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah Multi-Factor Authentication (MFA) digunakan untuk semua akses jaringan pada organisasi Anda?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah Multi-Factor Authentication (MFA) digunakan untuk mengakses data sensitif (misal data pribadi, data keuangan, dll)?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda memastikan penggunaan password yang kompleks untuk semua akses login?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda memastikan penggantian password secara berkala?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda menerapkan metode otentikasi melalui saluran terenkripsi?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda menambahkan verifikasi On Time Password (OTP) melalui SMS, WhatsApp Messenger, Telepon, Elektronil Mail, Google Authenticator, atau media lainnya untuk transaksi yang berisiko tinggi?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah akses ke data stakeholder / klien / konsumen / pelanggan diatur dengan hak akses?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda menerapkan IP reputation untuk memverifikasi alamat IP yang diizinkan dalam proses transaksi?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda dapat melacak dan dapat mendeteksi perilaku anomali transaksi yang dilakukan oleh karyawan maupun stakeholder / klien / konsumen / pelanggan?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda melakukan identifikasi perangkat pada setiap transaksi yang dilakukan oleh karyawan maupun stakeholder / klien / konsumen / pelanggan (seperti alamat IP, MAC Address, dan sebagainya)?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah pengguna selain admin database di organisasi Anda hanya memiliki akses read-only pada akses ke database?", + needFile: false, + subAspectName: "Manajemen Identitas dan Akses" + }, + { + question: "Apakah organisasi Anda menggunakan authorized cloud storage?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah cloud pada organisasi Anda menerapkan Single Sign-On?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah organisasi Anda hanya mengizinkan traffic pada layanan cloud untuk kebutuhan bisnis organisasi?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah akses traffic ke cloud di organisasi Anda hanya dibatasi dari alamat IP yang dikenal?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah penyedia cloud di organisasi Anda menerapkan multi-factor authentication?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah penyedia cloud di organisasi Anda memiliki Data Center Redudancy yang terpisah secara geografis dan memiliki Recovery Point dan Recovery Time Objective yang terdokumentasi?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah SSO di organisasi Anda dapat diakses melalui SSL VPN Tunel?", + needFile: false, + subAspectName: "Cloud" + }, + { + question: "Apakah semua data penting di organisasi Anda di-backup secara berkala?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah dilakukan pengujian data integrity secara berkala terhadap data yang di backup dengan melakukan restore data?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Seberapa lama log disimpan sehingga mempermudah untuk dilakukan audit dan forensik?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah semua data stakeholder / klien / konsumen / pelanggan dienkripsi saat disimpan?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah semua data stakeholder / klien / konsumen / pelanggan dienkripsi saat dikirim?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah penyimpanan data backup telah dilindungi secara tepat, baik secara fisik maupun non fisik (seperti: enkripsi, dsb)?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah semua critical system clocks telah disinkronkan dengan metode otomatis seperti Network Time Protocol?", + needFile: false, + subAspectName: "Data" + }, + { + question: "Apakah di organisasi Anda ada Change Advisory Board (CAB) yang meninjau dan menyetujui semua perubahan konfigurasi?", + needFile: false, + subAspectName: "Perubahan" + }, + { + question: "Apakah semua perubahan konfigurasi melalui proses Change Management System dan dilakukan reviu secara berkelanjutan?", + needFile: false, + subAspectName: "Perubahan" + }, + { + question: "Apakah perubahan konfigurasi pada peralatan jaringan terdeteksi secara otomatis?", + needFile: false, + subAspectName: "Perubahan" + }, + { + question: "Apakah di organisasi Anda terdapat mekanisme monitoring terhadap akses dan perubahan pada data sensitif? (seperti File Integrity Monitoring atau Event Monitoring)", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda sudah menerapkan monitoring (pemantauan dan notifikasi) terhadap aktivitas lalu lintas jaringan?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah mekanisme monitoring dan deteksi terhadap penggunaan enkripsi yang tidak sah sudah diterapkan?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda melakukan monitoring terhadap log dari perangkat security control, jaringan, dan aplikasi?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda mengaktifkan Enable Detailed Logging yang mencakup informasi terperinci seperti event source, tanggal, user, timestamp, source addresses, destination addresses, dan komponen lainnya?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda melakukan monitoring terhadap akses pengguna, koneksi jaringan, perangkat keras, dan perangkat lunak?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda memiliki sistem untuk memonitoring dan mencegah kehilangan data sensitif termasuk data stakeholder / klien / konsumen / pelanggan? contohnya penggunaan DLP (Data Loss Prevention).", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda menerapkan SIEM atau Log Analytic Tools untuk keperluan dokumentasi, korelasi, dan analisis log?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda dapat mendeteksi Wireless Access Point yang terhubung ke jaringan LAN (ethernet)?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda menjamin alokasi kapasitas penyimpanan log sesuai dengan kebutuhan?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah setiap orang yang tergabung dalam tim monitoring pada organisasi Anda mendapatkan peningkatan keterampilan?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda melakukan deteksi terhadap anomali pada jaringan untuk melihat potensi kejadian keamanan siber?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah aktivitas pihak ketiga di organisasi Anda dipantau untuk mendeteksi adanya potensi kejadian keamanan siber?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda memantau akses fisik terhadap perangkat yang berada di dalam ruangan data center untuk mendeteksi potensi kejadian keamanan siber?", + needFile: false, + subAspectName: "Monitor" + }, + { + question: "Apakah organisasi Anda memiliki mekanisme untuk mendeteksi adanya akses yang tidak diizinkan pada sistem?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah organisasi Anda dapat mendeteksi kegagalan login pada akun admin pada perangkat jaringan, server, dan aplikasi?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah organisasi Anda memiliki perangkat anti-malware yang secara otomatis melakukan scanning terhadap removable media yang terhubung ke perangkat?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah log hasil deteksi malware terhubung dengan perangkat anti-malware administrations dan event log servers sehingga dapat digunakan untuk analisis?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah organisasi Anda menerapkan automated port scan secara berkala terhadap semua sistem dan memberikan alert jika terdapat port yang tidak sah terdeteksi pada suatu sistem?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah organisasi Anda memiliki ticketing system yang digunakan untuk melacak progres dari events post-notification?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah ticketing system melacak kejadian berdasarkan tingkat keparahan / prioritas / dampak, kategori keamanan, dan jenis log yang berkorelasi untuk suatu kejadian?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah escalation profile dibuat untuk setiap security event yang ditemukan, kemudian disimpan sebagai panduan untuk digunakan di masa mendatang?", + needFile: false, + subAspectName: "Peringatan" + }, + { + question: "Apakah organisasi Anda memiliki SOC atau manajemen teknis yang dapat dihubungi setiap saat (24x7) untuk menangani kejadian dengan prioritas tinggi dan kritikal?", + needFile: false, + subAspectName: "Pemberitahuan" + }, + { + question: "Apakah organisasi Anda menyimpan semua log terhadap URL yang diakses oleh karyawan?", + needFile: false, + subAspectName: "Pemberitahuan" + }, + { + question: "Apakah organisasi Anda dapat mendeteksi aktivitas anomali login seperti waktu, lokasi, durasi, dan sebagainya?", + needFile: false, + subAspectName: "Pemberitahuan" + }, + { + question: "Apakah organisasi Anda memiliki contact tree untuk mengeskalasi dalam merespon suatu kejadian?", + needFile: false, + subAspectName: "Pemberitahuan" + }, + { + question: "Apakah organisasi Anda menerapkan event notification yang berbeda-beda untuk setiap jenis eskalasi?\nMisalnya:\nPrioritas rendah = pembuatan tiket,\nPrioritas sedang = pemberitahuan email dengan tiket,\nPrioritas tinggi = email, panggilan telepon dan pembuatan tiket.", + needFile: false, + subAspectName: "Pemberitahuan" + }, + { + question: "Apakah organisasi Anda memperoleh informasi dari multiple threat intelligence feeds untuk mendeteksi serangan siber?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah threat intelligence feeds dikonfigurasi secara otomatis untuk memperbarui kontrol pencegahan, seperti pembaruan signature IPS, update rules, dan konfigurasi lainnya?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Bagaimana organisasi Anda mendapatkan update terkait isu keamanan siber terkini?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah organisasi Anda menjalankan vulnerability scanning tools secara otomatis untuk mendeteksi kerentanan siber?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah organisasi Anda melakukan vulnerability scanning secara otomatis menggunakan agent/aplikasi yang diinstal pada endpoint?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah organisasi Anda mengaktifkan DNS query logging dalam mendeteksi hostname lookups untuk mengetahui adanya malicious domain?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah di dalam organisasi anda memiliki sistem yang untuk mendeteksi ancaman siber sehingga dapat memberikan input/feed bagi threat intelligence seperti penggunaan deception technology?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah di dalam organisasi Anda memiliki sistem untuk melakukan Malicious Code Detection untuk mendeteksi, menghapus, dan melindungi dari malicious code?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah di dalam organisasi Anda terdapat unit yang berfungsi untuk melakukan Cyber Threat Intelligence (CTI)?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah organisasi Anda mengetahui atau dapat mendefinisikan dimana program deteksi beroperasi dan tujuan apa yang akan dicapai/diidentifikasi?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Informasi apa saja yang dapat dideteksi oleh organisasi Anda dari sebuah serangan siber?", + needFile: false, + subAspectName: "Intelijen" + }, + { + question: "Apakah metrik security event digunakan untuk evaluasi dalam rangka menghitung efisiensi operasional pengelolaan TI?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah metrik security event di organisasi Anda menjadi pertimbangan dalam menilai keberhasilan penerapan keamanan, seperti menurunnya false-positive dan true-negative, pemblokiran otomatis terhadap upaya permintaan hak akses yang gagal?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Seberapa sering metrik security event di organisasi Anda di reviu untuk tujuan operasional?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Seberapa sering Top Level Management pada organisasi Anda menerima briefing tentang kondisi keamanan siber terkini?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah terdapat mekanisme sharing informasi hasil deteksi?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda memiliki kebijakan penanganan insiden dan selaras dengan kebijakan pengaturan kesinambungan organisasi atau business continuity planning (BCP)?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah terdapat standar operasional prosedur (SOP) dan form pelaporan penanganan insiden yang diketahui oleh pihak terkait?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah dokumen rencana respon insiden atau disaster recovery plan (DRP) dan standar operasional prosedur (SOP) penanganan insiden di reviu secara berkala?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda membuat skema penilaian insiden dan prioritas berdasarkan potensial dampak (aspek kerugian operasional, bisnis, reputasi, dan hukum) bagi organisasi Anda?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda merencanakan skenario insiden dan melakukan latihan respon insiden secara rutin untuk karyawan yang terlibat dalam respon insiden?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah latihan respon insiden mencakup pengujian saluran komunikasi, pengambilan keputusan, dan kemampuan teknis pelaporan insiden dengan menggunakan alat dan data yang tersedia?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda memberikan pelatihan untuk karyawan tentang cara mengidentifikasi, penanganan, dan pelaporan suatu insiden keamanan informasi?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda mempunyai daftar kontak tim penanganan insiden internal dan eksternal (misalnya penegak hukum, ambulance, pemadam kebakaran, dll) yang dapat dihubungi pada saat terjadi insiden?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda memastikan bahwa rencana respon insiden terdokumentasi dan dapat mendefinisikan peran personel pada fase penanganan/ manajemen insiden serta pembagian peran ke pihak eksternal termasuk eskalasi permasalahan?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Jika terdapat laporan terjadinya infeksi malware di organisasi Anda, berapa lama waktu yang dibutuhkan untuk melakukan diskoneksi segmen jaringan untuk mencegah penyebaran malware?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda mendesain jaringan yang dapat memastikan apabila server DMZ terkena serangan siber, penyerang tidak dapat mengakses server yang lain?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah organisasi Anda melakukan backup data yang ada di pc/laptop karyawan ke cloud organisasi?", + needFile: false, + subAspectName: "Penahanan" + }, + { + question: "Apakah tim respon insiden siber di organisasi Anda memiliki peralatan sumber daya analisis insiden (misalnya daftar host, packet snifer, analisis protokol, dokumentasi protokol keamanan, diagram jaringan, daftar aset penting, alat digital forensic, dan sebagainya)?", + needFile: false, + subAspectName: "Penanggulangan" + }, + { + question: "Apakah tim respon insiden organisasi Anda memiliki kemampuan mendeteksi insiden, melakukan analisis, dan rekomendasi solusi? (termasuk insiden tingkat lanjut misal pencurian data, illegal akses, penyusupan, aktivitas illegal, dan sebagainya)", + needFile: false, + subAspectName: "Penanggulangan" + }, + { + question: "Jika di organisasi Anda terdapat sistem penting/kritikal yang down karena insiden siber, apakah terdapat sumber daya redundan yang dapat langsung digunakan?", + needFile: false, + subAspectName: "Penanggulangan" + }, + { + question: "Setelah ditemukan kerentanan yang menyebabkan pelanggaran dan telah dilakukan patching, apakah dilakukan scanning ulang untuk memastikan bahwa kerentanan tersebut sudah ditutup?", + needFile: false, + subAspectName: "Penanggulangan" + }, + { + question: "Apakah organisasi Anda memiliki metode yang terdokumentasi dan diinformasikan kepada stakeholder / klien / konsumen / pelanggan untuk melaporkan penyalahgunaan informasi stakeholder / klien / konsumen / pelanggan?", + needFile: false, + subAspectName: "Penanggulangan" + }, + { + question: "Jika organisasi Anda mengalami insiden siber apakah tim respon insiden dapat dengan cepat mendapat bantuan dari tim manajemen krisis (contoh: spesialis keamanan teknis, tim bisnis, spesialis hukum, tim SDM, dan tim komunikasi eksternal) dan dapat dengan cepat mengakses informasi (dari penyedia pihak ketiga, dan informasi pendukung yang penting lainnya)?", + needFile: false, + subAspectName: "Pemulihan" + }, + { + question: "Apakah tim respon insiden di organisasi Anda mencatat setiap langkah yang dilakukan dalam rangka penanggulangan insiden menggunakan format yang baku (telah ditetapkan oleh organisasi)?", + needFile: false, + subAspectName: "Pemulihan" + }, + { + question: "Jika terjadi insiden siber di organisasi Anda yang menyebabkan server down/tidak berfungsi, apakah organisasi Anda dapat memastikan server dari backup dapat digunakan dalam kurun waktu kurang dari 3 jam?", + needFile: false, + subAspectName: "Pemulihan" + }, + { + question: "Berapa lama organisasi Anda dapat me-restore data dari backup sesuai waktu RPO (Recovery Point Objective)?", + needFile: false, + subAspectName: "Pemulihan" + }, + { + question: "Apakah organisasi Anda melakukan reviu terhadap root cause dari suatu insiden siber untuk mencegah kejadian serupa berulang?", + needFile: false, + subAspectName: "Kegiatan Paska Insiden" + }, + { + question: "Apakah organisasi Anda melakukan reviu terhadap rekap laporan insiden siber yang pernah terjadi untuk melihat apakah prosedur insiden respon sudah sesuai dengan standar yang ditetapkan?", + needFile: false, + subAspectName: "Kegiatan Paska Insiden" + }, + { + question: "Apakah hasil reviu terhadap rekap laporan insiden siber dilaporkan ke top management dan didistribusikan kepada para pemangku kepentingan serta digunakan dalam rangka mereviu kontrol yang ada untuk perbaikan respon penanganan insiden siber selanjutnya?", + needFile: false, + subAspectName: "Kegiatan Paska Insiden" + }, + { + question: "Apakah organisasi Anda memastikan pencapaian SLA dalam penanganan insiden?", + needFile: false, + subAspectName: "Kegiatan Paska Insiden" + }, + { + question: "Apakah semua rekaman insiden dan pelanggaran di organisasi Anda disimpan dan dilaporkan berdasarkan trends insiden dalam jangka waktu tertentu?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda memiliki metrik perhitungan biaya untuk mencegah insiden siber yang menggunakan metode perhitungan ROI (Return of Invesment) pada program keamanan siber di organisasi? Dan apakah di reviu secara berkala?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda menggunakan sumber referensi terpercaya untuk memperhitungkan biaya pengeluaran akibat insiden siber, yang selanjutnya digunakan untuk membuat ROI (Return of Invesment) dalam menentukan skala prioritas tindakan mitigasi risiko dan meminimalisir kerugian biaya akibat terjadinya insiden siber?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Jika terindikasi dan terkonfirmasi adanya kehilangan data pribadi dari stakeholder / klien / konsumen / pelanggan, tindakan apa yang dilakukan organisasi Anda?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda mempublikasikan informasi untuk semua karyawan dan stakeholder / klien / konsumen / pelanggan mengenai mekanisme pelaporan anomali dan insiden siber kepada tim penanganan insiden siber organisasi? Dan apakah informasi tersebut dimasukkan dalam kegiatan kesadaran keamanan informasi secara rutin?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah organisasi Anda merancang standar terkait waktu yang diperlukan bagi administrator sistem dan karyawan lainnya untuk melaporkan kejadian yang tidak wajar kepada tim penanganan insiden, mekanisme pelaporan tersebut, dan jenis informasi yang harus dimasukkan dalam pemberitahuan insiden?", + needFile: false, + subAspectName: "Pelaporan" + }, + { + question: "Apakah laporan insiden di organisasi Anda dilaporkan ke top management dan ke pihak eksternal yang berkepentingan/ wajib dilaporkan sesuai regulasi?", + needFile: false, + subAspectName: "Pelaporan" + }, ]; console.log("Seeding questions..."); diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 901e997..1e5f62b 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -35,6 +35,7 @@ "clsx": "^2.1.1", "dayjs": "^1.11.11", "hono": "^4.4.6", + "html2pdf.js": "^0.10.2", "lucide-react": "^0.414.0", "mantine-form-zod-resolver": "^1.1.0", "react": "^18.3.1", diff --git a/apps/frontend/src/routeTree.gen.ts b/apps/frontend/src/routeTree.gen.ts index 22543a9..6f7f054 100644 --- a/apps/frontend/src/routeTree.gen.ts +++ b/apps/frontend/src/routeTree.gen.ts @@ -13,12 +13,19 @@ import { createFileRoute } from '@tanstack/react-router' // Import Routes import { Route as rootRoute } from './routes/__root' +import { Route as VerifyingLayoutImport } from './routes/_verifyingLayout' import { Route as DashboardLayoutImport } from './routes/_dashboardLayout' +import { Route as AssessmentLayoutImport } from './routes/_assessmentLayout' +import { Route as VerifyingLayoutVerifyingIndexImport } from './routes/_verifyingLayout/verifying/index' import { Route as DashboardLayoutUsersIndexImport } from './routes/_dashboardLayout/users/index' import { Route as DashboardLayoutTimetableIndexImport } from './routes/_dashboardLayout/timetable/index' -import { Route as DashboardLayoutDashboardIndexImport } from './routes/_dashboardLayout/dashboard/index' +import { Route as DashboardLayoutQuestionsIndexImport } from './routes/_dashboardLayout/questions/index' +import { Route as DashboardLayoutAssessmentResultsManagementIndexImport } from './routes/_dashboardLayout/assessmentResultsManagement/index' +import { Route as DashboardLayoutAssessmentResultIndexImport } from './routes/_dashboardLayout/assessmentResult/index' +import { Route as DashboardLayoutAssessmentRequestManagementsIndexImport } from './routes/_dashboardLayout/assessmentRequestManagements/index' import { Route as DashboardLayoutAssessmentRequestIndexImport } from './routes/_dashboardLayout/assessmentRequest/index' import { Route as DashboardLayoutAspectIndexImport } from './routes/_dashboardLayout/aspect/index' +import { Route as AssessmentLayoutAssessmentIndexImport } from './routes/_assessmentLayout/assessment/index' // Create Virtual Routes @@ -33,11 +40,21 @@ const ForgotPasswordVerifyLazyImport = createFileRoute( // Create/Update Routes +const VerifyingLayoutRoute = VerifyingLayoutImport.update({ + id: '/_verifyingLayout', + getParentRoute: () => rootRoute, +} as any) + const DashboardLayoutRoute = DashboardLayoutImport.update({ id: '/_dashboardLayout', getParentRoute: () => rootRoute, } as any) +const AssessmentLayoutRoute = AssessmentLayoutImport.update({ + id: '/_assessmentLayout', + getParentRoute: () => rootRoute, +} as any) + const IndexLazyRoute = IndexLazyImport.update({ path: '/', getParentRoute: () => rootRoute, @@ -74,6 +91,16 @@ const ForgotPasswordVerifyLazyRoute = ForgotPasswordVerifyLazyImport.update({ import('./routes/forgot-password/verify.lazy').then((d) => d.Route), ) +const VerifyingLayoutVerifyingIndexRoute = + VerifyingLayoutVerifyingIndexImport.update({ + path: '/verifying/', + getParentRoute: () => VerifyingLayoutRoute, + } as any).lazy(() => + import('./routes/_verifyingLayout/verifying/index.lazy').then( + (d) => d.Route, + ), + ) + const DashboardLayoutUsersIndexRoute = DashboardLayoutUsersIndexImport.update({ path: '/users/', getParentRoute: () => DashboardLayoutRoute, @@ -87,11 +114,45 @@ const DashboardLayoutTimetableIndexRoute = getParentRoute: () => DashboardLayoutRoute, } as any) -const DashboardLayoutDashboardIndexRoute = - DashboardLayoutDashboardIndexImport.update({ - path: '/dashboard/', +const DashboardLayoutQuestionsIndexRoute = + DashboardLayoutQuestionsIndexImport.update({ + path: '/questions/', getParentRoute: () => DashboardLayoutRoute, - } as any) + } as any).lazy(() => + import('./routes/_dashboardLayout/questions/index.lazy').then( + (d) => d.Route, + ), + ) + +const DashboardLayoutAssessmentResultsManagementIndexRoute = + DashboardLayoutAssessmentResultsManagementIndexImport.update({ + path: '/assessmentResultsManagement/', + getParentRoute: () => DashboardLayoutRoute, + } as any).lazy(() => + import( + './routes/_dashboardLayout/assessmentResultsManagement/index.lazy' + ).then((d) => d.Route), + ) + +const DashboardLayoutAssessmentResultIndexRoute = + DashboardLayoutAssessmentResultIndexImport.update({ + path: '/assessmentResult/', + getParentRoute: () => DashboardLayoutRoute, + } as any).lazy(() => + import('./routes/_dashboardLayout/assessmentResult/index.lazy').then( + (d) => d.Route, + ), + ) + +const DashboardLayoutAssessmentRequestManagementsIndexRoute = + DashboardLayoutAssessmentRequestManagementsIndexImport.update({ + path: '/assessmentRequestManagements/', + getParentRoute: () => DashboardLayoutRoute, + } as any).lazy(() => + import( + './routes/_dashboardLayout/assessmentRequestManagements/index.lazy' + ).then((d) => d.Route), + ) const DashboardLayoutAssessmentRequestIndexRoute = DashboardLayoutAssessmentRequestIndexImport.update({ @@ -112,6 +173,16 @@ const DashboardLayoutAspectIndexRoute = DashboardLayoutAspectIndexImport.update( import('./routes/_dashboardLayout/aspect/index.lazy').then((d) => d.Route), ) +const AssessmentLayoutAssessmentIndexRoute = + AssessmentLayoutAssessmentIndexImport.update({ + path: '/assessment/', + getParentRoute: () => AssessmentLayoutRoute, + } as any).lazy(() => + import('./routes/_assessmentLayout/assessment/index.lazy').then( + (d) => d.Route, + ), + ) + // Populate the FileRoutesByPath interface declare module '@tanstack/react-router' { @@ -123,6 +194,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexLazyImport parentRoute: typeof rootRoute } + '/_assessmentLayout': { + id: '/_assessmentLayout' + path: '' + fullPath: '' + preLoaderRoute: typeof AssessmentLayoutImport + parentRoute: typeof rootRoute + } '/_dashboardLayout': { id: '/_dashboardLayout' path: '' @@ -130,6 +208,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DashboardLayoutImport parentRoute: typeof rootRoute } + '/_verifyingLayout': { + id: '/_verifyingLayout' + path: '' + fullPath: '' + preLoaderRoute: typeof VerifyingLayoutImport + parentRoute: typeof rootRoute + } '/forgot-password/verify': { id: '/forgot-password/verify' path: '/forgot-password/verify' @@ -165,6 +250,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof RegisterIndexLazyImport parentRoute: typeof rootRoute } + '/_assessmentLayout/assessment/': { + id: '/_assessmentLayout/assessment/' + path: '/assessment' + fullPath: '/assessment' + preLoaderRoute: typeof AssessmentLayoutAssessmentIndexImport + parentRoute: typeof AssessmentLayoutImport + } '/_dashboardLayout/aspect/': { id: '/_dashboardLayout/aspect/' path: '/aspect' @@ -179,11 +271,32 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DashboardLayoutAssessmentRequestIndexImport parentRoute: typeof DashboardLayoutImport } - '/_dashboardLayout/dashboard/': { - id: '/_dashboardLayout/dashboard/' - path: '/dashboard' - fullPath: '/dashboard' - preLoaderRoute: typeof DashboardLayoutDashboardIndexImport + '/_dashboardLayout/assessmentRequestManagements/': { + id: '/_dashboardLayout/assessmentRequestManagements/' + path: '/assessmentRequestManagements' + fullPath: '/assessmentRequestManagements' + preLoaderRoute: typeof DashboardLayoutAssessmentRequestManagementsIndexImport + parentRoute: typeof DashboardLayoutImport + } + '/_dashboardLayout/assessmentResult/': { + id: '/_dashboardLayout/assessmentResult/' + path: '/assessmentResult' + fullPath: '/assessmentResult' + preLoaderRoute: typeof DashboardLayoutAssessmentResultIndexImport + parentRoute: typeof DashboardLayoutImport + } + '/_dashboardLayout/assessmentResultsManagement/': { + id: '/_dashboardLayout/assessmentResultsManagement/' + path: '/assessmentResultsManagement' + fullPath: '/assessmentResultsManagement' + preLoaderRoute: typeof DashboardLayoutAssessmentResultsManagementIndexImport + parentRoute: typeof DashboardLayoutImport + } + '/_dashboardLayout/questions/': { + id: '/_dashboardLayout/questions/' + path: '/questions' + fullPath: '/questions' + preLoaderRoute: typeof DashboardLayoutQuestionsIndexImport parentRoute: typeof DashboardLayoutImport } '/_dashboardLayout/timetable/': { @@ -200,6 +313,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof DashboardLayoutUsersIndexImport parentRoute: typeof DashboardLayoutImport } + '/_verifyingLayout/verifying/': { + id: '/_verifyingLayout/verifying/' + path: '/verifying' + fullPath: '/verifying' + preLoaderRoute: typeof VerifyingLayoutVerifyingIndexImport + parentRoute: typeof VerifyingLayoutImport + } } } @@ -207,13 +327,22 @@ declare module '@tanstack/react-router' { export const routeTree = rootRoute.addChildren({ IndexLazyRoute, + AssessmentLayoutRoute: AssessmentLayoutRoute.addChildren({ + AssessmentLayoutAssessmentIndexRoute, + }), DashboardLayoutRoute: DashboardLayoutRoute.addChildren({ DashboardLayoutAspectIndexRoute, DashboardLayoutAssessmentRequestIndexRoute, - DashboardLayoutDashboardIndexRoute, + DashboardLayoutAssessmentRequestManagementsIndexRoute, + DashboardLayoutAssessmentResultIndexRoute, + DashboardLayoutAssessmentResultsManagementIndexRoute, + DashboardLayoutQuestionsIndexRoute, DashboardLayoutTimetableIndexRoute, DashboardLayoutUsersIndexRoute, }), + VerifyingLayoutRoute: VerifyingLayoutRoute.addChildren({ + VerifyingLayoutVerifyingIndexRoute, + }), ForgotPasswordVerifyLazyRoute, ForgotPasswordIndexLazyRoute, LoginIndexLazyRoute, @@ -230,7 +359,9 @@ export const routeTree = rootRoute.addChildren({ "filePath": "__root.tsx", "children": [ "/", + "/_assessmentLayout", "/_dashboardLayout", + "/_verifyingLayout", "/forgot-password/verify", "/forgot-password/", "/login/", @@ -241,16 +372,31 @@ export const routeTree = rootRoute.addChildren({ "/": { "filePath": "index.lazy.tsx" }, + "/_assessmentLayout": { + "filePath": "_assessmentLayout.tsx", + "children": [ + "/_assessmentLayout/assessment/" + ] + }, "/_dashboardLayout": { "filePath": "_dashboardLayout.tsx", "children": [ "/_dashboardLayout/aspect/", "/_dashboardLayout/assessmentRequest/", - "/_dashboardLayout/dashboard/", + "/_dashboardLayout/assessmentRequestManagements/", + "/_dashboardLayout/assessmentResult/", + "/_dashboardLayout/assessmentResultsManagement/", + "/_dashboardLayout/questions/", "/_dashboardLayout/timetable/", "/_dashboardLayout/users/" ] }, + "/_verifyingLayout": { + "filePath": "_verifyingLayout.tsx", + "children": [ + "/_verifyingLayout/verifying/" + ] + }, "/forgot-password/verify": { "filePath": "forgot-password/verify.lazy.tsx" }, @@ -266,6 +412,10 @@ export const routeTree = rootRoute.addChildren({ "/register/": { "filePath": "register/index.lazy.tsx" }, + "/_assessmentLayout/assessment/": { + "filePath": "_assessmentLayout/assessment/index.tsx", + "parent": "/_assessmentLayout" + }, "/_dashboardLayout/aspect/": { "filePath": "_dashboardLayout/aspect/index.tsx", "parent": "/_dashboardLayout" @@ -274,8 +424,20 @@ export const routeTree = rootRoute.addChildren({ "filePath": "_dashboardLayout/assessmentRequest/index.tsx", "parent": "/_dashboardLayout" }, - "/_dashboardLayout/dashboard/": { - "filePath": "_dashboardLayout/dashboard/index.tsx", + "/_dashboardLayout/assessmentRequestManagements/": { + "filePath": "_dashboardLayout/assessmentRequestManagements/index.tsx", + "parent": "/_dashboardLayout" + }, + "/_dashboardLayout/assessmentResult/": { + "filePath": "_dashboardLayout/assessmentResult/index.tsx", + "parent": "/_dashboardLayout" + }, + "/_dashboardLayout/assessmentResultsManagement/": { + "filePath": "_dashboardLayout/assessmentResultsManagement/index.tsx", + "parent": "/_dashboardLayout" + }, + "/_dashboardLayout/questions/": { + "filePath": "_dashboardLayout/questions/index.tsx", "parent": "/_dashboardLayout" }, "/_dashboardLayout/timetable/": { @@ -285,6 +447,10 @@ export const routeTree = rootRoute.addChildren({ "/_dashboardLayout/users/": { "filePath": "_dashboardLayout/users/index.tsx", "parent": "/_dashboardLayout" + }, + "/_verifyingLayout/verifying/": { + "filePath": "_verifyingLayout/verifying/index.tsx", + "parent": "/_verifyingLayout" } } } diff --git a/apps/frontend/src/routes/_dashboardLayout/assessmentResult/index.lazy.tsx b/apps/frontend/src/routes/_dashboardLayout/assessmentResult/index.lazy.tsx index 0dbe0b6..b0f8b30 100644 --- a/apps/frontend/src/routes/_dashboardLayout/assessmentResult/index.lazy.tsx +++ b/apps/frontend/src/routes/_dashboardLayout/assessmentResult/index.lazy.tsx @@ -1,4 +1,5 @@ -import { SetStateAction, useEffect, useState } from "react"; +import { SetStateAction, useEffect, useRef, useState } from "react"; +import html2pdf from "html2pdf.js"; import useAuth from "@/hooks/useAuth"; import { createLazyFileRoute } from "@tanstack/react-router"; import { getAllAspectsAverageScore, getAllSubAspectsAverageScore, getAllVerifiedAspectsAverageScore, getAllVerifiedSubAspectsAverageScore } from "@/modules/assessmentResult/queries/assessmentResultQueries"; @@ -185,14 +186,11 @@ export default function AssessmentResultPage() { }; const handleItemClick = () => { - // Mengubah antara "Hasil Sementara" dan "Hasil Terverifikasi" - if (selectedItem === 'Hasil Sementara') { - setSelectedItem('Hasil Terverifikasi'); // Mengubah teks dropdown - } else { - setSelectedItem('Hasil Sementara'); // Mengubah kembali ke teks awal - } - setIsOpen(false); // Menutup dropdown setelah item dipilih - }; + setSelectedItem(prev => + prev === 'Hasil Sementara' ? 'Hasil Terverifikasi' : 'Hasil Sementara' + ); + setIsOpen(false); // Tutup dropdown setelah klik item +}; // Pie Chart Component function PieChartComponent({ chartData, totalScore, chartConfig }: { chartData: { aspectName: string, score: number, fill: string }[], totalScore: number, chartConfig: ChartConfig }) { @@ -349,11 +347,64 @@ export default function AssessmentResultPage() { ); } + const cardRef = useRef(null); // Create a ref for your component + + const handlePrintPDF = async () => { + const element = cardRef.current; + + if (element) { + // Sembunyikan elemen yang tidak ingin dicetak + const noPrint = document.getElementById("no-print"); + if (noPrint) noPrint.style.visibility = 'hidden'; // Menggunakan visibility untuk tetap menjaga ruang + + // Pastikan elemen memiliki lebar 100% + element.style.width = '100%'; // Mengatur lebar konten + + const options = { + margin: [0.4, 0.5, 0.4, 0], // Margin kecil untuk mengurangi ruang kosong + image: { type: 'jpeg', quality: 0.98 }, + html2canvas: { + scale: 2, // Mengatur scale agar kualitas tinggi + width: element.scrollWidth, + height: element.scrollHeight, + }, + jsPDF: { + unit: 'in', + format: 'a4', + orientation: 'landscape', + } + }; + + try { + const pdfBlob: Blob = await html2pdf() + .set(options) + .from(element) + .toPdf() + .get('pdf') + .then((pdf: any) => { + pdf.setProperties({ + title: 'Hasil_Asesemen_Level_Maturitas', + }); + return pdf.output('blob'); // Menghasilkan PDF sebagai blob dengan title + }); + + // Buat URL dari Blob dan buka di tab baru untuk pratinjau + const pdfURL = URL.createObjectURL(pdfBlob); + window.open(pdfURL, '_blank'); // Pratinjau di tab baru tanpa unduh + } catch (err) { + console.error("Error generating PDF:", err); + } finally { + // Tampilkan kembali elemen yang disembunyikan + if (noPrint) noPrint.style.visibility = 'visible'; // Mengembalikan visibility + element.style.width = ""; // Reset lebar setelah selesai + } + } +}; return ( - -
-

Tingkatan Level Maturitas

+ +
+

Tingkatan Level Maturitas

{[ { level: 5, colorVar: '--levelFive-color', title: 'Implementasi Optimal', details: ['Otomatisasi', 'Terintegrasi', 'Membudaya'], textColor: 'white' }, @@ -403,28 +454,35 @@ export default function AssessmentResultPage() {
)} - {/* Dropdown */} -
- - - {selectedItem} - {isOpen ? ( - - ) : ( - +
+ +
+ + + {selectedItem} + {isOpen ? ( + + ) : ( + + )} + + {isOpen && ( + + + {selectedItem === 'Hasil Sementara' ? 'Hasil Terverifikasi' : 'Hasil Sementara'} + + )} - - {isOpen && ( - - - {selectedItem === 'Hasil Sementara' ? 'Hasil Terverifikasi' : 'Hasil Sementara'} - - - )} - + +
@@ -505,10 +563,10 @@ export default function AssessmentResultPage() { <> {/* Score Table */}

Tabel Level Maturitas

- -
+ +
{aspectsData?.data?.map((aspect) => ( -
+

{aspect.name}

{formatScore(getAspectScore(aspect.id))} @@ -516,7 +574,7 @@ export default function AssessmentResultPage() { {aspect.subAspects.map((subAspect) => (
-

{subAspect.name}

+

{subAspect.name}

{formatScore(getSubAspectScore(subAspect.id))}
@@ -526,8 +584,8 @@ export default function AssessmentResultPage() {
{/* Total score */} -
-

Level Maturitas:

+
+

Level Maturitas:

{totalScore}
@@ -536,7 +594,7 @@ export default function AssessmentResultPage() { <> {/* Verified Result Table */}

Tabel Level Maturitas Terverifikasi

- +
{aspectsData?.data?.map((aspect) => (
@@ -547,7 +605,7 @@ export default function AssessmentResultPage() { {aspect.subAspects.map((subAspect) => (
-

{subAspect.name}

+

{subAspect.name}

{formatScore(getVerifiedSubAspectScore(subAspect.id))}
@@ -557,98 +615,91 @@ export default function AssessmentResultPage() {
{/* Total verified score */} -
-

Level Maturitas:

+
+

Level Maturitas:

{totalVerifiedScore}
)} - + {/* Pie Chart */} {selectedItem === 'Hasil Sementara' ? ( - <> - - - Diagram Lingkaran - - - - - - + + + Diagram Lingkaran + + + + + ) : ( - <> - - - Diagram Lingkaran Terverifikasi - - - - - - + + + Diagram Lingkaran Terverifikasi + + + + + )} + {/* Radar Chart */} {selectedItem === 'Hasil Sementara' ? ( - <> - - - Diagram Radar - - - - - - + + + Diagram Radar + + + + + ) : ( - <> - - - Diagram Radar Terverifikasi - - - - - - + + + Diagram Radar Terverifikasi + + + + + )} {/* Bar Chart */} {selectedItem === 'Hasil Sementara' ? ( - <> - - - Diagram Batang - - - - - - - ) : ( - <> - - - Diagram Batang Terverifikasi - - - - - - - )} + <> + + + Diagram Batang + + + + + + + ) : ( + <> + + + Diagram Batang Terverifikasi + + + + + + + )} diff --git a/apps/frontend/src/types/html2pdf.d.ts b/apps/frontend/src/types/html2pdf.d.ts new file mode 100644 index 0000000..63982d1 --- /dev/null +++ b/apps/frontend/src/types/html2pdf.d.ts @@ -0,0 +1 @@ +declare module 'html2pdf.js'; \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b0d98b3..811b197 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -168,6 +168,9 @@ importers: hono: specifier: ^4.4.6 version: 4.4.6 + html2pdf.js: + specifier: ^0.10.2 + version: 0.10.2 lucide-react: specifier: ^0.414.0 version: 0.414.0(react@18.3.1) @@ -2400,6 +2403,9 @@ packages: '@types/prop-types@15.7.5': resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + '@types/raf@3.4.3': + resolution: {integrity: sha512-c4YAvMedbPZ5tEyxzQdMoOhhJ4RD3rngZIdwC2/qDN3d7JpEhB6fiBRKVY1lg5B7Wk+uPBjn5f39j1/2MY1oOw==} + '@types/react-dom@18.2.19': resolution: {integrity: sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==} @@ -2837,6 +2843,11 @@ packages: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} + atob@2.1.2: + resolution: {integrity: sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==} + engines: {node: '>= 4.5.0'} + hasBin: true + autoprefixer@10.4.19: resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} engines: {node: ^10 || ^12 || >=14} @@ -2887,6 +2898,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base64-arraybuffer@1.0.2: + resolution: {integrity: sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==} + engines: {node: '>= 0.6.0'} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -2932,6 +2947,11 @@ packages: bser@2.1.1: resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + btoa@1.2.1: + resolution: {integrity: sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==} + engines: {node: '>= 0.4.0'} + hasBin: true + buffer-equal-constant-time@1.0.1: resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} @@ -2980,6 +3000,10 @@ packages: caniuse-lite@1.0.30001667: resolution: {integrity: sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==} + canvg@3.0.10: + resolution: {integrity: sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==} + engines: {node: '>=10.0.0'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -3113,6 +3137,9 @@ packages: core-js-pure@3.32.1: resolution: {integrity: sha512-f52QZwkFVDPf7UEQZGHKx6NYxsxmVGJe5DIvbzOdRMJlmT6yv0KDjR8rmy3ngr/t5wU54c7Sp/qIJH0ppbhVpQ==} + core-js@3.39.0: + resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} + cosmiconfig@7.1.0: resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} engines: {node: '>=10'} @@ -3129,6 +3156,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} + css-line-break@2.1.0: + resolution: {integrity: sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -3341,6 +3371,9 @@ packages: dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dompurify@2.5.7: + resolution: {integrity: sha512-2q4bEI+coQM8f5ez7kt2xclg1XsecaV9ASJk/54vwlfRRNQfDqJz2pzQ8t0Ix/ToBpXlVjrRIx7pFC/o8itG2Q==} + dot-case@2.1.1: resolution: {integrity: sha512-HnM6ZlFqcajLsyudHq7LeeLDr2rFAVYtDv/hV5qchQEidSck8j9OPUsXY9KwJv/lHMtYlX4DjRQqwFYa+0r8Ug==} @@ -3499,6 +3532,9 @@ packages: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} + es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} + esbuild-register@3.5.0: resolution: {integrity: sha512-+4G/XmakeBAsvJuDugJvtyF1x+XJT4FMocynNpxrvEBViirpfUn2PgNpCHedfWhF4WokNsO/OvMKrmJOIJsI5A==} peerDependencies: @@ -3794,6 +3830,9 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fflate@0.8.2: + resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -4047,6 +4086,13 @@ packages: html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html2canvas@1.4.1: + resolution: {integrity: sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==} + engines: {node: '>=8.0.0'} + + html2pdf.js@0.10.2: + resolution: {integrity: sha512-WyHVeMb18Bp7vYTmBv1GVsThH//K7SRfHdSdhHPkl4JvyQarNQXnailkYn0QUbRRmnN5rdbbmSIGEsPZtzPy2Q==} + http-proxy-agent@7.0.0: resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} engines: {node: '>= 14'} @@ -4511,6 +4557,9 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} + jspdf@2.5.2: + resolution: {integrity: sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -4941,6 +4990,9 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} @@ -5128,6 +5180,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -5273,6 +5328,9 @@ packages: resolution: {integrity: sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==} engines: {node: '>= 0.4'} + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} @@ -5340,6 +5398,10 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + rgbcolor@1.0.1: + resolution: {integrity: sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==} + engines: {node: '>= 0.8.15'} + rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -5518,6 +5580,10 @@ packages: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} + stackblur-canvas@2.7.0: + resolution: {integrity: sha512-yf7OENo23AGJhBriGx0QivY5JP6Y1HbrrDI6WLt6C5auYZXlQrheoY8hD4ibekFKz1HOfE48Ww8kMWMnJD/zcQ==} + engines: {node: '>=0.1.14'} + string-length@4.0.2: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} @@ -5610,6 +5676,10 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + svg-pathdata@6.0.3: + resolution: {integrity: sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==} + engines: {node: '>=12.0.0'} + swap-case@1.1.2: resolution: {integrity: sha512-BAmWG6/bx8syfc6qXPprof3Mn5vQgf5dwdUNJhsNqU9WdPt5P+ES/wQ5bxfijy8zwZgZZHslC3iAsxsuQMCzJQ==} @@ -5645,6 +5715,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-segmentation@1.0.3: + resolution: {integrity: sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -5916,6 +5989,9 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utrie@1.0.2: + resolution: {integrity: sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==} + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -8242,6 +8318,9 @@ snapshots: '@types/prop-types@15.7.5': {} + '@types/raf@3.4.3': + optional: true + '@types/react-dom@18.2.19': dependencies: '@types/react': 18.2.61 @@ -8834,6 +8913,8 @@ snapshots: dependencies: tslib: 2.6.3 + atob@2.1.2: {} + autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.1 @@ -8922,6 +9003,8 @@ snapshots: balanced-match@1.0.2: {} + base64-arraybuffer@1.0.2: {} + base64-js@1.5.1: {} basic-ftp@5.0.3: {} @@ -8979,6 +9062,8 @@ snapshots: node-int64: 0.4.0 optional: true + btoa@1.2.1: {} + buffer-equal-constant-time@1.0.1: {} buffer-from@1.1.2: {} @@ -9024,6 +9109,18 @@ snapshots: caniuse-lite@1.0.30001667: optional: true + canvg@3.0.10: + dependencies: + '@babel/runtime': 7.24.7 + '@types/raf': 3.4.3 + core-js: 3.39.0 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + rgbcolor: 1.0.1 + stackblur-canvas: 2.7.0 + svg-pathdata: 6.0.3 + optional: true + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -9165,6 +9262,9 @@ snapshots: core-js-pure@3.32.1: {} + core-js@3.39.0: + optional: true + cosmiconfig@7.1.0: dependencies: '@types/parse-json': 4.0.2 @@ -9197,6 +9297,10 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 + css-line-break@2.1.0: + dependencies: + utrie: 1.0.2 + cssesc@3.0.0: {} csstype@3.1.2: {} @@ -9371,6 +9475,9 @@ snapshots: '@babel/runtime': 7.24.7 csstype: 3.1.3 + dompurify@2.5.7: + optional: true + dot-case@2.1.1: dependencies: no-case: 2.3.2 @@ -9513,6 +9620,8 @@ snapshots: is-date-object: 1.0.5 is-symbol: 1.0.4 + es6-promise@4.2.8: {} + esbuild-register@3.5.0(esbuild@0.19.12): dependencies: debug: 4.3.5 @@ -10019,6 +10128,8 @@ snapshots: bser: 2.1.1 optional: true + fflate@0.8.2: {} + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -10299,6 +10410,17 @@ snapshots: html-escaper@2.0.2: optional: true + html2canvas@1.4.1: + dependencies: + css-line-break: 2.1.0 + text-segmentation: 1.0.3 + + html2pdf.js@0.10.2: + dependencies: + es6-promise: 4.2.8 + html2canvas: 1.4.1 + jspdf: 2.5.2 + http-proxy-agent@7.0.0: dependencies: agent-base: 7.1.0 @@ -10993,6 +11115,18 @@ snapshots: ms: 2.1.3 semver: 7.6.2 + jspdf@2.5.2: + dependencies: + '@babel/runtime': 7.24.7 + atob: 2.1.2 + btoa: 1.2.1 + fflate: 0.8.2 + optionalDependencies: + canvg: 3.0.10 + core-js: 3.39.0 + dompurify: 2.5.7 + html2canvas: 1.4.1 + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.8 @@ -11431,6 +11565,9 @@ snapshots: path-type@4.0.0: {} + performance-now@2.1.0: + optional: true + pg-cloudflare@1.1.1: optional: true @@ -11606,6 +11743,11 @@ snapshots: queue-microtask@1.2.3: {} + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + optional: true + rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -11777,6 +11919,9 @@ snapshots: globalthis: 1.0.4 which-builtin-type: 1.1.3 + regenerator-runtime@0.13.11: + optional: true + regenerator-runtime@0.14.0: {} regenerator-runtime@0.14.1: {} @@ -11845,6 +11990,9 @@ snapshots: reusify@1.0.4: {} + rgbcolor@1.0.1: + optional: true + rimraf@3.0.2: dependencies: glob: 7.2.3 @@ -12069,6 +12217,9 @@ snapshots: escape-string-regexp: 2.0.0 optional: true + stackblur-canvas@2.7.0: + optional: true + string-length@4.0.2: dependencies: char-regex: 1.0.2 @@ -12179,6 +12330,9 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + svg-pathdata@6.0.3: + optional: true + swap-case@1.1.2: dependencies: lower-case: 1.1.4 @@ -12242,6 +12396,10 @@ snapshots: minimatch: 3.1.2 optional: true + text-segmentation@1.0.3: + dependencies: + utrie: 1.0.2 + text-table@0.2.0: {} thenify-all@1.6.0: @@ -12515,6 +12673,10 @@ snapshots: util-deprecate@1.0.2: {} + utrie@1.0.2: + dependencies: + base64-arraybuffer: 1.0.2 + v8-compile-cache-lib@3.0.1: {} v8-to-istanbul@9.3.0: