3333 <pre class =" pt-5" v-text =" description" />
3434 </v-col >
3535 </v-row >
36+ <v-row >
37+ <v-col cols =" 1" >
38+ <v-icon color =" primary" >mdi-information-variant-circle</v-icon >
39+ </v-col >
40+ <v-col >
41+ Both Manager and Administrator Reports can be data intensive, which
42+ can take longer for the browser to render the page.
43+ </v-col >
44+ </v-row >
3645 </v-card-text >
3746 <v-divider />
3847 <v-card-actions >
@@ -57,6 +66,7 @@ import {Filter} from '../../store/data_filters';
5766import {InspecDataModule } from ' ../../store/data_store' ;
5867import {SnackbarModule } from ' ../../store/snackbar' ;
5968import {FromHDFToHTMLMapper } from ' @mitre/hdf-converters' ;
69+ import {SourcedContextualizedEvaluation } from ' ../../store/report_intake' ;
6070
6171// All selectable export types for an HTML export
6272enum FileExportTypes {
@@ -118,23 +128,38 @@ export default class ExportHTMLModal extends Vue {
118128 return SnackbarModule .failure (' No files have been loaded.' );
119129 }
120130
131+ document .body .style .cursor = ' wait' ;
121132 const files = [];
133+ const filteredStatus = this .filter .status ! .toString () || ' ' ;
134+ const filteredSeverity = this .filter .severity ! .toString () || ' ' ;
135+
122136 for (const fileId of this .filter .fromFile ) {
123137 const file = InspecDataModule .allEvaluationFiles .find (
124138 (f ) => f .uniqueId === fileId
125139 );
140+
126141 if (file ) {
127142 const data = file .evaluation ;
128- const fileName = file .filename ;
129- const fileID = file .uniqueId ;
130- files .push ({data , fileName , fileID });
143+ const filteredControls = this .getFilterControlIds (
144+ data ,
145+ filteredStatus ,
146+ filteredSeverity
147+ );
148+
149+ // Only show files that have controls that meet
150+ // the status/severity criteria, could be all files
151+ if (filteredControls .length > 0 ) {
152+ const fileName = file .filename ;
153+ const fileID = file .uniqueId ;
154+ files .push ({data , fileName , fileID , filteredControls });
155+ }
131156 }
132157 }
133-
134158 // Generate and export HTML file
135159 const body = await new FromHDFToHTMLMapper (files , this .exportType ).toHTML (
136160 ' /static/export/'
137161 );
162+
138163 saveAs (
139164 new Blob ([s2ab (body )], {type: ' application/octet-stream' }),
140165 ` ${this .exportType }_Report_${new Date ().toString ()}.html ` .replace (
@@ -143,7 +168,83 @@ export default class ExportHTMLModal extends Vue {
143168 )
144169 );
145170
171+ document .body .style .cursor = ' default' ;
146172 this .closeModal ();
147173 }
174+
175+ /**
176+ * Generate an array containing the control identification numbers
177+ * (profiles.controls) selected. The Id is extracted for the
178+ * profiles.controls.id, it can be CIS, STIG (V or SV), CWEID, WASCID,
179+ * or any other control Id.
180+ *
181+ * Possible selection permutations are:
182+ * - Status (pass, failed, etc)
183+ * - Severity ( low, medium, etc)
184+ * - Combination of Status and Severity
185+ */
186+ getFilterControlIds(
187+ data : SourcedContextualizedEvaluation ,
188+ status : string ,
189+ severity : string
190+ ): string [] {
191+ /**
192+ * NOTE: The filterControls array is used to specify what controls
193+ * are selected based on Status and Severity selection.
194+ * If we use the approach of filtering the content from the data object
195+ * (e.g.
196+ * data.data.profiles[0].controls =
197+ * data.data.profiles[0].controls.filter((control) => {
198+ * if (filteredControls.includes(control.id)) {
199+ * return filteredControls.includes(control.id);
200+ * }
201+ * });
202+ * )
203+ * the contextualize object does not get updated and the results
204+ * in data_store get out of sync, there is, when utilizing the
205+ * ".contains" it returns the results object (child of the controls object)
206+ * where the file.evaluations returns the filtered controls.
207+ */
208+ let filteredControls: string [] = [];
209+ // Both Status and Severity selection
210+ if (status .length > 0 && severity .length > 0 ) {
211+ data .contains .map ((profile ) => {
212+ profile .contains .map ((result ) => {
213+ if (
214+ status ?.includes (result .root .hdf .status ) &&
215+ severity ?.includes (result .root .hdf .severity )
216+ ) {
217+ filteredControls .push (result .data .id );
218+ }
219+ });
220+ });
221+ // Status selection
222+ } else if (status .length > 0 ) {
223+ data .contains .map ((profile ) => {
224+ profile .contains .map ((result ) => {
225+ if (status ?.includes (result .root .hdf .status )) {
226+ filteredControls .push (result .data .id );
227+ }
228+ });
229+ });
230+ // Severity selection
231+ } else if (severity .length > 0 ) {
232+ data .contains .map ((profile ) => {
233+ profile .contains .map ((result ) => {
234+ if (severity ?.includes (result .root .hdf .severity )) {
235+ filteredControls .push (result .data .id );
236+ }
237+ });
238+ });
239+ // No selection
240+ } else {
241+ data .contains .map ((profile ) => {
242+ profile .contains .map ((result ) => {
243+ filteredControls .push (result .data .id );
244+ });
245+ });
246+ }
247+ return filteredControls ;
248+ }
148249}
149250 </script >
0 commit comments