1+ // SPDX-License-Identifier: Apache-2.0
2+ //
3+ // http://nexb.com and https://github.com/aboutcode-org/scancode.io
4+ // The ScanCode.io software is licensed under the Apache License version 2.0.
5+ // Data generated with ScanCode.io is provided as-is without warranties.
6+ // ScanCode is a trademark of nexB Inc.
7+ //
8+ // You may not use this software except in compliance with the License.
9+ // You may obtain a copy of the License at: http://apache.org/licenses/LICENSE-2.0
10+ // Unless required by applicable law or agreed to in writing, software distributed
11+ // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12+ // CONDITIONS OF ANY KIND, either express or implied. See the License for the
13+ // specific language governing permissions and limitations under the License.
14+ //
15+ // Data Generated with ScanCode.io is provided on an "AS IS" BASIS, WITHOUT WARRANTIES
16+ // OR CONDITIONS OF ANY KIND, either express or implied. No content created from
17+ // ScanCode.io should be considered or used as legal advice. Consult an Attorney
18+ // for any legal advice.
19+ //
20+ // ScanCode.io is a free software code scanning tool from nexB Inc. and others.
21+ // Visit https://github.com/aboutcode-org/scancode.io for support and download.
22+
23+ 'use strict' ;
24+
25+ ( function ( ) {
26+ const form = document . querySelector ( 'form' ) ;
27+ if ( ! form ) return ;
28+
29+ const pipelineSelect = document . getElementById ( "id_pipeline" ) ;
30+ if ( ! pipelineSelect ) return ;
31+
32+ // Upload progress overlay on form submit
33+ form . addEventListener ( 'submit' , function ( event ) {
34+ let background = displayOverlay ( ) ;
35+
36+ // The upload progress is only added when input files are provided.
37+ if ( ! form [ "input_files" ] . files . length ) return false ;
38+
39+ event . preventDefault ( ) ;
40+
41+ let progress_bar = document . createElement ( 'progress' ) ;
42+ progress_bar . className = 'progress is-success is-medium file-upload' ;
43+ progress_bar . setAttribute ( 'value' , '0' ) ;
44+ progress_bar . setAttribute ( 'max' , '100' ) ;
45+
46+ let progress_container = document . createElement ( 'div' ) ;
47+ progress_container . className = 'container is-max-desktop mt-6 px-6' ;
48+ progress_container . appendChild ( progress_bar )
49+ background . appendChild ( progress_container ) ;
50+
51+ let form_errors = document . getElementById ( 'form-errors' ) ;
52+ displayFormUploadProgress ( form , progress_bar , form_errors , true ) ;
53+ } ) ;
54+
55+ // Pipeline groups checkboxes
56+
57+ const availableGroupsDataSource = document . getElementById ( "pipelines_available_groups" ) ;
58+ if ( ! availableGroupsDataSource ) return ;
59+
60+ const availableGroupsMapping = JSON . parse ( availableGroupsDataSource . textContent ) ;
61+ const idSelectedGroups = document . getElementById ( "id_selected_groups" ) ;
62+
63+ function clearSelectedGroups ( ) {
64+ idSelectedGroups . replaceChildren ( ) ;
65+ }
66+
67+ function buildCheckbox ( group ) {
68+ const id = `id_${ group } ` ;
69+ const label = document . createElement ( 'label' ) ;
70+ label . className = 'checkbox ml-1 mb-1' ;
71+ label . htmlFor = id ;
72+
73+ const span = document . createElement ( 'span' ) ;
74+ span . className = 'tag is-warning has-text-weight-bold' ;
75+
76+ const input = document . createElement ( 'input' ) ;
77+ input . type = 'checkbox' ;
78+ input . name = 'selected_groups' ;
79+ input . value = group ;
80+ input . id = id ;
81+ input . className = 'mr-1' ;
82+
83+ span . appendChild ( input ) ;
84+ span . appendChild ( document . createTextNode ( ' ' + group ) ) ;
85+
86+ label . appendChild ( span ) ;
87+
88+ return label ;
89+ }
90+
91+ function handlePipelineChange ( ) {
92+ clearSelectedGroups ( ) ;
93+
94+ const selectedPipelineName = pipelineSelect . value ;
95+ if ( ! selectedPipelineName ) return ;
96+
97+ const availableGroups = availableGroupsMapping [ selectedPipelineName ] ;
98+ if ( availableGroups && availableGroups . length > 0 ) {
99+ const strongElement = document . createElement ( 'strong' ) ;
100+ const icon = document . createElement ( 'i' ) ;
101+ icon . className = 'fa-solid fa-circle-arrow-right' ;
102+ strongElement . appendChild ( icon ) ;
103+ strongElement . appendChild ( document . createTextNode ( ' Include:' ) ) ;
104+ idSelectedGroups . appendChild ( strongElement ) ;
105+
106+ availableGroups . forEach ( ( group ) => {
107+ const checkboxElement = buildCheckbox ( group ) ;
108+ idSelectedGroups . appendChild ( checkboxElement ) ;
109+ } ) ;
110+ }
111+ }
112+
113+ handlePipelineChange ( ) ;
114+ pipelineSelect . addEventListener ( "change" , handlePipelineChange ) ;
115+
116+ // Auto-detect pipeline from input value
117+
118+ function detectPipelineFromValue ( value ) {
119+ value = value . trim ( ) . toLowerCase ( ) ;
120+
121+ if ( ! value ) return "" ;
122+
123+ // Handle Docker reference
124+ if ( value . startsWith ( "docker:" ) ) return "analyze_docker_image" ;
125+
126+ // Handle Package URL
127+ if ( value . startsWith ( "pkg:" ) ) return "scan_single_package" ;
128+
129+ // Handle SBOM file formats
130+ if (
131+ value . endsWith ( ".spdx" ) ||
132+ value . endsWith ( ".spdx.json" ) ||
133+ value . endsWith ( ".spdx.yml" ) ||
134+ value . endsWith ( "bom.json" ) ||
135+ value . endsWith ( ".cdx.json" ) ||
136+ value . endsWith ( ".cyclonedx.json" ) ||
137+ value . endsWith ( "bom.xml" ) ||
138+ value . endsWith ( ".cdx.xml" ) ||
139+ value . endsWith ( ".cyclonedx.xml" )
140+ ) return "load_sbom" ;
141+
142+ // No match
143+ return "" ;
144+ }
145+
146+ const textarea = document . getElementById ( "id_input_urls" ) ;
147+ const fileInput = document . getElementById ( "id_input_files" ) ;
148+
149+ // Handle textarea input
150+ textarea . addEventListener ( "input" , ( ) => {
151+ const value = textarea . value . trim ( ) ;
152+ const pipeline = detectPipelineFromValue ( value ) ;
153+ pipelineSelect . value = pipeline ;
154+ } ) ;
155+
156+ // Handle file uploads
157+ fileInput . addEventListener ( "change" , ( ) => {
158+ const files = Array . from ( fileInput . files ) ;
159+
160+ // Detect based on first file, multiple input files not supported.
161+ if ( files . length === 1 ) {
162+ const firstFile = files [ 0 ] . name . toLowerCase ( ) ;
163+ const pipeline = detectPipelineFromValue ( firstFile ) ;
164+ pipelineSelect . value = pipeline ;
165+ } else {
166+ pipelineSelect . value = "" ;
167+ }
168+ } ) ;
169+
170+ } ) ( ) ;
0 commit comments